From 4815473a05b1bc2ae317bffdb679502c13cce574 Mon Sep 17 00:00:00 2001 From: Imbyungjun Date: Tue, 8 Nov 2022 00:46:36 +0900 Subject: [PATCH 01/75] Fix typo in toc_group --- truffle/docs/LanguageTutorial.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/truffle/docs/LanguageTutorial.md b/truffle/docs/LanguageTutorial.md index a90a8c9811a9..19db4cc957ca 100644 --- a/truffle/docs/LanguageTutorial.md +++ b/truffle/docs/LanguageTutorial.md @@ -1,6 +1,6 @@ --- layout: docs -toc_group: truffles +toc_group: truffle link_title: Implementing a New Language with Truffle permalink: /graalvm-as-a-platform/language-implementation-framework/LanguageTutorial/ --- From 6f2ebeba339f95c13a280bdfd6b6b61488cd397e Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Fri, 6 Oct 2023 17:04:52 -0400 Subject: [PATCH 02/75] handle FlightRecorderOptions add repositorypath option --- .../com/oracle/svm/core/SubstrateOptions.java | 3 + .../com/oracle/svm/core/jfr/JfrManager.java | 142 ++++++++++++++---- .../com/oracle/svm/core/jfr/JfrOptionSet.java | 10 ++ .../com/oracle/svm/core/jfr/SubstrateJVM.java | 3 +- 4 files changed, 127 insertions(+), 31 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index d827d45a9445..3c2fa85fbbc8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -918,6 +918,9 @@ public Boolean getValue(OptionValues values) { @Option(help = "file:doc-files/FlightRecorderLoggingHelp.txt")// public static final RuntimeOptionKey FlightRecorderLogging = new RuntimeOptionKey<>("all=warning", Immutable); + @Option(help = "Use additional flight recorder options.")// + public static final RuntimeOptionKey FlightRecorderOptions = new RuntimeOptionKey<>("", Immutable); + public static String reportsPath() { Path reportsPath = ImageSingletons.lookup(ReportingSupport.class).reportsPath; if (reportsPath.isAbsolute()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java index f77545e4f5e8..ea26519b8ad6 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java @@ -55,9 +55,11 @@ import jdk.jfr.internal.LogTag; import jdk.jfr.internal.Logger; import jdk.jfr.internal.OldObjectSample; +import jdk.jfr.internal.Options; import jdk.jfr.internal.PrivateAccess; import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.jfc.JFC; +import jdk.jfr.internal.Repository; /** * Called during VM startup and teardown. Also triggers the JFR argument parsing. @@ -73,7 +75,7 @@ public JfrManager(boolean hostedEnabled) { this.hostedEnabled = hostedEnabled; } - public static boolean isJFREnabled() { + public static boolean shouldBeginRecordingAtLaunch() { return SubstrateOptions.FlightRecorder.getValue() || !SubstrateOptions.StartFlightRecording.getValue().isEmpty(); } @@ -86,7 +88,7 @@ public RuntimeSupport.Hook startupHook() { return isFirstIsolate -> { parseFlightRecorderLogging(SubstrateOptions.FlightRecorderLogging.getValue()); periodicEventSetup(); - if (isJFREnabled()) { + if (shouldBeginRecordingAtLaunch()) { initRecording(); } }; @@ -115,17 +117,27 @@ private static void periodicEventSetup() throws SecurityException { } private static void initRecording() { - Map args = parseStartFlightRecording(); - String name = args.get(JfrStartArgument.Name); - String[] settings = parseSettings(args); - Long delay = parseDuration(args, JfrStartArgument.Delay); - Long duration = parseDuration(args, JfrStartArgument.Duration); - Boolean disk = parseBoolean(args, JfrStartArgument.Disk); - String path = args.get(JfrStartArgument.Filename); - Long maxAge = parseDuration(args, JfrStartArgument.MaxAge); - Long maxSize = parseMaxSize(args, JfrStartArgument.MaxSize); - Boolean dumpOnExit = parseBoolean(args, JfrStartArgument.DumpOnExit); - Boolean pathToGcRoots = parseBoolean(args, JfrStartArgument.PathToGCRoots); + Map startArgs = parseJfrOptions(SubstrateOptions.StartFlightRecording.getValue(), JfrStartArgument.values()); + Map optionsArgs = parseJfrOptions(SubstrateOptions.FlightRecorderOptions.getValue(), FlightRecorderOptionsArgument.values()); + + String name = startArgs.get(JfrStartArgument.Name); + String[] settings = parseSettings(startArgs); + Long delay = parseDuration(startArgs, JfrStartArgument.Delay); + Long duration = parseDuration(startArgs, JfrStartArgument.Duration); + Boolean disk = parseBoolean(startArgs, JfrStartArgument.Disk); + String path = startArgs.get(JfrStartArgument.Filename); + Long maxAge = parseDuration(startArgs, JfrStartArgument.MaxAge); + Long maxSize = parseMaxSize(startArgs, JfrStartArgument.MaxSize); + Boolean dumpOnExit = parseBoolean(startArgs, JfrStartArgument.DumpOnExit); + Boolean pathToGcRoots = parseBoolean(startArgs, JfrStartArgument.PathToGCRoots); + String stackDepth = optionsArgs.get(FlightRecorderOptionsArgument.StackDepth); + Long maxChunkSize = parseMaxSize(optionsArgs, FlightRecorderOptionsArgument.MaxChunkSize); + Long memorySize = parseMaxSize(optionsArgs, FlightRecorderOptionsArgument.MemorySize); + Long globalBufferSize = parseMaxSize(optionsArgs, FlightRecorderOptionsArgument.GlobalBufferSize); + Long globalBufferCount = parseMaxSize(optionsArgs, FlightRecorderOptionsArgument.GlobalBufferCount); + Long threadBufferSize = parseMaxSize(optionsArgs, FlightRecorderOptionsArgument.ThreadBufferSize); + Boolean preserveRepo = parseBoolean(optionsArgs, FlightRecorderOptionsArgument.PreserveRepository); + String repositoryPath = optionsArgs.get(FlightRecorderOptionsArgument.RepositoryPath); try { if (Logger.shouldLog(LogTag.JFR_DCMD, LogLevel.DEBUG)) { @@ -182,6 +194,47 @@ private static void initRecording() { } } + if (stackDepth != null) { + try { + Options.setStackDepth(Integer.valueOf(stackDepth)); + } catch (Throwable e) { + throw new Exception("Could not start recording, stack depth is not an integer.", e); + } + } + + if (repositoryPath != null) { + try { + SecuritySupport.SafePath repositorySafePath = new SecuritySupport.SafePath(repositoryPath); + Repository.getRepository().setBasePath(repositorySafePath); + } catch (Throwable e) { + throw new Exception("Could not start recording, repository path is invalid.", e); + } + } + + if (maxChunkSize != null) { + Options.setMaxChunkSize(maxChunkSize); + } + + if (preserveRepo != null) { + Options.setPreserveRepository(preserveRepo); + } + + if (threadBufferSize != null) { + Options.setThreadBufferSize(threadBufferSize); + } + + if (globalBufferCount != null) { + Options.setGlobalBufferCount(globalBufferCount); + } + + if (globalBufferSize != null) { + Options.setGlobalBufferSize(globalBufferSize); + } + + if (memorySize != null) { + Options.setMemorySize(memorySize); + } + Recording recording = new Recording(); if (name != null) { recording.setName(name); @@ -297,15 +350,13 @@ private static String getPath(Path path) { } } - private static Map parseStartFlightRecording() { - Map optionsMap = new HashMap<>(); - String text = SubstrateOptions.StartFlightRecording.getValue(); - if (!text.isEmpty()) { - JfrStartArgument[] possibleArguments = JfrStartArgument.values(); - String[] options = text.split(","); + private static Map parseJfrOptions(String userInput, JfrArgument[] possibleArguments) { + Map optionsMap = new HashMap<>(); + if (!userInput.isEmpty()) { + String[] options = userInput.split(","); for (String option : options) { String[] keyVal = option.split("="); - JfrStartArgument arg = findArgument(possibleArguments, keyVal[0]); + JfrArgument arg = findArgument(possibleArguments, keyVal[0]); if (arg == null) { throw VMError.shouldNotReachHere("Unknown argument '" + keyVal[0] + "' in " + SubstrateOptions.StartFlightRecording.getName()); } @@ -315,7 +366,7 @@ private static Map parseStartFlightRecording() { return optionsMap; } - private static String[] parseSettings(Map args) throws UserException { + private static String[] parseSettings(Map args) throws UserException { String settings = args.get(JfrStartArgument.Settings); if (settings == null) { return new String[]{DEFAULT_JFC_NAME}; @@ -327,7 +378,7 @@ private static String[] parseSettings(Map args) throws } @SuppressFBWarnings(value = "NP_BOOLEAN_RETURN_NULL", justification = "null allowed as return value") - private static Boolean parseBoolean(Map args, JfrStartArgument key) throws IllegalArgumentException { + private static Boolean parseBoolean(Map args, JfrArgument key) throws IllegalArgumentException { String value = args.get(key); if (value == null) { return null; @@ -336,11 +387,11 @@ private static Boolean parseBoolean(Map args, JfrStart } else if ("false".equalsIgnoreCase(value)) { return false; } else { - throw VMError.shouldNotReachHere("Could not parse JFR argument '" + key.cmdLineKey + "=" + value + "'. Expected a boolean value."); + throw VMError.shouldNotReachHere("Could not parse JFR argument '" + key.getCmdLineKey() + "=" + value + "'. Expected a boolean value."); } } - private static Long parseDuration(Map args, JfrStartArgument key) { + private static Long parseDuration(Map args, JfrStartArgument key) { String value = args.get(key); if (value != null) { try { @@ -384,7 +435,7 @@ private static Long parseDuration(Map args, JfrStartAr return null; } - private static Long parseMaxSize(Map args, JfrStartArgument key) { + private static Long parseMaxSize(Map args, JfrArgument key) { final String value = args.get(key); if (value != null) { try { @@ -417,7 +468,7 @@ private static Long parseMaxSize(Map args, JfrStartArg return number; } } catch (IllegalArgumentException e) { - throw VMError.shouldNotReachHere("Could not parse JFR argument '" + key.cmdLineKey + "=" + value + "'. " + e.getMessage()); + throw VMError.shouldNotReachHere("Could not parse JFR argument '" + key.getCmdLineKey() + "=" + value + "'. " + e.getMessage()); } } return null; @@ -431,16 +482,20 @@ private static int indexOfFirstNonDigitCharacter(String durationText) { return idx; } - private static JfrStartArgument findArgument(JfrStartArgument[] possibleArguments, String value) { - for (JfrStartArgument arg : possibleArguments) { - if (arg.cmdLineKey.equals(value)) { + private static JfrArgument findArgument(JfrArgument[] possibleArguments, String value) { + for (JfrArgument arg : possibleArguments) { + if (arg.getCmdLineKey().equals(value)) { return arg; } } return null; } - private enum JfrStartArgument { + private interface JfrArgument { + String getCmdLineKey(); + } + + private enum JfrStartArgument implements JfrArgument { Name("name"), Settings("settings"), Delay("delay"), @@ -457,5 +512,32 @@ private enum JfrStartArgument { JfrStartArgument(String key) { this.cmdLineKey = key; } + + @Override + public String getCmdLineKey() { + return cmdLineKey; + } + } + + private enum FlightRecorderOptionsArgument implements JfrArgument { + GlobalBufferCount("globalbuffercount"), + GlobalBufferSize("globalbuffersize"), + MaxChunkSize("maxchunksize"), + MemorySize("memorysize"), + RepositoryPath("repositorypath"), + StackDepth("stackdepth"), + ThreadBufferSize("thread_buffer_size"), + PreserveRepository("preserveRepository"); + + private final String cmdLineKey; + + FlightRecorderOptionsArgument(String key) { + this.cmdLineKey = key; + } + + @Override + public String getCmdLineKey() { + return cmdLineKey; + } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java index 977e82957dad..8f0a0b9674ab 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java @@ -35,6 +35,14 @@ /** * Holds all JFR-related options that can be set by the user. It is also used to validate and adjust * the option values as needed. + * + * Similar to OpenJDK, the options available by -XX:FlightRecorderOptions cannot be set after JFR is + * initialized. This means this that after {@link SubstrateJVM#createJFR(boolean)} is called, this + * class is no longer needed. + * + * This class is used to store options set at the OpenJDK Java-level which propagate down to the VM + * level via {@link jdk.jfr.internal.JVM}. The option values are stored here until they are + * eventually used when first recording is created and JFR is initialized. */ public class JfrOptionSet { private static final int MEMORY_SIZE = 1; @@ -54,6 +62,7 @@ public class JfrOptionSet { public final JfrOptionLong globalBufferCount; public final JfrOptionLong memorySize; public final JfrOptionLong maxChunkSize; + public final JfrOptionLong stackDepth; @Platforms(Platform.HOSTED_ONLY.class) public JfrOptionSet() { @@ -62,6 +71,7 @@ public JfrOptionSet() { globalBufferCount = new JfrOptionLong(Options.getGlobalBufferCount()); memorySize = new JfrOptionLong(Options.getMemorySize()); maxChunkSize = new JfrOptionLong(Options.getMaxChunkSize()); + stackDepth = new JfrOptionLong(Options.getStackDepth()); } public void validateAndAdjustMemoryOptions() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java index 8b4975136958..ad4eef6add53 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java @@ -209,6 +209,7 @@ public boolean createJFR(boolean simulateFailure) { threadLocal.initialize(options.threadBufferSize.getValue()); globalMemory.initialize(options.globalBufferSize.getValue(), options.globalBufferCount.getValue()); unlockedChunkWriter.initialize(options.maxChunkSize.getValue()); + stackTraceRepo.setStackTraceDepth((int) options.stackDepth.getValue()); recorderThread.start(); @@ -444,7 +445,7 @@ public void setCompressedIntegers(boolean compressed) { * See {@link JVM#setStackDepth}. */ public void setStackDepth(int depth) { - stackTraceRepo.setStackTraceDepth(depth); + options.stackDepth.setUserValue(depth); } /** From eed1498e8bcfa56cc27d856603eb971ae0bdc8f5 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Thu, 12 Oct 2023 12:42:59 -0400 Subject: [PATCH 03/75] add help descriptions --- .../com/oracle/svm/core/SubstrateOptions.java | 2 +- .../doc-files/FlightRecorderOptionsHelp.txt | 46 +++++++++++++++++++ .../com/oracle/svm/core/jfr/JfrManager.java | 2 +- 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index 3c2fa85fbbc8..e49dd75c94d2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -918,7 +918,7 @@ public Boolean getValue(OptionValues values) { @Option(help = "file:doc-files/FlightRecorderLoggingHelp.txt")// public static final RuntimeOptionKey FlightRecorderLogging = new RuntimeOptionKey<>("all=warning", Immutable); - @Option(help = "Use additional flight recorder options.")// + @Option(help = "file:doc-files/FlightRecorderOptionsHelp.txt")// public static final RuntimeOptionKey FlightRecorderOptions = new RuntimeOptionKey<>("", Immutable); public static String reportsPath() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt new file mode 100644 index 000000000000..0d8b351e11b0 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt @@ -0,0 +1,46 @@ +Usage: -XX:FlightRecorderOptions=[option[=value][,...]] + +This option expects a comma separated list of key-value pairs. None of the options are mandatory. Possible option keys are as follows: + +globalbuffercount (Optional) Number of global buffers. This option is a legacy + option: change the memorysize parameter to alter the number of + global buffers. This value cannot be changed once JFR has been" + initialized. (LONG, default determined by the value for + memorysize) + +globalbuffersize (Optional) Size of the global buffers, in bytes. This option is a + legacy option: change the memorysize parameter to alter the size + of the global buffers. This value cannot be changed once JFR has + been initialized. (STRING, default determined by the value for + memorysize) + +maxchunksize (Optional) Maximum size of an individual data chunk in bytes if + one of the following suffixes is not used: 'm' or 'M' for + megabytes OR 'g' or 'G' for gigabytes. This value cannot be + changed once JFR has been initialized. (STRING, 12M) + +memorysize (Optional) Overall memory size, in bytes if one of the following + suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for + gigabytes. This value cannot be changed once JFR has been + initialized. (STRING, 10M) + +repositorypath (Optional) Path to the location where recordings are stored until + they are written to a permanent file. (STRING, The default + location is the temporary directory for the operating system. On + Linux operating systems, the temporary directory is /tmp. On + Windows, the temporary directory is specified by the TMP + environment variable) + +stackdepth (Optional) Stack depth for stack traces. Setting this value + greater than the default of 64 may cause a performance + degradation. This value cannot be changed once JFR has been + initialized. (LONG, 64) + +thread_buffer_size (Optional) Local buffer size for each thread in bytes if one of + the following suffixes is not used: 'k' or 'K' for kilobytes or + 'm' or 'M' for megabytes. Overriding this parameter could reduce + performance and is not recommended. This value cannot be changed + once JFR has been initialized. (STRING, 8k) + +preserve-repository (Optional) Preserve files stored in the disk repository after the + Java Virtual Machine has exited. (BOOLEAN, false) \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java index ea26519b8ad6..c066c82b5354 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java @@ -527,7 +527,7 @@ private enum FlightRecorderOptionsArgument implements JfrArgument { RepositoryPath("repositorypath"), StackDepth("stackdepth"), ThreadBufferSize("thread_buffer_size"), - PreserveRepository("preserveRepository"); + PreserveRepository("preserve-repository"); private final String cmdLineKey; From 74e21750bd191a456ebd0671b5ce7d1aeb706a11 Mon Sep 17 00:00:00 2001 From: Robert Toyonaga Date: Mon, 4 Dec 2023 12:09:26 -0500 Subject: [PATCH 04/75] fix typo --- .../com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt index 0d8b351e11b0..06b737e77da7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt @@ -4,7 +4,7 @@ This option expects a comma separated list of key-value pairs. None of the optio globalbuffercount (Optional) Number of global buffers. This option is a legacy option: change the memorysize parameter to alter the number of - global buffers. This value cannot be changed once JFR has been" + global buffers. This value cannot be changed once JFR has been initialized. (LONG, default determined by the value for memorysize) From 92c8c6d486eb9d5e8fd0a79cf51da105daf826df Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 18:27:16 +0200 Subject: [PATCH 05/75] Allow UnsupportedSpecializationException's suppliedNodes argument to be null. --- .../UnsupportedSpecializationException.java | 41 +++++++++++++++---- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java index d73ede789f0a..cd512fd3ee9a 100644 --- a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java +++ b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/UnsupportedSpecializationException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -40,11 +40,13 @@ */ package com.oracle.truffle.api.dsl; -import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.nodes.Node; import java.util.Arrays; import java.util.Objects; +import com.oracle.truffle.api.CompilerAsserts; +import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; +import com.oracle.truffle.api.nodes.Node; + /** * Thrown by the generated code of Truffle-DSL if no compatible Specialization could be found for * the provided values. @@ -60,11 +62,25 @@ public final class UnsupportedSpecializationException extends RuntimeException { private final Node[] suppliedNodes; private final Object[] suppliedValues; - /** @since 0.8 or earlier */ + /** + * Constructs a new {@link UnsupportedSpecializationException}. + * + * @param node The node that does not support the provided values in any of its specializations. + * May be null. + * @param suppliedNodes The evaluated nodes that supplied the values. The array must much the + * length of {@code suppliedValues}, and may contain null elements for values not not + * provided by a child node but through an execute method parameter. If the array + * would consist of only nulls, as in the case of {@link GenerateUncached uncached} + * and {@link GenerateInline inlined} nodes, {@code null} may be provided instead and + * will be treated as an array of nulls of the expected length. + * @param suppliedValues The values for which no compatible specialization could be found. The + * array reference must not be {@code null}. + * @since 0.8 or earlier + */ @TruffleBoundary public UnsupportedSpecializationException(Node node, Node[] suppliedNodes, Object... suppliedValues) { - Objects.requireNonNull(suppliedNodes, "The suppliedNodes parameter must not be null."); - if (suppliedNodes.length != suppliedValues.length) { + Objects.requireNonNull(suppliedValues, "suppliedValues"); + if (suppliedNodes != null && suppliedNodes.length != suppliedValues.length) { throw new IllegalArgumentException("The length of suppliedNodes must match the length of suppliedValues."); } this.node = node; @@ -75,10 +91,12 @@ public UnsupportedSpecializationException(Node node, Node[] suppliedNodes, Objec /** @since 0.8 or earlier */ @Override public String getMessage() { + CompilerAsserts.neverPartOfCompilation(); StringBuilder str = new StringBuilder(); - str.append("Unexpected values provided for ").append(node).append(": ").append(Arrays.toString(suppliedValues)).append(", ["); - for (int i = 0; i < suppliedValues.length; i++) { - str.append(i == 0 ? "" : ",").append(suppliedValues[i] == null ? "null" : suppliedValues[i].getClass().getSimpleName()); + Object[] values = getSuppliedValues(); + str.append("Unexpected values provided for ").append(node).append(": ").append(Arrays.toString(values)).append(", ["); + for (int i = 0; i < values.length; i++) { + str.append(i == 0 ? "" : ",").append(values[i] == null ? "null" : values[i].getClass().getSimpleName()); } return str.append("]").toString(); } @@ -100,7 +118,12 @@ public Node getNode() { * * @since 0.8 or earlier */ + @TruffleBoundary public Node[] getSuppliedNodes() { + if (suppliedNodes == null) { + // Return dummy array to maintain API contract. + return new Node[getSuppliedValues().length]; + } return suppliedNodes; } From 7de0c5fa27dc326506b3f427e7c12bbfbc963210 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 18:42:18 +0200 Subject: [PATCH 06/75] Avoid all-null Node[] allocations in execute method of uncached DSL nodes. --- .../generator/FlatNodeGenFactory.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index 6d78553bf75c..65da35371937 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -3274,22 +3274,31 @@ private CodeTree createThrowUnsupported(final CodeTreeBuilder parent, final Fram } else { builder.string("this"); } - builder.startNewArray(new ArrayCodeTypeMirror(types.Node), null); - List values = new ArrayList<>(); + boolean hasNodes = false; + List nodes = new ArrayList<>(); + List values = new ArrayList<>(); for (NodeExecutionData execution : node.getChildExecutions()) { NodeChildData child = execution.getChild(); LocalVariable var = frameState.getValue(execution); if (child != null && !frameState.getMode().isUncached()) { - builder.string(accessNodeField(execution)); + hasNodes = true; + nodes.add(CodeTreeBuilder.singleString(accessNodeField(execution))); } else { - builder.string("null"); + nodes.add(CodeTreeBuilder.singleString("null")); } if (var != null) { values.add(var.createReference()); } } - builder.end(); + + if (hasNodes) { + builder.startNewArray(new ArrayCodeTypeMirror(types.Node), null); + builder.trees(nodes.toArray(new CodeTree[0])); + builder.end(); + } else { + builder.nullLiteral(); + } builder.trees(values.toArray(new CodeTree[0])); builder.end().end(); return builder.build(); From 12cf17ee0b5e2310a7c6ec379fb3617f64e60cdd Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 20:13:08 +0200 Subject: [PATCH 07/75] Move transferToInterpreterAndInvalidate() into nullError. --- .../src/com/oracle/truffle/api/dsl/InlineSupport.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/InlineSupport.java b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/InlineSupport.java index fbc8959c3a1f..0c007dc649eb 100644 --- a/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/InlineSupport.java +++ b/truffle/src/com.oracle.truffle.api.dsl/src/com/oracle/truffle/api/dsl/InlineSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -1200,7 +1200,6 @@ private Object resolveReceiverSlow(Object node) { } if (receiver == null) { - CompilerDirectives.transferToInterpreterAndInvalidate(); throw nullError(node); } return receiver; @@ -1233,6 +1232,7 @@ private boolean validateForParentLookup(Object inlineTarget, Object parent) { } private RuntimeException nullError(Object node) { + CompilerDirectives.transferToInterpreterAndInvalidate(); if (node == null) { throw nullReceiver(node); } else { @@ -1241,6 +1241,7 @@ private RuntimeException nullError(Object node) { } private NullPointerException nullReceiver(Object node) { + CompilerAsserts.neverPartOfCompilation(); return new NullPointerException(String.format( "Invalid inline context node passed to an inlined field. A receiver of type '%s' was expected but is null. " + "Did you pass the wrong node to an execute method of an inlined cached node?", @@ -1248,6 +1249,7 @@ private NullPointerException nullReceiver(Object node) { } private RuntimeException invalidReceiver(Object inlineTarget) { + CompilerAsserts.neverPartOfCompilation(); throw new ClassCastException(String.format("Invalid inline context node passed to an inlined field. A receiver of type '%s' was expected but is '%s'. " + // "Did you pass the wrong node to an execute method of an inlined cached node?", getEnclosingSimpleName(receiverClass), getEnclosingSimpleName(((Node) inlineTarget).getClass()))); From 30531852e4f4176a365d872be2f55886f2d1a3d8 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 08:20:53 +0200 Subject: [PATCH 08/75] Remove redundant transferToInterpreterAndInvalidate(). --- .../com/oracle/truffle/api/strings/AbstractTruffleString.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/AbstractTruffleString.java b/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/AbstractTruffleString.java index 67076a6e57dd..fa1a9eb9f484 100644 --- a/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/AbstractTruffleString.java +++ b/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/AbstractTruffleString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -297,7 +297,6 @@ final Object data() { final void setData(byte[] array) { if (offset() != 0 || length() << stride() != array.length) { - CompilerDirectives.transferToInterpreterAndInvalidate(); throw CompilerDirectives.shouldNotReachHere(); } this.data = array; From 0344d62eedd50bc643f018b3c808c5dcfbf6e228 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 23:44:24 +0200 Subject: [PATCH 09/75] Use fallback specialization to avoid UnsupportedSpecializationException branch and simplify uncached execute. --- .../truffle/api/strings/TruffleString.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TruffleString.java b/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TruffleString.java index 4c79daf1387c..93f28c6f94c2 100644 --- a/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TruffleString.java +++ b/truffle/src/com.oracle.truffle.api.strings/src/com/oracle/truffle/api/strings/TruffleString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -80,6 +80,7 @@ import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Exclusive; import com.oracle.truffle.api.dsl.Cached.Shared; +import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.GenerateCached; import com.oracle.truffle.api.dsl.GenerateInline; import com.oracle.truffle.api.dsl.GenerateUncached; @@ -5145,11 +5146,7 @@ public abstract static class SubstringByteIndexNode extends AbstractPublicNode { */ public abstract TruffleString execute(AbstractTruffleString a, int fromByteIndex, int byteLength, Encoding expectedEncoding, boolean lazy); - static boolean isSame(int v0, int v1) { - return v0 == v1; - } - - @Specialization(guards = "isSame(byteLength, 0)") + @Specialization(guards = "byteLength == 0") static TruffleString substringEmpty(AbstractTruffleString a, int fromByteIndex, @SuppressWarnings("unused") int byteLength, Encoding expectedEncoding, @SuppressWarnings("unused") boolean lazy) { a.checkEncoding(expectedEncoding); @@ -5158,10 +5155,11 @@ static TruffleString substringEmpty(AbstractTruffleString a, int fromByteIndex, return expectedEncoding.getEmpty(); } - @Specialization(guards = "byteLength != 0") + @Fallback final TruffleString substringRaw(AbstractTruffleString a, int fromByteIndex, int byteLength, Encoding expectedEncoding, boolean lazy, @Cached ToIndexableNode toIndexableNode, @Cached TStringInternalNodes.SubstringNode substringNode) { + assert byteLength != 0 : byteLength; a.checkEncoding(expectedEncoding); final int fromIndex = rawIndex(fromByteIndex, expectedEncoding); final int length = rawIndex(byteLength, expectedEncoding); @@ -5214,12 +5212,12 @@ public abstract static class EqualNode extends AbstractPublicNode { public abstract boolean execute(AbstractTruffleString a, AbstractTruffleString b, Encoding expectedEncoding); @SuppressWarnings("unused") - @Specialization(guards = "identical(a, b)") + @Specialization(guards = "a == b") static boolean sameObject(AbstractTruffleString a, AbstractTruffleString b, Encoding expectedEncoding) { return true; } - @Specialization(guards = "!identical(a, b)") + @Fallback final boolean check(AbstractTruffleString a, AbstractTruffleString b, Encoding expectedEncoding, @Cached ToIndexableNode toIndexableNodeA, @Cached ToIndexableNode toIndexableNodeB, @@ -5486,12 +5484,13 @@ final int doLazyLong(AbstractTruffleString a, @SuppressWarnings("unused") int ra return (int) value; } - @Specialization(guards = {"!a.isLazyLong() || radix != 10"}) + @Fallback final int doParse(AbstractTruffleString a, int radix, @Cached ToIndexableNode toIndexableNode, @Cached TStringInternalNodes.GetPreciseCodeRangeNode getCodeRangeANode, @Cached TStringInternalNodes.ParseIntNode parseIntNode, @Cached InlinedIntValueProfile radixProfile) throws NumberFormatException { + assert !a.isLazyLong() || radix != 10; Encoding encodingA = Encoding.get(a.encoding()); final int codeRangeA = getCodeRangeANode.execute(this, a, encodingA); return parseIntNode.execute(this, a, toIndexableNode.execute(this, a, a.data()), codeRangeA, encodingA, radixProfile.profile(this, radix)); @@ -5539,12 +5538,13 @@ static long doLazyLong(AbstractTruffleString a, @SuppressWarnings("unused") int return ((LazyLong) a.data()).value; } - @Specialization(guards = {"!a.isLazyLong() || radix != 10"}) + @Fallback final long doParse(AbstractTruffleString a, int radix, @Cached ToIndexableNode toIndexableNode, @Cached TStringInternalNodes.GetPreciseCodeRangeNode getCodeRangeANode, @Cached TStringInternalNodes.ParseLongNode parseLongNode, @Cached InlinedIntValueProfile radixProfile) throws NumberFormatException { + assert !a.isLazyLong() || radix != 10; Encoding encodingA = Encoding.get(a.encoding()); final int codeRangeA = getCodeRangeANode.execute(this, a, encodingA); return parseLongNode.execute(this, a, toIndexableNode.execute(this, a, a.data()), codeRangeA, encodingA, radixProfile.profile(this, radix)); @@ -5592,10 +5592,11 @@ static double doLazyLong(AbstractTruffleString a) { return ((LazyLong) a.data()).value; } - @Specialization(guards = "!isLazyLongSafeInteger(a)") + @Fallback final double parseDouble(AbstractTruffleString a, @Cached ToIndexableNode toIndexableNode, @Cached TStringInternalNodes.ParseDoubleNode parseDoubleNode) throws NumberFormatException { + assert !isLazyLongSafeInteger(a); return parseDoubleNode.execute(this, a, toIndexableNode.execute(this, a, a.data())); } From d71de4fa3bc0b178369cd89436314bb1098c9db9 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 10:56:29 +0100 Subject: [PATCH 10/75] [GR-51213] Verify that PlatformThreads.nonDaemonThreads does not turn negative. --- .../svm/core/thread/PlatformThreads.java | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index f17f0241238c..35ee06845b13 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -417,7 +417,13 @@ public static boolean ensureCurrentAssigned() { */ public static boolean ensureCurrentAssigned(String name, ThreadGroup group, boolean asDaemon) { if (currentThread.get() == null) { - assignCurrent(fromTarget(new Target_java_lang_Thread(name, group, asDaemon)), true); + Thread thread = fromTarget(new Target_java_lang_Thread(name, group, asDaemon)); + assignCurrent(thread); + + if (!thread.isDaemon()) { + int newValue = nonDaemonThreads.incrementAndGet(); + assert newValue >= 1; + } return true; } return false; @@ -425,27 +431,19 @@ public static boolean ensureCurrentAssigned(String name, ThreadGroup group, bool /** * Assign a {@link Thread} object to the current thread, which must have already been attached - * {@link VMThreads} as an {@link IsolateThread}. + * as an {@link IsolateThread}. * * The manuallyStarted parameter is true if this thread was started directly by calling * {@link #ensureCurrentAssigned(String, ThreadGroup, boolean)}. It is false when the thread is * started via {@link #doStartThread} and {@link #threadStartRoutine}. */ - static void assignCurrent(Thread thread, boolean manuallyStarted) { + static void assignCurrent(Thread thread) { /* * First of all, ensure we are in RUNNABLE state. If !manuallyStarted, we race with the * thread that launched us to set the status and we could still be in status NEW. */ setThreadStatus(thread, ThreadStatus.RUNNABLE); - assignCurrent0(thread); - - /* If the thread was manually started, finish initializing it. */ - if (manuallyStarted) { - if (!thread.isDaemon()) { - nonDaemonThreads.incrementAndGet(); - } - } } @Uninterruptible(reason = "Ensure consistency of vthread and cached vthread id.") @@ -507,7 +505,8 @@ public static void detachThread(IsolateThread vmThread) { toTarget(thread).threadData.detach(); toTarget(thread).isolateThread = WordFactory.nullPointer(); if (!thread.isDaemon()) { - nonDaemonThreads.decrementAndGet(); + int newValue = nonDaemonThreads.decrementAndGet(); + assert newValue >= 0; } } } @@ -729,7 +728,8 @@ protected T prepareStart(Thread thread, int startDat startData.setIsolate(CurrentIsolate.getIsolate()); startData.setThreadHandle(ObjectHandles.getGlobal().create(thread)); if (!thread.isDaemon()) { - nonDaemonThreads.incrementAndGet(); + int newValue = nonDaemonThreads.incrementAndGet(); + assert newValue >= 1; } return startData; } @@ -745,7 +745,8 @@ protected void undoPrepareStartOnError(Thread thread, ThreadStartData startData) private static void undoPrepareNonDaemonStartOnError() { VMThreads.lockThreadMutexInNativeCode(); try { - nonDaemonThreads.decrementAndGet(); + int newValue = nonDaemonThreads.decrementAndGet(); + assert newValue >= 0; VMThreads.THREAD_LIST_CONDITION.broadcast(); } finally { VMThreads.THREAD_MUTEX.unlock(); @@ -788,7 +789,7 @@ protected static void threadStartRoutine(ObjectHandle threadHandle) { Thread thread = ObjectHandles.getGlobal().get(threadHandle); try { - assignCurrent(thread, false); + assignCurrent(thread); ObjectHandles.getGlobal().destroy(threadHandle); singleton().unattachedStartedThreads.decrementAndGet(); From 4595abca828327a0837c3603240ba02c8efb005f Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 18:20:47 +0100 Subject: [PATCH 11/75] [GR-51198] Call PlatformThreads.beforeThreadRun() consistently. --- .../svm/core/posix/thread/PosixPlatformThreads.java | 5 +++++ .../oracle/svm/core/c/function/CEntryPointActions.java | 9 +++++---- .../src/com/oracle/svm/core/thread/PlatformThreads.java | 2 ++ 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java index bc9f8bfb5df6..d412771909a8 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java @@ -177,6 +177,11 @@ protected void yieldCurrent() { Sched.sched_yield(); } + /** + * Note that this method is only executed for Java threads that are started via + * {@link Thread#start()}. It is not executed if an existing native thread is attached to an + * isolate. + */ @Override protected void beforeThreadRun(Thread thread) { /* Complete the initialization of the thread, now that it is (nearly) running. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointActions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointActions.java index 5c051a033d86..003ff67acf9f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointActions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointActions.java @@ -65,10 +65,11 @@ private CEntryPointActions() { * @param startedByIsolate Whether the current thread has been launched directly by the isolate * (as opposed to being an externally started thread), which makes the isolate * responsible for cleanups when the thread detaches. - * @param ensureJavaThread when set to true, the method ensures that the {@link Thread} object - * for the newly attached thread is created. If the parameter is set to false, a - * later call to one of the {@link PlatformThreads#ensureCurrentAssigned} methods - * early after the prologue must be used to do the initialization manually. + * @param ensureJavaThread when set to true, {@link PlatformThreads#ensureCurrentAssigned()} is + * called to ensure that the Java {@link Thread} is fully initialized. If the + * parameter is set to false, the initialization must be done manually (early after + * the prologue). + * * @return 0 on success, otherwise non-zero (see {@link CEntryPointErrors}) */ public static native int enterAttachThread(Isolate isolate, boolean startedByIsolate, boolean ensureJavaThread); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 35ee06845b13..f89bcd3dcedc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -424,6 +424,8 @@ public static boolean ensureCurrentAssigned(String name, ThreadGroup group, bool int newValue = nonDaemonThreads.incrementAndGet(); assert newValue >= 1; } + + ThreadListenerSupport.get().beforeThreadRun(); return true; } return false; From 4ce7f0263f97ad23bc6e733cd68c0020e077ea95 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 11:58:35 +0100 Subject: [PATCH 12/75] [GR-51161] Handle exceptions in CEntryPointSnippets.ensureJavaThread(). --- .../graal/snippets/CEntryPointSnippets.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 8dfd1fe22fd9..119eca7ff375 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -421,8 +421,9 @@ public static int attachThreadSnippet(Isolate isolate, boolean startedByIsolate, if (MultiThreaded.getValue()) { Safepoint.transitionNativeToJava(false); } + if (ensureJavaThread) { - runtimeCallEnsureJavaThread(ENSURE_JAVA_THREAD); + return runtimeCallEnsureJavaThread(ENSURE_JAVA_THREAD); } return CEntryPointErrors.NO_ERROR; } @@ -530,11 +531,22 @@ public static void initializeIsolateThreadForCrashHandler(Isolate isolate, Isola } @NodeIntrinsic(value = ForeignCallNode.class) - public static native void runtimeCallEnsureJavaThread(@ConstantNodeParameter ForeignCallDescriptor descriptor); + public static native int runtimeCallEnsureJavaThread(@ConstantNodeParameter ForeignCallDescriptor descriptor); + @Uninterruptible(reason = "Prevent stack overflow errors; thread is no longer attached in error case.", calleeMustBe = false) @SubstrateForeignCallTarget(stubCallingConvention = false) - private static void ensureJavaThread() { - PlatformThreads.ensureCurrentAssigned(); + private static int ensureJavaThread() { + try { + PlatformThreads.ensureCurrentAssigned(); + return CEntryPointErrors.NO_ERROR; + } catch (Throwable e) { + int result = CEntryPointErrors.UNCAUGHT_EXCEPTION; + if (e instanceof OutOfMemoryError) { + result = CEntryPointErrors.ALLOCATION_FAILED; + } + CEntryPointActions.leaveDetachThread(); + return result; + } } @Snippet(allowMissingProbabilities = true) From 671eddff940878c207baa6af6fd64eed0e75c3e8 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 12:21:17 +0100 Subject: [PATCH 13/75] [GR-51160] Update JavaMonitor and JavaMonitorQueuedSynchronizer. --- .../oracle/svm/core/monitor/JavaMonitor.java | 4 +- .../JavaMonitorQueuedSynchronizer.java | 157 +++++++++++++----- 2 files changed, 113 insertions(+), 48 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java index dccd9aa4f8ae..9dede49f6015 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java @@ -46,7 +46,7 @@ /** * {@link JavaMonitor} is based on the code of {@link java.util.concurrent.locks.ReentrantLock} as - * of JDK 19 (git commit hash: f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-19+30). + * of JDK 21 (git commit hash: f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-21+26). * * Only the relevant methods from the JDK sources have been kept. Some additional Native * Image-specific functionality has been added. @@ -91,7 +91,7 @@ protected JavaMonitorConditionObject getOrCreateCondition(boolean createIfNotExi return existingCondition; } JavaMonitorConditionObject newCondition = new JavaMonitorConditionObject(); - if (!U.compareAndSetObject(this, CONDITION_FIELD_OFFSET, null, newCondition)) { + if (!U.compareAndSetReference(this, CONDITION_FIELD_OFFSET, null, newCondition)) { newCondition = condition; } return newCondition; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java index e21372597fe8..83d163541e87 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java @@ -27,20 +27,23 @@ package com.oracle.svm.core.monitor; import java.util.concurrent.TimeUnit; +import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.LockSupport; +import com.oracle.svm.core.NeverInline; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.jfr.JfrTicks; import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.jfr.events.JavaMonitorWaitEvent; import com.oracle.svm.core.thread.JavaThreads; +import com.oracle.svm.core.util.BasedOnJDKClass; import jdk.internal.misc.Unsafe; /** * {@link JavaMonitorQueuedSynchronizer} is based on the code of - * {@link java.util.concurrent.locks.AbstractQueuedLongSynchronizer} as of JDK 19 (git commit hash: - * f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-19+30). This class could be merged with + * {@link java.util.concurrent.locks.AbstractQueuedLongSynchronizer} as of JDK 21 (git commit hash: + * f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-21+26). This class could be merged with * {@link JavaMonitor} but we keep it separate because that way diffing against the JDK sources is * easier. * @@ -57,6 +60,7 @@ * {@link java.util.concurrent.ForkJoinPool#managedBlock}). * */ +@BasedOnJDKClass(AbstractQueuedLongSynchronizer.class) abstract class JavaMonitorQueuedSynchronizer { // Node.status field values static final int WAITING = 1; // must be 1 @@ -67,6 +71,7 @@ abstract class JavaMonitorQueuedSynchronizer { protected static final int SPIN_SUCCESS = -1; // see AbstractQueuedLongSynchronizer.Node + @BasedOnJDKClass(value = AbstractQueuedLongSynchronizer.class, innerClass = "Node") abstract static class Node { volatile Node prev; volatile Node next; @@ -75,12 +80,12 @@ abstract static class Node { // see AbstractQueuedLongSynchronizer.Node.casPrev(Node, Node) final boolean casPrev(Node c, Node v) { - return weakCompareAndSetReference(this, PREV, c, v); + return U.weakCompareAndSetReference(this, PREV, c, v); } // see AbstractQueuedLongSynchronizer.Node.casNext(Node, Node) final boolean casNext(Node c, Node v) { - return weakCompareAndSetReference(this, NEXT, c, v); + return U.weakCompareAndSetReference(this, NEXT, c, v); } // see AbstractQueuedLongSynchronizer.Node.getAndUnsetStatus(int) @@ -90,7 +95,7 @@ final int getAndUnsetStatus(int v) { // see AbstractQueuedLongSynchronizer.Node.setPrevRelaxed(Node) final void setPrevRelaxed(Node p) { - putReference(this, PREV, p); + U.putReference(this, PREV, p); } // see AbstractQueuedLongSynchronizer.Node.setStatusRelaxed(int) @@ -109,10 +114,12 @@ final void clearStatus() { } // see AbstractQueuedLongSynchronizer.ExclusiveNode + @BasedOnJDKClass(value = AbstractQueuedLongSynchronizer.class, innerClass = "ExclusiveNode") static final class ExclusiveNode extends Node { } // see AbstractQueuedLongSynchronizer.ConditionNode + @BasedOnJDKClass(value = AbstractQueuedLongSynchronizer.class, innerClass = "ConditionNode") static final class ConditionNode extends Node { ConditionNode nextWaiter; long notifierJfrTid; @@ -169,33 +176,52 @@ protected final boolean compareAndSetState(long expect, long update) { // see AbstractQueuedLongSynchronizer.casTail(Node, Node) private boolean casTail(Node c, Node v) { - return compareAndSetReference(this, TAIL, c, v); + return U.compareAndSetReference(this, TAIL, c, v); } // see AbstractQueuedLongSynchronizer.tryInitializeHead() - private void tryInitializeHead() { - Node h = new ExclusiveNode(); - if (compareAndSetReference(this, HEAD, null, h)) { - tail = h; + private Node tryInitializeHead() { + for (Node h = null, t;;) { + if ((t = tail) != null) { + return t; + } else if (head != null) { + Thread.onSpinWait(); + } else { + if (h == null) { + try { + h = allocateExclusiveNode(); + } catch (OutOfMemoryError oome) { + return null; + } + } + if (U.compareAndSetReference(this, HEAD, null, h)) { + return tail = h; + } + } } } // see AbstractQueuedLongSynchronizer.enqueue(Node) - final void enqueue(Node node) { + final void enqueue(ConditionNode node) { if (node != null) { - for (;;) { - Node t = tail; - node.setPrevRelaxed(t); // avoid unnecessary fence - if (t == null) { // initialize - tryInitializeHead(); - } else if (casTail(t, node)) { + boolean unpark = false; + for (Node t;;) { + if ((t = tail) == null && (t = tryInitializeHead()) == null) { + unpark = true; // wake up to spin on OOME + break; + } + node.setPrevRelaxed(t); // avoid unnecessary fence + if (casTail(t, node)) { t.next = node; - if (t.status < 0) { // wake up to clean link - LockSupport.unpark(node.waiter); + if (t.status < 0) { // wake up to clean link + unpark = true; } break; } } + if (unpark) { + LockSupport.unpark(node.waiter); + } } } @@ -298,15 +324,21 @@ final int acquire(Node node, long arg) { return 1; } } - if (node == null) { // allocate; retry before enqueue - node = new ExclusiveNode(); + Node t; + if ((t = tail) == null) { // initialize queue + if (tryInitializeHead() == null) { + return acquireOnOOME(arg); + } + } else if (node == null) { // allocate; retry before enqueue + try { + node = allocateExclusiveNode(); + } catch (OutOfMemoryError oome) { + return acquireOnOOME(arg); + } } else if (pred == null) { // try to enqueue node.waiter = current; - Node t = tail; node.setPrevRelaxed(t); // avoid unnecessary fence - if (t == null) { - tryInitializeHead(); - } else if (!casTail(t, node)) { + if (!casTail(t, node)) { node.setPrevRelaxed(null); // back out } else { t.next = node; @@ -324,6 +356,19 @@ final int acquire(Node node, long arg) { } } + // see AbstractQueuedLongSynchronizer.acquireOnOOME(boolean, long) + private int acquireOnOOME(long arg) { + for (long nanos = 1L;;) { + if (tryAcquire(arg)) { + return 1; + } + U.park(false, nanos); // must use Unsafe park to sleep + if (nanos < 1L << 30) { // max about 1 second + nanos <<= 1; + } + } + } + // see AbstractQueuedLongSynchronizer.cleanQueue() private void cleanQueue() { for (;;) { // restart point @@ -358,6 +403,11 @@ private void cleanQueue() { } } + @NeverInline("Can be removed once GR-51172 is resolved") + private static ExclusiveNode allocateExclusiveNode() { + return new ExclusiveNode(); + } + // see AbstractQueuedLongSynchronizer.cancelAcquire(Node, boolean, boolean) private int cancelAcquire(Node node) { if (node != null) { @@ -396,10 +446,13 @@ protected final boolean release(long arg) { } // see AbstractQueuedLongSynchronizer.ConditionObject + @BasedOnJDKClass(value = AbstractQueuedLongSynchronizer.class, innerClass = "ConditionObject") public final class JavaMonitorConditionObject { private transient ConditionNode firstWaiter; private transient ConditionNode lastWaiter; + static final long OOME_COND_WAIT_DELAY = 10L * 1000L * 1000L; // 10 ms + // see AbstractQueuedLongSynchronizer.ConditionObject.doSignal(ConditionNode, boolean) @SuppressWarnings("all") private void doSignal(ConditionNode first, boolean all) { @@ -424,8 +477,7 @@ public void signal() { ConditionNode first = firstWaiter; if (!isHeldExclusively()) { throw new IllegalMonitorStateException(); - } - if (first != null) { + } else if (first != null) { doSignal(first, false); } } @@ -435,8 +487,7 @@ public void signalAll() { ConditionNode first = firstWaiter; if (!isHeldExclusively()) { throw new IllegalMonitorStateException(); - } - if (first != null) { + } else if (first != null) { doSignal(first, true); } } @@ -495,6 +546,29 @@ private void unlinkCancelledWaiters(ConditionNode node) { } } + // see AbstractQueuedLongSynchronizer.ConditionObject.newConditionNode() + private ConditionNode newConditionNode() { + long savedState; + if (tryInitializeHead() != null) { + try { + return allocateConditionNode(); + } catch (OutOfMemoryError oome) { + } + } + // fall through if encountered OutOfMemoryError + if (!isHeldExclusively() || !release(savedState = getState())) { + throw new IllegalMonitorStateException(); + } + U.park(false, OOME_COND_WAIT_DELAY); + acquireOnOOME(savedState); + return null; + } + + @NeverInline("Can be removed once GR-51172 is resolved") + private static ConditionNode allocateConditionNode() { + return new ConditionNode(); + } + // see AbstractQueuedLongSynchronizer.ConditionObject.await() @SuppressWarnings("all") public void await(Object obj) throws InterruptedException { @@ -503,7 +577,10 @@ public void await(Object obj) throws InterruptedException { JavaMonitorWaitEvent.emit(startTicks, obj, 0, 0L, false); throw new InterruptedException(); } - ConditionNode node = new ConditionNode(); + ConditionNode node = newConditionNode(); + if (node == null) { + return; + } long savedAcquisitions = enableWait(node); boolean interrupted = false; boolean cancelled = false; @@ -540,7 +617,10 @@ public boolean await(Object obj, long time, TimeUnit unit) throws InterruptedExc JavaMonitorWaitEvent.emit(startTicks, obj, 0, 0L, false); throw new InterruptedException(); } - ConditionNode node = new ConditionNode(); + ConditionNode node = newConditionNode(); + if (node == null) { + return false; + } long savedAcquisitions = enableWait(node); long nanos = (nanosTimeout < 0L) ? 0L : nanosTimeout; long deadline = System.nanoTime() + nanos; @@ -571,21 +651,6 @@ public boolean await(Object obj, long time, TimeUnit unit) throws InterruptedExc } } - @SuppressWarnings("deprecation") - static boolean compareAndSetReference(Object object, long offset, Node expected, Node newValue) { - return U.compareAndSetObject(object, offset, expected, newValue); - } - - @SuppressWarnings("deprecation") - static boolean weakCompareAndSetReference(Object object, long offset, Node expected, Node newValue) { - return U.weakCompareAndSetObject(object, offset, expected, newValue); - } - - @SuppressWarnings("deprecation") - static void putReference(Object object, long offset, Node p) { - U.putObject(object, offset, p); - } - // Unsafe private static final Unsafe U = Unsafe.getUnsafe(); static final long STATE = U.objectFieldOffset(JavaMonitorQueuedSynchronizer.class, "state"); From 165a55c5f55db2f2796e5bb291df219be7d9828f Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 12:21:50 +0100 Subject: [PATCH 14/75] Minor fix for UncaughtExceptionHandler. --- .../oracle/svm/core/thread/JavaThreads.java | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index 03963b6fc951..a3a5158ce61e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -42,6 +42,7 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.jdk.StackTraceUtils; +import com.oracle.svm.core.log.Log; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.stack.StackFrameVisitor; import com.oracle.svm.core.threadlocal.FastThreadLocal; @@ -276,26 +277,27 @@ private static void visitCurrentVirtualThreadStackFrames(Pointer callerSP, Stack } } - /** If there is an uncaught exception handler, call it. */ public static void dispatchUncaughtException(Thread thread, Throwable throwable) { - /* Get the uncaught exception handler for the Thread, or the default one. */ - UncaughtExceptionHandler handler = thread.getUncaughtExceptionHandler(); - if (handler == null) { - handler = Thread.getDefaultUncaughtExceptionHandler(); - } - if (handler != null) { - try { + try { + /* Get the uncaught exception handler for the Thread, or the default one. */ + UncaughtExceptionHandler handler = thread.getUncaughtExceptionHandler(); + if (handler == null) { + handler = Thread.getDefaultUncaughtExceptionHandler(); + } + + if (handler != null) { handler.uncaughtException(thread, throwable); - } catch (Throwable t) { + } else { /* - * The JavaDoc for {@code Thread.UncaughtExceptionHandler.uncaughtException} says - * the VM ignores any exceptions thrown. + * If no uncaught exception handler is present, then just report the Throwable in + * the same way as it is done by ThreadGroup.uncaughtException(). */ + System.err.print("Exception in thread \"" + thread.getName() + "\" "); + throwable.printStackTrace(System.err); } - } else { - /* If no uncaught exception handler is present, then just report the throwable. */ - System.err.print("Exception in thread \"" + Thread.currentThread().getName() + "\" "); - throwable.printStackTrace(); + } catch (Throwable e) { + /* See JavaThread::exit() in HotSpot. */ + Log.log().newline().string("Exception: ").string(e.getClass().getName()).string(" thrown from the UncaughtExceptionHandler in thread \"").string(thread.getName()).string("\"").newline(); } } From 54c24aef987ef1785be7e1640f8771b41657a09d Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 12:23:20 +0100 Subject: [PATCH 15/75] [GR-51198] Fix execution order of ThreadListenerSupport.afterThreadRun(). --- .../oracle/svm/core/thread/ThreadListenerSupport.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java index 0f29e38303b5..58c4dedc5d18 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java @@ -26,7 +26,6 @@ import java.util.Arrays; -import jdk.graal.compiler.api.replacements.Fold; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -60,19 +59,19 @@ public static ThreadListenerSupport get() { @Uninterruptible(reason = "Force that all listeners are uninterruptible.") public void beforeThreadStart(IsolateThread isolateThread, Thread javaThread) { - for (int i = 0; i < listeners.length; i++) { - listeners[i].beforeThreadStart(isolateThread, javaThread); + for (ThreadListener listener : listeners) { + listener.beforeThreadStart(isolateThread, javaThread); } } public void beforeThreadRun() { - for (int i = 0; i < listeners.length; i++) { - listeners[i].beforeThreadRun(); + for (ThreadListener listener : listeners) { + listener.beforeThreadRun(); } } public void afterThreadRun() { - for (int i = 0; i < listeners.length; i++) { + for (int i = listeners.length - 1; i >= 0; i--) { listeners[i].afterThreadRun(); } } From 848a3628b8e766b0e1604318e8e692cb59affe39 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 12:26:42 +0100 Subject: [PATCH 16/75] [GR-51198] ThreadListener.afterThreadRun() and afterThreadExit() must not throw any exceptions. --- .../oracle/svm/core/thread/ThreadListener.java | 3 +++ .../svm/core/thread/ThreadListenerSupport.java | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java index 7db21aad40e8..485f697a18e2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java @@ -37,9 +37,12 @@ default void beforeThreadStart(IsolateThread isolateThread, Thread javaThread) { default void beforeThreadRun() { } + /** Implementations must not throw any exceptions. */ + @Uninterruptible(reason = "Only uninterruptible because we need to prevent stack overflow errors. Implementations may execute interruptible code.") default void afterThreadRun() { } + /** Implementations must not throw any exceptions. */ @Uninterruptible(reason = "Only uninterruptible code may be executed after Thread.exit.") @SuppressWarnings("unused") default void afterThreadExit(IsolateThread isolateThread, Thread javaThread) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java index 58c4dedc5d18..c4e0796aac5d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListenerSupport.java @@ -33,6 +33,9 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.util.VMError; + +import jdk.graal.compiler.api.replacements.Fold; @AutomaticallyRegisteredImageSingleton public class ThreadListenerSupport { @@ -70,16 +73,25 @@ public void beforeThreadRun() { } } + @Uninterruptible(reason = "Force that all listeners are uninterruptible.") public void afterThreadRun() { for (int i = listeners.length - 1; i >= 0; i--) { - listeners[i].afterThreadRun(); + try { + listeners[i].afterThreadRun(); + } catch (Throwable e) { + throw VMError.shouldNotReachHere(e); + } } } @Uninterruptible(reason = "Force that all listeners are uninterruptible.") public void afterThreadExit(IsolateThread isolateThread, Thread javaThread) { for (int i = listeners.length - 1; i >= 0; i--) { - listeners[i].afterThreadExit(isolateThread, javaThread); + try { + listeners[i].afterThreadExit(isolateThread, javaThread); + } catch (Throwable e) { + throw VMError.shouldNotReachHere(e); + } } } } From 6147443e248aa5f8458482e439db00dca6f33306 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 12:28:27 +0100 Subject: [PATCH 17/75] Minor cleanups. --- .../oracle/svm/core/genscavenge/HeapChunkProvider.java | 10 +++++----- .../svm/core/graal/snippets/CEntryPointSnippets.java | 6 ------ .../sampler/JfrRecurringCallbackExecutionSampler.java | 3 ++- .../svm/core/monitor/MultiThreadedMonitorSupport.java | 6 +++--- .../svm/core/sampler/SubstrateSigprofHandler.java | 1 + 5 files changed, 11 insertions(+), 15 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java index 71d45a158683..6569f15a6f06 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java @@ -68,7 +68,7 @@ final class HeapChunkProvider { * head}, but this is OK because we only need the number of chunks for policy code (to avoid * running down the list and counting the number of chunks). */ - private final AtomicUnsigned bytesInUnusedAlignedChunks = new AtomicUnsigned(); + private final AtomicUnsigned numUnusedAlignedChunks = new AtomicUnsigned(); @Platforms(Platform.HOSTED_ONLY.class) HeapChunkProvider() { @@ -76,7 +76,7 @@ final class HeapChunkProvider { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public UnsignedWord getBytesInUnusedChunks() { - return bytesInUnusedAlignedChunks.get(); + return numUnusedAlignedChunks.get().multiply(HeapParameters.getAlignedHeapChunkAlignment()); } private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk"); @@ -181,7 +181,7 @@ private void pushUnusedAlignedChunk(AlignedHeader chunk) { HeapChunk.setNext(chunk, unusedAlignedChunks.get()); unusedAlignedChunks.set(chunk); - bytesInUnusedAlignedChunks.addAndGet(HeapParameters.getAlignedHeapChunkSize()); + numUnusedAlignedChunks.addAndGet(WordFactory.unsigned(1)); } /** @@ -199,7 +199,7 @@ private AlignedHeader popUnusedAlignedChunk() { if (result.isNull()) { return WordFactory.nullPointer(); } else { - bytesInUnusedAlignedChunks.subtractAndGet(HeapParameters.getAlignedHeapChunkSize()); + numUnusedAlignedChunks.subtractAndGet(WordFactory.unsigned(1)); return result; } } @@ -235,7 +235,7 @@ private void freeUnusedAlignedChunksAtSafepoint(UnsignedWord count) { released = released.add(1); } unusedAlignedChunks.set(chunk); - bytesInUnusedAlignedChunks.subtractAndGet(released.multiply(HeapParameters.getAlignedHeapChunkSize())); + numUnusedAlignedChunks.subtractAndGet(released); } /** Acquire an UnalignedHeapChunk from the operating system. */ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 119eca7ff375..42810cd3781d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -556,12 +556,6 @@ public static int detachThreadSnippet() { IsolateThread thread = CurrentIsolate.getCurrentThread(); result = runtimeCall(DETACH_THREAD_MT, thread); } - - /* - * Note that we do not reset the fixed registers used for the thread and isolate to null: - * Since these values are not copied to different registers when they are used, we need to - * keep the registers intact until the last possible point where we are in Java code. - */ return result; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java index 33a5372d1fa1..edf7d1ce6f99 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java @@ -30,7 +30,6 @@ import java.util.Collections; import java.util.List; -import com.oracle.svm.core.jfr.JfrExecutionSamplerSupported; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -45,6 +44,7 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.jfr.JfrExecutionSamplerSupported; import com.oracle.svm.core.jfr.JfrFeature; import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.thread.ThreadListenerSupport; @@ -106,6 +106,7 @@ private static void install(IsolateThread thread, RecurringCallbackTimer callbac } } + @Override @Uninterruptible(reason = "Prevent VM operations that modify the recurring callbacks.") protected void uninstall(IsolateThread thread) { assert thread == CurrentIsolate.getCurrentThread() || VMOperation.isInProgressAtSafepoint(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java index c9ce4e04b414..e1b7f760201d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java @@ -33,8 +33,6 @@ import java.util.concurrent.locks.LockSupport; import java.util.concurrent.locks.ReentrantLock; -import jdk.graal.compiler.core.common.SuppressFBWarnings; -import jdk.graal.compiler.word.BarrieredAccess; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -56,6 +54,8 @@ import com.oracle.svm.core.thread.VMOperationControl; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.core.common.SuppressFBWarnings; +import jdk.graal.compiler.word.BarrieredAccess; import jdk.internal.misc.Unsafe; /** @@ -244,7 +244,7 @@ public void monitorEnter(Object obj, MonitorInflationCause cause) { long startTicks = JfrTicks.elapsedTicks(); JavaMonitor newMonitor = newMonitorLock(); newMonitor.setState(current); - monitor = (JavaMonitor) UNSAFE.compareAndExchangeObject(obj, monitorOffset, null, newMonitor); + monitor = (JavaMonitor) UNSAFE.compareAndExchangeReference(obj, monitorOffset, null, newMonitor); if (monitor == null) { // successful JavaMonitorInflateEvent.emit(obj, startTicks, MonitorInflationCause.MONITOR_ENTER); newMonitor.latestJfrTid = current; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SubstrateSigprofHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SubstrateSigprofHandler.java index 40baa1317a3b..cafa238be881 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SubstrateSigprofHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/sampler/SubstrateSigprofHandler.java @@ -163,6 +163,7 @@ private static void install(IsolateThread thread) { } } + @Override @Uninterruptible(reason = "Prevent VM operations that modify thread-local execution sampler state.") protected void uninstall(IsolateThread thread) { assert thread == CurrentIsolate.getCurrentThread() || VMOperation.isInProgressAtSafepoint(); From f3e2f3be2d6706466d47441df33267d789807a0d Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 14:24:30 +0100 Subject: [PATCH 18/75] Ignore exceptions that are triggered in Thread.exit(). --- .../com/oracle/svm/core/thread/PlatformThreads.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index f89bcd3dcedc..79fecf664947 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -667,7 +667,6 @@ private static boolean waitForTearDown() { loopNanos = TimeUtils.doNotLoopTooLong(startNanos, loopNanos, warningNanos, warningMessage); final boolean fatallyTooLong = TimeUtils.maybeFatallyTooLong(startNanos, failureNanos, failureMessage); if (fatallyTooLong) { - /* I took too long to tear down the VM. */ trace.string("Took too long to tear down the VM.").newline(); /* * Debugging tip: Insert a `BreakpointNode.breakpoint()` here to stop in gdb or get @@ -690,12 +689,18 @@ private static boolean isApplicationThread(IsolateThread isolateThread) { @SuppressFBWarnings(value = "NN", justification = "notifyAll is necessary for Java semantics, no shared state needs to be modified beforehand") public static void exit(Thread thread) { ThreadListenerSupport.get().afterThreadRun(); + /* * First call Thread.exit(). This allows waiters on the thread object to observe that a * daemon ThreadGroup is destroyed as well if this thread happens to be the last thread of a * daemon group. */ - toTarget(thread).exit(); + try { + toTarget(thread).exit(); + } catch (Throwable e) { + /* Ignore exception. */ + } + /* * Then set the threadStatus to TERMINATED. This makes Thread.isAlive() return false and * allows Thread.join() to complete once we notify all the waiters below. @@ -1053,6 +1058,7 @@ public static int getThreadStatus(Thread thread) { public static void setThreadStatus(Thread thread, int threadStatus) { assert !isVirtual(thread); + assert toTarget(thread).holder.threadStatus != ThreadStatus.TERMINATED : "once a thread is marked terminated, its status must not change"; toTarget(thread).holder.threadStatus = threadStatus; } From 8a6fd27b2403c8f25806c497a49ebd326d9c34df Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Mon, 8 Jan 2024 14:25:29 +0100 Subject: [PATCH 19/75] [GR-51204] Fix Thread.isAlive() so that its return value is consistent. --- .../oracle/svm/core/thread/PlatformThreads.java | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 79fecf664947..89ffb18de585 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -701,15 +701,13 @@ public static void exit(Thread thread) { /* Ignore exception. */ } - /* - * Then set the threadStatus to TERMINATED. This makes Thread.isAlive() return false and - * allows Thread.join() to complete once we notify all the waiters below. - */ - setThreadStatus(thread, ThreadStatus.TERMINATED); - /* - * And finally, wake up any threads waiting to join this one. - */ synchronized (thread) { + /* + * Then set the threadStatus to TERMINATED. This makes Thread.isAlive() return false and + * allows Thread.join() to complete once we notify all the waiters below. + */ + setThreadStatus(thread, ThreadStatus.TERMINATED); + /* And finally, wake up any threads waiting to join this one. */ thread.notifyAll(); } } From 43f91eb5d3ebbd688cf44e862d179d87f2943484 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 9 Jan 2024 18:08:23 +0100 Subject: [PATCH 20/75] [GR-51213] Ensure that PlatformThreads.unattachedStartedThreads and PlatformThreads.nonDaemonThreads have consistent values. --- .../posix/thread/PosixPlatformThreads.java | 30 ++++++-- .../core/windows/WindowsPlatformThreads.java | 30 ++++++-- .../graal/snippets/CEntryPointSnippets.java | 3 +- .../svm/core/thread/PlatformThreads.java | 68 ++++++++++++------- .../com/oracle/svm/core/thread/VMThreads.java | 6 ++ 5 files changed, 96 insertions(+), 41 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java index d412771909a8..bbab7d016f74 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java @@ -108,18 +108,34 @@ protected boolean doStartThread(Thread thread, long stackSize) { } } - ThreadStartData startData = prepareStart(thread, SizeOf.get(ThreadStartData.class)); + /* + * Prevent stack overflow errors so that starting the thread and reverting back to a + * safe state (in case of an error) works reliably. + */ + StackOverflowCheck.singleton().makeYellowZoneAvailable(); + try { + return doStartThread0(thread, attributes); + } finally { + StackOverflowCheck.singleton().protectYellowZone(); + } + } finally { + Pthread.pthread_attr_destroy(attributes); + } + } + /** Starts a thread to the point so that it is executing. */ + private boolean doStartThread0(Thread thread, pthread_attr_t attributes) { + ThreadStartData startData = prepareStart(thread, SizeOf.get(ThreadStartData.class)); + try { Pthread.pthread_tPointer newThread = UnsafeStackValue.get(Pthread.pthread_tPointer.class); if (Pthread.pthread_create(newThread, attributes, threadStartRoutine.getFunctionPointer(), startData) != 0) { undoPrepareStartOnError(thread, startData); return false; } - - setPthreadIdentifier(thread, newThread.read()); return true; - } finally { - Pthread.pthread_attr_destroy(attributes); + } catch (Throwable e) { + undoPrepareStartOnError(thread, startData); + throw e; } } @@ -145,8 +161,8 @@ static boolean hasThreadIdentifier(Thread thread) { protected void setNativeName(Thread thread, String name) { if (!hasThreadIdentifier(thread)) { /* - * The thread was not started from Java code, but started from C code and attached - * manually to SVM. We do not want to interfere with such threads. + * The thread was a. not started yet, b. not started from Java code (i.e., only attached + * to SVM). We do not want to interfere with such threads. */ return; } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java index c2cb0e7848d9..28787e57a522 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java @@ -61,21 +61,39 @@ public final class WindowsPlatformThreads extends PlatformThreads { @Override protected boolean doStartThread(Thread thread, long stackSize) { int threadStackSize = NumUtil.safeToUInt(stackSize); - int initFlag = 0; // If caller specified a stack size, don't commit it all at once. if (threadStackSize != 0) { initFlag |= Process.STACK_SIZE_PARAM_IS_A_RESERVATION(); } + /* + * Prevent stack overflow errors so that starting the thread and reverting back to a safe + * state (in case of an error) works reliably. + */ + StackOverflowCheck.singleton().makeYellowZoneAvailable(); + try { + return doStartThread0(thread, threadStackSize, initFlag); + } finally { + StackOverflowCheck.singleton().protectYellowZone(); + } + } + + /** Starts a thread to the point so that it is executing. */ + private boolean doStartThread0(Thread thread, int threadStackSize, int initFlag) { ThreadStartData startData = prepareStart(thread, SizeOf.get(ThreadStartData.class)); - WinBase.HANDLE osThreadHandle = Process._beginthreadex(WordFactory.nullPointer(), threadStackSize, threadStartRoutine.getFunctionPointer(), startData, initFlag, WordFactory.nullPointer()); - if (osThreadHandle.isNull()) { + try { + WinBase.HANDLE osThreadHandle = Process._beginthreadex(WordFactory.nullPointer(), threadStackSize, threadStartRoutine.getFunctionPointer(), startData, initFlag, WordFactory.nullPointer()); + if (osThreadHandle.isNull()) { + undoPrepareStartOnError(thread, startData); + return false; + } + WinBase.CloseHandle(osThreadHandle); + return true; + } catch (Throwable e) { undoPrepareStartOnError(thread, startData); - return false; + throw e; } - WinBase.CloseHandle(osThreadHandle); - return true; } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 42810cd3781d..76f214f123ba 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -155,8 +155,7 @@ public final class CEntryPointSnippets extends SubstrateTemplates implements Sni public static native int runtimeCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, CEntryPointCreateIsolateParameters parameters); @NodeIntrinsic(value = ForeignCallNode.class) - public static native int runtimeCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Isolate isolate, - boolean startedByIsolate, boolean ensuringJavaThread); + public static native int runtimeCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Isolate isolate, boolean startedByIsolate, boolean ensuringJavaThread); @NodeIntrinsic(value = ForeignCallNode.class) public static native int runtimeCall(@ConstantNodeParameter ForeignCallDescriptor descriptor, Isolate isolate); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 89ffb18de585..4ef47851a200 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -136,11 +136,8 @@ public static PlatformThreads singleton() { /** The platform {@link java.lang.Thread} for the {@link IsolateThread}. */ static final FastThreadLocalObject currentThread = FastThreadLocalFactory.createObject(Thread.class, "PlatformThreads.currentThread").setMaxOffset(FastThreadLocal.BYTE_OFFSET); - /** - * The number of running non-daemon threads. The initial value accounts for the main thread, - * which is implicitly running when the isolate is created. - */ - private static final UninterruptibleUtils.AtomicInteger nonDaemonThreads = new UninterruptibleUtils.AtomicInteger(1); + /** The number of running non-daemon threads. */ + private static final UninterruptibleUtils.AtomicInteger nonDaemonThreads = new UninterruptibleUtils.AtomicInteger(0); /** * Tracks the number of threads that have been started, but are not yet executing Java code. For @@ -419,12 +416,6 @@ public static boolean ensureCurrentAssigned(String name, ThreadGroup group, bool if (currentThread.get() == null) { Thread thread = fromTarget(new Target_java_lang_Thread(name, group, asDaemon)); assignCurrent(thread); - - if (!thread.isDaemon()) { - int newValue = nonDaemonThreads.incrementAndGet(); - assert newValue >= 1; - } - ThreadListenerSupport.get().beforeThreadRun(); return true; } @@ -434,12 +425,14 @@ public static boolean ensureCurrentAssigned(String name, ThreadGroup group, bool /** * Assign a {@link Thread} object to the current thread, which must have already been attached * as an {@link IsolateThread}. - * - * The manuallyStarted parameter is true if this thread was started directly by calling - * {@link #ensureCurrentAssigned(String, ThreadGroup, boolean)}. It is false when the thread is - * started via {@link #doStartThread} and {@link #threadStartRoutine}. */ + @Uninterruptible(reason = "Ensure consistency of nonDaemonThreads.") static void assignCurrent(Thread thread) { + if (!VMThreads.wasStartedByCurrentIsolate(CurrentIsolate.getCurrentThread()) && thread.isDaemon()) { + /* Correct the value of nonDaemonThreads, now that we have a Thread object. */ + decrementNonDaemonThreadsAndNotify(); + } + /* * First of all, ensure we are in RUNNABLE state. If !manuallyStarted, we race with the * thread that launched us to set the status and we could still be in status NEW. @@ -506,10 +499,16 @@ public static void detachThread(IsolateThread vmThread) { if (thread != null) { toTarget(thread).threadData.detach(); toTarget(thread).isolateThread = WordFactory.nullPointer(); + if (!thread.isDaemon()) { - int newValue = nonDaemonThreads.decrementAndGet(); - assert newValue >= 0; + decrementNonDaemonThreads(); } + } else if (!VMThreads.wasStartedByCurrentIsolate(vmThread)) { + /* + * Attached threads are treated like non-daemon threads as long as they don't have a + * thread object. + */ + decrementNonDaemonThreads(); } } @@ -714,7 +713,6 @@ public static void exit(Thread thread) { @RawStructure protected interface ThreadStartData extends PointerBase { - @RawField ObjectHandle getThreadHandle(); @@ -732,26 +730,45 @@ protected T prepareStart(Thread thread, int startDat T startData = UnmanagedMemory.malloc(startDataSize); startData.setIsolate(CurrentIsolate.getIsolate()); startData.setThreadHandle(ObjectHandles.getGlobal().create(thread)); + + int numThreads = unattachedStartedThreads.incrementAndGet(); + assert numThreads > 0; + if (!thread.isDaemon()) { - int newValue = nonDaemonThreads.incrementAndGet(); - assert newValue >= 1; + incrementNonDaemonThreads(); } return startData; } protected void undoPrepareStartOnError(Thread thread, ThreadStartData startData) { if (!thread.isDaemon()) { - undoPrepareNonDaemonStartOnError(); + decrementNonDaemonThreadsAndNotify(); } + + int numThreads = unattachedStartedThreads.decrementAndGet(); + assert numThreads >= 0; + freeStartData(startData); } + @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) + static void incrementNonDaemonThreads() { + int numThreads = nonDaemonThreads.incrementAndGet(); + assert numThreads > 0; + } + + /** A caller must call THREAD_LIST_CONDITION.broadcast() manually. */ + @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) + private static void decrementNonDaemonThreads() { + int numThreads = nonDaemonThreads.decrementAndGet(); + assert numThreads >= 0; + } + @Uninterruptible(reason = "Holding threads lock.") - private static void undoPrepareNonDaemonStartOnError() { + private static void decrementNonDaemonThreadsAndNotify() { VMThreads.lockThreadMutexInNativeCode(); try { - int newValue = nonDaemonThreads.decrementAndGet(); - assert newValue >= 0; + decrementNonDaemonThreads(); VMThreads.THREAD_LIST_CONDITION.broadcast(); } finally { VMThreads.THREAD_MUTEX.unlock(); @@ -763,10 +780,8 @@ protected static void freeStartData(ThreadStartData startData) { } void startThread(Thread thread, long stackSize) { - unattachedStartedThreads.incrementAndGet(); boolean started = doStartThread(thread, stackSize); if (!started) { - unattachedStartedThreads.decrementAndGet(); throw new OutOfMemoryError("Unable to create native thread: possibly out of memory or process/resource limits reached"); } } @@ -1054,6 +1069,7 @@ public static int getThreadStatus(Thread thread) { return toTarget(thread).holder.threadStatus; } + @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) public static void setThreadStatus(Thread thread, int threadStatus) { assert !isVirtual(thread); assert toTarget(thread).holder.threadStatus != ThreadStatus.TERMINATED : "once a thread is marked terminated, its status must not change"; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java index 44520a9fc8d1..b16b106e42f2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VMThreads.java @@ -325,6 +325,7 @@ public int attachThread(IsolateThread thread, boolean startedByCurrentIsolate) { return attachThread(thread); } + /* Needs to be protected due to legacy code. */ @Uninterruptible(reason = "Thread is not attached yet.") protected int attachThread(IsolateThread thread) { assert StatusSupport.isStatusCreated(thread) : "Status should be initialized on creation."; @@ -342,6 +343,11 @@ protected int attachThread(IsolateThread thread) { numAttachedThreads++; assert numAttachedThreads > 0; + if (!wasStartedByCurrentIsolate(thread)) { + /* Treat attached threads as non-daemon threads until we know better. */ + PlatformThreads.incrementNonDaemonThreads(); + } + Heap.getHeap().attachThread(CurrentIsolate.getCurrentThread()); /* On the initial transition to java code this thread should be synchronized. */ ActionOnTransitionToJavaSupport.setSynchronizeCode(thread); From 53f4b800c3ee0b5ed6f0d480021bf21eb32b17a5 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 10 Jan 2024 14:06:39 +0100 Subject: [PATCH 21/75] Use a common ThreadStartRoutinePrologue on all platforms. --- .../oracle/svm/core/thread/PlatformThreads.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 4ef47851a200..d2a2f742636b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -713,6 +713,7 @@ public static void exit(Thread thread) { @RawStructure protected interface ThreadStartData extends PointerBase { + @RawField ObjectHandle getThreadHandle(); @@ -1251,6 +1252,19 @@ static void enter(ThreadStartData data) { } } + protected static class ThreadStartRoutinePrologue implements CEntryPointOptions.Prologue { + private static final CGlobalData errorMessage = CGlobalDataFactory.createCString("Failed to attach a newly launched thread."); + + @SuppressWarnings("unused") + @Uninterruptible(reason = "prologue") + static void enter(ThreadStartData data) { + int code = CEntryPointActions.enterAttachThread(data.getIsolate(), true, false); + if (code != CEntryPointErrors.NO_ERROR) { + CEntryPointActions.failFatally(code, errorMessage.get()); + } + } + } + public interface ThreadLocalKey extends ComparableWord { } } From c01a5062ad3f545125397059d62fd3464d61bf4a Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 11 Jan 2024 11:53:42 +0100 Subject: [PATCH 22/75] Cleanups. --- .../svm/core/genscavenge/HeapChunkProvider.java | 2 +- .../com/oracle/svm/core/monitor/JavaMonitor.java | 2 +- .../monitor/JavaMonitorQueuedSynchronizer.java | 7 +++---- .../com/oracle/svm/core/util/BasedOnJDKClass.java | 15 +++++++++++++-- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java index 6569f15a6f06..18487ff5832f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapChunkProvider.java @@ -76,7 +76,7 @@ final class HeapChunkProvider { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) public UnsignedWord getBytesInUnusedChunks() { - return numUnusedAlignedChunks.get().multiply(HeapParameters.getAlignedHeapChunkAlignment()); + return numUnusedAlignedChunks.get().multiply(HeapParameters.getAlignedHeapChunkSize()); } private static final OutOfMemoryError ALIGNED_OUT_OF_MEMORY_ERROR = new OutOfMemoryError("Could not allocate an aligned heap chunk"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java index 9dede49f6015..f0d580123079 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitor.java @@ -46,7 +46,7 @@ /** * {@link JavaMonitor} is based on the code of {@link java.util.concurrent.locks.ReentrantLock} as - * of JDK 21 (git commit hash: f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-21+26). + * of JDK 21+26. * * Only the relevant methods from the JDK sources have been kept. Some additional Native * Image-specific functionality has been added. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java index 83d163541e87..561642445c48 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/JavaMonitorQueuedSynchronizer.java @@ -42,10 +42,9 @@ /** * {@link JavaMonitorQueuedSynchronizer} is based on the code of - * {@link java.util.concurrent.locks.AbstractQueuedLongSynchronizer} as of JDK 21 (git commit hash: - * f640fc5a1eb876a657d0de011dcd9b9a42b88eec, JDK tag: jdk-21+26). This class could be merged with - * {@link JavaMonitor} but we keep it separate because that way diffing against the JDK sources is - * easier. + * {@link java.util.concurrent.locks.AbstractQueuedLongSynchronizer} as of JDK 21+26. This class + * could be merged with {@link JavaMonitor} but we keep it separate because that way diffing against + * the JDK sources is easier. * * Only the relevant methods from the JDK sources have been kept. Some additional Native * Image-specific functionality has been added. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKClass.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKClass.java index b3989f3ac584..b2b4d29324ac 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKClass.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/util/BasedOnJDKClass.java @@ -35,10 +35,21 @@ import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.monitor.JavaMonitor; /** - * Documents that the class is based on a JDK class without {@linkplain TargetClass substituting} - * it. + * Documents that a class is based on JDK source code. For example, {@link JavaMonitor} (which is + * used to implement "synchronized" in Native Image) is a simplified and customized version of the + * JDK class {@link java.util.concurrent.locks.ReentrantLock}. + * + * Unless specified otherwise, we try to keep our custom implementations in sync with their JDK + * counterparts. When we update to a new JDK version, we therefore need to check if there were any + * relevant changes that need to be applied to our code base. Here is a basic rule of thumb: + *
    + *
  • master should follow JDK latest (unless there are incompatibilities with earlier JDK versions + * that we need to support on master)
  • + *
  • important bug/performance fixes need to be backported
  • + *
*/ @Repeatable(BasedOnJDKClass.List.class) @Retention(RetentionPolicy.RUNTIME) From ef1385315d7f16be67e7291801934ffad7dc5b70 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Tue, 16 Jan 2024 14:20:54 +0100 Subject: [PATCH 23/75] Cleanups and small fixes. --- .../posix/thread/PosixPlatformThreads.java | 3 +- .../core/windows/WindowsPlatformThreads.java | 3 +- .../com/oracle/svm/core/JavaMainWrapper.java | 3 -- .../graal/snippets/CEntryPointSnippets.java | 13 +++-- .../svm/core/thread/PlatformThreads.java | 47 +++++++++++++++---- 5 files changed, 49 insertions(+), 20 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java index bbab7d016f74..f3b29b1f170f 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/thread/PosixPlatformThreads.java @@ -134,8 +134,7 @@ private boolean doStartThread0(Thread thread, pthread_attr_t attributes) { } return true; } catch (Throwable e) { - undoPrepareStartOnError(thread, startData); - throw e; + throw VMError.shouldNotReachHere("No exception must be thrown after creating the thread start data.", e); } } diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java index 28787e57a522..27d8fc105ec1 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java @@ -91,8 +91,7 @@ private boolean doStartThread0(Thread thread, int threadStackSize, int initFlag) WinBase.CloseHandle(osThreadHandle); return true; } catch (Throwable e) { - undoPrepareStartOnError(thread, startData); - throw e; + throw VMError.shouldNotReachHere("No exception must be thrown after creating the thread start data.", e); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java index 5295e0aa7757..c8546bda3d51 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/JavaMainWrapper.java @@ -72,7 +72,6 @@ import com.oracle.svm.core.log.Log; import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.thread.PlatformThreads; -import com.oracle.svm.core.thread.ThreadListenerSupport; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.thread.VMThreads.OSThreadHandle; import com.oracle.svm.core.util.CounterSupport; @@ -221,8 +220,6 @@ private static int runCore0() { return VMInspectionOptions.dumpImageHeap() ? 0 : 1; } - ThreadListenerSupport.get().beforeThreadRun(); - // Ensure that native code using JNI_GetCreatedJavaVMs finds this isolate. JNIJavaVMList.addJavaVM(JNIFunctionTables.singleton().getGlobalJavaVM()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 76f214f123ba..18a590364b46 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -88,6 +88,7 @@ import com.oracle.svm.core.stack.StackOverflowCheck; import com.oracle.svm.core.thread.PlatformThreads; import com.oracle.svm.core.thread.Safepoint; +import com.oracle.svm.core.thread.ThreadListenerSupport; import com.oracle.svm.core.thread.VMOperationControl; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; @@ -201,7 +202,6 @@ public static int createIsolateSnippet(CEntryPointCreateIsolateParameters parame writeCurrentVMThread(WordFactory.nullPointer()); } int result = runtimeCall(CREATE_ISOLATE, parameters); - if (result != CEntryPointErrors.NO_ERROR) { return result; } @@ -268,8 +268,7 @@ private static int createIsolate0(CLongPointer parsedArgs, Isolate isolate) { if (error != CEntryPointErrors.NO_ERROR) { return error; } - - PlatformThreads.singleton().initializeIsolate(); + PlatformThreads.singleton().assignMainThread(); return CEntryPointErrors.NO_ERROR; } @@ -404,6 +403,14 @@ private static int initializeIsolateInterruptibly0(CEntryPointCreateIsolateParam return CEntryPointErrors.ISOLATE_INITIALIZATION_FAILED; } + /* The isolate is now initialized, so we can finally finish initializing the main thread. */ + try { + ThreadListenerSupport.get().beforeThreadRun(); + } catch (Throwable t) { + System.err.println("Uncaught exception in beforeThreadRun():"); + t.printStackTrace(); + return CEntryPointErrors.ISOLATE_INITIALIZATION_FAILED; + } return CEntryPointErrors.NO_ERROR; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index d2a2f742636b..95892000a33f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -463,10 +463,15 @@ public static Thread getMountedVirtualThread(Thread thread) { return toTarget(thread).vthread; } - @Uninterruptible(reason = "Called during isolate initialization") - public void initializeIsolate() { + @Uninterruptible(reason = "Called during isolate creation.") + public void assignMainThread() { /* The thread that creates the isolate is considered the "main" thread. */ assignCurrent0(mainThread); + + /* + * Note that we can't call ThreadListenerSupport.beforeThreadRun() because the isolate is + * not fully initialized yet. This is done later on, during isolate initialization. + */ } /** @@ -728,17 +733,39 @@ protected interface ThreadStartData extends PointerBase { } protected T prepareStart(Thread thread, int startDataSize) { - T startData = UnmanagedMemory.malloc(startDataSize); - startData.setIsolate(CurrentIsolate.getIsolate()); - startData.setThreadHandle(ObjectHandles.getGlobal().create(thread)); + T startData = WordFactory.nullPointer(); + ObjectHandle threadHandle = WordFactory.zero(); + try { + startData = UnmanagedMemory.malloc(startDataSize); + threadHandle = ObjectHandles.getGlobal().create(thread); - int numThreads = unattachedStartedThreads.incrementAndGet(); - assert numThreads > 0; + startData.setIsolate(CurrentIsolate.getIsolate()); + startData.setThreadHandle(threadHandle); + } catch (Throwable e) { + if (startData.isNonNull()) { + UnmanagedMemory.free(startData); + } + if (threadHandle.equal(WordFactory.zero())) { + ObjectHandles.getGlobal().destroy(threadHandle); + } + throw e; + } - if (!thread.isDaemon()) { - incrementNonDaemonThreads(); + /* + * From this point onwards, no exceptions must be thrown (otherwise, we would need to + * partially undo the increment operations below). + */ + try { + int numThreads = unattachedStartedThreads.incrementAndGet(); + assert numThreads > 0; + + if (!thread.isDaemon()) { + incrementNonDaemonThreads(); + } + return startData; + } catch (Throwable e) { + throw VMError.shouldNotReachHere("No exception must be thrown after creating the thread start data.", e); } - return startData; } protected void undoPrepareStartOnError(Thread thread, ThreadStartData startData) { From 5d163e2c87753f7c929bf37fa913a311cb245edb Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 19 Jan 2024 11:24:52 +0100 Subject: [PATCH 24/75] Enforce that java.lang.Thread and all its subclasses have a Java monitor slot. --- .../monitor/MultiThreadedMonitorSupport.java | 32 ++++++++++++------- .../svm/core/thread/PlatformThreads.java | 2 +- .../svm/hosted/HostedConfiguration.java | 12 +++++-- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java index e1b7f760201d..15c0e9a5fcff 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java @@ -25,9 +25,8 @@ package com.oracle.svm.core.monitor; import java.util.Collections; -import java.util.HashSet; +import java.util.HashMap; import java.util.Map; -import java.util.Set; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.LockSupport; @@ -101,10 +100,11 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * Types that are used to implement the secondary storage for monitor slots cannot themselves * use the additionalMonitors map. That could result in recursive manipulation of the * additionalMonitors map which could lead to table corruptions and double insertion of a - * monitor for the same object. Therefore these types will always get a monitor slot. + * monitor for the same object. Therefore these types will always get a monitor slot. The + * boolean values specifies if the monitor slot is also needed for subtypes. */ @Platforms(Platform.HOSTED_ONLY.class)// - public static final Set> FORCE_MONITOR_SLOT_TYPES; + public static final Map, Boolean> FORCE_MONITOR_SLOT_TYPES; static { try { @@ -113,9 +113,9 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * com.oracle.svm.core.monitor.MultiThreadedMonitorSupport#additionalMonitors map uses * java.lang.ref.ReferenceQueue internally. */ - HashSet> monitorTypes = new HashSet<>(); + HashMap, Boolean> monitorTypes = new HashMap<>(); /* The WeakIdentityHashMap also synchronizes on its internal ReferenceQueue field. */ - monitorTypes.add(java.lang.ref.ReferenceQueue.class); + monitorTypes.put(java.lang.ref.ReferenceQueue.class, false); /* * Whenever the monitor allocation in @@ -124,7 +124,7 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * LinuxPhysicalMemory$PhysicalMemorySupportImpl.sizeFromCGroup() is called which * triggers file IO using the synchronized java.io.FileDescriptor.attach(). */ - monitorTypes.add(java.io.FileDescriptor.class); + monitorTypes.put(java.io.FileDescriptor.class, false); /* * LinuxPhysicalMemory$PhysicalMemorySupportImpl.sizeFromCGroup() also calls @@ -135,7 +135,7 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * This should also take care of the synchronization in * ReferenceInternals.processPendingReferences(). */ - monitorTypes.add(java.lang.Object.class); + monitorTypes.put(java.lang.Object.class, false); /* * The map access in MultiThreadedMonitorSupport.getOrCreateMonitorFromMap() calls @@ -144,22 +144,30 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * SplittableRandomAccessors.initialize() which synchronizes on an instance of * SplittableRandomAccessors. */ - monitorTypes.add(Class.forName("com.oracle.svm.core.jdk.SplittableRandomAccessors")); + monitorTypes.put(Class.forName("com.oracle.svm.core.jdk.SplittableRandomAccessors"), false); /* * PhantomCleanable.remove() synchronizes on an instance of PhantomCleanable. When the * secondary storage monitors map is modified it can trigger a slow-path-new-instance * allocation which in turn can trigger a GC which processes all the pending cleaners. */ - monitorTypes.add(Class.forName("jdk.internal.ref.PhantomCleanable")); + monitorTypes.put(Class.forName("jdk.internal.ref.PhantomCleanable"), false); /* * Use as the delegate for locking on {@link Class} (i.e. {@link DynamicHub}) since the * hub itself must be immutable. */ - monitorTypes.add(DynamicHubCompanion.class); + monitorTypes.put(DynamicHubCompanion.class, false); - FORCE_MONITOR_SLOT_TYPES = Collections.unmodifiableSet(monitorTypes); + /* + * When a thread exits, it locks its own thread mutex and changes its state to + * TERMINATED. Without an explict monitor slot, the thread could get parked when + * unlocking its own mutex (because we need to lock the shared monitor map). If the + * thread gets blocked during unlocking, its thread state would change unexpectedly. + */ + monitorTypes.put(Thread.class, true); + + FORCE_MONITOR_SLOT_TYPES = Collections.unmodifiableMap(monitorTypes); } catch (ClassNotFoundException e) { throw VMError.shouldNotReachHere("Error building the list of types that always need a monitor slot.", e); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 95892000a33f..3ba38a76fa5c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -1100,7 +1100,7 @@ public static int getThreadStatus(Thread thread) { @Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true) public static void setThreadStatus(Thread thread, int threadStatus) { assert !isVirtual(thread); - assert toTarget(thread).holder.threadStatus != ThreadStatus.TERMINATED : "once a thread is marked terminated, its status must not change"; + assert toTarget(thread).holder.threadStatus != ThreadStatus.TERMINATED : "once a thread is marked as terminated, its status must not change"; toTarget(thread).holder.threadStatus = threadStatus; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 9a5d1f444efb..b3d96c725957 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -264,9 +264,15 @@ public void collectMonitorFieldInfo(BigBang bb, HostedUniverse hUniverse, Set getForceMonitorSlotTypes(BigBang bb) { Set forceMonitorTypes = new HashSet<>(); - for (Class forceMonitorType : MultiThreadedMonitorSupport.FORCE_MONITOR_SLOT_TYPES) { - Optional aType = bb.getMetaAccess().optionalLookupJavaType(forceMonitorType); - aType.ifPresent(forceMonitorTypes::add); + for (var entry : MultiThreadedMonitorSupport.FORCE_MONITOR_SLOT_TYPES.entrySet()) { + Optional optionalType = bb.getMetaAccess().optionalLookupJavaType(entry.getKey()); + if (optionalType.isPresent()) { + AnalysisType aType = optionalType.get(); + forceMonitorTypes.add(aType); + if (entry.getValue()) { + forceMonitorTypes.addAll(aType.getAllSubtypes()); + } + } } return forceMonitorTypes; } From beb61820a13b4c9463c37692b26187a31035e3f8 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Fri, 19 Jan 2024 20:24:41 +0100 Subject: [PATCH 25/75] Cleanups and small bugfix. --- .../monitor/MultiThreadedMonitorSupport.java | 4 +-- .../svm/core/thread/PlatformThreads.java | 25 ++++--------------- .../svm/core/thread/ThreadListener.java | 10 ++++++-- 3 files changed, 15 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java index 15c0e9a5fcff..bd477fb4ae6d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/monitor/MultiThreadedMonitorSupport.java @@ -100,8 +100,8 @@ public class MultiThreadedMonitorSupport extends MonitorSupport { * Types that are used to implement the secondary storage for monitor slots cannot themselves * use the additionalMonitors map. That could result in recursive manipulation of the * additionalMonitors map which could lead to table corruptions and double insertion of a - * monitor for the same object. Therefore these types will always get a monitor slot. The - * boolean values specifies if the monitor slot is also needed for subtypes. + * monitor for the same object. Therefore, these types will always get a monitor slot. The + * boolean value specifies if the monitor slot is also needed for subtypes. */ @Platforms(Platform.HOSTED_ONLY.class)// public static final Map, Boolean> FORCE_MONITOR_SLOT_TYPES; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java index 3ba38a76fa5c..70beb69e6024 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/PlatformThreads.java @@ -510,8 +510,9 @@ public static void detachThread(IsolateThread vmThread) { } } else if (!VMThreads.wasStartedByCurrentIsolate(vmThread)) { /* - * Attached threads are treated like non-daemon threads as long as they don't have a - * thread object. + * Attached threads are treated like non-daemon threads before they are assigned a + * thread object which defines whether they are a daemon thread (which might never + * happen). */ decrementNonDaemonThreads(); } @@ -745,16 +746,13 @@ protected T prepareStart(Thread thread, int startDat if (startData.isNonNull()) { UnmanagedMemory.free(startData); } - if (threadHandle.equal(WordFactory.zero())) { + if (threadHandle.notEqual(WordFactory.zero())) { ObjectHandles.getGlobal().destroy(threadHandle); } throw e; } - /* - * From this point onwards, no exceptions must be thrown (otherwise, we would need to - * partially undo the increment operations below). - */ + /* To ensure that we have consistent thread counts, no exception must be thrown. */ try { int numThreads = unattachedStartedThreads.incrementAndGet(); assert numThreads > 0; @@ -1279,19 +1277,6 @@ static void enter(ThreadStartData data) { } } - protected static class ThreadStartRoutinePrologue implements CEntryPointOptions.Prologue { - private static final CGlobalData errorMessage = CGlobalDataFactory.createCString("Failed to attach a newly launched thread."); - - @SuppressWarnings("unused") - @Uninterruptible(reason = "prologue") - static void enter(ThreadStartData data) { - int code = CEntryPointActions.enterAttachThread(data.getIsolate(), true, false); - if (code != CEntryPointErrors.NO_ERROR) { - CEntryPointActions.failFatally(code, errorMessage.get()); - } - } - } - public interface ThreadLocalKey extends ComparableWord { } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java index 485f697a18e2..ce3480130689 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ThreadListener.java @@ -37,12 +37,18 @@ default void beforeThreadStart(IsolateThread isolateThread, Thread javaThread) { default void beforeThreadRun() { } - /** Implementations must not throw any exceptions. */ + /** + * Implementations must not throw any exceptions. Note that this method is called on listeners + * in the reverse order of {@link #beforeThreadRun}. + */ @Uninterruptible(reason = "Only uninterruptible because we need to prevent stack overflow errors. Implementations may execute interruptible code.") default void afterThreadRun() { } - /** Implementations must not throw any exceptions. */ + /** + * Implementations must not throw any exceptions. Note that this method is called on listeners + * in the reverse order of {@link #beforeThreadStart}. + */ @Uninterruptible(reason = "Only uninterruptible code may be executed after Thread.exit.") @SuppressWarnings("unused") default void afterThreadExit(IsolateThread isolateThread, Thread javaThread) { From f4af90a3b5da18e8024ff3a22f928fdc1c4c3ef9 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 22 Jan 2024 17:23:56 +0100 Subject: [PATCH 26/75] Exclude pom.xml and pom.properties files from shadowed ICU4J. --- truffle/mx.truffle/suite.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 9e71e6230976..a447a6d0b85d 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -1156,6 +1156,8 @@ "META-INF/MANIFEST.MF", "META-INF/services/*", # deliberately excluding java.nio.charset.spi.CharsetProvider "**/*.html", + "**/pom.xml", + "**/pom.properties", ], "patch" : { "com/ibm/icu/ICUConfig.properties" : { From 02467c20f4a3a80d6acfdc377eababe238436f7f Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 22 Jan 2024 17:38:24 +0100 Subject: [PATCH 27/75] Shadow ASM for truffle module from source using mx. --- truffle/mx.truffle/suite.py | 69 +++++++++++++++++++++++++++++++++++-- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index a447a6d0b85d..cc75c7b12872 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -105,6 +105,41 @@ "license": ["MIT"], }, + "ASM_9.5": { + "digest": "sha512:9e65f2983783725bae196ca939b45246958731246df1c495089c8ea5ce646de77c4e01a5a9ba10642016bb3258e1727e9ebcece6e74d9e3c32f528025d76b955", + "sourceDigest": "sha512:64262b68c1acd473a49be3c8a89190200be66808034c55fb23ed08d8a977111c234b6dc77b6ca95310e1f1cbc43437cdc863aadb6217976cc1720d63ef01e937", + "maven": { + "groupId": "org.ow2.asm", + "artifactId": "asm", + "version": "9.5", + }, + "license": "BSD-new", + }, + + "ASM_TREE_9.5": { + "digest": "sha512:816de8f84c216a7bd97b2458bde64a4b99a039b7b59fbd1ef52edf8bf869edabb93967736fe0c61e8eb3e1520e0cefe69ba59cda12df30f9f85db75fb6c064f3", + "sourceDigest": "sha512:a107043c05398091e3f3c614270c626be8ea5a1a547e30dc5709ef92069c8c8baa315c385a68f244c3a37bc148c3aeeec26adc8c00afc2a03a1d21a40e076a4c", + "maven": { + "groupId": "org.ow2.asm", + "artifactId": "asm-tree", + "version": "9.5", + }, + "dependencies" : ["ASM_9.5"], + "license": "BSD-new", + }, + + "ASM_COMMONS_9.5": { + "digest": "sha512:6121a9d033627a33839d9bd264fce4a531b6a3f974720adc6150816f0316d1522c3d8caf7df039fdd46cb66bedd788e50f709d4a1f75d3525912ad7a4d87f7da", + "sourceDigest": "sha512:688d56a1b4fb6f7d86b79b7493a848851892910d00067a0c5effdaf7132266ec7a1ba57a8248c2fd6c0ebdef18a4918908a36e85f5927b9acb55448047a1e333", + "maven": { + "groupId": "org.ow2.asm", + "artifactId": "asm-commons", + "version": "9.5", + }, + "dependencies" : ["ASM_9.5", "ASM_TREE_9.5"], + "license": "BSD-new", + }, + "TRUFFLE_ASM_9.5" : { "digest" : "sha512:7a49aaa0c4b513ca54ce684a74a3848ba4caf486320125f08cb8872720dc1e789538729f45c46d6ccf1b1ea54f7c3770dc9682d13a3f1813a348168ee5c40b82", "urls": ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/com.oracle.truffle.api.impl.asm-9.5.0.jar"], @@ -308,7 +343,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.truffle.api.exception", - "truffle:TRUFFLE_ASM_9.5", + "com.oracle.truffle.api.impl.asm", ], "requires" : [ "java.sql", @@ -663,7 +698,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.truffle.api", - "truffle:TRUFFLE_ASM_9.5", + "com.oracle.truffle.api.impl.asm", ], "requires" : [ "jdk.unsupported", # sun.misc.Unsafe @@ -1322,6 +1357,36 @@ "jacoco" : "exclude", "graalCompilerSourceEdition": "ignore", }, + + "com.oracle.truffle.api.impl.asm" : { + # Shadowed ASM libraries (org.ow2.asm:asm,asm-tree,asm-commons) + "subDir" : "src", + "sourceDirs" : ["src"], + "javaCompliance" : "17+", + "spotbugs" : "false", + "shadedDependencies" : [ + "truffle:ASM_9.5", + "truffle:ASM_TREE_9.5", + "truffle:ASM_COMMONS_9.5", + ], + "class" : "ShadedLibraryProject", + "shade" : { + "packages" : { + "org.objectweb.asm" : "com.oracle.truffle.api.impl.asm", + }, + "exclude" : [ + "META-INF/MANIFEST.MF", + "**/package.html", + ], + }, + "description" : "ASM library shadowed for Truffle.", + "allowsJavadocWarnings": True, + # We need to force javac because the generated sources in this project produce warnings in JDT. + "forceJavac" : "true", + "javac.lint.overrides" : "none", + "jacoco" : "exclude", + "graalCompilerSourceEdition": "ignore", + }, }, "licenses" : { From daa5113a6ef765061c849887e115dc48bb6ef125 Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Tue, 16 Jan 2024 14:56:05 +0100 Subject: [PATCH 28/75] [GR-50951] Fix graalpy dependencies. --- vm/ci/ci_common/common.jsonnet | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vm/ci/ci_common/common.jsonnet b/vm/ci/ci_common/common.jsonnet index 0ae680ee9aa8..bb57b1198363 100644 --- a/vm/ci/ci_common/common.jsonnet +++ b/vm/ci/ci_common/common.jsonnet @@ -138,7 +138,7 @@ local devkits = graal_common.devkits; }, # GRAALPYTHON - graalpython_linux_amd64: self.sulong_linux + { + graalpython_common_linux: { packages+: { libffi: '>=3.2.1', bzip2: '>=1.0.6', @@ -146,10 +146,9 @@ local devkits = graal_common.devkits; }, }, - graalpython_linux_aarch64: self.sulong_linux + {}, - + graalpython_linux_amd64: self.sulong_linux + self.graalpython_common_linux, + graalpython_linux_aarch64: self.sulong_linux + self.graalpython_common_linux, graalpython_darwin_amd64: self.sulong_darwin_amd64 + {}, - graalpython_darwin_aarch64: self.sulong_darwin_aarch64 + {}, vm_linux_amd64_common: graal_common.deps.svm { From 61ac71ede1973ebf904e0f34f6a5e3ee96bd784d Mon Sep 17 00:00:00 2001 From: Benoit Daloze Date: Wed, 24 Jan 2024 11:56:24 +0100 Subject: [PATCH 29/75] Remove unused env file --- vm/mx.vm/ce-ruby | 5 ----- vm/mx.vm/mx_vm.py | 2 -- 2 files changed, 7 deletions(-) delete mode 100644 vm/mx.vm/ce-ruby diff --git a/vm/mx.vm/ce-ruby b/vm/mx.vm/ce-ruby deleted file mode 100644 index e76849e8ea34..000000000000 --- a/vm/mx.vm/ce-ruby +++ /dev/null @@ -1,5 +0,0 @@ -DYNAMIC_IMPORTS=/compiler,/regex,/sdk,/substratevm,/sulong,/tools,/truffle,truffleruby -COMPONENTS=antlr4,cmp,cov,dap,gvm,icu4j,ins,insight,insightheap,lg,llp,llrc,llrn,lsp,nfi-libffi,pro,rby,rbyl,rgx,sdk,sdkl,tfl,tfla,tflc,tflm,truffle-json -EXCLUDE_COMPONENTS=libpoly -NATIVE_IMAGES=graalvm-native-binutil,graalvm-native-clang,graalvm-native-clang-cl,graalvm-native-clang++,graalvm-native-flang,graalvm-native-ld,lib:jvmcicompiler,lib:rubyvm -DISABLE_INSTALLABLES=False diff --git a/vm/mx.vm/mx_vm.py b/vm/mx.vm/mx_vm.py index bf6e08e2cc66..afffff5fb60c 100644 --- a/vm/mx.vm/mx_vm.py +++ b/vm/mx.vm/mx_vm.py @@ -192,7 +192,6 @@ def local_path_to_url(args): ce_unchained_components = ['bnative-image-configure', 'cmp', 'lg', 'ni', 'nic', 'nil', 'nr_lib_jvmcicompiler', 'sdkc', 'sdkni', 'svm', 'svmsl', 'svmt', 'tflc', 'tflsm'] ce_components_minimal = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'lg', 'libpoly', 'lsp', 'nfi-libffi', 'nfi', 'poly', 'polynative', 'pro', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'spolyglot', 'tfl', 'tfla', 'tflc', 'tflm', 'truffle-json'] ce_components = ce_components_minimal + ['nr_lib_jvmcicompiler', 'bnative-image-configure', 'ni', 'nic', 'nil', 'svm', 'svmt', 'svmnfi', 'svmsl'] -ce_ruby_components = ['antlr4', 'cmp', 'cov', 'dap', 'gvm', 'icu4j', 'ins', 'insight', 'insightheap', 'lg', 'llp', 'llrc', 'llrlf', 'llrn', 'lsp', 'nfi-libffi', 'nfi', 'pro', 'rby', 'rbyl', 'rgx', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'tfl', 'tfla', 'tflc', 'tflm', 'truffle-json'] ce_python_components = ['antlr4', 'sllvmvm', 'bpolybench', 'bpolyglot', 'cmp', 'cov', 'dap', 'dis', 'gu', 'gvm', 'icu4j', 'xz', 'ins', 'insight', 'insightheap', 'lg', 'libpoly', 'llp', 'llrc', 'llrl', 'llrlf', 'llrn', 'lsp', 'nfi-libffi', 'nfi', 'pbm', 'pmh', 'poly', 'polynative', 'pro', 'pyn', 'pynl', 'rgx', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'spolyglot', 'tfl', 'tfla', 'tflc', 'tflm', 'truffle-json'] ce_fastr_components = ce_components + llvm_components + ['antlr4', 'xz', 'sllvmvm', 'llp', 'bnative-image', 'snative-image-agent', 'R', 'bRMain', 'bnative-image-configure', 'llrc', 'snative-image-diagnostics-agent', 'llrn', 'llrl', 'llrlf'] ce_no_native_components = ['bpolyglot', 'cmp', 'cov', 'dap', 'gu', 'gvm', 'ins', 'insight', 'insightheap', 'lsp', 'nfi-libffi', 'nfi', 'polynative', 'pro', 'sdk', 'sdkni', 'sdkc', 'sdkl', 'spolyglot', 'tfl', 'tfla', 'tflc', 'tflm', 'truffle-json', 'libpoly', 'poly'] @@ -204,7 +203,6 @@ def local_path_to_url(args): mx_sdk_vm.register_vm_config('community', ce_unchained_components, _suite, env_file='ce-darwin-aarch64') mx_sdk_vm.register_vm_config('community', ce_unchained_components, _suite, env_file='ce') # Other GraalVMs -mx_sdk_vm.register_vm_config('ruby-community', ce_ruby_components, _suite, env_file='ce-ruby') mx_sdk_vm.register_vm_config('espresso-community', ['antlr4', 'ejc', 'ejvm', 'ellvm', 'gvm', 'java', 'llp', 'llrc', 'llrlf', 'llrn', 'nfi', 'nfi-libffi', 'nr_lib_javavm', 'sdk', 'sdkc', 'sdkl', 'sdkni', 'tfl', 'tfla', 'tflc', 'tflm'], _suite, env_file='ce-llvm-espresso') mx_sdk_vm.register_vm_config('espresso-community', ['ejc', 'ejvm', 'gvm', 'java', 'nfi', 'nfi-libffi', 'nr_lib_javavm', 'sdk', 'sdkc', 'sdkl', 'sdkni', 'tfl', 'tfla', 'tflc', 'tflm'], _suite, env_file='ce-espresso') mx_sdk_vm.register_vm_config('ce', ce_components + ['icu4j', 'js', 'jsl', 'jss', 'rgx', 'bnative-image', 'snative-image-agent', 'snative-image-diagnostics-agent'], _suite, dist_name='ce-js', env_file='ce-js') From 8a178aba9633919db52bbe741993369348a07538 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Wed, 6 Dec 2023 15:35:26 +0100 Subject: [PATCH 30/75] Lower AMD64 float conversions to assembly --- .../AArch64ArithmeticLIRGenerator.java | 3 +- .../amd64/AMD64ArithmeticLIRGenerator.java | 39 +++- .../core/amd64/AMD64NodeMatchRules.java | 7 +- .../core/common/type/ArithmeticOpTable.java | 20 +- .../compiler/core/common/type/FloatStamp.java | 64 ++++- .../amd64/AMD64HotSpotLoweringProvider.java | 10 +- .../lir/amd64/AMD64FloatConvertOp.java | 152 ++++++++++++ .../lir/gen/ArithmeticLIRGeneratorTool.java | 14 +- .../compiler/nodes/calc/FloatConvertNode.java | 20 +- .../amd64/AMD64ConvertSnippets.java | 218 ------------------ .../amd64/AMD64FloatConvertNode.java | 182 --------------- .../svm/core/graal/llvm/LLVMGenerator.java | 2 +- .../amd64/AMD64NonSnippetLowerings.java | 28 +-- 13 files changed, 303 insertions(+), 456 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64ConvertSnippets.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64FloatConvertNode.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java index 73082f13097f..ac8f35114c23 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/aarch64/AArch64ArithmeticLIRGenerator.java @@ -63,7 +63,6 @@ import jdk.graal.compiler.lir.aarch64.AArch64RoundFloatToIntegerOp; import jdk.graal.compiler.lir.gen.ArithmeticLIRGenerator; import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool; - import jdk.vm.ci.aarch64.AArch64Kind; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.JavaConstant; @@ -242,7 +241,7 @@ public Value emitUShr(Value a, Value b) { } @Override - public Value emitFloatConvert(FloatConvert op, Value inputVal) { + public Value emitFloatConvert(FloatConvert op, Value inputVal, boolean canBeNaN, boolean canOverflow) { PlatformKind resultPlatformKind = getFloatConvertResultKind(op); LIRKind resultLirKind = LIRKind.combine(inputVal).changeType(resultPlatformKind); Variable result = getLIRGen().newVariable(resultLirKind); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index c5801691068e..05b00e89a84c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -107,6 +107,7 @@ import jdk.graal.compiler.core.common.LIRKind; import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.calc.FloatConvert; +import jdk.graal.compiler.core.common.calc.FloatConvertCategory; import jdk.graal.compiler.core.common.memory.MemoryExtendKind; import jdk.graal.compiler.core.common.memory.MemoryOrderMode; import jdk.graal.compiler.debug.Assertions; @@ -122,6 +123,7 @@ import jdk.graal.compiler.lir.amd64.AMD64BinaryConsumer; import jdk.graal.compiler.lir.amd64.AMD64BitSwapOp; import jdk.graal.compiler.lir.amd64.AMD64ClearRegisterOp; +import jdk.graal.compiler.lir.amd64.AMD64FloatConvertOp; import jdk.graal.compiler.lir.amd64.AMD64FloatToHalfFloatOp; import jdk.graal.compiler.lir.amd64.AMD64HalfFloatToFloatOp; import jdk.graal.compiler.lir.amd64.AMD64MathCopySignOp; @@ -816,6 +818,17 @@ private AllocatableValue emitConvertOp(LIRKind kind, AMD64MROp op, OperandSize s return result; } + /** + * Emit a floating point to integer conversion that needs fixup code to adjust the result to + * Java semantics. + */ + private AllocatableValue emitFloatConvertWithFixup(LIRKind kind, AMD64RMOp op, OperandSize size, Value input, boolean canBeNaN, boolean canOverflow) { + Variable result = getLIRGen().newVariable(kind); + AMD64FloatConvertOp.OpcodeEmitter emitter = (crb, masm, dst, src) -> op.emit(masm, size, dst, src); + getLIRGen().append(new AMD64FloatConvertOp(getLIRGen(), emitter, result, input, canBeNaN, canOverflow)); + return result; + } + @Override public Value emitReinterpret(LIRKind to, Value inputVal) { ValueKind from = inputVal.getValueKind(); @@ -874,20 +887,26 @@ private static AMD64Kind scalarKind(AMD64Kind kind) { } @Override - public Value emitFloatConvert(FloatConvert op, Value input) { + public Value emitFloatConvert(FloatConvert op, Value input, boolean canBeNaN, boolean canOverflow) { + if (op.getCategory().equals(FloatConvertCategory.FloatingPointToInteger)) { + switch (op) { + case D2I: + return emitFloatConvertWithFixup(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSD2SI, DWORD, input, canBeNaN, canOverflow); + case D2L: + return emitFloatConvertWithFixup(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSD2SI, QWORD, input, canBeNaN, canOverflow); + case F2I: + return emitFloatConvertWithFixup(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSS2SI, DWORD, input, canBeNaN, canOverflow); + case F2L: + return emitFloatConvertWithFixup(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSS2SI, QWORD, input, canBeNaN, canOverflow); + default: + throw GraalError.shouldNotReachHereUnexpectedValue(op); // ExcludeFromJacocoGeneratedReport + } + } switch (op) { case D2F: return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.SINGLE), SSEOp.CVTSD2SS, SD, input); - case D2I: - return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSD2SI, DWORD, input); - case D2L: - return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSD2SI, QWORD, input); case F2D: return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSS2SD, SS, input); - case F2I: - return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DWORD), SSEOp.CVTTSS2SI, DWORD, input); - case F2L: - return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.QWORD), SSEOp.CVTTSS2SI, QWORD, input); case I2D: return emitConvertOp(LIRKind.combine(input).changeType(AMD64Kind.DOUBLE), SSEOp.CVTSI2SD, DWORD, input); case I2F: diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64NodeMatchRules.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64NodeMatchRules.java index 3033fb551ca0..ed43a48ddae2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64NodeMatchRules.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64NodeMatchRules.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,7 @@ import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.calc.CanonicalCondition; import jdk.graal.compiler.core.common.calc.Condition; +import jdk.graal.compiler.core.common.calc.FloatConvertCategory; import jdk.graal.compiler.core.common.memory.MemoryExtendKind; import jdk.graal.compiler.core.common.memory.MemoryOrderMode; import jdk.graal.compiler.core.gen.NodeLIRBuilder; @@ -681,6 +682,10 @@ public ComplexMatchResult signExtendNarrowRead(SignExtendNode root, NarrowNode n @MatchRule("(FloatConvert Read=access)") @MatchRule("(FloatConvert FloatingRead=access)") public ComplexMatchResult floatConvert(FloatConvertNode root, LIRLowerableAccess access) { + if (root.getFloatConvert().getCategory().equals(FloatConvertCategory.FloatingPointToInteger) && (root.inputCanBeNaN() || root.canOverflow())) { + /* We need to fix up the result of the conversion, the input should be in a register. */ + return null; + } switch (root.getFloatConvert()) { case D2F: return emitConvertMemoryOp(AMD64Kind.SINGLE, SSEOp.CVTSD2SS, SD, access); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java index acb397289373..7a2ffa20373c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.function.Function; import jdk.graal.compiler.core.common.calc.FloatConvert; +import jdk.graal.compiler.core.common.calc.FloatConvertCategory; import jdk.graal.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add; import jdk.graal.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; import jdk.graal.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Compress; @@ -59,7 +60,6 @@ import jdk.graal.compiler.core.common.type.ArithmeticOpTable.UnaryOp.Sqrt; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.util.CollectionsUtil; - import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaKind; @@ -908,6 +908,22 @@ public FloatConvertOp unwrap() { return this; } + /** Determine if this input is a floating-point stamp that can be NaN. */ + public boolean inputCanBeNaN(Stamp inputStamp) { + return inputStamp instanceof FloatStamp floatStamp && floatStamp.canBeNaN(); + } + + /** + * Determine if this is a floating-point to integer conversion whose result may be outside + * the range of the target type. + */ + public boolean canOverflowInteger(Stamp inputStamp) { + if (op.getCategory().equals(FloatConvertCategory.FloatingPointToInteger)) { + throw GraalError.unimplementedOverride(); + } + return false; + } + @Override public int hashCode() { final int prime = 31; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/FloatStamp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/FloatStamp.java index cdc66ddc1554..8d10ba767847 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/FloatStamp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/FloatStamp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,6 +35,7 @@ import java.util.function.DoubleBinaryOperator; import jdk.graal.compiler.core.common.LIRKind; +import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.calc.ReinterpretUtils; import jdk.graal.compiler.core.common.spi.LIRKindTool; import jdk.graal.compiler.debug.Assertions; @@ -385,6 +386,47 @@ private static Stamp maybeFoldConstant(ArithmeticOpTable.BinaryOp op, FloatSt return null; } + public static boolean floatingToIntegerCanOverflow(FloatStamp floatStamp, int integerBits) { + final boolean canBeInfinity = Double.isInfinite(floatStamp.lowerBound()) || Double.isInfinite(floatStamp.upperBound()); + if (canBeInfinity) { + return true; + } + final boolean conversionCanOverflow = integralPartLargerMaxValue(floatStamp, integerBits) || integralPartSmallerMinValue(floatStamp, integerBits); + return conversionCanOverflow; + } + + private static boolean integralPartLargerMaxValue(FloatStamp floatStamp, int integerBits) { + double upperBound = floatStamp.upperBound(); + if (Double.isInfinite(upperBound) || Double.isNaN(upperBound)) { + return true; + } + assert integerBits == 32 || integerBits == 64 : "Must be int or long " + Assertions.errorMessage(integerBits, upperBound); + long maxValue = NumUtil.maxValue(integerBits); + /* + * There could be conversion loss here when casting maxValue from long to double - given + * that max can be Long.MAX_VALUE. In order to avoid checking if upperBound is larger than + * max with arbitrary precision numbers (BigDecimal for example) we use some trick. + * + * (double) Long.MAX_VALUE is 9223372036854775808, which is 1 more than Long.MAX_VALUE. So + * (long) (double) Long.MAX_VALUE will already overflow. So we need upperBound >= (double) + * maxValue, with >= instead of >. The next lower double value is Math.nextDown((double) + * Long.MAX_VALUE) == 9223372036854774784, which fits into long. So if upperBound >= + * (double) maxValue does not hold, i.e., upperBound < (double) maxValue does hold, then + * (long) upperBound will not overflow. + */ + return upperBound >= maxValue; + } + + private static boolean integralPartSmallerMinValue(FloatStamp floatStamp, int integerBits) { + double lowerBound = floatStamp.lowerBound(); + if (Double.isInfinite(lowerBound) || Double.isNaN(lowerBound)) { + return true; + } + assert integerBits == 32 || integerBits == 64 : "Must be int or long " + Assertions.errorMessage(integerBits, lowerBound); + long minValue = NumUtil.minValue(integerBits); + return lowerBound <= minValue; + } + public static final ArithmeticOpTable OPS = new ArithmeticOpTable( new ArithmeticOpTable.UnaryOp.Neg() { @@ -1059,6 +1101,11 @@ protected Stamp foldStampImpl(Stamp stamp) { } return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound); } + + @Override + public boolean canOverflowInteger(Stamp inputStamp) { + return inputStamp instanceof FloatStamp floatStamp && floatingToIntegerCanOverflow(floatStamp, Integer.SIZE); + } }, new ArithmeticOpTable.FloatConvertOp(F2L) { @@ -1088,6 +1135,11 @@ protected Stamp foldStampImpl(Stamp stamp) { } return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound); } + + @Override + public boolean canOverflowInteger(Stamp inputStamp) { + return inputStamp instanceof FloatStamp floatStamp && floatingToIntegerCanOverflow(floatStamp, Long.SIZE); + } }, new ArithmeticOpTable.FloatConvertOp(D2I) { @@ -1117,6 +1169,11 @@ protected Stamp foldStampImpl(Stamp stamp) { } return StampFactory.forInteger(JavaKind.Int, lowerBound, upperBound); } + + @Override + public boolean canOverflowInteger(Stamp inputStamp) { + return inputStamp instanceof FloatStamp floatStamp && floatingToIntegerCanOverflow(floatStamp, Integer.SIZE); + } }, new ArithmeticOpTable.FloatConvertOp(D2L) { @@ -1146,6 +1203,11 @@ protected Stamp foldStampImpl(Stamp stamp) { } return StampFactory.forInteger(JavaKind.Long, lowerBound, upperBound); } + + @Override + public boolean canOverflowInteger(Stamp inputStamp) { + return inputStamp instanceof FloatStamp floatStamp && floatingToIntegerCanOverflow(floatStamp, Long.SIZE); + } }, new ArithmeticOpTable.FloatConvertOp(F2D) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java index 510dd5b7a0d4..eb77c8768f29 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotLoweringProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,11 +38,9 @@ import jdk.graal.compiler.hotspot.replacements.HotSpotAllocationSnippets; import jdk.graal.compiler.hotspot.replacements.arraycopy.HotSpotArraycopySnippets; import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.nodes.calc.FloatConvertNode; import jdk.graal.compiler.nodes.spi.LoweringTool; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.replacements.amd64.AMD64ConvertSnippets; import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode; import jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation; import jdk.vm.ci.amd64.AMD64; @@ -53,7 +51,6 @@ public class AMD64HotSpotLoweringProvider extends DefaultHotSpotLoweringProvider implements AMD64LoweringProviderMixin { - private AMD64ConvertSnippets.Templates convertSnippets; private AMD64X87MathSnippets.Templates mathSnippets; public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAccessProvider metaAccess, ForeignCallsProvider foreignCalls, HotSpotRegistersProvider registers, @@ -66,7 +63,6 @@ public AMD64HotSpotLoweringProvider(HotSpotGraalRuntimeProvider runtime, MetaAcc public void initialize(OptionValues options, Iterable factories, HotSpotProviders providers, GraalHotSpotVMConfig config, HotSpotArraycopySnippets.Templates arraycopySnippetTemplates, HotSpotAllocationSnippets.Templates allocationSnippetTemplates) { - convertSnippets = new AMD64ConvertSnippets.Templates(options, providers); mathSnippets = new AMD64X87MathSnippets.Templates(options, providers); super.initialize(options, factories, providers, config, arraycopySnippetTemplates, allocationSnippetTemplates); } @@ -76,9 +72,7 @@ public void lower(Node n, LoweringTool tool) { if (lowerAMD64(n)) { return; } - if (n instanceof FloatConvertNode) { - convertSnippets.lower((FloatConvertNode) n, tool); - } else if (n instanceof UnaryMathIntrinsicNode) { + if (n instanceof UnaryMathIntrinsicNode) { lowerUnaryMath((UnaryMathIntrinsicNode) n, tool); } else { super.lower(n, tool); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java new file mode 100644 index 000000000000..5d51fb2d7493 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.graal.compiler.lir.amd64; + +import static jdk.graal.compiler.asm.amd64.AMD64Assembler.SSEOp.UCOMIS; +import static jdk.graal.compiler.asm.amd64.AMD64BaseAssembler.OperandSize; +import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.ILLEGAL; +import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.REG; +import static jdk.vm.ci.code.ValueUtil.asRegister; + +import jdk.graal.compiler.asm.Label; +import jdk.graal.compiler.asm.amd64.AMD64Address; +import jdk.graal.compiler.asm.amd64.AMD64Assembler; +import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; +import jdk.graal.compiler.asm.amd64.AVXKind; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.lir.LIRInstructionClass; +import jdk.graal.compiler.lir.asm.CompilationResultBuilder; +import jdk.graal.compiler.lir.gen.LIRGeneratorTool; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.Value; + +/** + * Floating point to integer conversion according to Java semantics. This wraps an AMD64 conversion + * instruction and adjusts its result as needed. According to Java semantics, NaN inputs should be + * mapped to 0, and values outside the integer type's range should be mapped to {@code MIN_VALUE} or + * {@code MAX_VALUE} according to the input's sign. The AMD64 instructions produce {@code MIN_VALUE} + * for NaNs and all values outside the integer type's range. So we need to fix up the result for + * NaNs and positive overflowing values. Negative overflowing values keep {@code MIN_VALUE}. + */ +public class AMD64FloatConvertOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64FloatConvertOp.class); + + @Def({REG}) protected Value dstValue; + @Alive({REG}) protected Value srcValue; + @Temp({REG, ILLEGAL}) protected Value tmpValue; + + private final OpcodeEmitter opcode; + private final boolean canBeNaN; + private final boolean canOverflow; + + @FunctionalInterface + public interface OpcodeEmitter { + /** Emit the actual conversion instruction. */ + void emit(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, Register src); + } + + public AMD64FloatConvertOp(LIRGeneratorTool tool, OpcodeEmitter opcode, Value dstValue, Value srcValue, boolean canBeNaN, boolean canOverflow) { + super(TYPE); + this.dstValue = dstValue; + this.srcValue = srcValue; + this.opcode = opcode; + this.tmpValue = canOverflow ? tool.newVariable(srcValue.getValueKind()) : Value.ILLEGAL; + this.canBeNaN = canBeNaN; + this.canOverflow = canOverflow; + } + + @Override + public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + Register dst = asRegister(dstValue); + Register src = asRegister(srcValue); + Label isNotNaN = new Label(); + Label done = new Label(); + + opcode.emit(crb, masm, dst, src); + + if (!canBeNaN && !canOverflow) { + /* No fixup needed. */ + return; + } + + int integerBytes = dstValue.getPlatformKind().getSizeInBytes(); + GraalError.guarantee(integerBytes == 4 || integerBytes == 8, "unexpected target %s", dstValue); + OperandSize floatSize = switch (srcValue.getPlatformKind().getSizeInBytes()) { + case 4 -> OperandSize.PS; + case 8 -> OperandSize.PD; + default -> throw GraalError.shouldNotReachHere("unexpected input %s".formatted(srcValue)); + }; + + /* + * if (dst != MIN_VALUE) { goto done; } + */ + if (integerBytes == 4) { + masm.cmplAndJcc(dst, Integer.MIN_VALUE, AMD64Assembler.ConditionFlag.NotEqual, done, true); + } else { + masm.cmpq(dst, (AMD64Address) crb.asLongConstRef(JavaConstant.forLong(Long.MIN_VALUE))); + masm.jcc(AMD64Assembler.ConditionFlag.NotEqual, done, true); + } + + if (canBeNaN) { + /* + * if (isNaN(src)) { result = 0; goto done; } + * + * The isNaN check is implemented as src != src. C2's fixup stubs check for a NaN bit + * pattern directly, using the same number of cycles but using an extra general purpose + * register. + */ + UCOMIS.emit(masm, floatSize, src, src); + masm.jcc(AMD64Assembler.ConditionFlag.NoParity, isNotNaN, true); + masm.movl(dst, 0); + masm.jmp(done); + masm.bind(isNotNaN); + } + + if (canOverflow) { + /* + * if (src > 0.0) { result = MAX_VALUE; } + * + * We use an actual floating point compare, C2's stubs check the sign bit in a GPR. + */ + Register zero = asRegister(tmpValue); + masm.pxor(AVXKind.AVXSize.XMM, zero, zero); + UCOMIS.emit(masm, floatSize, src, zero); + masm.jcc(AMD64Assembler.ConditionFlag.BelowEqual, done, true); + /* + * MAX_VALUE is the bitwise negation of MIN_VALUE, which is already in dst. A negation + * takes the same number of cycles as a move, but its encoding is shorter. + */ + if (integerBytes == 4) { + masm.notl(dst); + } else { + masm.notq(dst); + } + } + + masm.bind(done); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java index 27c77878ccde..95a09e99196c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/ArithmeticLIRGeneratorTool.java @@ -31,7 +31,6 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.lir.LIRFrameState; import jdk.graal.compiler.lir.Variable; - import jdk.vm.ci.meta.Value; import jdk.vm.ci.meta.ValueKind; @@ -82,7 +81,18 @@ public interface ArithmeticLIRGeneratorTool { Value emitUShr(Value a, Value b); - Value emitFloatConvert(FloatConvert op, Value inputVal); + /** + * Emit a floating point to floating point, floating point to integer, or integer to floating + * point conversion. + * + * @param op the conversion to be performed + * @param inputVal the input value + * @param canBeNaN whether the input can be NaN; only relevant for floating point to integer + * conversions + * @param canOverflow whether the input can be infinite or otherwise outside the target type's + * range; only relevant for floating point to integer conversions + */ + Value emitFloatConvert(FloatConvert op, Value inputVal, boolean canBeNaN, boolean canOverflow); Value emitReinterpret(LIRKind to, Value inputVal); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/FloatConvertNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/FloatConvertNode.java index 5277eb6fbc20..c220e1d979f5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/FloatConvertNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/calc/FloatConvertNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. * 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,17 +32,17 @@ import jdk.graal.compiler.core.common.type.ArithmeticOpTable.UnaryOp; import jdk.graal.compiler.core.common.type.FloatStamp; import jdk.graal.compiler.core.common.type.IntegerStamp; +import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass; +import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool; +import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodes.NodeView; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.spi.ArithmeticLIRLowerable; import jdk.graal.compiler.nodes.spi.CanonicalizerTool; import jdk.graal.compiler.nodes.spi.Lowerable; import jdk.graal.compiler.nodes.spi.NodeLIRBuilderTool; -import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool; -import jdk.graal.compiler.nodeinfo.NodeInfo; - import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; @@ -108,6 +108,16 @@ public boolean isLossless() { } } + public boolean inputCanBeNaN() { + Stamp inputStamp = getValue().stamp(NodeView.DEFAULT); + return ArithmeticOpTable.forStamp(inputStamp).getFloatConvert(op).inputCanBeNaN(inputStamp); + } + + public boolean canOverflow() { + Stamp inputStamp = getValue().stamp(NodeView.DEFAULT); + return ArithmeticOpTable.forStamp(inputStamp).getFloatConvert(op).canOverflowInteger(inputStamp); + } + private static boolean isLosslessIntegerToFloatingPoint(IntegerStamp inputStamp, FloatStamp resultStamp) { int mantissaBits; switch (resultStamp.getBits()) { @@ -143,7 +153,7 @@ public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { @Override public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { - nodeValueMap.setResult(this, gen.emitFloatConvert(getFloatConvert(), nodeValueMap.operand(getValue()))); + nodeValueMap.setResult(this, gen.emitFloatConvert(getFloatConvert(), nodeValueMap.operand(getValue()), inputCanBeNaN(), canOverflow())); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64ConvertSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64ConvertSnippets.java deleted file mode 100644 index 2184524945e2..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64ConvertSnippets.java +++ /dev/null @@ -1,218 +0,0 @@ -/* - * 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 - * 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.graal.compiler.replacements.amd64; - -import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; -import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.probability; -import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.unknownProbability; - -import jdk.graal.compiler.api.replacements.Snippet; -import jdk.graal.compiler.core.common.calc.FloatConvert; -import jdk.graal.compiler.core.common.type.IntegerStamp; -import jdk.graal.compiler.nodes.AbstractBeginNode; -import jdk.graal.compiler.nodes.FixedNode; -import jdk.graal.compiler.nodes.GraphState.StageFlag; -import jdk.graal.compiler.nodes.NodeView; -import jdk.graal.compiler.nodes.PiNode; -import jdk.graal.compiler.nodes.SnippetAnchorNode; -import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.nodes.ValueNode; -import jdk.graal.compiler.nodes.calc.FloatConvertNode; -import jdk.graal.compiler.nodes.extended.GuardingNode; -import jdk.graal.compiler.nodes.spi.LoweringTool; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.util.Providers; -import jdk.graal.compiler.replacements.SnippetTemplate; -import jdk.graal.compiler.replacements.Snippets; - -/** - * Snippets used for conversion operations on AMD64 where the AMD64 instruction used does not match - * the semantics of the JVM specification. - */ -public class AMD64ConvertSnippets implements Snippets { - - /** - * Converts a float to an int. - *

- * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the - * conversion. If the float value is a NaN, infinity or if the result of the conversion is - * larger than {@link Integer#MAX_VALUE} then CVTTSS2SI returns {@link Integer#MIN_VALUE} and - * extra tests are required on the float value to return the correct int value. - * - * @param input the float being converted - */ - @Snippet - public static int f2i(float input) { - if (probability(SLOW_PATH_PROBABILITY, Float.isNaN(input))) { - return 0; - } - GuardingNode guard = SnippetAnchorNode.anchor(); - float nonNanInput = PiNode.piCastNonNanFloat(input, guard); - int result = AMD64FloatConvertNode.convertToInt(FloatConvert.F2I, nonNanInput); - if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) { - if (unknownProbability(input > 0.0d)) { - // input is positive -> return maxInt - return Integer.MAX_VALUE; - } - } - return result; - } - - /** - * Converts a float to a long. - *

- * This snippet accounts for the semantics of the x64 CVTTSS2SI instruction used to do the - * conversion. If the float value is a NaN or infinity then CVTTSS2SI returns - * {@link Long#MIN_VALUE} and extra tests are required on the float value to return the correct - * long value. - * - * @param input the float being converted - */ - @Snippet - public static long f2l(float input) { - if (probability(SLOW_PATH_PROBABILITY, Float.isNaN(input))) { - return 0; - } - GuardingNode guard = SnippetAnchorNode.anchor(); - float nonNanInput = PiNode.piCastNonNanFloat(input, guard); - long result = AMD64FloatConvertNode.convertToLong(FloatConvert.F2L, nonNanInput); - if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) { - if (unknownProbability(input > 0.0d)) { - // input is positive -> return maxInt - return Long.MAX_VALUE; - } - } - return result; - } - - /** - * Converts a double to an int. - *

- * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the - * conversion. If the double value is a NaN, infinity or if the result of the conversion is - * larger than {@link Integer#MAX_VALUE} then CVTTSD2SI returns {@link Integer#MIN_VALUE} and - * extra tests are required on the double value to return the correct int value. - * - * @param input the double being converted - */ - @Snippet - public static int d2i(double input) { - if (probability(SLOW_PATH_PROBABILITY, Double.isNaN(input))) { - return 0; - } - GuardingNode guard = SnippetAnchorNode.anchor(); - double nonNanInput = PiNode.piCastNonNanDouble(input, guard); - int result = AMD64FloatConvertNode.convertToInt(FloatConvert.D2I, nonNanInput); - if (probability(SLOW_PATH_PROBABILITY, result == Integer.MIN_VALUE)) { - if (unknownProbability(input > 0.0d)) { - // input is positive -> return maxInt - return Integer.MAX_VALUE; - } - } - return result; - } - - /** - * Converts a double to a long. - *

- * This snippet accounts for the semantics of the x64 CVTTSD2SI instruction used to do the - * conversion. If the double value is a NaN, infinity or if the result of the conversion is - * larger than {@link Long#MAX_VALUE} then CVTTSD2SI returns {@link Long#MIN_VALUE} and extra - * tests are required on the double value to return the correct long value. - * - * @param input the double being converted - */ - @Snippet - public static long d2l(double input) { - if (probability(SLOW_PATH_PROBABILITY, Double.isNaN(input))) { - return 0; - } - GuardingNode guard = SnippetAnchorNode.anchor(); - double nonNanInput = PiNode.piCastNonNanDouble(input, guard); - long result = AMD64FloatConvertNode.convertToLong(FloatConvert.D2L, nonNanInput); - if (probability(SLOW_PATH_PROBABILITY, result == Long.MIN_VALUE)) { - if (unknownProbability(input > 0.0d)) { - // input is positive -> return maxInt - return Long.MAX_VALUE; - } - } - return result; - } - - public static class Templates extends SnippetTemplate.AbstractTemplates { - - private final SnippetTemplate.SnippetInfo f2i; - private final SnippetTemplate.SnippetInfo f2l; - private final SnippetTemplate.SnippetInfo d2i; - private final SnippetTemplate.SnippetInfo d2l; - - @SuppressWarnings("this-escape") - public Templates(OptionValues options, Providers providers) { - super(options, providers); - - f2i = snippet(providers, AMD64ConvertSnippets.class, "f2i"); - f2l = snippet(providers, AMD64ConvertSnippets.class, "f2l"); - d2i = snippet(providers, AMD64ConvertSnippets.class, "d2i"); - d2l = snippet(providers, AMD64ConvertSnippets.class, "d2l"); - } - - public void lower(FloatConvertNode convert, LoweringTool tool) { - if (!convert.graph().isAfterStage(StageFlag.VALUE_PROXY_REMOVAL)) { - return; - } - - SnippetTemplate.SnippetInfo key; - StructuredGraph graph = convert.graph(); - switch (convert.getFloatConvert()) { - case F2I: - key = f2i; - break; - case F2L: - key = f2l; - break; - case D2I: - key = d2i; - break; - case D2L: - key = d2l; - break; - default: - return; - } - IntegerStamp oldRetStamp = (IntegerStamp) convert.stamp(NodeView.DEFAULT); - SnippetTemplate.Arguments args = new SnippetTemplate.Arguments(key, graph.getGuardsStage(), tool.getLoweringStage()); - args.add("input", convert.getValue()); - FixedNode oldNext = tool.lastFixedNode().next(); - SnippetTemplate template = template(tool, convert, args); - convert.getDebug().log("Lowering %s in %s: node=%s, template=%s, arguments=%s", convert.getFloatConvert(), graph, convert, template, args); - ValueNode replacer = template.instantiate(tool.getMetaAccess(), convert, SnippetTemplate.DEFAULT_REPLACER, tool, args); - convert.safeDelete(); - if (replacer.stamp(NodeView.DEFAULT).canBeImprovedWith(oldRetStamp)) { - PiNode pi = graph.addOrUnique(new PiNode(replacer, oldRetStamp, AbstractBeginNode.prevBegin(oldNext))); - replacer.replaceAtMatchingUsages(pi, x -> x != pi); - } - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64FloatConvertNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64FloatConvertNode.java deleted file mode 100644 index e6f4f877c1c3..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64FloatConvertNode.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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.graal.compiler.replacements.amd64; - -import static jdk.graal.compiler.nodeinfo.NodeCycles.CYCLES_8; -import static jdk.graal.compiler.nodeinfo.NodeSize.SIZE_1; -import static jdk.graal.compiler.nodes.calc.BinaryArithmeticNode.getArithmeticOpTable; - -import jdk.graal.compiler.core.common.NumUtil; -import jdk.graal.compiler.core.common.calc.FloatConvert; -import jdk.graal.compiler.core.common.type.ArithmeticOpTable; -import jdk.graal.compiler.core.common.type.ArithmeticOpTable.FloatConvertOp; -import jdk.graal.compiler.core.common.type.ArithmeticOpTable.UnaryOp; -import jdk.graal.compiler.core.common.type.FloatStamp; -import jdk.graal.compiler.core.common.type.IntegerStamp; -import jdk.graal.compiler.core.common.type.Stamp; -import jdk.graal.compiler.core.common.type.StampFactory; -import jdk.graal.compiler.debug.Assertions; -import jdk.graal.compiler.graph.NodeClass; -import jdk.graal.compiler.lir.gen.ArithmeticLIRGeneratorTool; -import jdk.graal.compiler.nodeinfo.NodeInfo; -import jdk.graal.compiler.nodes.ConstantNode; -import jdk.graal.compiler.nodes.NodeView; -import jdk.graal.compiler.nodes.ValueNode; -import jdk.graal.compiler.nodes.calc.FloatConvertNode; -import jdk.graal.compiler.nodes.calc.UnaryArithmeticNode; -import jdk.graal.compiler.nodes.spi.ArithmeticLIRLowerable; -import jdk.graal.compiler.nodes.spi.CanonicalizerTool; -import jdk.graal.compiler.nodes.spi.NodeLIRBuilderTool; -import jdk.vm.ci.meta.JavaConstant; - -/** - * This node has the semantics of the AMD64 floating point conversions. It is used in the lowering - * of the {@link FloatConvertNode} which, on AMD64 needs a {@link AMD64FloatConvertNode} plus some - * fixup code that handles the corner cases that differ between AMD64 and Java. - * - * Since this node evaluates to a special value if the conversion is inexact, its stamp must be - * modified to avoid optimizing away {@link AMD64ConvertSnippets}. - */ -@NodeInfo(cycles = CYCLES_8, size = SIZE_1) -public final class AMD64FloatConvertNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable { - public static final NodeClass TYPE = NodeClass.create(AMD64FloatConvertNode.class); - - /** - * Convert operation of this node. - */ - protected final FloatConvert op; - - public AMD64FloatConvertNode(FloatConvert op, ValueNode value) { - super(TYPE, getArithmeticOpTable(value).getFloatConvert(op), value); - this.op = op; - } - - @Override - protected UnaryOp getOp(ArithmeticOpTable table) { - return table.getFloatConvert(op); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isJavaConstant()) { - // This doesn't match the semantics of CVTTSS2SI but since this is only used by - // AMD64ConvertSnippets this will fold to still produce the right result. - UnaryOp floatConvertOp = getOp(getArithmeticOpTable(value)); - return ConstantNode.forPrimitive(floatConvertOp.foldStamp(forValue.stamp(NodeView.DEFAULT)), floatConvertOp.foldConstant(forValue.asConstant())); - } - // nothing to do - return this; - } - - @Override - public Stamp foldStamp(Stamp newStamp) { - Stamp resultStamp = super.foldStamp(newStamp); - /** - * The semantics of the x64 CVTTSD2SI - * https://frama-c.com/2013/10/09/Overflow-float-integer.html instruction allow returning - * MIN_VALUE (for convert to int Integer.MIN_VALUE, for covert to long Long.MIN_VALUE) in - * special cases. Those cases are - * - *

    - *
  • Input is NAN
  • - *
  • Input is infinity
  • * - *
  • Integral part of the floating point number is smaller MIN_VALUE or larger MAX_VALUE - * in which case an overflow happens during conversion
  • - *
- * - * We must ensure during stamp folding the special cases are considered and accounted for. - */ - if (resultStamp instanceof IntegerStamp integerStamp && newStamp instanceof FloatStamp inputStamp) { - final boolean canBeNan = inputStamp.canBeNaN(); - final boolean canBeInfinity = Double.isInfinite(inputStamp.lowerBound()) || Double.isInfinite(inputStamp.upperBound()); - final boolean conversionCanOverflow = integralPartLargerMaxValue(inputStamp, integerStamp) || integralPartSmallerMinValue(inputStamp, integerStamp); - final boolean canGenerateSpecialValue = canBeNan || canBeInfinity || conversionCanOverflow; - if (canGenerateSpecialValue) { - return resultStamp.meet(createInexactCaseStamp()); - } else { - return resultStamp; - } - } else { - return resultStamp.unrestricted(); - } - } - - private static boolean integralPartLargerMaxValue(FloatStamp stamp, IntegerStamp integerStamp) { - double upperBound = stamp.upperBound(); - if (Double.isInfinite(upperBound) || Double.isNaN(upperBound)) { - return true; - } - int bits = integerStamp.getBits(); - assert bits == 32 || bits == 64 : "Must be int or long " + Assertions.errorMessage(stamp, upperBound); - long maxValue = NumUtil.maxValue(bits); - /* - * There could be conversion loss here when casting maxValue from long to double - given - * that max can be Long.MAX_VALUE. In order to avoid checking if upperBound is large than - * max with arbitrary precision numbers (BigDecimal for example) we use some trick. - * - * (double) Long.MAX_VALUE is 9223372036854775808, which is 1 more than Long.MAX_VALUE. So - * (long) (double) Long.MAX_VALUE will already overflow. So we need upperBound >= (double) - * maxValue, with >= instead of >. The next lower double value is Math.nextDown((double) - * Long.MAX_VALUE) == 9223372036854774784, which fits into long. So if upperBound >= - * (double) maxValue does not hold, i.e., upperBound < (double) maxValue does hold, then - * (long) upperBound will not overflow. - */ - return upperBound >= maxValue; - } - - private static boolean integralPartSmallerMinValue(FloatStamp stamp, IntegerStamp integerStamp) { - double lowerBound = stamp.lowerBound(); - if (Double.isInfinite(lowerBound) || Double.isNaN(lowerBound)) { - return true; - } - int bits = integerStamp.getBits(); - assert bits == 32 || bits == 64 : "Must be int or long " + Assertions.errorMessage(stamp, lowerBound); - long minValue = NumUtil.minValue(bits); - return lowerBound <= minValue; - } - - private Stamp createInexactCaseStamp() { - IntegerStamp intStamp = (IntegerStamp) this.stamp; - long inexactValue = intStamp.getBits() <= 32 ? 0x8000_0000L : 0x8000_0000_0000_0000L; - return StampFactory.forConstant(JavaConstant.forPrimitiveInt(intStamp.getBits(), inexactValue)); - } - - @Override - public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { - nodeValueMap.setResult(this, gen.emitFloatConvert(op, nodeValueMap.operand(getValue()))); - } - - @NodeIntrinsic - public static native int convertToInt(@ConstantNodeParameter FloatConvert op, float input); - - @NodeIntrinsic - public static native long convertToLong(@ConstantNodeParameter FloatConvert op, float input); - - @NodeIntrinsic - public static native int convertToInt(@ConstantNodeParameter FloatConvert op, double input); - - @NodeIntrinsic - public static native long convertToLong(@ConstantNodeParameter FloatConvert op, double input); -} diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java index 2edd8bc5db68..f5a6a4a44778 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java @@ -1383,7 +1383,7 @@ private LLVMValueRef emitIntegerConvert(LLVMValueRef value, LLVMTypeRef type) { } @Override - public Value emitFloatConvert(FloatConvert op, Value inputVal) { + public Value emitFloatConvert(FloatConvert op, Value inputVal, boolean canBeNaN, boolean canOverflow) { LLVMTypeRef destType; switch (op) { case F2I: diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/amd64/AMD64NonSnippetLowerings.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/amd64/AMD64NonSnippetLowerings.java index a1810e57211d..4240a8a241a1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/amd64/AMD64NonSnippetLowerings.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/amd64/AMD64NonSnippetLowerings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,17 +27,13 @@ import java.util.Map; import java.util.function.Predicate; -import jdk.graal.compiler.graph.Node; -import jdk.graal.compiler.nodes.calc.FloatConvertNode; -import jdk.graal.compiler.nodes.spi.LoweringTool; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.util.Providers; -import jdk.graal.compiler.replacements.amd64.AMD64ConvertSnippets; - import com.oracle.svm.core.graal.meta.RuntimeConfiguration; import com.oracle.svm.core.graal.snippets.NodeLoweringProvider; import com.oracle.svm.core.graal.snippets.NonSnippetLowerings; +import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.util.Providers; import jdk.vm.ci.meta.ResolvedJavaMethod; final class AMD64NonSnippetLowerings extends NonSnippetLowerings { @@ -53,21 +49,5 @@ private AMD64NonSnippetLowerings(RuntimeConfiguration runtimeConfig, Predicate, NodeLoweringProvider> lowerings, boolean hosted) { super(runtimeConfig, mustNotAllocatePredicate, options, providers, lowerings, hosted); - - lowerings.put(FloatConvertNode.class, new FloatConvertLowering(options, providers)); - } - - private static class FloatConvertLowering implements NodeLoweringProvider { - - private final AMD64ConvertSnippets.Templates convertSnippets; - - FloatConvertLowering(OptionValues options, Providers providers) { - convertSnippets = new AMD64ConvertSnippets.Templates(options, providers); - } - - @Override - public void lower(FloatConvertNode node, LoweringTool tool) { - convertSnippets.lower(node, tool); - } } } From a3d430045336e2da3e59562a8f80e80f33f3ec37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Wed, 24 Jan 2024 13:08:42 +0100 Subject: [PATCH 31/75] Cleanups for review comments --- .../core/amd64/AMD64ArithmeticLIRGenerator.java | 6 +++--- ...onvertOp.java => AMD64ConvertFloatToIntegerOp.java} | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) rename compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/{AMD64FloatConvertOp.java => AMD64ConvertFloatToIntegerOp.java} (88%) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java index 05b00e89a84c..bc88b9b13a1d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/amd64/AMD64ArithmeticLIRGenerator.java @@ -123,7 +123,7 @@ import jdk.graal.compiler.lir.amd64.AMD64BinaryConsumer; import jdk.graal.compiler.lir.amd64.AMD64BitSwapOp; import jdk.graal.compiler.lir.amd64.AMD64ClearRegisterOp; -import jdk.graal.compiler.lir.amd64.AMD64FloatConvertOp; +import jdk.graal.compiler.lir.amd64.AMD64ConvertFloatToIntegerOp; import jdk.graal.compiler.lir.amd64.AMD64FloatToHalfFloatOp; import jdk.graal.compiler.lir.amd64.AMD64HalfFloatToFloatOp; import jdk.graal.compiler.lir.amd64.AMD64MathCopySignOp; @@ -824,8 +824,8 @@ private AllocatableValue emitConvertOp(LIRKind kind, AMD64MROp op, OperandSize s */ private AllocatableValue emitFloatConvertWithFixup(LIRKind kind, AMD64RMOp op, OperandSize size, Value input, boolean canBeNaN, boolean canOverflow) { Variable result = getLIRGen().newVariable(kind); - AMD64FloatConvertOp.OpcodeEmitter emitter = (crb, masm, dst, src) -> op.emit(masm, size, dst, src); - getLIRGen().append(new AMD64FloatConvertOp(getLIRGen(), emitter, result, input, canBeNaN, canOverflow)); + AMD64ConvertFloatToIntegerOp.OpcodeEmitter emitter = (crb, masm, dst, src) -> op.emit(masm, size, dst, src); + getLIRGen().append(new AMD64ConvertFloatToIntegerOp(getLIRGen(), emitter, result, input, canBeNaN, canOverflow)); return result; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java similarity index 88% rename from compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java rename to compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java index 5d51fb2d7493..202346f4ce87 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64FloatConvertOp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java @@ -40,6 +40,7 @@ import jdk.graal.compiler.lir.LIRInstructionClass; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import jdk.graal.compiler.lir.gen.LIRGeneratorTool; +import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.Value; @@ -52,8 +53,8 @@ * for NaNs and all values outside the integer type's range. So we need to fix up the result for * NaNs and positive overflowing values. Negative overflowing values keep {@code MIN_VALUE}. */ -public class AMD64FloatConvertOp extends AMD64LIRInstruction { - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64FloatConvertOp.class); +public class AMD64ConvertFloatToIntegerOp extends AMD64LIRInstruction { + public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64ConvertFloatToIntegerOp.class); @Def({REG}) protected Value dstValue; @Alive({REG}) protected Value srcValue; @@ -69,7 +70,7 @@ public interface OpcodeEmitter { void emit(CompilationResultBuilder crb, AMD64MacroAssembler masm, Register dst, Register src); } - public AMD64FloatConvertOp(LIRGeneratorTool tool, OpcodeEmitter opcode, Value dstValue, Value srcValue, boolean canBeNaN, boolean canOverflow) { + public AMD64ConvertFloatToIntegerOp(LIRGeneratorTool tool, OpcodeEmitter opcode, Value dstValue, Value srcValue, boolean canBeNaN, boolean canOverflow) { super(TYPE); this.dstValue = dstValue; this.srcValue = srcValue; @@ -77,6 +78,9 @@ public AMD64FloatConvertOp(LIRGeneratorTool tool, OpcodeEmitter opcode, Value ds this.tmpValue = canOverflow ? tool.newVariable(srcValue.getValueKind()) : Value.ILLEGAL; this.canBeNaN = canBeNaN; this.canOverflow = canOverflow; + + GraalError.guarantee(srcValue.getPlatformKind() instanceof AMD64Kind kind && kind.getVectorLength() == 1 && kind.isXMM(), "source must be scalar floating-point: %s", srcValue); + GraalError.guarantee(dstValue.getPlatformKind() instanceof AMD64Kind kind && kind.getVectorLength() == 1 && kind.isInteger(), "destination must be integer: %s", dstValue); } @Override From 88d521c82d08143048e2a60f25aaf64890bc9353 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gerg=C3=B6=20Barany?= Date: Wed, 24 Jan 2024 14:41:09 +0100 Subject: [PATCH 32/75] Move floating point to integer fixup path out of line --- .../amd64/AMD64ConvertFloatToIntegerOp.java | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java index 202346f4ce87..00eb931f22f6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64ConvertFloatToIntegerOp.java @@ -87,7 +87,7 @@ public AMD64ConvertFloatToIntegerOp(LIRGeneratorTool tool, OpcodeEmitter opcode, public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { Register dst = asRegister(dstValue); Register src = asRegister(srcValue); - Label isNotNaN = new Label(); + Label fixupPath = new Label(); Label done = new Label(); opcode.emit(crb, masm, dst, src); @@ -106,50 +106,58 @@ public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { }; /* - * if (dst != MIN_VALUE) { goto done; } + * if (dst == MIN_VALUE) { goto fixupPath; } */ if (integerBytes == 4) { - masm.cmplAndJcc(dst, Integer.MIN_VALUE, AMD64Assembler.ConditionFlag.NotEqual, done, true); + masm.cmplAndJcc(dst, Integer.MIN_VALUE, AMD64Assembler.ConditionFlag.Equal, fixupPath, false); } else { masm.cmpq(dst, (AMD64Address) crb.asLongConstRef(JavaConstant.forLong(Long.MIN_VALUE))); - masm.jcc(AMD64Assembler.ConditionFlag.NotEqual, done, true); + masm.jcc(AMD64Assembler.ConditionFlag.Equal, fixupPath); } - if (canBeNaN) { - /* - * if (isNaN(src)) { result = 0; goto done; } - * - * The isNaN check is implemented as src != src. C2's fixup stubs check for a NaN bit - * pattern directly, using the same number of cycles but using an extra general purpose - * register. - */ - UCOMIS.emit(masm, floatSize, src, src); - masm.jcc(AMD64Assembler.ConditionFlag.NoParity, isNotNaN, true); - masm.movl(dst, 0); - masm.jmp(done); - masm.bind(isNotNaN); - } + crb.getLIR().addSlowPath(this, () -> { + masm.bind(fixupPath); + + if (canBeNaN) { + /* + * if (isNaN(src)) { result = 0; goto done; } + * + * The isNaN check is implemented as src != src. C2's fixup stubs check for a NaN + * bit pattern directly, using the same number of cycles but using an extra general + * purpose register. + */ + Label isNotNaN = new Label(); + UCOMIS.emit(masm, floatSize, src, src); + masm.jcc(AMD64Assembler.ConditionFlag.NoParity, isNotNaN, true); + masm.movl(dst, 0); + masm.jmp(done); + masm.bind(isNotNaN); + } - if (canOverflow) { - /* - * if (src > 0.0) { result = MAX_VALUE; } - * - * We use an actual floating point compare, C2's stubs check the sign bit in a GPR. - */ - Register zero = asRegister(tmpValue); - masm.pxor(AVXKind.AVXSize.XMM, zero, zero); - UCOMIS.emit(masm, floatSize, src, zero); - masm.jcc(AMD64Assembler.ConditionFlag.BelowEqual, done, true); - /* - * MAX_VALUE is the bitwise negation of MIN_VALUE, which is already in dst. A negation - * takes the same number of cycles as a move, but its encoding is shorter. - */ - if (integerBytes == 4) { - masm.notl(dst); - } else { - masm.notq(dst); + if (canOverflow) { + /* + * if (src > 0.0) { result = MAX_VALUE; } + * + * We use an actual floating point compare, C2's stubs check the sign bit in a GPR. + */ + Register zero = asRegister(tmpValue); + masm.pxor(AVXKind.AVXSize.XMM, zero, zero); + UCOMIS.emit(masm, floatSize, src, zero); + masm.jcc(AMD64Assembler.ConditionFlag.BelowEqual, done); + /* + * MAX_VALUE is the bitwise negation of MIN_VALUE, which is already in dst. A + * negation takes the same number of cycles as a move, but its encoding is shorter. + */ + if (integerBytes == 4) { + masm.notl(dst); + } else { + masm.notq(dst); + } } - } + + /* Return to inline code. */ + masm.jmp(done); + }); masm.bind(done); } From b61e3d2ba12857da415d0b08fdd06a09a31ac312 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 22 Jan 2024 19:47:15 +0100 Subject: [PATCH 33/75] Enhance shading to support changing the destination path of included resources. --- sdk/mx.sdk/mx_sdk_shaded.py | 38 ++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/sdk/mx.sdk/mx_sdk_shaded.py b/sdk/mx.sdk/mx_sdk_shaded.py index e43bd6337676..f8c1583557ba 100644 --- a/sdk/mx.sdk/mx_sdk_shaded.py +++ b/sdk/mx.sdk/mx_sdk_shaded.py @@ -61,22 +61,28 @@ class ShadedLibraryProject(mx.JavaProject): ], "shade": { "packages" : { - # a list of package name/path prefixes that should be shaded. + # a dict of package name/path prefixes that should be shaded. # only .java/.class files that are in one of these packages are included. # package names must contain at least one '.' (i.e., two package parts). "old.pkg.name": "new.pkg.name", }, - "include" : [ - # a list of resource path patterns that should be copied. - # by default, only shaded .java/.class files are included. + "include" : { + # either: a list/set of path glob patterns of resources that should be copied. + # package-prefixed paths are automatically replaced according to "packages". "pkg/name/**", - ], + # or: a dict of resources that should be copied in the form of: + # {"path glob pattern" : {"path prefix" : "substitution"}} + "old/path/prefix/*.res" : { + "old/path/prefix" : "new/path/prefix", + }, + # by default, only shaded .java/.class files are included. + }, "exclude" : [ # a list of (re)source path patterns that should be excluded from the generated jar "**/*.html", ], "patch" : { - # a list of (re)source path patterns that should be patched with regex substitutions + # a dict of (re)source path patterns that should be patched with regex substitutions "pkg/name/my.properties" : { "" : "", }, @@ -121,7 +127,8 @@ def shaded_package_names(self): return self.shade.get('packages', {}) def included_paths(self): - return self.shade.get('include', []) + includes = self.shade.get('include', {}) + return includes if isinstance(includes, dict) else {i: None for i in includes} def excluded_paths(self): return self.shade.get('exclude', []) @@ -196,6 +203,8 @@ def _collect_files(self): continue for zipFilePath, outDir in [(srcFilePath, proj.source_gen_dir())]: + excludedPaths = proj.excluded_paths() + includedPaths = proj.included_paths() try: with zipfile.ZipFile(zipFilePath, 'r') as zf: for zi in zf.infolist(): @@ -204,12 +213,14 @@ def _collect_files(self): old_filename = zi.filename filepath = PurePosixPath(old_filename) - if any(glob_match(filepath, i) for i in proj.excluded_paths()): + if any(glob_match(filepath, i) for i in excludedPaths): continue - if filepath.suffix not in ['.java', '.class'] and not any(glob_match(filepath, i) for i in proj.included_paths()): + + path_mappings = None + if filepath.suffix not in ['.java', '.class'] and not any((i, path_mappings := m) for (i, m) in includedPaths.items() if glob_match(filepath, i)): continue - new_filename = proj.substitute_path(old_filename) + new_filename = proj.substitute_path(old_filename, mappings=path_mappings) src_gen_path = os.path.join(outDir, new_filename) if filepath.suffix == '.java': javafiles.setdefault(src_gen_path, os.path.join(binDir, new_filename[:-len('.java')] + '.class')) @@ -222,9 +233,9 @@ def _collect_files(self): def build(self): dist = self.subject shadedDeps = dist.shaded_deps() + excludedPaths = dist.excluded_paths() includedPaths = dist.included_paths() patch = dist.shade.get('patch', {}) - excludedPaths = dist.excluded_paths() binDir = dist.output_dir() srcDir = dist.source_gen_dir() @@ -261,11 +272,12 @@ def build(self): mx.logv(f'ignoring file {old_filename} (matches {", ".join(i for i in excludedPaths if glob_match(filepath, i))})') continue - if filepath.suffix not in ['.java', '.class'] and not any(glob_match(filepath, i) for i in includedPaths): + path_mappings = None + if filepath.suffix not in ['.java', '.class'] and not any((i, path_mappings := m) for (i, m) in includedPaths.items() if glob_match(filepath, i)): mx.warn(f'file {old_filename} is not included (if this is intended, please add the file to the exclude list)') continue - new_filename = dist.substitute_path(old_filename) + new_filename = dist.substitute_path(old_filename, mappings=path_mappings) applicableSubs = [] if filepath.suffix == '.java': From 886f5efb9da8b472d9ed0fd45d1edc02ada06535 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Pejovi=C4=87?= Date: Wed, 24 Jan 2024 22:54:00 +0100 Subject: [PATCH 34/75] Fix rbp handling when configuring registers on Windows --- .../svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java index 27db1e4c7331..bba26f71bb87 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64RegisterConfig.java @@ -69,7 +69,6 @@ import java.util.HashSet; import java.util.Set; -import jdk.graal.compiler.core.common.LIRKind; import org.graalvm.nativeimage.Platform; import com.oracle.svm.core.ReservedRegisters; @@ -83,6 +82,7 @@ import com.oracle.svm.core.graal.meta.SubstrateRegisterConfig; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.core.common.LIRKind; import jdk.vm.ci.amd64.AMD64; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.CallingConvention; @@ -154,7 +154,9 @@ public SubstrateAMD64RegisterConfig(ConfigKind config, MetaAccessProvider metaAc nativeParamsStackOffset = 4 * target.wordSize; regs.remove(ReservedRegisters.singleton().getFrameRegister()); - regs.remove(rbp); + if (useBasePointer) { + regs.remove(rbp); + } regs.remove(ReservedRegisters.singleton().getHeapBaseRegister()); regs.remove(ReservedRegisters.singleton().getThreadRegister()); allocatableRegs = new RegisterArray(regs); From 38cc7aa5e097a3f1335c4d7450363d92883e8455 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 2 Jan 2024 19:17:37 +0100 Subject: [PATCH 35/75] Add test constructing UnsupportedSpecializationException with null arrays. --- .../test/UnsupportedSpecializationTest.java | 34 ++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java index 82f7722d9c37..65bf738dafa0 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/UnsupportedSpecializationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -63,6 +63,38 @@ @SuppressWarnings({"truffle-inlining", "truffle-neverdefault", "truffle-sharing"}) public class UnsupportedSpecializationTest { + @Test + public void testNullNodesArray() { + var node = UnsupportedUncachedNodeGen.getUncached(); + var ex = new UnsupportedSpecializationException(node, null); + Assert.assertNotNull(ex.getSuppliedValues()); + Assert.assertNotNull(ex.getSuppliedNodes()); + Assert.assertEquals(0, ex.getSuppliedValues().length); + Assert.assertEquals(0, ex.getSuppliedNodes().length); + Assert.assertSame(node, ex.getNode()); + Assert.assertTrue(ex.getMessage(), ex.getMessage().contains("UnsupportedSpecializationTestFactory.UnsupportedUncachedNodeGen.Uncached")); + + var ey = new UnsupportedSpecializationException(null, null, 42d); + Assert.assertNotNull(ey.getSuppliedValues()); + Assert.assertNotNull(ey.getSuppliedNodes()); + Assert.assertEquals(1, ey.getSuppliedValues().length); + Assert.assertEquals(1, ey.getSuppliedNodes().length); + Assert.assertEquals(null, ey.getSuppliedNodes()[0]); + Assert.assertEquals(42d, ey.getSuppliedValues()[0]); + Assert.assertNull(ey.getNode()); + Assert.assertTrue(ey.getMessage(), ey.getMessage().contains("null")); + } + + @Test + public void testNullValuesArray() { + var node = UnsupportedUncachedNodeGen.getUncached(); + try { + Assert.assertNotNull(new UnsupportedSpecializationException(node, null, (Object[]) null)); + Assert.fail("should have thrown NullPointerException"); + } catch (NullPointerException npe) { + } + } + @Test public void testUnsupported1() { TestRootNode root = TestHelper.createRoot(Unsupported1Factory.getInstance()); From 7b109aa6073ad9122f9f4eda84c78e0a30e5fda6 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 26 Oct 2023 23:04:02 +0200 Subject: [PATCH 36/75] Outline new UnsupportedSpecializationException from uncached execute methods. --- .../generator/FlatNodeGenFactory.java | 115 +++++++++++++----- .../processor/generator/HelperMethods.java | 66 ++++++++++ .../dsl/processor/java/ElementUtils.java | 16 ++- .../processor/library/ExportsGenerator.java | 7 +- 4 files changed, 171 insertions(+), 33 deletions(-) create mode 100644 truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index 65da35371937..16458d45cf8c 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -88,6 +88,7 @@ import java.util.Set; import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; +import java.util.stream.Collectors; import javax.lang.model.element.AnnotationMirror; import javax.lang.model.element.Element; @@ -1183,6 +1184,7 @@ public CodeTypeElement create(CodeTypeElement clazz) { if (node.isUncachable() && node.isGenerateUncached()) { CodeTypeElement uncached = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, STATIC, FINAL), "Uncached", node.getTemplateType().asType()); + HelperMethods helperMethods = new HelperMethods(); uncached.getEnclosedElements().addAll(createUncachedFields()); uncached.addAnnotationMirror(new CodeAnnotationMirror(types.DenyReplace)); @@ -1212,15 +1214,15 @@ public CodeTypeElement create(CodeTypeElement clazz) { } for (ExecutableTypeData type : genericExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); } for (ExecutableTypeData type : specializedExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); } for (ExecutableTypeData type : voidExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); } if ((cost == null || cost.equals("MONOMORPHIC") /* the default */) && isUndeclaredOrOverrideable(uncached, "getCost")) { @@ -1230,6 +1232,8 @@ public CodeTypeElement create(CodeTypeElement clazz) { isAdoptable.createBuilder().returnFalse(); uncached.add(isAdoptable); + helperMethods.appendToClass(uncached); + clazz.add(uncached); GeneratedTypeMirror uncachedType = new GeneratedTypeMirror("", uncached.getSimpleName().toString()); CodeVariableElement uncachedField = clazz.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), uncachedType, "UNCACHED")); @@ -2773,7 +2777,7 @@ private CodeExecutableElement createExecute(CodeTypeElement clazz, ExecutableTyp return method; } - public CodeExecutableElement createUncached() { + public CodeExecutableElement createUncached(HelperMethods helperMethods) { SpecializationData fallback = node.getFallbackSpecialization(); TypeMirror returnType = fallback.getReturnType().getType(); List parameterTypes = new ArrayList<>(); @@ -2781,10 +2785,10 @@ public CodeExecutableElement createUncached() { parameterTypes.add(parameter.getType()); } ExecutableTypeData forType = new ExecutableTypeData(node, returnType, "uncached", null, parameterTypes); - return createUncachedExecute(forType); + return createUncachedExecute(forType, helperMethods); } - private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType) { + private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType, HelperMethods helperMethods) { final Collection allSpecializations = node.computeUncachedSpecializations(node.getReachableSpecializations()); final List compatibleSpecializations = filterCompatibleSpecializations(allSpecializations, forType); @@ -2835,7 +2839,7 @@ private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType) FrameState originalFrameState = frameState.copy(); builder.tree(visitSpecializationGroup(builder, null, group, forType, frameState, allSpecializations)); if (group.hasFallthrough()) { - builder.tree(createThrowUnsupported(builder, originalFrameState)); + builder.tree(createThrowUnsupported(builder, originalFrameState, true, helperMethods)); } generateTraceOnExceptionEnd(builder); } @@ -3265,44 +3269,95 @@ private static String getSetNewName(BitSet bitSet) { return "new" + ElementUtils.firstLetterUpperCase(bitSet.getName()); } - private CodeTree createThrowUnsupported(final CodeTreeBuilder parent, final FrameState frameState) { - CodeTreeBuilder builder = parent.create(); - builder.startThrow().startNew(types.UnsupportedSpecializationException); - ExecutableElement method = parent.findMethod(); - if (method != null && method.getModifiers().contains(STATIC)) { - builder.string("null"); - } else { - builder.string("this"); - } + private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState) { + return createThrowUnsupported(parent, frameState, false, null); + } - boolean hasNodes = false; - List nodes = new ArrayList<>(); - List values = new ArrayList<>(); + /** + * Throws an UnsupportedSpecializationException, optionally outlining the allocations when + * called from an uncached node execute method. + */ + private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState, boolean uncachedExecute, HelperMethods helperMethods) { + List nodes = new ArrayList<>(); + List locals = new ArrayList<>(); for (NodeExecutionData execution : node.getChildExecutions()) { NodeChildData child = execution.getChild(); LocalVariable var = frameState.getValue(execution); if (child != null && !frameState.getMode().isUncached()) { - hasNodes = true; - nodes.add(CodeTreeBuilder.singleString(accessNodeField(execution))); + nodes.add(accessNodeField(execution)); } else { - nodes.add(CodeTreeBuilder.singleString("null")); + nodes.add("null"); } if (var != null) { - values.add(var.createReference()); + locals.add(var); } } - if (hasNodes) { - builder.startNewArray(new ArrayCodeTypeMirror(types.Node), null); - builder.trees(nodes.toArray(new CodeTree[0])); + CodeExecutableElement parentMethod = (CodeExecutableElement) parent.findMethod(); + boolean isStaticMethod = parentMethod != null && parentMethod.getModifiers().contains(STATIC); + + boolean outline = uncachedExecute && parentMethod != null && helperMethods != null; + if (outline) { + boolean hasPrimitives = locals.stream().anyMatch(local -> local.getTypeMirror().getKind().isPrimitive()); + boolean needsBoundary = ElementUtils.findAnnotationMirror(parentMethod, types.CompilerDirectives_TruffleBoundary) == null; + String signatureId = (isStaticMethod ? "Static" : "") + + (needsBoundary ? "Boundary" : "") + + locals.size() + + (hasPrimitives ? locals.stream().map(l -> ElementUtils.basicTypeId(l.typeMirror)).collect(Collectors.joining()) : ""); + String throwMethodName = "newUnsupportedSpecializationException" + signatureId; + + helperMethods.add(throwMethodName, () -> { + Set throwMethodModifiers = modifiers(PRIVATE); + if (isStaticMethod) { + throwMethodModifiers.add(STATIC); + } + CodeExecutableElement throwMethod = new CodeExecutableElement(throwMethodModifiers, types.UnsupportedSpecializationException, throwMethodName); + for (LocalVariable local : locals) { + TypeMirror erasedType = ElementUtils.isPrimitive(local.getTypeMirror()) ? local.getTypeMirror() : context.getType(Object.class); + throwMethod.addParameter(local.newType(erasedType).createParameter()); + } + + CodeTreeBuilder builder = throwMethod.createBuilder(); + if (needsBoundary) { + GeneratorUtils.addBoundaryOrTransferToInterpreter(throwMethod, builder); + } + builder.startReturn(); + newUnsupportedSpecializationException(builder, nodes, locals, isStaticMethod, var -> CodeTreeBuilder.singleString(var.getName())); + builder.end(); + return throwMethod; + }); + + CodeTreeBuilder callBuilder = parent.create(); + callBuilder.startThrow().startCall(throwMethodName); + callBuilder.trees(locals.stream().map(var -> var.createReference()).toArray(CodeTree[]::new)); + callBuilder.end().end(); + return callBuilder.build(); + } else { + CodeTreeBuilder builder = parent.create(); + builder.startThrow(); + newUnsupportedSpecializationException(builder, nodes, locals, isStaticMethod, var -> var.createReference()); builder.end(); + return builder.build(); + } + } + + private void newUnsupportedSpecializationException(CodeTreeBuilder builder, List nodes, List locals, boolean staticMethod, Function localMapper) { + builder.startNew(types.UnsupportedSpecializationException); + if (staticMethod) { + builder.string("null"); } else { + builder.string("this"); + } + boolean allNodesNull = nodes.stream().allMatch(n -> "null".equals(n)); + if (allNodesNull) { builder.nullLiteral(); + } else { + builder.startNewArray(new ArrayCodeTypeMirror(types.Node), null); + builder.trees(nodes.stream().map(CodeTreeBuilder::singleString).toArray(CodeTree[]::new)); + builder.end(); } - builder.trees(values.toArray(new CodeTree[0])); - builder.end().end(); - return builder.build(); - + builder.trees(locals.stream().map(localMapper).toArray(CodeTree[]::new)); + builder.end(); } private CodeTree createFastPath(CodeTreeBuilder parent, List allSpecializations, SpecializationGroup originalGroup, final ExecutableTypeData currentType, diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java new file mode 100644 index 000000000000..e6d402862348 --- /dev/null +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.truffle.dsl.processor.generator; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.function.Supplier; + +import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; +import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; + +/** + * Helper methods per generated node class. + */ +public final class HelperMethods { + + private final Map helperMethods = new LinkedHashMap<>(); + + public void appendToClass(CodeTypeElement clazz) { + clazz.getEnclosedElements().addAll(helperMethods.values()); + helperMethods.clear(); + } + + public void add(String name, Supplier method) { + helperMethods.computeIfAbsent(name, k -> method.get()); + } + +} diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java index bcfc6e45b9ce..d16955e0e05b 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/ElementUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -1809,6 +1809,20 @@ public static String getBinaryName(TypeElement provider) { } } + public static String basicTypeId(TypeMirror type) { + return switch (type.getKind()) { + case BOOLEAN -> "Z"; + case BYTE -> "B"; + case SHORT -> "S"; + case INT -> "I"; + case LONG -> "J"; + case CHAR -> "C"; + case FLOAT -> "F"; + case DOUBLE -> "D"; + default -> "L"; + }; + } + public static final int COMPRESSED_POINTER_SIZE = 4; public static final int COMPRESSED_HEADER_SIZE = 12; diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java index 711e7ce6d87b..d654ea6720f3 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -86,6 +86,7 @@ import com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory; import com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory.GeneratorMode; import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; +import com.oracle.truffle.dsl.processor.generator.HelperMethods; import com.oracle.truffle.dsl.processor.generator.NodeConstants; import com.oracle.truffle.dsl.processor.generator.StaticConstants; import com.oracle.truffle.dsl.processor.java.ElementUtils; @@ -1293,6 +1294,7 @@ CodeTypeElement createUncached(ExportsLibrary libraryExports, Map Date: Wed, 24 Jan 2024 18:22:08 +0100 Subject: [PATCH 37/75] Move static helper methods to NodeConstants. --- .../generator/FlatNodeGenFactory.java | 52 +++++++-------- .../processor/generator/HelperMethods.java | 66 ------------------- .../processor/generator/NodeConstants.java | 16 ++++- .../processor/library/ExportsGenerator.java | 5 +- 4 files changed, 37 insertions(+), 102 deletions(-) delete mode 100644 truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index 16458d45cf8c..d056a71ef783 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -1184,7 +1184,6 @@ public CodeTypeElement create(CodeTypeElement clazz) { if (node.isUncachable() && node.isGenerateUncached()) { CodeTypeElement uncached = GeneratorUtils.createClass(node, null, modifiers(PRIVATE, STATIC, FINAL), "Uncached", node.getTemplateType().asType()); - HelperMethods helperMethods = new HelperMethods(); uncached.getEnclosedElements().addAll(createUncachedFields()); uncached.addAnnotationMirror(new CodeAnnotationMirror(types.DenyReplace)); @@ -1214,15 +1213,15 @@ public CodeTypeElement create(CodeTypeElement clazz) { } for (ExecutableTypeData type : genericExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); } for (ExecutableTypeData type : specializedExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); } for (ExecutableTypeData type : voidExecutableTypes) { - wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type, helperMethods))); + wrapWithTraceOnReturn(uncached.add(createUncachedExecute(type))); } if ((cost == null || cost.equals("MONOMORPHIC") /* the default */) && isUndeclaredOrOverrideable(uncached, "getCost")) { @@ -1232,8 +1231,6 @@ public CodeTypeElement create(CodeTypeElement clazz) { isAdoptable.createBuilder().returnFalse(); uncached.add(isAdoptable); - helperMethods.appendToClass(uncached); - clazz.add(uncached); GeneratedTypeMirror uncachedType = new GeneratedTypeMirror("", uncached.getSimpleName().toString()); CodeVariableElement uncachedField = clazz.add(new CodeVariableElement(modifiers(PRIVATE, STATIC, FINAL), uncachedType, "UNCACHED")); @@ -2777,7 +2774,7 @@ private CodeExecutableElement createExecute(CodeTypeElement clazz, ExecutableTyp return method; } - public CodeExecutableElement createUncached(HelperMethods helperMethods) { + public CodeExecutableElement createUncached() { SpecializationData fallback = node.getFallbackSpecialization(); TypeMirror returnType = fallback.getReturnType().getType(); List parameterTypes = new ArrayList<>(); @@ -2785,10 +2782,10 @@ public CodeExecutableElement createUncached(HelperMethods helperMethods) { parameterTypes.add(parameter.getType()); } ExecutableTypeData forType = new ExecutableTypeData(node, returnType, "uncached", null, parameterTypes); - return createUncachedExecute(forType, helperMethods); + return createUncachedExecute(forType); } - private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType, HelperMethods helperMethods) { + private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType) { final Collection allSpecializations = node.computeUncachedSpecializations(node.getReachableSpecializations()); final List compatibleSpecializations = filterCompatibleSpecializations(allSpecializations, forType); @@ -2839,7 +2836,7 @@ private CodeExecutableElement createUncachedExecute(ExecutableTypeData forType, FrameState originalFrameState = frameState.copy(); builder.tree(visitSpecializationGroup(builder, null, group, forType, frameState, allSpecializations)); if (group.hasFallthrough()) { - builder.tree(createThrowUnsupported(builder, originalFrameState, true, helperMethods)); + builder.tree(createThrowUnsupported(builder, originalFrameState, true)); } generateTraceOnExceptionEnd(builder); } @@ -3270,14 +3267,14 @@ private static String getSetNewName(BitSet bitSet) { } private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState) { - return createThrowUnsupported(parent, frameState, false, null); + return createThrowUnsupported(parent, frameState, false); } /** * Throws an UnsupportedSpecializationException, optionally outlining the allocations when * called from an uncached node execute method. */ - private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState, boolean uncachedExecute, HelperMethods helperMethods) { + private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState, boolean uncachedExecute) { List nodes = new ArrayList<>(); List locals = new ArrayList<>(); for (NodeExecutionData execution : node.getChildExecutions()) { @@ -3295,23 +3292,21 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame CodeExecutableElement parentMethod = (CodeExecutableElement) parent.findMethod(); boolean isStaticMethod = parentMethod != null && parentMethod.getModifiers().contains(STATIC); + boolean allNodesNull = nodes.stream().allMatch("null"::equals); - boolean outline = uncachedExecute && parentMethod != null && helperMethods != null; + boolean outline = uncachedExecute && parentMethod != null && allNodesNull; if (outline) { boolean hasPrimitives = locals.stream().anyMatch(local -> local.getTypeMirror().getKind().isPrimitive()); boolean needsBoundary = ElementUtils.findAnnotationMirror(parentMethod, types.CompilerDirectives_TruffleBoundary) == null; - String signatureId = (isStaticMethod ? "Static" : "") + - (needsBoundary ? "Boundary" : "") + + String signatureId = (needsBoundary ? "Boundary" : "") + locals.size() + (hasPrimitives ? locals.stream().map(l -> ElementUtils.basicTypeId(l.typeMirror)).collect(Collectors.joining()) : ""); String throwMethodName = "newUnsupportedSpecializationException" + signatureId; - helperMethods.add(throwMethodName, () -> { - Set throwMethodModifiers = modifiers(PRIVATE); - if (isStaticMethod) { - throwMethodModifiers.add(STATIC); - } - CodeExecutableElement throwMethod = new CodeExecutableElement(throwMethodModifiers, types.UnsupportedSpecializationException, throwMethodName); + nodeConstants.addHelperMethod(throwMethodName, () -> { + CodeExecutableElement throwMethod = new CodeExecutableElement(modifiers(PRIVATE, STATIC), types.UnsupportedSpecializationException, throwMethodName); + String thisNodeParamName = "thisNode_"; + throwMethod.addParameter(new LocalVariable(types.Node, thisNodeParamName, null).createParameter()); for (LocalVariable local : locals) { TypeMirror erasedType = ElementUtils.isPrimitive(local.getTypeMirror()) ? local.getTypeMirror() : context.getType(Object.class); throwMethod.addParameter(local.newType(erasedType).createParameter()); @@ -3322,33 +3317,30 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame GeneratorUtils.addBoundaryOrTransferToInterpreter(throwMethod, builder); } builder.startReturn(); - newUnsupportedSpecializationException(builder, nodes, locals, isStaticMethod, var -> CodeTreeBuilder.singleString(var.getName())); + newUnsupportedSpecializationException(builder, nodes, locals, thisNodeParamName, var -> CodeTreeBuilder.singleString(var.getName())); builder.end(); return throwMethod; }); CodeTreeBuilder callBuilder = parent.create(); callBuilder.startThrow().startCall(throwMethodName); + callBuilder.string(isStaticMethod ? "null" : "this"); callBuilder.trees(locals.stream().map(var -> var.createReference()).toArray(CodeTree[]::new)); callBuilder.end().end(); return callBuilder.build(); } else { CodeTreeBuilder builder = parent.create(); builder.startThrow(); - newUnsupportedSpecializationException(builder, nodes, locals, isStaticMethod, var -> var.createReference()); + newUnsupportedSpecializationException(builder, nodes, locals, isStaticMethod ? "null" : "this", var -> var.createReference()); builder.end(); return builder.build(); } } - private void newUnsupportedSpecializationException(CodeTreeBuilder builder, List nodes, List locals, boolean staticMethod, Function localMapper) { + private void newUnsupportedSpecializationException(CodeTreeBuilder builder, List nodes, List locals, String nodeRef, Function localMapper) { builder.startNew(types.UnsupportedSpecializationException); - if (staticMethod) { - builder.string("null"); - } else { - builder.string("this"); - } - boolean allNodesNull = nodes.stream().allMatch(n -> "null".equals(n)); + builder.string(nodeRef); + boolean allNodesNull = nodes.stream().allMatch("null"::equals); if (allNodesNull) { builder.nullLiteral(); } else { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java deleted file mode 100644 index e6d402862348..000000000000 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/HelperMethods.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * The Universal Permissive License (UPL), Version 1.0 - * - * Subject to the condition set forth below, permission is hereby granted to any - * person obtaining a copy of this software, associated documentation and/or - * data (collectively the "Software"), free of charge and under any and all - * copyright rights in the Software, and any and all patent rights owned or - * freely licensable by each licensor hereunder covering either (i) the - * unmodified Software as contributed to or provided by such licensor, or (ii) - * the Larger Works (as defined below), to deal in both - * - * (a) the Software, and - * - * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if - * one is included with the Software each a "Larger Work" to which the Software - * is contributed by such licensors), - * - * without restriction, including without limitation the rights to copy, create - * derivative works of, display, perform, and distribute the Software and make, - * use, sell, offer for sale, import, export, have made, and have sold the - * Software and the Larger Work(s), and to sublicense the foregoing rights on - * either these or other terms. - * - * This license is subject to the following condition: - * - * The above copyright notice and either this complete permission notice or at a - * minimum a reference to the UPL must be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -package com.oracle.truffle.dsl.processor.generator; - -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.function.Supplier; - -import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; -import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; - -/** - * Helper methods per generated node class. - */ -public final class HelperMethods { - - private final Map helperMethods = new LinkedHashMap<>(); - - public void appendToClass(CodeTypeElement clazz) { - clazz.getEnclosedElements().addAll(helperMethods.values()); - helperMethods.clear(); - } - - public void add(String name, Supplier method) { - helperMethods.computeIfAbsent(name, k -> method.get()); - } - -} diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java index 1d16b0dc9b5f..d0043fdd563e 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -42,20 +42,32 @@ import java.util.LinkedHashMap; import java.util.Map; +import java.util.function.Supplier; +import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; import com.oracle.truffle.dsl.processor.java.model.CodeVariableElement; /** - * Constants per generated specialized node. + * Constants and helper methods per generated specialized node. */ public final class NodeConstants { public final Map updaterReferences = new LinkedHashMap<>(); + private final Map helperMethods = new LinkedHashMap<>(); public void prependToClass(CodeTypeElement clazz) { + // prepend constant fields. clazz.getEnclosedElements().addAll(0, updaterReferences.values()); updaterReferences.clear(); + + // append helper methods + clazz.getEnclosedElements().addAll(helperMethods.values()); + helperMethods.clear(); + } + + public void addHelperMethod(String name, Supplier method) { + helperMethods.computeIfAbsent(name, k -> method.get()); } } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java index d654ea6720f3..0aa4a9f5a0a6 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java @@ -86,7 +86,6 @@ import com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory; import com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory.GeneratorMode; import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; -import com.oracle.truffle.dsl.processor.generator.HelperMethods; import com.oracle.truffle.dsl.processor.generator.NodeConstants; import com.oracle.truffle.dsl.processor.generator.StaticConstants; import com.oracle.truffle.dsl.processor.java.ElementUtils; @@ -1294,7 +1293,6 @@ CodeTypeElement createUncached(ExportsLibrary libraryExports, Map Date: Wed, 24 Jan 2024 18:31:46 +0100 Subject: [PATCH 38/75] Rename prependToClass to addToClass. --- .../truffle/dsl/processor/generator/NodeCodeGenerator.java | 4 ++-- .../oracle/truffle/dsl/processor/generator/NodeConstants.java | 2 +- .../truffle/dsl/processor/library/ExportsGenerator.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java index 1e0c29476fbd..c115eeb892be 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -295,7 +295,7 @@ private static List generateNodes(ProcessorContext context, Nod t.addSuppressed(e); throw t; } - nodeConstants.prependToClass(type); + nodeConstants.addToClass(type); return Arrays.asList(type); } diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java index d0043fdd563e..9f2708c126bf 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeConstants.java @@ -56,7 +56,7 @@ public final class NodeConstants { public final Map updaterReferences = new LinkedHashMap<>(); private final Map helperMethods = new LinkedHashMap<>(); - public void prependToClass(CodeTypeElement clazz) { + public void addToClass(CodeTypeElement clazz) { // prepend constant fields. clazz.getEnclosedElements().addAll(0, updaterReferences.values()); updaterReferences.clear(); diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java index 0aa4a9f5a0a6..25596b4b0c4c 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/library/ExportsGenerator.java @@ -915,7 +915,7 @@ CodeTypeElement createCached(ExportsLibrary libraryExports, Map Date: Thu, 25 Jan 2024 01:13:33 +0100 Subject: [PATCH 39/75] Always add TruffleBoundary to outlined newUnsupportedSpecializationException method. --- .../dsl/processor/generator/FlatNodeGenFactory.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index d056a71ef783..9edaaec20013 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -3297,9 +3297,7 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame boolean outline = uncachedExecute && parentMethod != null && allNodesNull; if (outline) { boolean hasPrimitives = locals.stream().anyMatch(local -> local.getTypeMirror().getKind().isPrimitive()); - boolean needsBoundary = ElementUtils.findAnnotationMirror(parentMethod, types.CompilerDirectives_TruffleBoundary) == null; - String signatureId = (needsBoundary ? "Boundary" : "") + - locals.size() + + String signatureId = locals.size() + (hasPrimitives ? locals.stream().map(l -> ElementUtils.basicTypeId(l.typeMirror)).collect(Collectors.joining()) : ""); String throwMethodName = "newUnsupportedSpecializationException" + signatureId; @@ -3313,9 +3311,7 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame } CodeTreeBuilder builder = throwMethod.createBuilder(); - if (needsBoundary) { - GeneratorUtils.addBoundaryOrTransferToInterpreter(throwMethod, builder); - } + GeneratorUtils.addBoundaryOrTransferToInterpreter(throwMethod, builder); builder.startReturn(); newUnsupportedSpecializationException(builder, nodes, locals, thisNodeParamName, var -> CodeTreeBuilder.singleString(var.getName())); builder.end(); From fb87294dbf077ae88e836e37e99e1190dd33f0bb Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 25 Jan 2024 01:16:00 +0100 Subject: [PATCH 40/75] Share newUnsupportedSpecializationException method between Uncached and Inlined node, if any. --- .../truffle/dsl/processor/generator/FlatNodeGenFactory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java index 9edaaec20013..b70742a8eec6 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/FlatNodeGenFactory.java @@ -3027,7 +3027,7 @@ private CodeExecutableElement createExecuteAndSpecialize(boolean inlined) { builder.tree(execution); if (group.hasFallthrough()) { - builder.tree(createThrowUnsupported(builder, originalFrameState)); + builder.tree(createThrowUnsupported(builder, originalFrameState, inlined && node.isGenerateUncached())); } if (reportPolymorphismAction.required()) { @@ -3274,7 +3274,7 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame * Throws an UnsupportedSpecializationException, optionally outlining the allocations when * called from an uncached node execute method. */ - private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState, boolean uncachedExecute) { + private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frameState, boolean outlineIfPossible) { List nodes = new ArrayList<>(); List locals = new ArrayList<>(); for (NodeExecutionData execution : node.getChildExecutions()) { @@ -3294,7 +3294,7 @@ private CodeTree createThrowUnsupported(CodeTreeBuilder parent, FrameState frame boolean isStaticMethod = parentMethod != null && parentMethod.getModifiers().contains(STATIC); boolean allNodesNull = nodes.stream().allMatch("null"::equals); - boolean outline = uncachedExecute && parentMethod != null && allNodesNull; + boolean outline = outlineIfPossible && parentMethod != null && allNodesNull; if (outline) { boolean hasPrimitives = locals.stream().anyMatch(local -> local.getTypeMirror().getKind().isPrimitive()); String signatureId = locals.size() + From d5ab9f1761050c2915fcd045c0b4780c9866acb6 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 25 Jan 2024 08:12:06 +0100 Subject: [PATCH 41/75] Remove old heap dump implementation. --- .../AllocationFreeFileOutputStreamPosix.java | 151 -- .../heapdump/AllocationFreeOutputStream.java | 49 - .../core/heapdump/HeapDumpSupportImpl.java | 54 - .../svm/core/heapdump/HeapDumpUtils.java | 352 ---- .../svm/core/heapdump/HeapDumpWriter.java | 56 - .../svm/core/heapdump/HeapDumpWriterImpl.java | 1762 ----------------- .../UninterruptibleAnnotationChecker.java | 32 +- .../svm/hosted/heap/HeapDumpFeature.java | 45 +- .../svm/hosted/heap/HeapDumpHostedUtils.java | 141 -- 9 files changed, 19 insertions(+), 2623 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/heapdump/AllocationFreeFileOutputStreamPosix.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/AllocationFreeOutputStream.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpSupportImpl.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpUtils.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriter.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriterImpl.java delete mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpHostedUtils.java diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/heapdump/AllocationFreeFileOutputStreamPosix.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/heapdump/AllocationFreeFileOutputStreamPosix.java deleted file mode 100644 index 64298d6cc20e..000000000000 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/heapdump/AllocationFreeFileOutputStreamPosix.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.posix.heapdump; - -import java.io.FileDescriptor; -import java.io.FileOutputStream; -import java.io.IOException; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.c.type.CCharPointer; -import org.graalvm.word.WordFactory; - -import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import com.oracle.svm.core.graal.stackvalue.UnsafeStackValue; -import com.oracle.svm.core.heapdump.HeapDumpWriterImpl.AllocationFreeFileOutputStream; -import com.oracle.svm.core.posix.PosixUtils; -import com.oracle.svm.core.posix.headers.Unistd; -import com.oracle.svm.core.util.VMError; - -/** - * Legacy implementation, only used by other legacy code (see GR-44538). - * - * Posix implementation of allocation-free output stream created from FileOutputStream. - * - * The limitation to Linux and Darwin is necessary because the implementation currently uses - * posix-dependent low-level code. See GR-9725. - */ -@AutomaticallyRegisteredImageSingleton(AllocationFreeFileOutputStream.class) -@Platforms({Platform.LINUX.class, Platform.DARWIN.class}) -final class AllocationFreeFileOutputStreamPosix extends AllocationFreeFileOutputStream { - - /** - * Pre-allocated exceptions, for throwing from code that must not allocate. - */ - private static final IOException preallocatedIOException = new IOException("Write failed."); - private static final ArrayIndexOutOfBoundsException preallocatedArrayIndexOutOfBoundsException = new ArrayIndexOutOfBoundsException(); - - private FileOutputStream fos; - private FileDescriptor fileDescriptor; - - AllocationFreeFileOutputStreamPosix() { - - } - - private AllocationFreeFileOutputStreamPosix(FileOutputStream fileOutputStream) throws IOException { - fos = fileOutputStream; - fileDescriptor = fos.getFD(); - - if (!(Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.DARWIN.class))) { - /* See GR-9725 */ - throw VMError.unsupportedFeature("Heap dump writing currently contains Posix specific code"); - } - } - - @Override - public AllocationFreeFileOutputStream newStreamFor(FileOutputStream fileOutputStream) throws IOException { - return new AllocationFreeFileOutputStreamPosix(fileOutputStream); - } - - @Override - public void write(int b) throws IOException { - final CCharPointer buffer = UnsafeStackValue.get(CCharPointer.class); - buffer.write((byte) b); - final boolean writeResult = PosixUtils.writeBytes(fileDescriptor, buffer, WordFactory.unsigned(1)); - if (!writeResult) { - throw preallocatedIOException; - } - } - - @Override - public void write(byte[] b, int off, int len) throws IOException { - /* Sanity check the arguments. */ - if ((b == null) || ((off < 0) || (len < 0) || ((b.length - off) < len))) { - throw preallocatedArrayIndexOutOfBoundsException; - } - - /* - * Stack allocation needs an allocation size that is a compile time constant, so we split - * the byte array up in multiple chunks and write them separately. - */ - final int chunkSize = 256; - final CCharPointer bytes = UnsafeStackValue.get(chunkSize); - - int chunkOffset = off; - int inputLength = len; - while (inputLength > 0) { - int chunkLength = Math.min(inputLength, chunkSize); - - for (int i = 0; i < chunkLength; i++) { - bytes.write(i, b[chunkOffset + i]); - } - - if (!PosixUtils.writeBytes(fileDescriptor, bytes, WordFactory.unsigned(chunkLength))) { - throw preallocatedIOException; - } - - chunkOffset += chunkLength; - inputLength -= chunkLength; - } - } - - @Override - public void close() throws IOException { - fos.close(); - } - - @Override - public void flush() throws IOException { - } - - /** - * Read the current position in a file descriptor. - */ - @Override - protected long position() { - int fd = PosixUtils.getFD(fileDescriptor); - return Unistd.lseek(fd, WordFactory.zero(), Unistd.SEEK_CUR()).rawValue(); - } - - /** - * Set the current position in a file descriptor. - */ - @Override - protected long position(long offset) { - int fd = PosixUtils.getFD(fileDescriptor); - return Unistd.lseek(fd, WordFactory.signed(offset), Unistd.SEEK_SET()).rawValue(); - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/AllocationFreeOutputStream.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/AllocationFreeOutputStream.java deleted file mode 100644 index 46248182c3f4..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/AllocationFreeOutputStream.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heapdump; - -import java.io.IOException; - -/** - * Legacy implementation, only used by other legacy code (see GR-44538). - * - * Simple interface for writing heap dump to arbitrary data source. - */ -public interface AllocationFreeOutputStream { - - void write(int b) throws IOException; - - void write(byte[] b, int offset, int length) throws IOException; - - /** - * close method is called outside of critical section and can allocate objects. - * - * @throws IOException - */ - void close() throws IOException; - - void flush() throws IOException; - -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpSupportImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpSupportImpl.java deleted file mode 100644 index 329fbbc46691..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpSupportImpl.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heapdump; - -import java.io.FileOutputStream; - -import com.oracle.svm.core.heap.dump.HeapDumping; - -/* Legacy implementation, only used by other legacy code (see GR-44538). */ -public class HeapDumpSupportImpl extends HeapDumping { - @Override - public void initializeDumpHeapOnOutOfMemoryError() { - /* Nothing to do. */ - } - - @Override - public void teardownDumpHeapOnOutOfMemoryError() { - /* Nothing to do. */ - } - - @Override - public void dumpHeapOnOutOfMemoryError() { - throw new UnsupportedOperationException(); - } - - @Override - public void dumpHeap(String outputFile, boolean live) throws java.io.IOException { - try (FileOutputStream fileOutputStream = new FileOutputStream(outputFile)) { - com.oracle.svm.core.heapdump.HeapDumpWriter.singleton().writeHeapTo(fileOutputStream, live); - } - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpUtils.java deleted file mode 100644 index cdd51a81350e..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpUtils.java +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heapdump; - -import static com.oracle.svm.core.snippets.KnownIntrinsics.readCallerStackPointer; - -import jdk.graal.compiler.word.Word; -import org.graalvm.nativeimage.CurrentIsolate; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.IsolateThread; -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.c.function.CodePointer; -import org.graalvm.word.Pointer; -import org.graalvm.word.UnsignedWord; -import org.graalvm.word.WordFactory; - -import com.oracle.svm.core.BuildPhaseProvider.AfterCompilation; -import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.code.CodeInfo; -import com.oracle.svm.core.code.CodeInfoTable; -import com.oracle.svm.core.deopt.DeoptimizedFrame; -import com.oracle.svm.core.heap.Heap; -import com.oracle.svm.core.heap.ObjectReferenceVisitor; -import com.oracle.svm.core.heap.ObjectVisitor; -import com.oracle.svm.core.heap.RestrictHeapAccess; -import com.oracle.svm.core.heap.UnknownObjectField; -import com.oracle.svm.core.heap.VMOperationInfos; -import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.hub.InteriorObjRefWalker; -import com.oracle.svm.core.hub.LayoutEncoding; -import com.oracle.svm.core.snippets.KnownIntrinsics; -import com.oracle.svm.core.stack.JavaStackWalker; -import com.oracle.svm.core.stack.StackFrameVisitor; -import com.oracle.svm.core.thread.JavaVMOperation; -import com.oracle.svm.core.thread.VMThreads; - -/** - * Legacy implementation, only used by other legacy code (see GR-44538). - * - * A collection of utilities that might assist heap dumps. - */ -public class HeapDumpUtils { - - @UnknownObjectField(availability = AfterCompilation.class) private byte[] fieldsMap; - - /** Extra methods for testing. */ - private final TestingBackDoor testingBackDoor; - - /** Constructor. */ - public HeapDumpUtils() { - this.testingBackDoor = new TestingBackDoor(this); - } - - /** Accessor for the singleton. */ - public static HeapDumpUtils getHeapDumpUtils() { - return ImageSingletons.lookup(HeapDumpUtils.class); - } - - @Platforms(Platform.HOSTED_ONLY.class) - public void setFieldsMap(byte[] map) { - fieldsMap = map; - } - - /** - * Walk all the objects in the heap, both the image heap and the garbage collected heap applying - * a visitor to each. - */ - public boolean walkHeapObjects(ObjectVisitor imageHeapVisitor, ObjectVisitor collectedHeapVisitor) { - final WalkHeapObjectsOperation operation = new WalkHeapObjectsOperation(imageHeapVisitor, collectedHeapVisitor); - return walkHeapObjectsWithoutAllocating(operation); - } - - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Iterating the heap must not allocate in the heap.") - boolean walkHeapObjectsWithoutAllocating(WalkHeapObjectsOperation operation) { - operation.enqueue(); - return operation.getResult(); - } - - public int instanceSizeOf(Class cls) { - final int encoding = DynamicHub.fromClass(cls).getLayoutEncoding(); - if (LayoutEncoding.isPureInstance(encoding)) { - /* - * May underestimate the object size if the identity hashcode field is optional. This is - * the best that what can do because the HPROF format does not support that instances of - * one class have different object sizes. - */ - return (int) LayoutEncoding.getPureInstanceAllocationSize(encoding).rawValue(); - } else { - return 0; - } - } - - boolean isPrimitiveArray(Object obj) { - final int encoding = KnownIntrinsics.readHub(obj).getLayoutEncoding(); - return LayoutEncoding.isPrimitiveArray(encoding); - } - - public boolean isJavaPrimitiveArray(Object obj) { - return (isPrimitiveArray(obj) && - ((obj instanceof char[]) || - (obj instanceof byte[]) || - (obj instanceof int[]) || - (obj instanceof long[]) || - (obj instanceof boolean[]) || - (obj instanceof short[]) || - (obj instanceof double[]) || - (obj instanceof float[]))); - } - - /** - * Return a pointer to an object. The result is untracked by the collector: it is treated as an - * integer. - */ - public Pointer objectToPointer(Object obj) { - return Word.objectToUntrackedPointer(obj); - } - - public byte[] getFieldsMap() { - return fieldsMap; - } - - public boolean walkStacks(StacksSlotsVisitor stacksSlotsVisitor) { - final WalkStacksSlotsOperation walkStacksOperation = new WalkStacksSlotsOperation(stacksSlotsVisitor); - walkStacksOperation.enqueue(); - return walkStacksOperation.getResult(); - } - - private static final class WalkHeapObjectsOperation extends JavaVMOperation { - - /* Instance state. */ - private final ObjectVisitor imageHeapVisitor; - private final ObjectVisitor collectedHeapVisitor; - boolean result; - - /** Constructor. */ - WalkHeapObjectsOperation(ObjectVisitor imageHeapVisitor, ObjectVisitor collectedHeapVisitor) { - super(VMOperationInfos.get(WalkHeapObjectsOperation.class, "Walk Java heap for heap dump", SystemEffect.SAFEPOINT)); - this.imageHeapVisitor = imageHeapVisitor; - this.collectedHeapVisitor = collectedHeapVisitor; - } - - @Override - public void operate() { - operateWithoutAllocation(); - } - - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Do not allocate while walking the heap.") - private void operateWithoutAllocation() { - result = Heap.getHeap().walkImageHeapObjects(imageHeapVisitor) && Heap.getHeap().walkCollectedHeapObjects(collectedHeapVisitor); - } - - private boolean getResult() { - return result; - } - } - - private static final class WalkStacksSlotsOperation extends JavaVMOperation { - - private final StacksSlotsVisitor stacksSlotsVisitor; - private boolean result; - - WalkStacksSlotsOperation(StacksSlotsVisitor stacksSlotsVisitor) { - super(VMOperationInfos.get(WalkStacksSlotsOperation.class, "Walk stack for heap dump", SystemEffect.SAFEPOINT)); - this.stacksSlotsVisitor = stacksSlotsVisitor; - } - - @Override - public void operate() { - operateWithoutAllocation(); - } - - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Do not allocate while walking thread stacks.") - private void operateWithoutAllocation() { - result = stacksSlotsVisitor.visitStacksSlots(); - } - - private boolean getResult() { - return result; - } - } - - public abstract static class StacksSlotsVisitor extends StackFrameVisitor implements ObjectReferenceVisitor { - - private IsolateThread currentVMThread; - private Pointer currentStackSP; - private Pointer currentFrameSP; - private CodePointer currentFrameIP; - private DeoptimizedFrame currentDeoptimizedFrame; - - /** Constructor for subclasses. */ - public StacksSlotsVisitor() { - /* Nothing to do. */ - } - - /* - * Access methods for subclasses. - */ - - /** The current VMThread. */ - protected IsolateThread getVMThread() { - return currentVMThread; - } - - /** The stack pointer for the current VMThread. */ - protected Pointer getStackSP() { - return currentStackSP; - } - - /** The stack pointer for the current frame. */ - protected Pointer getFrameSP() { - return currentFrameSP; - } - - /** The instruction pointer for the current frame. */ - protected CodePointer getFrameIP() { - return currentFrameIP; - } - - /** The DeoptimizedFrame for the current frame. */ - protected DeoptimizedFrame getDeoptimizedFrame() { - return currentDeoptimizedFrame; - } - - @NeverInline("Starting a stack walk in the caller frame") - protected boolean visitStacksSlots() { - /* Visit the current thread, because it does not have a JavaFrameAnchor. */ - currentVMThread = CurrentIsolate.getCurrentThread(); - currentStackSP = readCallerStackPointer(); - JavaStackWalker.walkCurrentThread(currentStackSP, this); - if (SubstrateOptions.MultiThreaded.getValue()) { - /* - * Scan the stacks of all the threads. Other threads will be blocked at a safepoint - * (or in native code) so they will each have a JavaFrameAnchor in their VMThread. - */ - for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (vmThread == CurrentIsolate.getCurrentThread()) { - /* - * The current thread is already scanned by code above, so we do not have to - * do anything for it here. It might have a JavaFrameAnchor from earlier - * Java-to-C transitions, but certainly not at the top of the stack since it - * is running this code, so just this scan would be incomplete. - */ - continue; - } - currentVMThread = vmThread; - currentStackSP = WordFactory.nullPointer(); - currentFrameSP = WordFactory.nullPointer(); - currentFrameIP = WordFactory.nullPointer(); - currentDeoptimizedFrame = null; - JavaStackWalker.walkThread(vmThread, this); - } - } - return true; - } - - @Override - public boolean visitFrame(Pointer sp, CodePointer ip, CodeInfo codeInfo, DeoptimizedFrame deoptimizedFrame) { - /* Notice a change in thread. */ - if (currentStackSP.isNull()) { - currentStackSP = sp; - } - currentFrameSP = sp; - currentFrameIP = ip; - currentDeoptimizedFrame = deoptimizedFrame; - return CodeInfoTable.visitObjectReferences(sp, ip, codeInfo, deoptimizedFrame, this); - } - } - - public TestingBackDoor getTestingBackDoor() { - return testingBackDoor; - } - - /** Expose some {@link HeapDumpUtils} methods for testing. */ - public static class TestingBackDoor { - - /** The HeapDumpUtils instance to use. */ - private final HeapDumpUtils heapDumpUtils; - - /** Constructor. */ - TestingBackDoor(HeapDumpUtils utils) { - this.heapDumpUtils = utils; - } - - public byte[] getFieldsMap() { - return heapDumpUtils.getFieldsMap(); - } - - public int instanceSizeOf(Class cls) { - return heapDumpUtils.instanceSizeOf(cls); - } - - public boolean isJavaPrimitiveArray(Object obj) { - return heapDumpUtils.isJavaPrimitiveArray(obj); - } - - public boolean isPrimitiveArray(Object obj) { - return heapDumpUtils.isPrimitiveArray(obj); - } - - public Pointer objectToPointer(Object obj) { - return heapDumpUtils.objectToPointer(obj); - } - - public long sizeOf(Object obj) { - final long result; - if (obj == null) { - result = 0; - } else { - final UnsignedWord objectSize = LayoutEncoding.getMomentarySizeFromObject(obj); - result = objectSize.rawValue(); - } - return result; - } - - public boolean walkHeapObjects(ObjectVisitor imageHeapVisitor, ObjectVisitor collectedHeapVisitor) { - return heapDumpUtils.walkHeapObjects(imageHeapVisitor, collectedHeapVisitor); - } - - @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Iterating the heap must not allocate in the heap.") - public boolean walkInteriorReferences(Object obj, ObjectReferenceVisitor visitor) { - return InteriorObjRefWalker.walkObject(obj, visitor); - } - - public boolean walkStacks(StacksSlotsVisitor stacksSlotsVisitor) { - return heapDumpUtils.walkStacks(stacksSlotsVisitor); - } - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriter.java deleted file mode 100644 index 176776c12a03..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriter.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heapdump; - -import java.io.FileOutputStream; -import java.io.IOException; - -import org.graalvm.nativeimage.ImageSingletons; - -/** Legacy implementation, only used by other legacy code (see GR-44538). */ -public abstract class HeapDumpWriter { - /** - * Writes heap in hprof format to ordinary file. - * - * @param fileOutputStream Underlying file stream to write the bytes to - * @param gcBefore Run GC before dumping the heap. - * @throws IOException - */ - public abstract void writeHeapTo(FileOutputStream fileOutputStream, boolean gcBefore) throws IOException; - - /** - * Writes heap in hprof format to output stream, which does not support seeking. - * - * @param outputStream Underlying stream to write the bytes to - * @param gcBefore Run GC before dumping the heap. - * @throws IOException - */ - public abstract void writeHeapTo(AllocationFreeOutputStream outputStream, boolean gcBefore) throws IOException; - - public static HeapDumpWriter singleton() { - return ImageSingletons.lookup(HeapDumpWriter.class); - } - -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriterImpl.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriterImpl.java deleted file mode 100644 index 00ebaa3fef48..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpWriterImpl.java +++ /dev/null @@ -1,1762 +0,0 @@ -/* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heapdump; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.lang.management.ManagementFactory; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.graalvm.nativeimage.CurrentIsolate; -import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.IsolateThread; -import org.graalvm.word.Pointer; -import org.graalvm.word.WordBase; - -import com.oracle.svm.core.StaticFieldsSupport; -import com.oracle.svm.core.code.FrameInfoQueryResult; -import com.oracle.svm.core.config.ConfigurationValues; -import com.oracle.svm.core.heap.Heap; -import com.oracle.svm.core.heap.ObjectVisitor; -import com.oracle.svm.core.heap.ReferenceAccess; -import com.oracle.svm.core.heap.VMOperationInfos; -import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.stack.JavaStackFrameVisitor; -import com.oracle.svm.core.stack.JavaStackWalker; -import com.oracle.svm.core.thread.JavaVMOperation; -import com.oracle.svm.core.thread.PlatformThreads; -import com.oracle.svm.core.thread.VMOperation; -import com.oracle.svm.core.thread.VMThreads; -import com.oracle.svm.core.util.VMError; - -/* - * Legacy implementation, only used by other legacy code (see GR-44538). - * - * This class writes Java heap in hprof binary format. The class is heavily - * influenced by 'HeapHprofBinWriter' implementation. - */ - -/* hprof binary format originally published at: -* -* -* -* header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" (0-terminated) -* u4 size of identifiers. Identifiers are used to represent -* UTF8 strings, objects, stack traces, etc. They usually -* have the same size as host pointers. For example, on -* Solaris and Win32, the size is 4. -* u4 high word -* u4 low word number of milliseconds since 0:00 GMT, 1/1/70 -* [record]* a sequence of records. -* -*/ - -/* -* -* Record format: -* -* u1 a TAG denoting the type of the record -* u4 number of *microseconds* since the time stamp in the -* header. (wraps around in a little more than an hour) -* u4 number of bytes *remaining* in the record. Note that -* this number excludes the tag and the length field itself. -* [u1]* BODY of the record (a sequence of bytes) -*/ - -/* -* The following TAGs are supported: -* -* TAG BODY notes -*---------------------------------------------------------- -* HPROF_UTF8 a UTF8-encoded name -* -* id name ID -* [u1]* UTF8 characters (no trailing zero) -* -* HPROF_LOAD_CLASS a newly loaded class -* -* u4 class serial number (> 0) -* id class object ID -* u4 stack trace serial number -* id class name ID -* -* HPROF_UNLOAD_CLASS an unloading class -* -* u4 class serial_number -* -* HPROF_FRAME a Java stack frame -* -* id stack frame ID -* id method name ID -* id method signature ID -* id source file name ID -* u4 class serial number -* i4 line number. >0: normal -* -1: unknown -* -2: compiled method -* -3: native method -* -* HPROF_TRACE a Java stack trace -* -* u4 stack trace serial number -* u4 thread serial number -* u4 number of frames -* [id]* stack frame IDs -* -* -* HPROF_ALLOC_SITES a set of heap allocation sites, obtained after GC -* -* u2 flags 0x0001: incremental vs. complete -* 0x0002: sorted by allocation vs. live -* 0x0004: whether to force a GC -* u4 cutoff ratio -* u4 total live bytes -* u4 total live instances -* u8 total bytes allocated -* u8 total instances allocated -* u4 number of sites that follow -* [u1 is_array: 0: normal object -* 2: object array -* 4: boolean array -* 5: char array -* 6: float array -* 7: double array -* 8: byte array -* 9: short array -* 10: int array -* 11: long array -* u4 class serial number (may be zero during startup) -* u4 stack trace serial number -* u4 number of bytes alive -* u4 number of instances alive -* u4 number of bytes allocated -* u4]* number of instance allocated -* -* HPROF_START_THREAD a newly started thread. -* -* u4 thread serial number (> 0) -* id thread object ID -* u4 stack trace serial number -* id thread name ID -* id thread group name ID -* id thread group parent name ID -* -* HPROF_END_THREAD a terminating thread. -* -* u4 thread serial number -* -* HPROF_HEAP_SUMMARY heap summary -* -* u4 total live bytes -* u4 total live instances -* u8 total bytes allocated -* u8 total instances allocated -* -* HPROF_HEAP_DUMP denote a heap dump -* -* [heap dump sub-records]* -* -* There are four kinds of heap dump sub-records: -* -* u1 sub-record type -* -* HPROF_GC_ROOT_UNKNOWN unknown root -* -* id object ID -* -* HPROF_GC_ROOT_THREAD_OBJ thread object -* -* id thread object ID (may be 0 for a -* thread newly attached through JNI) -* u4 thread sequence number -* u4 stack trace sequence number -* -* HPROF_GC_ROOT_JNI_GLOBAL JNI global ref root -* -* id object ID -* id JNI global ref ID -* -* HPROF_GC_ROOT_JNI_LOCAL JNI local ref -* -* id object ID -* u4 thread serial number -* u4 frame # in stack trace (-1 for empty) -* -* HPROF_GC_ROOT_JAVA_FRAME Java stack frame -* -* id object ID -* u4 thread serial number -* u4 frame # in stack trace (-1 for empty) -* -* HPROF_GC_ROOT_NATIVE_STACK Native stack -* -* id object ID -* u4 thread serial number -* -* HPROF_GC_ROOT_STICKY_CLASS System class -* -* id object ID -* -* HPROF_GC_ROOT_THREAD_BLOCK Reference from thread block -* -* id object ID -* u4 thread serial number -* -* HPROF_GC_ROOT_MONITOR_USED Busy monitor -* -* id object ID -* -* HPROF_GC_CLASS_DUMP dump of a class object -* -* id class object ID -* u4 stack trace serial number -* id super class object ID -* id class loader object ID -* id signers object ID -* id protection domain object ID -* id reserved -* id reserved -* -* u4 instance size (in bytes) -* -* u2 size of constant pool -* [u2, constant pool index, -* ty, type -* 2: object -* 4: boolean -* 5: char -* 6: float -* 7: double -* 8: byte -* 9: short -* 10: int -* 11: long -* vl]* and value -* -* u2 number of static fields -* [id, static field name, -* ty, type, -* vl]* and value -* -* u2 number of inst. fields (not inc. super) -* [id, instance field name, -* ty]* type -* -* HPROF_GC_INSTANCE_DUMP dump of a normal object -* -* id object ID -* u4 stack trace serial number -* id class object ID -* u4 number of bytes that follow -* [vl]* instance field values (class, followed -* by super, super's super ...) -* -* HPROF_GC_OBJ_ARRAY_DUMP dump of an object array -* -* id array object ID -* u4 stack trace serial number -* u4 number of elements -* id array class ID -* [id]* elements -* -* HPROF_GC_PRIM_ARRAY_DUMP dump of a primitive array -* -* id array object ID -* u4 stack trace serial number -* u4 number of elements -* u1 element type -* 4: boolean array -* 5: char array -* 6: float array -* 7: double array -* 8: byte array -* 9: short array -* 10: int array -* 11: long array -* [u1]* elements -* -* HPROF_CPU_SAMPLES a set of sample traces of running threads -* -* u4 total number of samples -* u4 # of traces -* [u4 # of samples -* u4]* stack trace serial number -* -* HPROF_CONTROL_SETTINGS the settings of on/off switches -* -* u4 0x00000001: alloc traces on/off -* 0x00000002: cpu sampling on/off -* u2 stack trace depth -* -* -* When the header is "JAVA PROFILE 1.0.2" a heap dump can optionally -* be generated as a sequence of heap dump segments. This sequence is -* terminated by an end record. The additional tags allowed by format -* "JAVA PROFILE 1.0.2" are: -* -* HPROF_HEAP_DUMP_SEGMENT denote a heap dump segment -* -* [heap dump sub-records]* -* The same sub-record types allowed by HPROF_HEAP_DUMP -* -* HPROF_HEAP_DUMP_END denotes the end of a heap dump -* -*/ -public class HeapDumpWriterImpl extends HeapDumpWriter { - - /** - * The heap size threshold used to determine if segmented format ("JAVA PROFILE 1.0.2") should - * be used. - */ - private static final long HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD = 2L * 1024 * 1024 * 1024; - - /** - * The approximate size of a heap segment. Used to calculate when to create a new segment. - */ - private static final long HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE = 1L * 1024 * 1024 * 1024; - - /** - * The approximate size of a heap segment for no seek case. Used to calculate when to create a - * new segment. - */ - private static final int HPROF_NOSEEK_HEAP_DUMP_SEGMENT_SIZE = 1 * 1024 * 1024; - - /** hprof binary file header. */ - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; - private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; - - /** Constants in enum HprofTag. */ - private static final int HPROF_UTF8 = 0x01; - private static final int HPROF_LOAD_CLASS = 0x02; - /* private static final int HPROF_UNLOAD_CLASS = 0x03; */ - private static final int HPROF_FRAME = 0x04; - private static final int HPROF_TRACE = 0x05; - /* private static final int HPROF_ALLOC_SITES = 0x06; */ - /* private static final int HPROF_HEAP_SUMMARY = 0x07; */ - /* private static final int HPROF_START_THREAD = 0x0A; */ - /* private static final int HPROF_END_THREAD = 0x0B; */ - private static final int HPROF_HEAP_DUMP = 0x0C; - /* private static final int HPROF_CPU_SAMPLES = 0x0D; */ - /* private static final int HPROF_CONTROL_SETTINGS = 0x0E; */ - - /* 1.0.2 record types. */ - private static final int HPROF_HEAP_DUMP_SEGMENT = 0x1C; - private static final int HPROF_HEAP_DUMP_END = 0x2C; - - /* Heap dump constants */ - /* Constants in enum HprofGcTag. */ - private static final int HPROF_GC_ROOT_UNKNOWN = 0xFF; - private static final int HPROF_GC_ROOT_JNI_GLOBAL = 0x01; - /* private static final int HPROF_GC_ROOT_JNI_LOCAL = 0x02; */ - /* private static final int HPROF_GC_ROOT_JAVA_FRAME = 0x03; */ - /* private static final int HPROF_GC_ROOT_NATIVE_STACK = 0x04; */ - private static final int HPROF_GC_ROOT_STICKY_CLASS = 0x05; - /* private static final int HPROF_GC_ROOT_THREAD_BLOCK = 0x06; */ - /* private static final int HPROF_GC_ROOT_MONITOR_USED = 0x07; */ - private static final int HPROF_GC_ROOT_THREAD_OBJ = 0x08; - private static final int HPROF_GC_CLASS_DUMP = 0x20; - private static final int HPROF_GC_INSTANCE_DUMP = 0x21; - private static final int HPROF_GC_OBJ_ARRAY_DUMP = 0x22; - private static final int HPROF_GC_PRIM_ARRAY_DUMP = 0x23; - - /* Constants in enum HprofType. */ - private static final int HPROF_NORMAL_OBJECT = 2; - private static final int HPROF_BOOLEAN = 4; - private static final int HPROF_CHAR = 5; - private static final int HPROF_FLOAT = 6; - private static final int HPROF_DOUBLE = 7; - private static final int HPROF_BYTE = 8; - private static final int HPROF_SHORT = 9; - private static final int HPROF_INT = 10; - private static final int HPROF_LONG = 11; - - /* Java type codes. */ - private static final char JVM_SIGNATURE_BOOLEAN = 'Z'; - private static final char JVM_SIGNATURE_CHAR = 'C'; - private static final char JVM_SIGNATURE_BYTE = 'B'; - private static final char JVM_SIGNATURE_SHORT = 'S'; - private static final char JVM_SIGNATURE_INT = 'I'; - private static final char JVM_SIGNATURE_LONG = 'J'; - private static final char JVM_SIGNATURE_FLOAT = 'F'; - private static final char JVM_SIGNATURE_DOUBLE = 'D'; - private static final char JVM_SIGNATURE_ARRAY = '['; - private static final char JVM_SIGNATURE_CLASS = 'L'; - - /* - * We don't have allocation site info. We write a dummy stack trace with this id. - */ - private static final int DUMMY_STACK_TRACE_ID = 1; - /* private static final int EMPTY_FRAME_DEPTH = -1; */ - - private static final Field[] ZERO_FIELD_ARR = new Field[0]; - - /** Pre-allocated exceptions, for throwing from code that must not allocate. */ - private static final RuntimeException heapSegmentSizeOverflowException = new RuntimeException("Heap segment size overflow."); - - private AllocationFreeDataOutputStream out; - private HeapDumpUtils heapDumpUtils; - private Map> fieldsMap; - private ClassToClassDataMap classDataCache; - - /* Added for hprof file format 1.0.2 support. */ - private boolean useSegmentedHeapDump; - private long currentSegmentStart; - private long segmentSize; - - @Override - public void writeHeapTo(AllocationFreeOutputStream dataOutputStream, boolean gcBefore) throws IOException { - initialize(true, HPROF_NOSEEK_HEAP_DUMP_SEGMENT_SIZE); - - WriterOperation writerOperation = new WriterOperation(dataOutputStream, gcBefore, HPROF_NOSEEK_HEAP_DUMP_SEGMENT_SIZE); - writerOperation.enqueue(); - IOException operationException = writerOperation.getException(); - if (operationException != null) { - throw operationException; - } - - /* - * Close the data stream. Needs to be done outside of the VMOperation because it uses - * synchronization. - */ - dataOutputStream.close(); - } - - @Override - public void writeHeapTo(FileOutputStream fileOutputStream, boolean gcBefore) throws IOException { - initialize(ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getUsed() > HPROF_SEGMENTED_HEAP_DUMP_THRESHOLD, HPROF_SEGMENTED_HEAP_DUMP_SEGMENT_SIZE); - - WriterOperation writerOperation = new WriterOperation(fileOutputStream, gcBefore); - writerOperation.enqueue(); - IOException operationException = writerOperation.getException(); - if (operationException != null) { - throw operationException; - } - - /* - * Close the file stream. Needs to be done outside of the VMOperation because it uses - * synchronization. - */ - fileOutputStream.close(); - } - - @SuppressWarnings("hiding") - private void initialize(boolean useSegmentedHeapDump, long segmentSize) { - this.currentSegmentStart = 0L; - this.useSegmentedHeapDump = useSegmentedHeapDump; - this.segmentSize = segmentSize; - } - - /* This method runs as part of a VMOperation. */ - private void writeTo(AllocationFreeDataOutputStream outputStream, boolean gcBefore) throws IOException { - /* If requested, clean up the heap. */ - if (gcBefore) { - System.gc(); - } - - out = outputStream; - heapDumpUtils = HeapDumpUtils.getHeapDumpUtils(); - - /* hprof bin format header. */ - writeFileHeader(); - - /* Dummy stack trace. */ - writeDummyTrace(); - - ArrayList> classList = new ArrayList<>(); - Heap.getHeap().visitLoadedClasses((clazz) -> classList.add(clazz)); - - /* hprof UTF-8 symbols section. */ - writeClassNames(classList); - - byte[] fieldsMapData = heapDumpUtils.getFieldsMap(); - if (fieldsMapData.length == 0) { - throw new IOException("Empty fieldsMap"); - } - fieldsMap = createFieldsMap(fieldsMapData); - - /* HPROF_LOAD_CLASS records for all classes. */ - writeClasses(classList); - - /* write HPROF_FRAME and HPROF_TRACE records */ - dumpStackTraces(); - - /* Write CLASS_DUMP records. */ - writeClassDumpRecords(classList); - - /* Write HEAP_DUMP record. */ - writeInstanceDumpRecords(classList); - - /* get current position to calculate length. */ - long dumpEnd = out.position(); - - /* Calculate length of heap data. */ - long dumpLenLong = (dumpEnd - currentSegmentStart - 4L); - /* Fill in final length. */ - fillInHeapRecordLength(dumpLenLong); - - if (useSegmentedHeapDump) { - /* Write heap segment-end record. */ - out.writeByte((byte) HPROF_HEAP_DUMP_END); - out.writeInt(0); - out.writeInt(0); - } - - /* Flush buffer stream and throw fields away. */ - out.flush(); - out = null; - heapDumpUtils = null; - fieldsMap = null; - classDataCache = null; - } - - private void writeHeapRecordPrologue() throws IOException { - if (currentSegmentStart == 0) { - out.flush(); - /* Write heap data header, depending on heap size use segmented heap format. */ - out.writeByte((byte) (useSegmentedHeapDump ? HPROF_HEAP_DUMP_SEGMENT - : HPROF_HEAP_DUMP)); - out.writeInt(0); - - /* - * Remember position of dump length, we will fixup length later: hprof format requires - * length. - */ - currentSegmentStart = out.position(); - - /* Write dummy length of 0 and we'll fix it later. */ - out.writeInt(0); - } - } - - private void writeHeapRecordEpilogue() throws IOException { - writeHeapRecordEpilogue(0); - } - - private void writeHeapRecordEpilogue(long dumpLenSize) throws IOException { - if (useSegmentedHeapDump) { - /* get current position (plus dumpLenLong) to calculate length. */ - long dumpEnd = out.position() + dumpLenSize; - - /* Calculate length of heap data. */ - long dumpLenLong = dumpEnd - currentSegmentStart - 4L; - if (dumpLenLong >= segmentSize) { - fillInHeapRecordLength(dumpLenLong); - out.flush(); - currentSegmentStart = 0; - } - } - } - - private void fillInHeapRecordLength(long dumpLenLong) throws IOException { - /* Check length boundary, overflow of 4GB could happen but is _very_ unlikely. */ - if (dumpLenLong >= (4L * 1024 * 1024 * 1024)) { - throw heapSegmentSizeOverflowException; - } - - /* Save the current position. */ - long currentPosition = out.position(); - - /* Seek the position to write length. */ - out.position(currentSegmentStart); - - int dumpLen = (int) dumpLenLong; - - /* Write length as integer. */ - out.writeInt(dumpLen); - - /* Reset to previous current position. */ - out.position(currentPosition); - } - - private void writeClassDumpRecords(List> classList) throws IOException { - for (Class cls : classList) { - writeHeapRecordPrologue(); - writeClassDumpRecord(cls); - writeHeapRecordEpilogue(); - } - } - - private void writeInstanceDumpRecords(List> classList) throws IOException { - final StacksSlotsVisitorImpl stackVisitor = new StacksSlotsVisitorImpl(); - final CollectedHeapVisitorImpl collectedVisitor = new CollectedHeapVisitorImpl(); - final ImageHeapVisitorImpl imageVisitor = new ImageHeapVisitorImpl(); - IOException visitorException; - - heapDumpUtils.walkStacks(stackVisitor); - visitorException = stackVisitor.getException(); - if (visitorException != null) { - throw visitorException; - } - - heapDumpUtils.walkHeapObjects(imageVisitor, collectedVisitor); - visitorException = collectedVisitor.getException(); - if (visitorException != null) { - throw visitorException; - } - visitorException = imageVisitor.getException(); - if (visitorException != null) { - throw visitorException; - } - /* Write root sticky class. */ - writeStickyClasses(classList); - - /* write JavaThreads */ - writeJavaThreads(); - } - - private void writeStickyClasses(List> classList) throws IOException { - for (Class cls : classList) { - writeHeapRecordPrologue(); - out.writeByte((byte) HPROF_GC_ROOT_STICKY_CLASS); - writeObjectID(cls); - writeHeapRecordEpilogue(); - } - } - - private void writeImageGCRoot(Object obj) throws IOException { - if (!(obj instanceof Class)) { - writeHeapRecordPrologue(); - out.writeByte((byte) HPROF_GC_ROOT_JNI_GLOBAL); - writeObjectID(obj); - writeObjectID(null); - writeHeapRecordEpilogue(); - } - } - - private void writeUnknownGCRoot(Object obj) throws IOException { - if (obj != null) { - writeHeapRecordPrologue(); - out.writeByte((byte) HPROF_GC_ROOT_UNKNOWN); - writeObjectID(obj); - writeHeapRecordEpilogue(); - } - } - - private void writeJavaThreads() throws IOException { - int threadSerialNum = 1; // Note that the thread serial number range is 1-to-N - - for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (vmThread == CurrentIsolate.getCurrentThread()) { - /* Skip itself */ - continue; - } - - Thread jt = PlatformThreads.fromVMThread(vmThread); - writeJavaThread(jt, threadSerialNum++); - } - } - - private void writeJavaThread(Thread jt, int threadSerialNum) throws IOException { - writeHeapRecordPrologue(); - out.writeByte((byte) HPROF_GC_ROOT_THREAD_OBJ); - writeObjectID(jt); - out.writeInt(threadSerialNum); // thread serial number - out.writeInt(threadSerialNum + DUMMY_STACK_TRACE_ID); // stack trace serial number - writeHeapRecordEpilogue(); - } - - private void writeClass(Class clazz) throws IOException { - /* - * All ordinary Class objects are covered by writeClassDumpRecords and they are in - * classDataCache. - */ - if (classDataCache.get(clazz) == null) { - /* Unknown class. */ - writeInstance(clazz); - } - } - - private void writeClassDumpRecord(Class cls) throws IOException { - out.writeByte((byte) HPROF_GC_CLASS_DUMP); - writeObjectID(cls); - out.writeInt(DUMMY_STACK_TRACE_ID); - writeObjectID(cls.getSuperclass()); - - if (!isArray(cls)) { - writeObjectID(cls.getClassLoader()); - writeObjectID(null); /* Signers. */ - writeObjectID(null); /* Protection domain. */ - writeObjectID(null); /* Reserved field 1. */ - writeObjectID(null); /* Reserved field 2. */ - out.writeInt(heapDumpUtils.instanceSizeOf(cls)); - - /* Ignore constant pool output number of cp entries as zero. */ - out.writeShort((short) 0); - - List declaredFields = getImmediateFields(cls); - int staticFields = 0; - int instanceFields = 0; - for (int i = 0; i < declaredFields.size(); i++) { - Field field = declaredFields.get(i); - if (field.isStatic()) { - staticFields++; - } else { - instanceFields++; - } - } - - /* Dump static field descriptors. */ - writeFieldDescriptors(true, staticFields, declaredFields); - - /* Dump instance field descriptors. */ - writeFieldDescriptors(false, instanceFields, declaredFields); - } else { - /* Array. */ - Class baseClass = getBaseClass(cls); - writeObjectID(baseClass.getClassLoader()); - writeObjectID(null); - writeObjectID(null); - /* Two reserved id fields. */ - writeObjectID(null); - writeObjectID(null); - /* Write zero instance size: instance size is variable for arrays. */ - out.writeInt(0); - /* No constant pool for array klasses. */ - out.writeShort((short) 0); - /* No static fields for array klasses. */ - out.writeShort((short) 0); - /* No instance fields for array klasses. */ - out.writeShort((short) 0); - } - } - - private void dumpStackTraces() throws IOException { - // write a HPROF_TRACE record without any frames to be referenced as object alloc sites - writeHeader(HPROF_TRACE, 3 * 4); - out.writeInt(DUMMY_STACK_TRACE_ID); - out.writeInt(0); // thread number - out.writeInt(0); // frame count - - int frameSerialNum = 0; - int numThreads = 0; - Set names = new HashSet<>(); - for (IsolateThread vmThread = VMThreads.firstThread(); vmThread.isNonNull(); vmThread = VMThreads.nextThread(vmThread)) { - if (vmThread == CurrentIsolate.getCurrentThread()) { - /* Skip itself */ - continue; - } - - final List stack = new ArrayList<>(); - - // dump thread stack trace - JavaStackFrameVisitor visitor = new JavaStackFrameVisitor() { - @Override - public boolean visitFrame(FrameInfoQueryResult frameInfo) { - if (frameInfo.getSourceClass() != null) { - stack.add(frameInfo); - } - return true; - } - }; - JavaStackWalker.walkThread(vmThread, visitor); - numThreads++; - - // write HPROF_FRAME records for this thread's stack trace - int depth = stack.size(); - int threadFrameStart = frameSerialNum; - for (int j = 0; j < depth; j++) { - FrameInfoQueryResult frame = stack.get(j); - ClassData cd = classDataCache.get(frame.getSourceClass()); - int classSerialNum = cd.serialNum; - - // the class serial number starts from 1 - assert classSerialNum > 0 : "class not found"; - dumpStackFrame(++frameSerialNum, classSerialNum, frame, names); - } - - // write HPROF_TRACE record for one thread - writeHeader(HPROF_TRACE, 3 * 4 + depth * getObjIDSize()); - int stackSerialNum = numThreads + DUMMY_STACK_TRACE_ID; - out.writeInt(stackSerialNum); // stack trace serial number - out.writeInt(numThreads); // thread serial number - out.writeInt(depth); // frame count - for (int j = 1; j <= depth; j++) { - writeObjectAddress(threadFrameStart + j); - } - } - names = null; - } - - private void dumpStackFrame(int frameSN, int classSN, FrameInfoQueryResult frame, Set names) throws IOException { - int lineNumber; - if (frame.isNativeMethod()) { - lineNumber = -3; // native frame - } else { - lineNumber = frame.getSourceLineNumber(); - } - // First dump UTF8 if needed - String method = frame.getSourceMethodName(); - String source = frame.getSourceFileName(); - if (method == null || method.isEmpty()) { - method = ""; - } - if (source == null || source.isEmpty()) { - source = "Unknown Source"; - } - writeName(method, names); // method's name - writeName("", names); // method's signature - writeName(source, names); // source file name - // Then write FRAME descriptor - writeHeader(HPROF_FRAME, 4 * getObjIDSize() + 2 * 4); - writeObjectAddress(frameSN); // frame serial number - writeSymbolID(method); // method's name - writeSymbolID(""); // method's signature - writeSymbolID(source); // source file name - out.writeInt(classSN); // class serial number - out.writeInt(lineNumber); // line number - } - - private void writeName(String name, Set names) throws IOException { - if (names.add(name)) { - writeSymbol(name); - } - } - - private void writeHeapInstance(Object obj) throws IOException { - writeHeapRecordPrologue(); - if (obj instanceof Class) { - writeClass((Class) obj); - writeHeapRecordEpilogue(); - } else if (heapDumpUtils.isJavaPrimitiveArray(obj)) { - writePrimitiveArray(obj); - } else if (isArray(obj.getClass())) { - writeObjectArray((Object[]) obj); - } else { - writeInstance(obj); - writeHeapRecordEpilogue(); - } - } - - private List getImmediateFields(Class cls) { - String clsName = cls.getName(); - List fields = fieldsMap.get(clsName); - if (fields == null) { - return Collections.emptyList(); - } - return fields; - } - - private void writeObjectArray(Object[] array) throws IOException { - out.writeByte((byte) HPROF_GC_OBJ_ARRAY_DUMP); - writeObjectID(array); - out.writeInt(DUMMY_STACK_TRACE_ID); - out.writeInt(array.length); - writeObjectID(array.getClass()); - writeHeapRecordEpilogue(array.length * getObjIDSize()); - for (Object o : array) { - writeObjectID(o); - } - } - - private void writePrimitiveArray(Object pArray) throws IOException { - out.writeByte((byte) HPROF_GC_PRIM_ARRAY_DUMP); - writeObjectID(pArray); - out.writeInt(DUMMY_STACK_TRACE_ID); - /* These are ordered by expected frequency. */ - if (pArray instanceof char[]) { - writeCharArray((char[]) pArray); - } else if (pArray instanceof byte[]) { - writeByteArray((byte[]) pArray); - } else if (pArray instanceof int[]) { - writeIntArray((int[]) pArray); - } else if (pArray instanceof long[]) { - writeLongArray((long[]) pArray); - } else if (pArray instanceof boolean[]) { - writeBooleanArray((boolean[]) pArray); - } else if (pArray instanceof short[]) { - writeShortArray((short[]) pArray); - } else if (pArray instanceof double[]) { - writeDoubleArray((double[]) pArray); - } else if (pArray instanceof float[]) { - writeFloatArray((float[]) pArray); - } else { - throw VMError.shouldNotReachHere(pArray.getClass().getName()); - } - } - - private void writeBooleanArray(boolean[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_BOOLEAN); - writeHeapRecordEpilogue(array.length * 1); - for (boolean b : array) { - out.writeBoolean(b); - } - } - - private void writeByteArray(byte[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_BYTE); - writeHeapRecordEpilogue(array.length * 1); - for (byte b : array) { - out.writeByte(b); - } - } - - private void writeShortArray(short[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_SHORT); - writeHeapRecordEpilogue(array.length * 2); - for (short s : array) { - out.writeShort(s); - } - } - - private void writeIntArray(int[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_INT); - writeHeapRecordEpilogue(array.length * 4); - for (int i : array) { - out.writeInt(i); - } - } - - private void writeLongArray(long[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_LONG); - writeHeapRecordEpilogue(array.length * 8); - for (long l : array) { - out.writeLong(l); - } - } - - private void writeCharArray(char[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_CHAR); - writeHeapRecordEpilogue(array.length * 2); - for (char c : array) { - out.writeChar(c); - } - } - - private void writeFloatArray(float[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_FLOAT); - writeHeapRecordEpilogue(array.length * 4); - for (float f : array) { - out.writeFloat(f); - } - } - - private void writeDoubleArray(double[] array) throws IOException { - out.writeInt(array.length); - out.writeByte((byte) HPROF_DOUBLE); - writeHeapRecordEpilogue(array.length * 8); - for (double d : array) { - out.writeDouble(d); - } - } - - private void writeInstance(Object instance) throws IOException { - out.writeByte((byte) HPROF_GC_INSTANCE_DUMP); - writeObjectID(instance); - out.writeInt(DUMMY_STACK_TRACE_ID); - Class cls = instance.getClass(); - writeObjectID(cls); - - final ClassData cd = classDataCache.get(cls); - out.writeInt(cd.instSize); - final Pointer objRef = heapDumpUtils.objectToPointer(instance); - for (int i = 0; i < cd.fields.length; i++) { - writeField(cd.fields[i], objRef); - } - } - - private void writeFieldDescriptors(boolean isStatic, int size, List fields) throws IOException { - /* cls == null for instance fields. */ - out.writeShort((short) size); - for (int i = 0; i < fields.size(); i++) { - Field field = fields.get(i); - if (isStatic == field.isStatic()) { - writeSymbolIDFromField(field); - char typeCode = field.getStorageSignature(); - int kind = signatureToHprofKind(typeCode); - out.writeByte((byte) kind); - if (field.isStatic()) { - /* Static field. */ - Object staticData; - char javaSignature = field.getStorageSignature(); - if (javaSignature == JVM_SIGNATURE_CLASS || javaSignature == JVM_SIGNATURE_ARRAY) { - staticData = StaticFieldsSupport.getStaticObjectFields(); - } else { - staticData = StaticFieldsSupport.getStaticPrimitiveFields(); - } - writeField(field, heapDumpUtils.objectToPointer(staticData)); - } - } - } - } - - private static int signatureToHprofKind(char ch) { - switch (ch) { - case JVM_SIGNATURE_CLASS: - case JVM_SIGNATURE_ARRAY: - return HPROF_NORMAL_OBJECT; - case JVM_SIGNATURE_BOOLEAN: - return HPROF_BOOLEAN; - case JVM_SIGNATURE_CHAR: - return HPROF_CHAR; - case JVM_SIGNATURE_FLOAT: - return HPROF_FLOAT; - case JVM_SIGNATURE_DOUBLE: - return HPROF_DOUBLE; - case JVM_SIGNATURE_BYTE: - return HPROF_BYTE; - case JVM_SIGNATURE_SHORT: - return HPROF_SHORT; - case JVM_SIGNATURE_INT: - return HPROF_INT; - case JVM_SIGNATURE_LONG: - return HPROF_LONG; - default: - throw new RuntimeException("Should not reach here"); - } - } - - private void writeField(Field field, Pointer p) throws IOException { - char storageSignature = field.getStorageSignature(); - int location = field.getLocation(); - - switch (storageSignature) { - case JVM_SIGNATURE_BOOLEAN: - out.writeByte(p.readByte(location)); - break; - case JVM_SIGNATURE_CHAR: - out.writeChar(p.readChar(location)); - break; - case JVM_SIGNATURE_BYTE: - out.writeByte(p.readByte(location)); - break; - case JVM_SIGNATURE_SHORT: - out.writeShort(p.readShort(location)); - break; - case JVM_SIGNATURE_INT: - out.writeInt(p.readInt(location)); - break; - case JVM_SIGNATURE_LONG: - out.writeLong(p.readLong(location)); - break; - case JVM_SIGNATURE_FLOAT: - out.writeFloat(p.readFloat(location)); - break; - case JVM_SIGNATURE_DOUBLE: - out.writeDouble(p.readDouble(location)); - break; - case JVM_SIGNATURE_CLASS: - case JVM_SIGNATURE_ARRAY: - writeObjectID(ReferenceAccess.singleton().readObjectAt(p.add(location), true)); - break; - default: - throw VMError.shouldNotReachHere("HeapDumpWriter.writeField: storageSignature"); - } - } - - private void writeHeader(int tag, int len) throws IOException { - out.writeByte((byte) tag); - out.writeInt(0); /* current ticks. */ - out.writeInt(len); - } - - private void writeDummyTrace() throws IOException { - writeHeader(HPROF_TRACE, 3 * 4); - out.writeInt(DUMMY_STACK_TRACE_ID); - out.writeInt(0); - out.writeInt(0); - } - - private void writeSymbolFromField(byte[] data, Field field) throws IOException { - writeHeader(HPROF_UTF8, field.getNameLength() + getObjIDSize()); - writeSymbolIDFromField(field); - out.write(data, field.getNameStartOffset(), field.getNameLength()); - } - - private void writeSymbol(String clsName) throws IOException { - byte[] buf = clsName.getBytes(StandardCharsets.UTF_8); - writeHeader(HPROF_UTF8, buf.length + getObjIDSize()); - writeSymbolID(clsName); - out.write(buf); - } - - private void writeClassNames(List> classList) throws IOException { - /* hprof UTF-8 symbols section. */ - for (Class cls : classList) { - writeSymbol(cls.getName()); - } - } - - private void writeClasses(List> classList) throws IOException { - int serialNum = 1; - /* - * Build a temporary map from Class to ClassData while I can allocate, but turn it into a - * map between arrays for later use. - */ - Map, ClassData> classDataMap = new HashMap<>(); - List fields = new ArrayList<>(); - for (Class cls : classList) { - writeHeader(HPROF_LOAD_CLASS, 2 * (getObjIDSize() + 4)); - out.writeInt(serialNum); - writeObjectID(cls); - out.writeInt(DUMMY_STACK_TRACE_ID); - writeSymbolID(cls.getName()); - assert fields.isEmpty(); - addInstanceFieldsTo(fields, cls); - int instSize = getSizeForFields(fields); - classDataMap.put(cls, new ClassData(serialNum, instSize, fields.toArray(ZERO_FIELD_ARR))); - fields.clear(); - serialNum++; - } - classDataCache = new ClassToClassDataMap(classDataMap); - } - - /** Writes hprof binary file header. */ - private void writeFileHeader() throws IOException { - /* Version string. */ - if (useSegmentedHeapDump) { - out.writeBytes(HPROF_HEADER_1_0_2); - } else { - out.writeBytes(HPROF_HEADER_1_0_1); - } - out.writeByte((byte) '\0'); - - /* Write identifier size. we use pointers as identifiers. */ - out.writeInt(getObjIDSize()); - - /* Time stamp: file creation time. */ - out.writeLong(System.currentTimeMillis()); - } - - /** Writes unique ID for an object. */ - private void writeObjectID(Object obj) throws IOException { - if (obj != null) { - WordBase ptr = ReferenceAccess.singleton().getCompressedRepresentation(obj); - writeObjectAddress(ptr.rawValue()); - } else { - writeObjectAddress(0L); - } - } - - private void writeSymbolID(String clsName) throws IOException { - writeObjectID(clsName); - } - - private void writeSymbolIDFromField(Field field) throws IOException { - writeObjectID(field); - } - - private void writeObjectAddress(long address) throws IOException { - if (getObjIDSize() == 4) { - out.writeInt((int) address); - } else { - out.writeLong(address); - } - } - - /** Get all declared as well as inherited (directly/indirectly) fields. */ - private void addInstanceFieldsTo(List res, final Class cls) { - Class clazz = cls; - while (clazz != null) { - List curFields = getImmediateFields(clazz); - for (int i = 0; i < curFields.size(); i++) { - Field f = curFields.get(i); - - if (!f.isStatic()) { - res.add(f); - } - } - clazz = clazz.getSuperclass(); - } - } - - /** - * Get size in bytes (in stream) required for given fields. Note that this is not the same as - * object size in heap. The size in heap will include size of padding/alignment bytes as well. - */ - private static int getSizeForFields(List fields) { - int size = 0; - for (int i = 0; i < fields.size(); i++) { - Field field = fields.get(i); - char typeCode = field.getStorageSignature(); - switch (typeCode) { - case JVM_SIGNATURE_BOOLEAN: - case JVM_SIGNATURE_BYTE: - size++; - break; - case JVM_SIGNATURE_CHAR: - case JVM_SIGNATURE_SHORT: - size += 2; - break; - case JVM_SIGNATURE_INT: - case JVM_SIGNATURE_FLOAT: - size += 4; - break; - case JVM_SIGNATURE_CLASS: - case JVM_SIGNATURE_ARRAY: - size += getObjIDSize(); - break; - case JVM_SIGNATURE_LONG: - case JVM_SIGNATURE_DOUBLE: - size += 8; - break; - default: - throw new RuntimeException("Should not reach here"); - } - } - return size; - } - - private static int getObjIDSize() { - return ConfigurationValues.getObjectLayout().getReferenceSize(); - } - - private static boolean isArray(Class cls) { - return cls.getName().startsWith("["); - } - - private static Class getBaseClass(final Class array) { - Class arr = array; - while (isArray(arr)) { - arr = arr.getComponentType(); - } - return arr; - } - - private Map> createFieldsMap(byte[] data) throws IOException { - int offset = 0; - Map> fldMap = new HashMap<>(); - while (offset < data.length) { - List fields; - String className = readString(data, offset); - offset += className.length() + 1; - - if (data[offset] == 0 && data[offset + 1] == 0) { - /* No fields. */ - fields = Collections.emptyList(); - offset += 2; - } else { - fields = new ArrayList<>(); - offset = readFields(false, data, offset, fields); - offset++; - offset = readFields(true, data, offset, fields); - offset++; - } - fldMap.put(className, fields); - } - return fldMap; - } - - private int readFields(boolean isStatic, byte[] data, int dataOffset, List fields) throws IOException { - int offset = dataOffset; - while (data[offset] != 0) { - /* Read field. */ - int stringStart = offset; - int stringLength = readStringLength(data, offset); - offset += stringLength + 1; - char javaSig = (char) data[offset++]; - char storageSig = (char) data[offset++]; - int location = readInt(data, offset); - offset += 4; - Field fieldDef = new Field(stringStart, stringLength, javaSig, storageSig, isStatic, location); - writeSymbolFromField(data, fieldDef); - fields.add(fieldDef); - } - return offset; - } - - private static int readInt(final byte[] data, final int st) { - int start = st; - int ch1 = data[start++] & 0xFF; - int ch2 = data[start++] & 0xFF; - int ch3 = data[start++] & 0xFF; - int ch4 = data[start++] & 0xFF; - return ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0)); - } - - private static String readString(byte[] data, int start) { - int len = readStringLength(data, start); - - return new String(data, start, len, StandardCharsets.UTF_8); - } - - /** - * Returns size of the null-terminated string. - * - * @param data byte[] array that is the source of string. - * @param start the initial offset to data array. - * @return the number of characters (bytes) in a null-terminated character sequence, without - * including the null-terminating character. - */ - private static int readStringLength(byte[] data, int start) { - int offset = start; - - while (data[offset] != 0) { - offset++; - } - return offset - start; - } - - private static class ClassData { - - int serialNum; - int instSize; - Field[] fields; - - ClassData(int serialNum, int instSize, Field[] fields) { - this.serialNum = serialNum; - this.instSize = instSize; - this.fields = fields; - } - } - - private static final class Field { - - private final int nameStart; - private final int nameLength; - private final char javaSig; - private final char storageSig; - private final boolean isStatic; - private final int location; - - private Field(final int ss, final int sl, final char jsig, final char ssig, - final boolean s, int loc) { - nameStart = ss; - nameLength = sl; - javaSig = jsig == 'A' ? JVM_SIGNATURE_CLASS : jsig; - storageSig = ssig == 'A' ? JVM_SIGNATURE_CLASS : ssig; - isStatic = s; - location = loc; - } - - private boolean isStatic() { - return isStatic; - } - - @SuppressWarnings({"unused"}) - private char getJavaSignature() { - return javaSig; - } - - private char getStorageSignature() { - return storageSig; - } - - private int getNameStartOffset() { - return nameStart; - } - - private int getNameLength() { - return nameLength; - } - - private int getLocation() { - return location; - } - } - - private class CollectedHeapVisitorImpl implements ObjectVisitor { - - private IOException exception; - - @Override - public boolean visitObject(Object obj) { - Object asObject = obj; - try { - writeHeapInstance(asObject); - } catch (IOException ex) { - /* Remember exception and abort VM operation. */ - exception = ex; - return false; - } - return true; - } - - private IOException getException() { - return exception; - } - } - - private class ImageHeapVisitorImpl implements ObjectVisitor { - - private IOException exception; - - @Override - public boolean visitObject(Object obj) { - Object asObject = obj; - try { - writeHeapInstance(asObject); - writeImageGCRoot(asObject); - } catch (IOException ex) { - /* Remember exception and abort VM operation. */ - exception = ex; - return false; - } - return true; - } - - private IOException getException() { - return exception; - } - } - - private class StacksSlotsVisitorImpl extends HeapDumpUtils.StacksSlotsVisitor { - - private IOException exception; - - @Override - public boolean visitObjectReference(Pointer objRef, boolean compressed, Object holderObject) { - try { - /* Get the referent of the reference. */ - final Object obj = ReferenceAccess.singleton().readObjectAt(objRef, compressed); - writeUnknownGCRoot(obj); - return true; - } catch (IOException ex) { - /* Remember exception. */ - exception = ex; - return false; - } - } - - private IOException getException() { - return exception; - } - } - - /** - * Abstract Allocation-free output stream created from FileOutputStream. This is the base class - * used by HeapDumpWriteImpl class. - */ - public abstract static class AllocationFreeFileOutputStream extends OutputStream { - - // constructor - public abstract AllocationFreeFileOutputStream newStreamFor(FileOutputStream fileOutputStream) throws IOException; - - @Override - public abstract void write(int b) throws IOException; - - @Override - public abstract void write(byte[] b, int offset, int length) throws IOException; - - @Override - public abstract void close() throws IOException; - - @Override - public void flush() throws IOException { - } - - /** Read the current position in a file descriptor. */ - protected abstract long position() throws IOException; - - /** Set the current position in a file descriptor. */ - protected abstract long position(long offset) throws IOException; - } - - /** - * Implementation of allocation-free output stream, which delegates to - * AllocationFreeOutputStream interface. - */ - private final class AllocationFreeFileOutputStreamWrapper extends AllocationFreeFileOutputStream { - - private final AllocationFreeOutputStream out; - private long position; - - private AllocationFreeFileOutputStreamWrapper(AllocationFreeOutputStream outputStream) { - out = outputStream; - position = 0; - } - - @Override - public AllocationFreeFileOutputStream newStreamFor(FileOutputStream fileOutputStream) throws IOException { - throw VMError.shouldNotReachHereAtRuntime(); - } - - @Override - public void write(int b) throws IOException { - out.write(b); - position++; - } - - @Override - public void write(byte[] b, int offset, int length) throws IOException { - out.write(b, offset, length); - position += length; - } - - @Override - public void close() throws IOException { - out.close(); - } - - @Override - public void flush() throws IOException { - out.flush(); - } - - @Override - protected long position() throws IOException { - return position; - } - - @Override - protected long position(long offset) throws IOException { - throw VMError.shouldNotReachHereAtRuntime(); - } - } - - private static final class AllocationFreeDataOutputStream { - - private final AllocationFreeBufferedOutputStream out; - - private AllocationFreeDataOutputStream(AllocationFreeBufferedOutputStream o) { - out = o; - } - - private void writeBoolean(boolean v) throws IOException { - out.write(v ? 1 : 0); - } - - private void writeByte(int v) throws IOException { - out.write(v); - } - - private void writeChar(int v) throws IOException { - out.write((v >>> 8) & 0xFF); - out.write((v >>> 0) & 0xFF); - } - - private void writeShort(int v) throws IOException { - out.write((v >>> 8) & 0xFF); - out.write((v >>> 0) & 0xFF); - } - - private void writeInt(int v) throws IOException { - out.write((v >>> 24) & 0xFF); - out.write((v >>> 16) & 0xFF); - out.write((v >>> 8) & 0xFF); - out.write((v >>> 0) & 0xFF); - } - - private void writeFloat(float v) throws IOException { - writeInt(Float.floatToIntBits(v)); - } - - private void writeLong(long v) throws IOException { - out.write((byte) (v >>> 56)); - out.write((byte) (v >>> 48)); - out.write((byte) (v >>> 40)); - out.write((byte) (v >>> 32)); - out.write((byte) (v >>> 24)); - out.write((byte) (v >>> 16)); - out.write((byte) (v >>> 8)); - out.write((byte) (v >>> 0)); - } - - private void writeDouble(double v) throws IOException { - writeLong(Double.doubleToLongBits(v)); - } - - private void flush() throws IOException { - out.flush(); - } - - private void write(byte[] buf) throws IOException { - out.write(buf, 0, buf.length); - } - - private void write(byte[] buf, int off, int len) throws IOException { - out.write(buf, off, len); - } - - private void writeBytes(String s) throws IOException { - int len = s.length(); - for (int i = 0; i < len; i++) { - out.write((byte) s.charAt(i)); - } - } - - private long position() throws IOException { - return out.position(); - } - - private void position(long pos) throws IOException { - out.position(pos); - } - } - - private static final class AllocationFreeBufferedOutputStream { - - private byte[] buf; - // current index in buf array - private int position; - // size of valid data in buf array - private int size; - private AllocationFreeFileOutputStream out; - - private AllocationFreeBufferedOutputStream(AllocationFreeFileOutputStream out) { - this(out, 8192); - } - - private AllocationFreeBufferedOutputStream(AllocationFreeFileOutputStream out, int size) { - this.out = out; - if (size <= 0) { - throw new IllegalArgumentException("Buffer size <= 0"); - } - buf = new byte[size]; - } - - private void flushBuffer() throws IOException { - if (size > 0) { - out.write(buf, 0, size); - position = 0; - size = 0; - } - } - - private void write(int b) throws IOException { - if (position >= buf.length) { - flushBuffer(); - } - buf[position++] = (byte) b; - setSize(); - } - - public void write(byte[] b, int off, int len) throws IOException { - if (len >= buf.length) { - flushBuffer(); - out.write(b, off, len); - return; - } - if (len > buf.length - position) { - flushBuffer(); - } - System.arraycopy(b, off, buf, position, len); - position += len; - setSize(); - } - - void flush() throws IOException { - flushBuffer(); - out.flush(); - } - - private long position() throws IOException { - return out.position() + position; - } - - private void position(long pos) throws IOException { - long currentFlushPos = out.position(); - long newCount = pos - currentFlushPos; - - if (newCount >= 0 && newCount <= size) { - position = (int) newCount; - } else { - flush(); - out.position(pos); - } - } - - private void setSize() { - if (position > size) { - size = position; - } - } - } - - private class WriterOperation extends JavaVMOperation { - - private final AllocationFreeDataOutputStream dataOutput; - private final boolean gcBefore; - private IOException exception; - - WriterOperation(FileOutputStream fileOutputStream, boolean gcBefore) throws IOException { - super(VMOperationInfos.get(WriterOperation.class, "Write heap dump", VMOperation.SystemEffect.SAFEPOINT)); - /* open file stream and create buffered data output stream. */ - AllocationFreeFileOutputStream fos = ImageSingletons.lookup(AllocationFreeFileOutputStream.class).newStreamFor(fileOutputStream); - dataOutput = new AllocationFreeDataOutputStream(new AllocationFreeBufferedOutputStream(fos)); - this.gcBefore = gcBefore; - } - - WriterOperation(AllocationFreeOutputStream outputStream, boolean gcBefore, int bufferSize) { - super(VMOperationInfos.get(WriterOperation.class, "Write heap dump", VMOperation.SystemEffect.SAFEPOINT)); - /* open file stream and create buffered data output stream. */ - AllocationFreeFileOutputStream fos = new AllocationFreeFileOutputStreamWrapper(outputStream); - dataOutput = new AllocationFreeDataOutputStream(new AllocationFreeBufferedOutputStream(fos, bufferSize + 32768)); - this.gcBefore = gcBefore; - } - - @Override - protected void operate() { - try { - writeTo(dataOutput, gcBefore); - } catch (IOException ex) { - exception = ex; - } - } - - private IOException getException() { - return exception; - } - - } - - /** A map from Class to ClassData. */ - private static class ClassToClassDataMap { - - private final ClassData[] classDataArray; - - ClassToClassDataMap(Map, ClassData> map) { - /* Find the maximum typeID among the classes. */ - int maxTypeID = 0; - for (Class key : map.keySet()) { - maxTypeID = Integer.max(maxTypeID, typeIDFromClass(key)); - } - /* Make up an array large enough to be indexed by typeID. */ - classDataArray = new ClassData[maxTypeID + 1]; - /* Fill in the array. */ - for (Class key : map.keySet()) { - classDataArray[typeIDFromClass(key)] = map.get(key); - } - } - - /** Use typeID to find the Class. */ - ClassData get(Class clazz) { - int id = typeIDFromClass(clazz); - if (id >= classDataArray.length) { - return null; // class not loaded, there can be no instances - } - return classDataArray[id]; - } - - /** Look up the typeID of a Class from the DynamicHub. */ - private static int typeIDFromClass(Class clazz) { - return DynamicHub.fromClass(clazz).getTypeID(); - } - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java index 20fa428f8aaa..cf38b9a86f0b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/UninterruptibleAnnotationChecker.java @@ -28,30 +28,27 @@ import java.util.Set; import java.util.TreeSet; -import jdk.graal.compiler.graph.Node; -import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.nodes.java.AbstractNewObjectNode; -import jdk.graal.compiler.nodes.java.MonitorEnterNode; -import jdk.graal.compiler.nodes.java.NewMultiArrayNode; -import jdk.graal.compiler.nodes.virtual.CommitAllocationNode; -import jdk.graal.compiler.options.Option; -import jdk.graal.compiler.options.OptionsParser; import org.graalvm.nativeimage.AnnotationAccess; import org.graalvm.nativeimage.ImageSingletons; -import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.c.function.CFunction; import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; import com.oracle.svm.core.option.HostedOptionKey; -import com.oracle.svm.core.os.RawFileOperationSupport; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.meta.HostedMethod; +import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.nodes.StructuredGraph; +import jdk.graal.compiler.nodes.java.AbstractNewObjectNode; +import jdk.graal.compiler.nodes.java.MonitorEnterNode; +import jdk.graal.compiler.nodes.java.NewMultiArrayNode; +import jdk.graal.compiler.nodes.virtual.CommitAllocationNode; +import jdk.graal.compiler.options.Option; +import jdk.graal.compiler.options.OptionsParser; import jdk.vm.ci.meta.ResolvedJavaMethod; /** Checks that {@linkplain Uninterruptible} has been used consistently. */ @@ -111,7 +108,7 @@ private void reportViolations() { } private void checkSpecifiedOptions(HostedMethod method, Uninterruptible annotation) { - if (annotation == null || !useStrictChecking()) { + if (annotation == null) { return; } @@ -168,17 +165,6 @@ private static boolean isSimilarToUnspecificReason(String reason) { return OptionsParser.stringSimilarity(Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE, reason) > 0.75; } - private static boolean useStrictChecking() { - if (SubstrateOptions.AllowVMInternalThreads.getValue()) { - return true; - } - /* - * Use less strict checking for certain legacy code. The strict checking activates once a - * custom RawFileOperationSupport is implemented (see GR-44538). - */ - return RawFileOperationSupport.isPresent() && !Platform.includedIn(Platform.LINUX.class); - } - /** * Check that each method annotated with {@linkplain Uninterruptible} is overridden with * implementations that are also annotated with {@linkplain Uninterruptible}, with the same diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java index fb89f3d9bede..c572af6f462a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpFeature.java @@ -31,8 +31,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; -import jdk.graal.compiler.core.common.util.TypeConversion; -import jdk.graal.compiler.core.common.util.UnsafeArrayTypeWriter; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.hosted.Feature; @@ -47,17 +45,15 @@ import com.oracle.svm.core.heap.dump.HeapDumpStartupHook; import com.oracle.svm.core.heap.dump.HeapDumpWriter; import com.oracle.svm.core.heap.dump.HeapDumping; -import com.oracle.svm.core.heapdump.HeapDumpSupportImpl; -import com.oracle.svm.core.heapdump.HeapDumpUtils; -import com.oracle.svm.core.heapdump.HeapDumpWriterImpl; import com.oracle.svm.core.jdk.RuntimeSupport; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SharedType; -import com.oracle.svm.core.os.RawFileOperationSupport; import com.oracle.svm.core.util.ByteArrayReader; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl.AfterCompilationAccessImpl; +import jdk.graal.compiler.core.common.util.TypeConversion; +import jdk.graal.compiler.core.common.util.UnsafeArrayTypeWriter; import jdk.vm.ci.meta.ResolvedJavaField; /** @@ -82,26 +78,12 @@ public boolean isInConfiguration(IsInConfigurationAccess access) { @Override public void duringSetup(DuringSetupAccess access) { - if (useLegacyImplementation()) { - HeapDumping heapDumpSupport = new HeapDumpSupportImpl(); - - ImageSingletons.add(HeapDumpSupport.class, heapDumpSupport); - ImageSingletons.add(HeapDumping.class, heapDumpSupport); - ImageSingletons.add(HeapDumpUtils.class, new HeapDumpUtils()); - ImageSingletons.add(com.oracle.svm.core.heapdump.HeapDumpWriter.class, new HeapDumpWriterImpl()); - } else { - HeapDumpMetadata metadata = new HeapDumpMetadata(); - HeapDumping heapDumpSupport = new com.oracle.svm.core.heap.dump.HeapDumpSupportImpl(metadata); + HeapDumpMetadata metadata = new HeapDumpMetadata(); + HeapDumping heapDumpSupport = new com.oracle.svm.core.heap.dump.HeapDumpSupportImpl(metadata); - ImageSingletons.add(HeapDumpSupport.class, heapDumpSupport); - ImageSingletons.add(HeapDumping.class, heapDumpSupport); - ImageSingletons.add(HeapDumpMetadata.class, metadata); - } - } - - public static boolean useLegacyImplementation() { - /* See GR-44538. */ - return !RawFileOperationSupport.isPresent(); + ImageSingletons.add(HeapDumpSupport.class, heapDumpSupport); + ImageSingletons.add(HeapDumping.class, heapDumpSupport); + ImageSingletons.add(HeapDumpMetadata.class, metadata); } @Override @@ -116,16 +98,9 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { @Override public void afterCompilation(Feature.AfterCompilationAccess access) { AfterCompilationAccessImpl accessImpl = (AfterCompilationAccessImpl) access; - if (useLegacyImplementation()) { - byte[] fieldMap = HeapDumpHostedUtils.dumpFieldsMap(accessImpl.getTypes()); - - HeapDumpUtils.getHeapDumpUtils().setFieldsMap(fieldMap); - access.registerAsImmutable(fieldMap); - } else { - byte[] metadata = encodeMetadata(accessImpl.getTypes()); - HeapDumpMetadata.singleton().setData(metadata); - access.registerAsImmutable(metadata); - } + byte[] metadata = encodeMetadata(accessImpl.getTypes()); + HeapDumpMetadata.singleton().setData(metadata); + access.registerAsImmutable(metadata); } /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpHostedUtils.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpHostedUtils.java deleted file mode 100644 index 8fd3c0114683..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/HeapDumpHostedUtils.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.hosted.heap; - -import java.io.UnsupportedEncodingException; -import java.util.Collection; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -import com.oracle.svm.core.meta.SharedField; -import com.oracle.svm.core.meta.SharedType; -import com.oracle.svm.core.util.ByteArrayReader; -import com.oracle.svm.core.util.VMError; - -import jdk.graal.compiler.core.common.util.TypeConversion; -import jdk.graal.compiler.core.common.util.UnsafeArrayTypeWriter; -import jdk.vm.ci.meta.ResolvedJavaField; - -/** Legacy implementation, only used by other legacy code (see GR-44538). */ -class HeapDumpHostedUtils { - - @Platforms(Platform.HOSTED_ONLY.class) - public static byte[] dumpFieldsMap(Collection types) { - UnsafeArrayTypeWriter writeBuffer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); - - writeFieldsInfo(writeBuffer, types); - int length = TypeConversion.asS4(writeBuffer.getBytesWritten()); - return writeBuffer.toArray(new byte[length]); - } - - @Platforms(Platform.HOSTED_ONLY.class) - public static void writeFieldsInfo(UnsafeArrayTypeWriter writeBuffer, Collection types) { - for (SharedType type : types) { - /* I am only interested in instance types. */ - if (type.isInstanceClass()) { - /* Get the direct fields of the class. */ - final ResolvedJavaField[] fields = type.getInstanceFields(false); - /* Get the static fields of the class. */ - final ResolvedJavaField[] sfields = type.getStaticFields(); - /* I am only interested in classes with some fields. */ - if (fields.length == 0 && sfields.length == 0) { - continue; - } - /* Write the class name */ - writeString(writeBuffer, type.toClassName()); - - /* Write each direct field and offset. */ - for (ResolvedJavaField resolvedJavaField : inHotSpotFieldOrder(fields)) { - if (resolvedJavaField instanceof SharedField) { - final SharedField field = (SharedField) resolvedJavaField; - - writeField(field, writeBuffer); - } - } - writeBuffer.putU1(0); - /* Write each static field and offset. */ - for (ResolvedJavaField resolvedJavaField : inHotSpotFieldOrder(sfields)) { - if (resolvedJavaField instanceof SharedField) { - final SharedField field = (SharedField) resolvedJavaField; - if (!field.isAccessed()) { - /* I am only interested in fields that are used. */ - continue; - } - if (!field.isWritten() && field.isValueAvailable()) { - /* I am only interested in fields that are not constants. */ - continue; - } - writeField(field, writeBuffer); - } - } - writeBuffer.putU1(0); - } - } - } - - @Platforms(Platform.HOSTED_ONLY.class) - private static void writeField(final SharedField field, UnsafeArrayTypeWriter writeBuffer) { - final int location = field.getLocation(); - /* I am only interested in fields that have locations. */ - if (location < 0) { - return; - } - writeString(writeBuffer, field.getName()); - writeBuffer.putU1(field.getJavaKind().getTypeChar()); - writeBuffer.putU1(field.getStorageKind().getTypeChar()); - writeBuffer.putU1((location >>> 24) & 0xFF); - writeBuffer.putU1((location >>> 16) & 0xFF); - writeBuffer.putU1((location >>> 8) & 0xFF); - writeBuffer.putU1((location >>> 0) & 0xFF); - } - - /* - * Write fields in the same order as in HotSpot heap dump. This is the reverse order of what SVM - * hands out. See also GR-6758. - */ - @Platforms(Platform.HOSTED_ONLY.class) - private static ResolvedJavaField[] inHotSpotFieldOrder(ResolvedJavaField[] fields) { - ResolvedJavaField[] reversed = new ResolvedJavaField[fields.length]; - - for (int i = 0; i < fields.length; i++) { - reversed[fields.length - 1 - i] = fields[i]; - } - return reversed; - } - - @Platforms(Platform.HOSTED_ONLY.class) - private static void writeString(UnsafeArrayTypeWriter writeBuffer, String name) { - try { - byte[] buf = name.getBytes("UTF-8"); - for (byte b : buf) { - writeBuffer.putU1(b); - } - writeBuffer.putU1(0); - } catch (UnsupportedEncodingException ex) { - VMError.shouldNotReachHere(ex); - } - } -} From ec7c3f092bf4fe1d419817fe6ea11cc2da4b6d79 Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Mon, 22 Jan 2024 17:38:31 +0100 Subject: [PATCH 42/75] array length test: add test penetrating non inlined case --- .../core/test/ArrayLengthProviderTest.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/ArrayLengthProviderTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/ArrayLengthProviderTest.java index 32b68c2ad08b..546b1ec23aff 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/ArrayLengthProviderTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/ArrayLengthProviderTest.java @@ -30,6 +30,12 @@ import org.junit.Test; +import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.java.BytecodeParserOptions; +import jdk.graal.compiler.nodes.spi.ProfileProvider; +import jdk.graal.compiler.options.OptionValues; +import jdk.vm.ci.meta.ResolvedJavaMethod; + public class ArrayLengthProviderTest extends GraalCompilerTest { public static Object test0Snippet(ArrayList list, boolean a) { @@ -56,7 +62,7 @@ public static Object test0Snippet(ArrayList list, boolean a) { } } - public static Object test1Snippet(ArrayList list, boolean a, boolean b) { + public static Object test1Snippet(List list, boolean a, boolean b) { while (true) { Object[] array = toArray(list); if (a || b) { @@ -72,6 +78,16 @@ public static Object[] toArray(List list) { return new Object[list.size()]; } + @Override + protected ProfileProvider getProfileProvider(ResolvedJavaMethod method) { + if (profile) { + return null; + } + return NO_PROFILE_PROVIDER; + } + + boolean profile = true; + @Test public void test0() { test("test0Snippet", new ArrayList<>(Arrays.asList("a", "b")), true); @@ -80,5 +96,15 @@ public void test0() { @Test public void test1() { test("test1Snippet", new ArrayList<>(Arrays.asList("a", "b")), true, true); + + } + + @Test + public void test2() { + resetCache(); + profile = false; + OptionValues o = new OptionValues(getInitialOptions(), GraalOptions.LoopUnswitch, false, BytecodeParserOptions.InlineDuringParsing, false); + test(o, "test1Snippet", new ArrayList<>(Arrays.asList("a", "b")), true, true); + profile = true; } } From 2f1f657d73fa709aebfa9693c16e8e4450d7ac5a Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Tue, 23 Jan 2024 13:17:38 +0100 Subject: [PATCH 43/75] loop utility: unify canUseWithoutProxy --- ...minatorBasedGlobalValueNumberingPhase.java | 22 ++------- .../phases/common/util/LoopUtility.java | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 18 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java index 858fd1c8fdba..e511c4f00203 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/DominatorBasedGlobalValueNumberingPhase.java @@ -28,6 +28,7 @@ import java.util.Arrays; import java.util.Optional; +import jdk.graal.compiler.phases.common.util.LoopUtility; import jdk.graal.compiler.phases.util.GraphOrder; import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.core.common.GraalOptions; @@ -612,24 +613,9 @@ public void substitute(Node n, ControlFlowGraph cfg, NodeBitMap licmNodes, LoopE } } - HIRBlock useBlock = cfg.blockFor(n); - Loop defLoop = defBlock.getLoop(); - Loop useLoop = useBlock.getLoop(); - - if (defLoop != null) { - // the def is inside a loop, either a parent or a disjunct loop - if (useLoop != null) { - // we are only safe without proxies if we are included in the def loop, - // i.e., the def loop is a parent loop - if (!useLoop.isAncestorOrSelf(defLoop)) { - earlyGVNAbort.increment(graph.getDebug()); - return; - } - } else { - // the use is not in a loop but the def is, needs proxies, fail - earlyGVNAbort.increment(graph.getDebug()); - return; - } + if (!LoopUtility.canUseWithoutProxy(cfg, edgeDataEqual, n)) { + earlyGVNAbort.increment(graph.getDebug()); + return; } graph.getDebug().log(DebugContext.VERY_DETAILED_LEVEL, "Early GVN: replacing %s with %s", n, edgeDataEqual); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/util/LoopUtility.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/util/LoopUtility.java index 0d44d1e19a33..8fe102300bab 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/util/LoopUtility.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/util/LoopUtility.java @@ -26,10 +26,14 @@ import java.util.EnumSet; +import jdk.graal.compiler.core.common.cfg.Loop; import jdk.graal.compiler.core.common.type.IntegerStamp; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.graph.Graph.NodeEvent; import jdk.graal.compiler.graph.Graph.NodeEventScope; +import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.nodes.FixedNode; +import jdk.graal.compiler.nodes.GraphState.StageFlag; import jdk.graal.compiler.nodes.LoopExitNode; import jdk.graal.compiler.nodes.NodeView; import jdk.graal.compiler.nodes.ProxyNode; @@ -39,6 +43,8 @@ import jdk.graal.compiler.nodes.calc.AddNode; import jdk.graal.compiler.nodes.calc.IntegerConvertNode; import jdk.graal.compiler.nodes.calc.MulNode; +import jdk.graal.compiler.nodes.cfg.ControlFlowGraph; +import jdk.graal.compiler.nodes.cfg.HIRBlock; import jdk.graal.compiler.nodes.loop.BasicInductionVariable; import jdk.graal.compiler.nodes.loop.InductionVariable; import jdk.graal.compiler.nodes.loop.LoopEx; @@ -48,6 +54,47 @@ public class LoopUtility { + /** + * Determine if the def can use node {@code use} without the need for value proxies. This means + * there is no loop exit between the schedule point of def and use that would require a + * {@link ProxyNode}. + */ + public static boolean canUseWithoutProxy(ControlFlowGraph cfg, Node def, Node use) { + if (def.graph() instanceof StructuredGraph g && g.isAfterStage(StageFlag.VALUE_PROXY_REMOVAL)) { + return true; + } + if (!isFixedNode(def) || !isFixedNode(use)) { + /* + * If def or use are not fixed nodes we cannot determine the schedule point for them. + * Without the schedule point we cannot find their basic block in the control flow + * graph. If we would schedule the graph we could answer the question for floating nodes + * as well but this is too much overhead. Thus, for floating nodes we give up and assume + * a proxy is necessary. + */ + return false; + } + HIRBlock useBlock = cfg.blockFor(use); + HIRBlock defBlock = cfg.blockFor(def); + Loop defLoop = defBlock.getLoop(); + Loop useLoop = useBlock.getLoop(); + if (defLoop != null) { + // the def is inside a loop, either a parent or a disjunct loop + if (useLoop != null) { + // we are only safe without proxies if we are included in the def loop, + // i.e., the def loop is a parent loop + return useLoop.isAncestorOrSelf(defLoop); + } else { + // the use is not in a loop but the def is, needs proxies, fail + return false; + } + } + return true; + } + + private static boolean isFixedNode(Node n) { + return n instanceof FixedNode; + } + public static boolean isNumericInteger(ValueNode v) { Stamp s = v.stamp(NodeView.DEFAULT); return s instanceof IntegerStamp; From 4ac09fc596b7f5ecbc14aded344c07cd979e4854 Mon Sep 17 00:00:00 2001 From: Olga MaciaszekSharma Date: Mon, 20 Nov 2023 15:05:51 +0100 Subject: [PATCH 44/75] Update java.security path. --- docs/reference-manual/native-image/JCASecurityServices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference-manual/native-image/JCASecurityServices.md b/docs/reference-manual/native-image/JCASecurityServices.md index 97ad6428e423..86cbbb35da8b 100644 --- a/docs/reference-manual/native-image/JCASecurityServices.md +++ b/docs/reference-manual/native-image/JCASecurityServices.md @@ -39,7 +39,7 @@ The report will detail all registered service classes, the API methods that trig ## Provider Registration The `native-image` builder captures the list of providers and their preference order from the underlying JVM. -The provider order is specified in the `java.security` file under `/lib/security/java.security`. +The provider order is specified in the `java.security` file under `/conf/security/java.security`. New security providers cannot be registered at run time; all providers must be statically configured at executable build time. ## Providers Reordering at Run Time From 8e70229d54e38e1194f0062ea16d0ff96dc5be42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Wed, 8 Nov 2023 09:52:48 +0100 Subject: [PATCH 45/75] Document debugging native image agent --- .../src/com.oracle.svm.agent/README.md | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 substratevm/src/com.oracle.svm.agent/README.md diff --git a/substratevm/src/com.oracle.svm.agent/README.md b/substratevm/src/com.oracle.svm.agent/README.md new file mode 100644 index 000000000000..31509d3b28ab --- /dev/null +++ b/substratevm/src/com.oracle.svm.agent/README.md @@ -0,0 +1,77 @@ +# Debugging the agent with GDB + +The native image agent is a native library that uses JVMTI. +In this document you will learn how to debug the agent. + +Debugging an agent requires building it with its debug symbols. +To do that, execute: + +```bash +$ native-image -g --macro:native-image-agent-library +``` + +Next, in order to debug the agent, +the java process that runs agent needs to be executed from within GDB, +assuming that the `java` executable is located in the same `JAVA_HOME` as `native-image`, the agent and its debug symbols: + +```bash +$ gdb java +``` + +Then set the agent arguments for the java process: + +```bash +(gdb) set args -agentlib:native-image-agent=config-output-dir=./native-image-config -jar app.jar +``` + +You can verify that the debug symbols for the agent have been loaded correctly by doing a function lookup: + +```bash +(gdb) info functions .*NativeImageAgent.* +All functions matching regular expression ".*NativeImageAgent.*": +File com/oracle/svm/agent/NativeImageAgent.java: + java.lang.Thread *com.oracle.svm.agent.NativeImageAgent$$Lambda$6779d0e96277d8fe370fc5f15b4e13f019254f7b::newThread(java.lang.Runnable*); + java.lang.Object *com.oracle.svm.agent.NativeImageAgent$$Lambda$6a9ae4f1adc7f691a2f72e41ee6242d9fe025668::apply(java.lang.Object*); + void com.oracle.svm.agent.NativeImageAgent$$Lambda$9615ae4da57d74c8ad20a2e088bd90fe293fc9de::run(); + java.lang.Object *com.oracle.svm.agent.NativeImageAgent$$Lambda$cd8007efd97585a6afbd18bf031cf260625a4fde::apply(java.lang.Object*); + boolean com.oracle.svm.agent.NativeImageAgent$$Lambda$cdd28b87151f02b2dfa4883a6fb6fe7d0b2ee020::test(java.lang.Object*); +508: int com.oracle.svm.agent.NativeImageAgent::buildImage(com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEnv); +663: void com.oracle.svm.agent.NativeImageAgent::compulsoryDelete(java.nio.file.Path*); +639: void com.oracle.svm.agent.NativeImageAgent::expectUnmodified(java.nio.file.Path*); +111: boolean com.oracle.svm.agent.NativeImageAgent::getBooleanTokenValue(java.lang.String*); +654: java.nio.file.attribute.FileTime *com.oracle.svm.agent.NativeImageAgent::getMostRecentlyModified(java.nio.file.Path*, java.nio.file.attribute.FileTime*); +107: java.lang.String *com.oracle.svm.agent.NativeImageAgent::getTokenValue(java.lang.String*); +481: void com.oracle.svm.agent.NativeImageAgent::ignoreConfigFromClasspath(com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEnv, com.oracle.svm.configure.config.ConfigurationFileCollection*); +405: void com.oracle.svm.agent.NativeImageAgent::inform(java.lang.String*); +119: boolean com.oracle.svm.agent.NativeImageAgent::isBooleanOption(java.lang.String*, java.lang.String*); +350: java.lang.Exception *com.oracle.svm.agent.NativeImageAgent::lambda$onLoadCallback$1(java.io.IOException*); +469: java.lang.Thread *com.oracle.svm.agent.NativeImageAgent::lambda$setupExecutorServiceForPeriodicConfigurationCapture$2(java.lang.Runnable*); +134: int com.oracle.svm.agent.NativeImageAgent::onLoadCallback(com.oracle.svm.core.jni.headers.JNIJavaVM, com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEnv, com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEventCallbacks, java.lang.String*); +... +``` + +Put a breakpoint: + +```bash +(gdb) break com.oracle.svm.agent.NativeImageAgent::onLoadCallback +Breakpoint 2 at 0x7ffff4cdf550: file com/oracle/svm/agent/NativeImageAgent.java, line 134. +``` + +Optionally, disable `SIGSEGV` signal is recommended to avoid signal handlers that HotSpot uses for safepoints: + +```bash +(gdb) handle SIGSEGV nostop noprint +``` + +Finally, execute the process from within GDB to stop at the breakpoint: + +```bash +(gdb) run +Starting program: java -agentlib:native-image-agent=config-output-dir=./native-image-config -jar app.jar +[Thread debugging using libthread_db enabled] +Using host libthread_db library "/lib64/libthread_db.so.1". +[Switching to Thread 0x7ffff67ff6c0 (LWP 50250)] + +Thread 2 "java" hit Breakpoint 2, com.oracle.svm.agent.NativeImageAgent::onLoadCallback(com.oracle.svm.core.jni.headers.JNIJavaVM, com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEnv, com.oracle.svm.jvmtiagentbase.jvmti.JvmtiEventCallbacks, java.lang.String*) (this=0x7fffe4e5b6f0, vm=0x7ffff7be8fa0 , + jvmti=, callbacks=, options=) at com/oracle/svm/agent/NativeImageAgent.java:134 +``` From 7a7ce85af24e94d0113b9c0b4d01a4e04a0a3e78 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Galder=20Zamarren=CC=83o?= Date: Thu, 9 Nov 2023 06:18:44 +0100 Subject: [PATCH 46/75] Merge java command with its args and minor grammar fix --- substratevm/src/com.oracle.svm.agent/README.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/substratevm/src/com.oracle.svm.agent/README.md b/substratevm/src/com.oracle.svm.agent/README.md index 31509d3b28ab..5e44254a1903 100644 --- a/substratevm/src/com.oracle.svm.agent/README.md +++ b/substratevm/src/com.oracle.svm.agent/README.md @@ -15,13 +15,7 @@ the java process that runs agent needs to be executed from within GDB, assuming that the `java` executable is located in the same `JAVA_HOME` as `native-image`, the agent and its debug symbols: ```bash -$ gdb java -``` - -Then set the agent arguments for the java process: - -```bash -(gdb) set args -agentlib:native-image-agent=config-output-dir=./native-image-config -jar app.jar +$ gdb java --args -agentlib:native-image-agent=config-output-dir=./native-image-config -jar app.jar ``` You can verify that the debug symbols for the agent have been loaded correctly by doing a function lookup: @@ -57,7 +51,7 @@ Put a breakpoint: Breakpoint 2 at 0x7ffff4cdf550: file com/oracle/svm/agent/NativeImageAgent.java, line 134. ``` -Optionally, disable `SIGSEGV` signal is recommended to avoid signal handlers that HotSpot uses for safepoints: +Optionally, disabling `SIGSEGV` signal is recommended to avoid signal handlers that HotSpot uses for safepoints: ```bash (gdb) handle SIGSEGV nostop noprint From 889de267e6030cf9280c475d36b722285026fa4d Mon Sep 17 00:00:00 2001 From: "dmitrii.bocharov" Date: Wed, 11 Oct 2023 10:22:55 +0200 Subject: [PATCH 47/75] Update main CONTRIBUTING.md When trying to find the info about how-to contribute the first time, it is a long way from CONTRIBUTING.md to graalvm website then to the youtube video, which will lead you to the compiler/README.md. I think with this change the way to your first contribution becomes much straighter and shorter --- CONTRIBUTING.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 333b3f83e71a..575838c4515c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,4 +3,5 @@ platform. There have been significant contributions from both industry and academia so far and we thank you for considering to contribute your changes! - Learn [how to become a GraalVM contributor](https://www.graalvm.org/community/contributors/). + - Check individual README.md and CONTRIBUTING.md files in the subprojects to learn how to build and import them into your IDE (for example, [the compiler README.md](compiler/README.md)) - Subscribe and post to [graalvm-dev@oss.oracle.com](https://oss.oracle.com/mailman/listinfo/graalvm-dev) for questions related to working with the sources or extending the GraalVM ecosystem by creating new languages, tools, or embeddings. From 1ac39ecc215c7d0c4cc6ba3f4c029234a36c7585 Mon Sep 17 00:00:00 2001 From: Lucas Werkmeister Date: Sat, 19 Sep 2020 21:15:13 +0200 Subject: [PATCH 48/75] Fix code samples in Dynamic Object Model tutorial --- truffle/docs/DynamicObjectModel.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/truffle/docs/DynamicObjectModel.md b/truffle/docs/DynamicObjectModel.md index 9e06845ad12e..4bfcc97a9ef5 100644 --- a/truffle/docs/DynamicObjectModel.md +++ b/truffle/docs/DynamicObjectModel.md @@ -168,8 +168,8 @@ public abstract class MakePairNode extends BinaryExpressionNode { @Specialization Object makePair(Object left, Object right, @CachedLanguage MyLanguage language, - @CachedLibrary(limit = "3") putLeft, - @CachedLibrary(limit = "3") putRight) { + @CachedLibrary(limit = "3") DynamicObjectLibrary putLeft, + @CachedLibrary(limit = "3") DynamicObjectLibrary putRight) { MyObject obj = language.createObject(); putLeft.put(obj, "left", left); putRight.put(obj, "right", right); From 945331f11d84ac0a1ae5beb996b0c4ff1b271e38 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 25 Jan 2024 09:46:42 +0100 Subject: [PATCH 49/75] Add missing reference to `ProxyInstantiable`. Thanks to @souenzzo for pointing this out. --- .../src/org/graalvm/polyglot/proxy/Proxy.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/Proxy.java b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/Proxy.java index 8592c185523f..f1b195e9e401 100644 --- a/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/Proxy.java +++ b/sdk/src/org.graalvm.polyglot/src/org/graalvm/polyglot/proxy/Proxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -80,6 +80,7 @@ * @see ProxyTimeZone to mimic timezone objects * @see ProxyDuration to mimic duration objects * @see ProxyInstant to mimic timestamp objects + * @see ProxyInstantiable to mimic objects that are instantiable * @see ProxyIterable to mimic iterable objects * @see ProxyIterator to mimic iterator objects * @see ProxyHashMap to mimic map objects From 28deb3314587d63343b1c38098ca362d1630ad66 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Thu, 14 Dec 2023 14:43:25 +0100 Subject: [PATCH 50/75] Make code compatible with ECJ 3.36. --- .../nodeinfo/processor/GraphNodeVerifier.java | 2 +- .../compiler/core/phases/CEOptimization.java | 3 +- .../stubs/AbstractForeignCallStub.java | 11 +++-- .../hotspot/stubs/ForeignCallStub.java | 12 ++--- .../jdk/graal/compiler/lir/GenerateStub.java | 14 +++--- .../amd64/AMD64CalcStringAttributesOp.java | 11 ++--- .../phases/StackMoveOptimizationPhase.java | 9 ++-- .../stackslotalloc/LSStackSlotAllocator.java | 4 +- .../compiler/nodes/extended/RawLoadNode.java | 2 +- .../phases/common/HighTierLoweringPhase.java | 2 +- .../phases/common/LowTierLoweringPhase.java | 2 +- .../phases/common/MidTierLoweringPhase.java | 2 +- .../replacements/NonNullParameterPlugin.java | 3 +- .../replacements/ReplacementsImpl.java | 13 ++++-- .../replacements/nodes/MethodHandleNode.java | 6 +-- .../processor/test/TestJNIConfig.java | 2 +- .../benchmark/DSLInterpreterBenchmark.java | 16 +++---- .../api/benchmark/NodeInliningBenchmark.java | 20 ++++---- .../truffle/api/dsl/test/NodeCostTest.java | 9 ++-- .../truffle/api/dsl/test/NodeFieldTest.java | 46 +++++++------------ .../truffle/api/dsl/test/PolymorphicTest.java | 2 +- .../dsl/processor/model/MessageContainer.java | 2 +- .../processor/model/SpecializationData.java | 2 +- .../dsl/processor/parser/NodeParser.java | 8 ++-- .../truffle/runtime/ModulesAccessor.java | 4 +- .../runtime/OptimizedTruffleRuntime.java | 2 +- 26 files changed, 93 insertions(+), 116 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java index 5791c3a61f28..ce6f7e870e39 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/nodeinfo/processor/GraphNodeVerifier.java @@ -82,7 +82,7 @@ public GraphNodeVerifier(AbstractProcessor processor) { /** * Returns a type element given a canonical name. * - * @throws {@link NoClassDefFoundError} if a type element does not exist for {@code name} + * @throws NoClassDefFoundError if a type element does not exist for {@code name} */ public TypeElement getTypeElement(String name) { return processor.getTypeElement(name); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java index 3d3df746bc1f..71a1e989f84b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java @@ -25,7 +25,6 @@ package jdk.graal.compiler.core.phases; import jdk.graal.compiler.core.common.GraalOptions; -import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import jdk.graal.compiler.loop.phases.LoopFullUnrollPhase; import jdk.graal.compiler.loop.phases.LoopPartialUnrollPhase; @@ -74,7 +73,7 @@ public enum CEOptimization { * * @see Canonicalizable#canonical(CanonicalizerTool) * @see Simplifiable#simplify(SimplifierTool) - * @see Node.ValueNumberable + * @see jdk.graal.compiler.graph.Node.ValueNumberable * */ Canonicalization(null, CanonicalizerPhase.class), diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java index bea574ddd69c..54f5fe2362a9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java @@ -60,11 +60,12 @@ import jdk.vm.ci.meta.Signature; /** - * A {@linkplain #getGraph generated} stub for a {@link HotSpotForeignCallDescriptor.Transition - * non-leaf} foreign call from compiled code. A stub is required for such calls as the caller may be - * scheduled for deoptimization while the call is in progress. And since these are foreign/runtime - * calls on slow paths, we don't want to force the register allocator to spill around the call. As - * such, this stub saves and restores all allocatable registers. It also + * A {@linkplain #getGraph generated} stub for a + * {@link jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition non-leaf} foreign + * call from compiled code. A stub is required for such calls as the caller may be scheduled for + * deoptimization while the call is in progress. And since these are foreign/runtime calls on slow + * paths, we don't want to force the register allocator to spill around the call. As such, this stub + * saves and restores all allocatable registers. It also * {@linkplain ForeignCallSnippets#handlePendingException handles} any exceptions raised during the * foreign call. */ diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java index 761e3560b066..82445cc1905f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java @@ -38,16 +38,16 @@ import jdk.graal.compiler.replacements.GraphKit; import jdk.graal.compiler.replacements.nodes.ReadRegisterNode; import jdk.graal.compiler.word.Word; - import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.JavaKind; /** - * A {@linkplain #getGraph generated} stub for a {@link HotSpotForeignCallDescriptor.Transition - * non-leaf} foreign call from compiled code. A stub is required for such calls as the caller may be - * scheduled for deoptimization while the call is in progress. And since these are foreign/runtime - * calls on slow paths, we don't want to force the register allocator to spill around the call. As - * such, this stub saves and restores all allocatable registers. It also + * A {@linkplain #getGraph generated} stub for a + * {@link jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition non-leaf} foreign + * call from compiled code. A stub is required for such calls as the caller may be scheduled for + * deoptimization while the call is in progress. And since these are foreign/runtime calls on slow + * paths, we don't want to force the register allocator to spill around the call. As such, this stub + * saves and restores all allocatable registers. It also * {@linkplain ForeignCallSnippets#handlePendingException handles} any exceptions raised during the * foreign call. */ diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java index a6567364859f..47259ff267b5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.lir; -import jdk.graal.compiler.graph.Node; - import java.lang.annotation.ElementType; import java.lang.annotation.Repeatable; import java.lang.annotation.Retention; @@ -34,8 +32,9 @@ /** * Generate a stub to be called via foreign call. This annotation is valid for methods annotated - * with {@link Node.NodeIntrinsic} only. To trigger stub generation, a marker class annotated with - * {@link GeneratedStubsHolder} is required. Processed by {@code IntrinsicStubProcessor}. + * with {@link jdk.graal.compiler.graph.Node.NodeIntrinsic} only. To trigger stub generation, a + * marker class annotated with {@link GeneratedStubsHolder} is required. Processed by + * {@code IntrinsicStubProcessor}. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) @@ -48,9 +47,10 @@ String name() default ""; /** - * Optional values for parameters annotated with {@link Node.ConstantNodeParameter}. The string - * content is pasted as-is into the generated code, with the only exception being enum values - - * in that case, the enum class name and a dot is prepended to the string. + * Optional values for parameters annotated with + * {@link jdk.graal.compiler.graph.Node.ConstantNodeParameter}. The string content is pasted + * as-is into the generated code, with the only exception being enum values - in that case, the + * enum class name and a dot is prepended to the string. */ String[] parameters() default {}; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java index d88d96b8f487..063a169815dd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java @@ -24,10 +24,6 @@ */ package jdk.graal.compiler.lir.amd64; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.rsi; -import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Equal; import static jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag.Less; import static jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag.NotEqual; @@ -37,6 +33,10 @@ import static jdk.graal.compiler.asm.amd64.AVXKind.AVXSize.QWORD; import static jdk.graal.compiler.asm.amd64.AVXKind.AVXSize.XMM; import static jdk.graal.compiler.asm.amd64.AVXKind.AVXSize.YMM; +import static jdk.vm.ci.amd64.AMD64.rcx; +import static jdk.vm.ci.amd64.AMD64.rdx; +import static jdk.vm.ci.amd64.AMD64.rsi; +import static jdk.vm.ci.code.ValueUtil.asRegister; import java.util.Arrays; import java.util.EnumSet; @@ -56,7 +56,6 @@ import jdk.graal.compiler.lir.Opcode; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import jdk.graal.compiler.lir.gen.LIRGeneratorTool; - import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; @@ -172,7 +171,7 @@ private int elementsPerVector(AMD64BaseAssembler.OperandSize size) { * @param array arbitrary array. * @param byteOffset byteOffset to start from. Must include array base byteOffset! * @param length length of the array region to consider, scaled to - * {@link LIRGeneratorTool.CalcStringAttributesEncoding#stride}. + * {@link jdk.graal.compiler.lir.gen.LIRGeneratorTool.CalcStringAttributesEncoding#stride}. * @param assumeValid assume that the string is encoded correctly. */ public static AMD64CalcStringAttributesOp movParamsAndCreate(LIRGeneratorTool tool, LIRGeneratorTool.CalcStringAttributesEncoding encoding, EnumSet runtimeCheckedCPUFeatures, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index 0967dd67cfb8..adcf6a249ed7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -41,19 +41,18 @@ import jdk.graal.compiler.options.NestedBooleanOptionKey; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionType; - import jdk.vm.ci.code.Register; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Value; /** - * Replaces sequential {@link AMD64Move.AMD64StackMove}s of the same type with a single - * {@link AMD64Move.AMD64MultiStackMove} to avoid storing/restoring the scratch register multiple - * times. + * Replaces sequential {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64StackMove}s of the same + * type with a single {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove} to avoid + * storing/restoring the scratch register multiple times. * * Note: this phase must be inserted after {@link RedundantMoveElimination} phase because - * {@link AMD64Move.AMD64MultiStackMove} are not probably detected. + * {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove} are not probably detected. */ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase { public static class Options { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java index c1f4bd333d39..d163ca151431 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java @@ -38,6 +38,7 @@ import java.util.function.Predicate; import org.graalvm.collections.EconomicSet; + import jdk.graal.compiler.core.common.LIRKind; import jdk.graal.compiler.core.common.cfg.BasicBlock; import jdk.graal.compiler.debug.DebugCloseable; @@ -61,7 +62,6 @@ import jdk.graal.compiler.options.NestedBooleanOptionKey; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionType; - import jdk.vm.ci.code.CodeUtil; import jdk.vm.ci.code.StackSlot; import jdk.vm.ci.code.TargetDescription; @@ -74,7 +74,7 @@ * Remark: The analysis works under the assumption that a stack slot is no longer live after * its last usage. If an {@link LIRInstruction instruction} transfers the raw address of the stack * slot to another location, e.g. a registers, and this location is referenced later on, the - * {@link LIRInstruction.Use usage} of the stack slot must be marked with the + * {@link jdk.graal.compiler.lir.LIRInstruction.Use usage} of the stack slot must be marked with the * {@link OperandFlag#UNINITIALIZED}. Otherwise the stack slot might be reused and its content * destroyed. */ diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java index a2311dfd8678..b2f2d8baaada 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java @@ -82,7 +82,7 @@ public RawLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, Loca /** * This constructor exists for node intrinsics that need a stamp based on the return type of the - * {@link Node.NodeIntrinsic} annotated method. + * {@link jdk.graal.compiler.graph.Node.NodeIntrinsic} annotated method. */ public RawLoadNode(@InjectedNodeParameter Stamp stamp, ValueNode object, ValueNode offset, LocationIdentity locationIdentity, JavaKind accessKind) { super(TYPE, stamp, object, offset, accessKind, locationIdentity, false, MemoryOrderMode.PLAIN); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java index 825641b1d1c1..f7fdbcb9dd0c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java @@ -33,7 +33,7 @@ /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link LoweringTool.StandardLoweringStage#HIGH_TIER} stage. + * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#HIGH_TIER} stage. */ public class HighTierLoweringPhase extends LoweringPhase { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java index 9ea8b257713f..00856c5b1917 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java @@ -33,7 +33,7 @@ /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link LoweringTool.StandardLoweringStage#LOW_TIER} stage. + * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#LOW_TIER} stage. */ public class LowTierLoweringPhase extends LoweringPhase { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java index 9994bf2624cf..62c1a85674ba 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java @@ -33,7 +33,7 @@ /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link LoweringTool.StandardLoweringStage#MID_TIER} stage. + * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#MID_TIER} stage. */ public class MidTierLoweringPhase extends LoweringPhase { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java index 606424cb3e50..d7789b26b924 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java @@ -26,7 +26,6 @@ import java.util.BitSet; -import jdk.graal.compiler.api.replacements.Snippet; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.common.type.StampPair; @@ -38,7 +37,7 @@ /** * A {@link ParameterPlugin} that sets non-null stamps for parameters annotated with - * {@link Snippet.NonNullParameter}. + * {@link jdk.graal.compiler.api.replacements.Snippet.NonNullParameter}. */ public class NonNullParameterPlugin implements ParameterPlugin { private final BitSet nonNullParameters; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java index bbab25fe4e85..aad168b9d028 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java @@ -24,14 +24,14 @@ */ package jdk.graal.compiler.replacements; -import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; -import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import static jdk.graal.compiler.core.common.GraalOptions.UseSnippetGraphCache; import static jdk.graal.compiler.debug.DebugOptions.DebugStubsAndSnippets; import static jdk.graal.compiler.debug.DebugOptions.DumpOnError; import static jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import static jdk.graal.compiler.phases.common.DeadCodeEliminationPhase.Optionality.Required; +import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; +import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; import java.util.BitSet; import java.util.concurrent.ConcurrentHashMap; @@ -41,6 +41,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.Equivalence; import org.graalvm.collections.Pair; + import jdk.graal.compiler.api.replacements.Fold; import jdk.graal.compiler.api.replacements.Snippet; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; @@ -89,7 +90,6 @@ import jdk.graal.compiler.word.Word; import jdk.graal.compiler.word.WordOperationPlugin; import jdk.graal.compiler.word.WordTypes; - import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -353,7 +353,9 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo * @param nonNullParameters * @param original XXX always null? * @param trackNodeSourcePosition record source information - * @param context {@link IntrinsicContext.CompilationContext compilation context} for the graph + * @param context + * {@link jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext + * compilation context} for the graph */ public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, BitSet nonNullParameters, ResolvedJavaMethod original, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { @@ -362,7 +364,8 @@ public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodePr /** * Creates a preprocessed graph for a snippet or method substitution with a context of . - * {@link IntrinsicContext.CompilationContext#INLINE_AFTER_PARSING} . + * {@link jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext#INLINE_AFTER_PARSING} + * . * * @param bytecodeProvider how to access the bytecode of {@code method} * @param method the snippet or method substitution for which a graph will be created diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java index 20182616178f..9fea27f94a34 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java @@ -56,7 +56,6 @@ import jdk.graal.compiler.nodes.spi.SimplifierTool; import jdk.graal.compiler.nodes.type.StampTool; import jdk.graal.compiler.nodes.util.GraphUtil; - import jdk.vm.ci.meta.Assumptions; import jdk.vm.ci.meta.Assumptions.AssumptionResult; import jdk.vm.ci.meta.DeoptimizationAction; @@ -127,8 +126,9 @@ public GraphAdder(StructuredGraph graph) { } /** - * Call {@link StructuredGraph#addOrUnique(Node)} on {@code node} and link any - * {@link FixedWithNextNode}s into the current control flow. + * Call + * {@link jdk.graal.compiler.nodes.StructuredGraph#addOrUnique(jdk.graal.compiler.graph.Node)} + * on {@code node} and link any {@link FixedWithNextNode}s into the current control flow. * * @return the newly added node */ diff --git a/sdk/src/org.graalvm.nativebridge.processor.test/src/org/graalvm/nativebridge/processor/test/TestJNIConfig.java b/sdk/src/org.graalvm.nativebridge.processor.test/src/org/graalvm/nativebridge/processor/test/TestJNIConfig.java index e125162110a6..3b220c7dd247 100644 --- a/sdk/src/org.graalvm.nativebridge.processor.test/src/org/graalvm/nativebridge/processor/test/TestJNIConfig.java +++ b/sdk/src/org.graalvm.nativebridge.processor.test/src/org/graalvm/nativebridge/processor/test/TestJNIConfig.java @@ -52,7 +52,7 @@ public final class TestJNIConfig { - private static final BinaryMarshaller UNSUPPORTED = new BinaryMarshaller() { + private static final BinaryMarshaller UNSUPPORTED = new BinaryMarshaller<>() { @Override public Object read(BinaryInput input) { throw new UnsupportedOperationException(); diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java index 1bec23046618..15be6cf8d610 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java @@ -51,8 +51,6 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; -import com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen; -import com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.GenerateInline; import com.oracle.truffle.api.dsl.NeverDefault; @@ -86,7 +84,7 @@ public static class SimpleFirstIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(SimpleDSLNodeGen::create); + nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); } } @@ -105,7 +103,7 @@ public static class CachedFirstIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(CachedDSLNodeGen::create); + nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); } } @@ -123,7 +121,7 @@ public void tearDown() { @Setup public void setupInterpreterProfile() { for (int i = 0; i < 100; i++) { - AbstractNode node = createNode(SimpleDSLNodeGen::create); + AbstractNode node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); node.execute(42L); node.execute(42); try { @@ -131,7 +129,7 @@ public void setupInterpreterProfile() { } catch (UnsupportedSpecializationException e) { } - node = createNode(SimpleDSLNodeGen::create); + node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); node.execute(42); node.execute(42L); try { @@ -139,7 +137,7 @@ public void setupInterpreterProfile() { } catch (UnsupportedSpecializationException e) { } - node = createNode(CachedDSLNodeGen::create); + node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); node.execute(42); node.execute(42L); try { @@ -157,7 +155,7 @@ public static class SimpleSecondIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(SimpleDSLNodeGen::create); + nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); nodes[i].execute(42); } } @@ -172,7 +170,7 @@ public static class CachedSecondIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(CachedDSLNodeGen::create); + nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); nodes[i].execute(42); } } diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java index 46b84b17c9f7..d33501a35da3 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java @@ -52,10 +52,6 @@ import org.openjdk.jmh.annotations.TearDown; import com.oracle.truffle.api.Truffle; -import com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen; -import com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedSharedExclusiveNodeGen; -import com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen; -import com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedSharedExclusiveNodeGen; import com.oracle.truffle.api.dsl.Bind; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Cached.Shared; @@ -87,11 +83,11 @@ public static class BenchmarkState { final CachedSharedExclusiveNode[] sharedExclusiveCachedNodes = new CachedSharedExclusiveNode[INNER_LOOP]; { for (int i = 0; i < INNER_LOOP; i++) { - inlinedNodes[i] = InlinedNodeGen.create(); - cachedNodes[i] = CachedNodeGen.create(); + inlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); + cachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); - sharedExclusiveInlinedNodes[i] = InlinedSharedExclusiveNodeGen.create(); - sharedExclusiveCachedNodes[i] = CachedSharedExclusiveNodeGen.create(); + sharedExclusiveInlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedSharedExclusiveNodeGen.create(); + sharedExclusiveCachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedSharedExclusiveNodeGen.create(); sharedExclusiveInlinedNodes[i].execute(0, 0, 0, 0); sharedExclusiveInlinedNodes[i].execute(1, 0, 0, 0); @@ -118,8 +114,8 @@ public static class FirstCallState extends BenchmarkState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < INNER_LOOP; i++) { - inlinedNodes[i] = InlinedNodeGen.create(); - cachedNodes[i] = CachedNodeGen.create(); + inlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); + cachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); } } @@ -135,7 +131,7 @@ public void tearDownIteration() { public void createInlined(BenchmarkState state) { InlinedNode[] nodes = state.inlinedNodes; for (int i = 0; i < nodes.length; i++) { - nodes[i] = InlinedNodeGen.create(); + nodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); } } @@ -144,7 +140,7 @@ public void createInlined(BenchmarkState state) { public void createCached(BenchmarkState state) { CachedNode[] nodes = state.cachedNodes; for (int i = 0; i < nodes.length; i++) { - nodes[i] = CachedNodeGen.create(); + nodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); } } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java index 5d75415498d2..a8ed7c0d06c5 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java @@ -47,9 +47,6 @@ import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostViaMethodOverrideNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostWithNodeInfoNodeFactory; import com.oracle.truffle.api.dsl.test.TypeSystemTest.TestRootNode; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.nodes.NodeCost; @@ -59,7 +56,7 @@ public class NodeCostTest { @Test public void testNodeCost() { - TestRootNode node = TestHelper.createRoot(CostTestNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostTestNodeFactory.getInstance()); assertEquals(NodeCost.UNINITIALIZED, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); @@ -91,7 +88,7 @@ Object cost(Object left) { @Test public void testNodeCostViaMethodOverride() { - TestRootNode node = TestHelper.createRoot(CostViaMethodOverrideNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostViaMethodOverrideNodeFactory.getInstance()); assertEquals(NodeCost.NONE, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.NONE, node.getNode().getCost()); @@ -114,7 +111,7 @@ public final NodeCost getCost() { @Test public void testNodeCostWithNodeInfo() { - TestRootNode node = TestHelper.createRoot(CostWithNodeInfoNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostWithNodeInfoNodeFactory.getInstance()); assertEquals(NodeCost.NONE, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.NONE, node.getNode().getCost()); diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java index b91570859e4c..5a1b9ef7374b 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java @@ -58,18 +58,6 @@ import com.oracle.truffle.api.dsl.GenerateUncached; import com.oracle.truffle.api.dsl.NodeField; import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldTestNodeGen; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen; -import com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen; import com.oracle.truffle.api.dsl.test.TypeSystemTest.ValueNode; import com.oracle.truffle.api.nodes.Node; import com.oracle.truffle.api.source.SourceSection; @@ -78,7 +66,7 @@ public class NodeFieldTest { @Test public void testIntField() { - assertEquals(42, createCallTarget(IntFieldTestNodeFactory.create(42)).call()); + assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory.create(42)).call()); } @NodeField(name = "field", type = int.class) @@ -95,7 +83,7 @@ int intField() { @Test public void testIntFieldNoGetter() { - assertEquals(42, createCallTarget(IntFieldNoGetterTestNodeFactory.create(42)).call()); + assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory.create(42)).call()); } @NodeField(name = "field", type = int.class) @@ -110,7 +98,7 @@ int intField(int field) { @Test public void testMultipleFields() { - assertEquals(42, createCallTarget(MultipleFieldsTestNodeFactory.create(21, 21)).call()); + assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory.create(21, 21)).call()); } @NodeField(name = "field0", type = int.class) @@ -129,7 +117,7 @@ int intField() { @Test public void testStringField() { - assertEquals("42", createCallTarget(StringFieldTestNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory.create("42")).call()); } @NodeField(name = "field", type = String.class) @@ -146,7 +134,7 @@ String stringField() { @Test public void testRewrite() { - assertEquals("42", createCallTarget(RewriteTestNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory.create("42")).call()); } @NodeField(name = "field", type = String.class) @@ -167,7 +155,7 @@ Object returnField() { @Test public void testStringContainer() { - assertEquals(42, createCallTarget(TestContainerFactory.create("42")).call()); + assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory.create("42")).call()); } @NodeField(name = "field", type = int.class) @@ -189,7 +177,7 @@ int containerField(String field) { @Test public void testObjectContainer() { - assertEquals("42", createCallTarget(ObjectContainerNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory.create("42")).call()); } @NodeField(name = "object", type = Object.class) @@ -206,8 +194,8 @@ Object containerField() { @Test public void testUncachedNodeIntFieldTest() { - assertEquals(42, UncachedNodeIntFieldTestNodeGen.create(42).execute()); - assertFails(() -> UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); + assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldTestNodeGen.create(42).execute()); + assertFails(() -> com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); } @GenerateUncached @@ -233,8 +221,8 @@ public SourceSection getSourceSection() { @Test public void testUncachedNodeObjectFieldTest() { Object instance = new Object(); - assertSame(instance, UncachedNodeObjectFieldTestNodeGen.create(instance).execute()); - assertFails(() -> UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); + assertSame(instance, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.create(instance).execute()); + assertFails(() -> com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); } @GenerateUncached @@ -259,8 +247,8 @@ public SourceSection getSourceSection() { @Test public void testUncachedNodeIntFieldRef() { - assertEquals(42, UncachedNodeIntFieldRefNodeGen.create(42).execute()); - assertEquals(0, UncachedNodeIntFieldRefNodeGen.getUncached().execute()); + assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.create(42).execute()); + assertEquals(0, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.getUncached().execute()); } @GenerateUncached @@ -277,7 +265,7 @@ static Object s0(int foo) { @Test public void testUncachedNodeSettableIntFieldRef() throws Exception { - UncachedNodeSettableIntFieldRef cached = UncachedNodeSettableIntFieldRefNodeGen.create(); + UncachedNodeSettableIntFieldRef cached = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.create(); assertEquals(0, cached.execute()); assertEquals(0, cached.getFoo()); cached.setFoo(42); @@ -286,7 +274,7 @@ public void testUncachedNodeSettableIntFieldRef() throws Exception { assertNull(cached.getClass().getDeclaredMethod("getFoo").getAnnotation(TruffleBoundary.class)); assertNull(cached.getClass().getDeclaredMethod("setFoo", int.class).getAnnotation(TruffleBoundary.class)); - UncachedNodeSettableIntFieldRef uncached = UncachedNodeSettableIntFieldRefNodeGen.getUncached(); + UncachedNodeSettableIntFieldRef uncached = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.getUncached(); assertFails(() -> uncached.execute(), UnsupportedOperationException.class); assertFails(() -> uncached.getFoo(), UnsupportedOperationException.class); assertFails(() -> uncached.setFoo(42), UnsupportedOperationException.class); @@ -368,8 +356,8 @@ int s0() { @Test public void testConstructorAnnotations() throws NoSuchMethodException, SecurityException { - assertEquals(42, ConstructorAnnotationsTestNodeGen.create(21, 21).execute()); - Method method = ConstructorAnnotationsTestNodeGen.class.getMethod("create", int.class, int.class); + assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.create(21, 21).execute()); + Method method = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.class.getMethod("create", int.class, int.class); MyAnnotation annotation = method.getParameters()[0].getAnnotation(MyAnnotation.class); assertEquals("42", annotation.string()); assertEquals("41", annotation.stringArray()[0]); diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java index 1fb6752cc565..f7e886a25b63 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/PolymorphicTest.java @@ -78,7 +78,7 @@ private static void assertParent(Node expectedParent, Node child) { } public static void assertNoDuplicates(Node node, Node... ignored) { - assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet>(), node); + assertNoDuplicatesRec(new HashSet<>(Arrays.asList(ignored)), new HashSet<>(), node); } private static void assertNoDuplicatesRec(Set ignored, Set> seenClasses, Node current) { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java index 88dc4b3dc30d..5e69305359f0 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java @@ -317,7 +317,7 @@ public final boolean hasErrorsOrWarnings() { } private boolean visit(Predicate vistor) { - return visitImpl(new HashSet(), vistor); + return visitImpl(new HashSet<>(), vistor); } private boolean visitImpl(Set visited, Predicate visitor) { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java index 407779eef138..8575e62e0b5a 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/SpecializationData.java @@ -111,7 +111,7 @@ public SpecializationData(NodeData node, TemplateMethod template, Specialization } public SpecializationData(NodeData node, TemplateMethod template, SpecializationKind kind) { - this(node, template, kind, new ArrayList(), false, true, false); + this(node, template, kind, new ArrayList<>(), false, true, false); } public SpecializationData copy() { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java index 30cf74ef6ae7..dc1ea0e454de 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @@ -299,7 +299,7 @@ public NodeData parseNode(TypeElement originalTemplateType) { return null; } - List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + List lookupTypes = collectSuperClasses(new ArrayList<>(), templateType); NodeData node = parseNodeData(templateType, lookupTypes); @@ -1103,7 +1103,7 @@ private void initializeAOT(NodeData node) { TypeMirror type = cache.getParameter().getType(); if (NodeCodeGenerator.isSpecializedNode(type)) { - List lookupTypes = collectSuperClasses(new ArrayList(), ElementUtils.castTypeElement(type)); + List lookupTypes = collectSuperClasses(new ArrayList<>(), ElementUtils.castTypeElement(type)); AnnotationMirror generateAOT = findFirstAnnotation(lookupTypes, types.GenerateAOT); if (generateAOT == null) { cache.addError("Failed to generate code for @%s: " + // @@ -2538,7 +2538,7 @@ private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, Ty return null; } - List lookupTypes = collectSuperClasses(new ArrayList(), templateType); + List lookupTypes = collectSuperClasses(new ArrayList<>(), templateType); // Declaration order is not required for child nodes. List members = processingEnv.getElementUtils().getAllMembers(templateType); @@ -2835,7 +2835,7 @@ private void resolveReplaces(NodeData node) { // transitively resolve includes Set foundSpecializations = new LinkedHashSet<>(); - collectIncludes(specialization, foundSpecializations, new HashSet()); + collectIncludes(specialization, foundSpecializations, new HashSet<>()); specialization.getReplaces().addAll(foundSpecializations); } diff --git a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/ModulesAccessor.java b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/ModulesAccessor.java index da604ce74d19..f3316d96e01e 100644 --- a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/ModulesAccessor.java +++ b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/ModulesAccessor.java @@ -60,8 +60,6 @@ import com.oracle.truffle.api.impl.asm.ClassWriter; import com.oracle.truffle.api.impl.asm.MethodVisitor; import com.oracle.truffle.api.impl.asm.Opcodes; -import com.oracle.truffle.runtime.ModulesAccessor.DirectImpl; -import com.oracle.truffle.runtime.ModulesAccessor.IsolatedImpl; import jdk.internal.module.Modules; @@ -69,7 +67,7 @@ * We want to avoid exporting the Modules class to all classes in the unnamed module. So instead we * load it in an isolated class loader and module layer. */ -abstract sealed class ModulesAccessor permits DirectImpl, IsolatedImpl { +abstract sealed class ModulesAccessor permits ModulesAccessor.DirectImpl, ModulesAccessor.IsolatedImpl { /** * @see Modules#addExports(Module, String, Module) diff --git a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedTruffleRuntime.java b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedTruffleRuntime.java index 3d68d824f099..5786b76e6887 100644 --- a/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedTruffleRuntime.java +++ b/truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedTruffleRuntime.java @@ -1237,7 +1237,7 @@ public static void logHostAndGuestStacktrace(String reason, OptimizedCallTarget final OptimizedTruffleRuntime runtime = OptimizedTruffleRuntime.getRuntime(); final StringBuilder messageBuilder = new StringBuilder(); messageBuilder.append(reason).append(" at\n"); - runtime.iterateFrames(new FrameInstanceVisitor() { + runtime.iterateFrames(new FrameInstanceVisitor<>() { int frameIndex = 0; @Override From 86e160f5db221b852cf56cf0d8a754a33ca99a14 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Fri, 19 Jan 2024 17:23:10 +0100 Subject: [PATCH 51/75] Make ECJ build work for mx build in the graal-enterprise dir. --- .../processor/InstrumentableProcessor.java | 3 +- .../expression/DSLExpressionResolver.java | 3 +- .../generator/NodeCodeGenerator.java | 4 ++- .../processor/java/compiler/JDTCompiler.java | 31 +++++++++++++++---- .../dsl/processor/parser/NodeParser.java | 4 +-- 5 files changed, 34 insertions(+), 11 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentableProcessor.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentableProcessor.java index 416ac927e689..d5b1d6d9f226 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentableProcessor.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/InstrumentableProcessor.java @@ -69,6 +69,7 @@ import com.oracle.truffle.dsl.processor.generator.GeneratorUtils; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.compiler.CompilerFactory; import com.oracle.truffle.dsl.processor.java.model.CodeAnnotationMirror; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTree; @@ -378,7 +379,7 @@ private CodeTypeElement generateWrapper(ProcessorContext context, Element e, boo List wrappedMethods = new ArrayList<>(); List wrappedExecuteMethods = new ArrayList<>(); List wrappedResumeMethods = isResume ? new ArrayList<>() : Collections.emptyList(); - List elementList = context.getEnvironment().getElementUtils().getAllMembers(sourceType); + List elementList = CompilerFactory.getCompiler(sourceType).getAllMembersInDeclarationOrder(context.getEnvironment(), sourceType); ExecutableElement genericExecuteDelegate = null; ExecutableElement genericResumeDelegate = null; diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java index eb2a9fdc8b05..10b8a37f9267 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/expression/DSLExpressionResolver.java @@ -66,6 +66,7 @@ import com.oracle.truffle.dsl.processor.expression.DSLExpression.Negate; import com.oracle.truffle.dsl.processor.expression.DSLExpression.Variable; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.compiler.CompilerFactory; import com.oracle.truffle.dsl.processor.java.model.CodeTypeMirror; import com.oracle.truffle.dsl.processor.java.model.CodeVariableElement; @@ -374,7 +375,7 @@ public void visitVariable(Variable variable) { } private List getMembers(TypeElement t) { - return context.getEnvironment().getElementUtils().getAllMembers(t); + return CompilerFactory.getCompiler(t).getAllMembersInDeclarationOrder(context.getEnvironment(), t); } public void visitBooleanLiteral(BooleanLiteral binary) { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java index f91ddcdb7402..3f762e6d2b7f 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/generator/NodeCodeGenerator.java @@ -65,6 +65,7 @@ import com.oracle.truffle.dsl.processor.ProcessorContext; import com.oracle.truffle.dsl.processor.generator.FlatNodeGenFactory.GeneratorMode; import com.oracle.truffle.dsl.processor.java.ElementUtils; +import com.oracle.truffle.dsl.processor.java.compiler.CompilerFactory; import com.oracle.truffle.dsl.processor.java.model.CodeExecutableElement; import com.oracle.truffle.dsl.processor.java.model.CodeTreeBuilder; import com.oracle.truffle.dsl.processor.java.model.CodeTypeElement; @@ -315,7 +316,8 @@ private static void generateErrorNode(ProcessorContext context, NodeData node, C type.add(constructor); } - for (ExecutableElement method : ElementFilter.methodsIn(context.getEnvironment().getElementUtils().getAllMembers(node.getTemplateType()))) { + for (ExecutableElement method : ElementFilter.methodsIn( + CompilerFactory.getCompiler(node.getTemplateType()).getAllMembersInDeclarationOrder(context.getEnvironment(), node.getTemplateType()))) { if (method.getModifiers().contains(Modifier.ABSTRACT) && ElementUtils.getVisibility(method.getModifiers()) != Modifier.PRIVATE) { CodeExecutableElement overrideMethod = CodeExecutableElement.clone(method); overrideMethod.getModifiers().remove(Modifier.ABSTRACT); diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java index 2dd2ba0fefe1..30aa6b4de8a4 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java @@ -40,6 +40,7 @@ */ package com.oracle.truffle.dsl.processor.java.compiler; +import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -50,16 +51,19 @@ import java.util.TreeMap; import javax.annotation.processing.ProcessingEnvironment; +import javax.lang.model.element.AnnotationMirror; +import javax.lang.model.element.AnnotationValue; import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; import javax.lang.model.element.TypeElement; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.util.Elements; +import javax.tools.Diagnostic.Kind; import com.oracle.truffle.dsl.processor.ProcessorContext; import com.oracle.truffle.dsl.processor.java.ElementUtils; -import java.lang.reflect.Field; -import javax.lang.model.element.AnnotationMirror; -import javax.lang.model.element.AnnotationValue; -import javax.lang.model.element.ElementKind; -import javax.tools.Diagnostic.Kind; public class JDTCompiler extends AbstractCompiler { @@ -87,7 +91,22 @@ private static final class AllMembersDeclarationOrder { @Override public List getAllMembersInDeclarationOrder(ProcessingEnvironment environment, TypeElement type) { Map> cache = ProcessorContext.getInstance().getCacheMap(AllMembersDeclarationOrder.class); - return cache.computeIfAbsent(type, (t) -> sortBySourceOrder(newElementList(environment.getElementUtils().getAllMembers(type)))); + return cache.computeIfAbsent(type, (t) -> sortBySourceOrder(newElementList(getAllMembers(environment, type)))); + } + + private static List getAllMembers(ProcessingEnvironment environment, TypeElement type) { + Elements elements = environment.getElementUtils(); + List allMembers = new ArrayList<>(elements.getAllMembers(type)); + TypeElement superTypeElement = type.getSuperclass() != null ? ElementUtils.castTypeElement(type.getSuperclass()) : null; + while (superTypeElement != null) { + for (ExecutableElement method : ElementFilter.methodsIn(superTypeElement.getEnclosedElements())) { + if (method.getModifiers().contains(Modifier.STATIC)) { + allMembers.add(method); + } + } + superTypeElement = superTypeElement.getSuperclass() != null ? ElementUtils.castTypeElement(superTypeElement.getSuperclass()) : null; + } + return allMembers; } private static final class EnclosedDeclarationOrder { diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java index dc1ea0e454de..0483fffeb3ff 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/parser/NodeParser.java @@ -1844,7 +1844,7 @@ public static List importVisibleStaticMembers(TypeElement relativeTo, T TypeElement importElement = fromTypeMirror(context.reloadType(importType.asType())); List members = new ArrayList<>(); - List importMembers = context.getEnvironment().getElementUtils().getAllMembers(importType); + List importMembers = CompilerFactory.getCompiler(importType).getAllMembersInDeclarationOrder(context.getEnvironment(), importType); // add default constructor if (includeConstructors && ElementUtils.isVisible(relativeTo, importElement) && ElementFilter.constructorsIn(importMembers).isEmpty()) { CodeExecutableElement executable = new CodeExecutableElement(modifiers(Modifier.PUBLIC), importElement.asType(), null); @@ -2541,7 +2541,7 @@ private NodeData parseChildNodeData(NodeData parentNode, NodeChildData child, Ty List lookupTypes = collectSuperClasses(new ArrayList<>(), templateType); // Declaration order is not required for child nodes. - List members = processingEnv.getElementUtils().getAllMembers(templateType); + List members = CompilerFactory.getCompiler(templateType).getAllMembersInDeclarationOrder(processingEnv, templateType); NodeData node = parseNodeData(templateType, lookupTypes); if (node.hasErrors()) { return node; From 655f937cbd749c69dd1c8c0b708c2a7d7eac7ca7 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Fri, 19 Jan 2024 21:57:11 +0100 Subject: [PATCH 52/75] Remove full qualification of classes where not needed. --- .../benchmark/DSLInterpreterBenchmark.java | 14 ++++---- .../api/benchmark/NodeInliningBenchmark.java | 16 ++++----- .../truffle/api/dsl/test/NodeCostTest.java | 6 ++-- .../truffle/api/dsl/test/NodeFieldTest.java | 34 +++++++++---------- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java index 15be6cf8d610..b3bf570782d2 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/DSLInterpreterBenchmark.java @@ -84,7 +84,7 @@ public static class SimpleFirstIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); + nodes[i] = createNode(DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); } } @@ -103,7 +103,7 @@ public static class CachedFirstIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); + nodes[i] = createNode(DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); } } @@ -121,7 +121,7 @@ public void tearDown() { @Setup public void setupInterpreterProfile() { for (int i = 0; i < 100; i++) { - AbstractNode node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); + AbstractNode node = createNode(DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); node.execute(42L); node.execute(42); try { @@ -129,7 +129,7 @@ public void setupInterpreterProfile() { } catch (UnsupportedSpecializationException e) { } - node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); + node = createNode(DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); node.execute(42); node.execute(42L); try { @@ -137,7 +137,7 @@ public void setupInterpreterProfile() { } catch (UnsupportedSpecializationException e) { } - node = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); + node = createNode(DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); node.execute(42); node.execute(42L); try { @@ -155,7 +155,7 @@ public static class SimpleSecondIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); + nodes[i] = createNode(DSLInterpreterBenchmarkFactory.SimpleDSLNodeGen::create); nodes[i].execute(42); } } @@ -170,7 +170,7 @@ public static class CachedSecondIterationState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < NODES; i++) { - nodes[i] = createNode(com.oracle.truffle.api.benchmark.DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); + nodes[i] = createNode(DSLInterpreterBenchmarkFactory.CachedDSLNodeGen::create); nodes[i].execute(42); } } diff --git a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java index d33501a35da3..7164a18ab6aa 100644 --- a/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java +++ b/truffle/src/com.oracle.truffle.api.benchmark/src/com/oracle/truffle/api/benchmark/NodeInliningBenchmark.java @@ -83,11 +83,11 @@ public static class BenchmarkState { final CachedSharedExclusiveNode[] sharedExclusiveCachedNodes = new CachedSharedExclusiveNode[INNER_LOOP]; { for (int i = 0; i < INNER_LOOP; i++) { - inlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); - cachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); + inlinedNodes[i] = NodeInliningBenchmarkFactory.InlinedNodeGen.create(); + cachedNodes[i] = NodeInliningBenchmarkFactory.CachedNodeGen.create(); - sharedExclusiveInlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedSharedExclusiveNodeGen.create(); - sharedExclusiveCachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedSharedExclusiveNodeGen.create(); + sharedExclusiveInlinedNodes[i] = NodeInliningBenchmarkFactory.InlinedSharedExclusiveNodeGen.create(); + sharedExclusiveCachedNodes[i] = NodeInliningBenchmarkFactory.CachedSharedExclusiveNodeGen.create(); sharedExclusiveInlinedNodes[i].execute(0, 0, 0, 0); sharedExclusiveInlinedNodes[i].execute(1, 0, 0, 0); @@ -114,8 +114,8 @@ public static class FirstCallState extends BenchmarkState { @Setup(Level.Invocation) public void setup() { for (int i = 0; i < INNER_LOOP; i++) { - inlinedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); - cachedNodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); + inlinedNodes[i] = NodeInliningBenchmarkFactory.InlinedNodeGen.create(); + cachedNodes[i] = NodeInliningBenchmarkFactory.CachedNodeGen.create(); } } @@ -131,7 +131,7 @@ public void tearDownIteration() { public void createInlined(BenchmarkState state) { InlinedNode[] nodes = state.inlinedNodes; for (int i = 0; i < nodes.length; i++) { - nodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.InlinedNodeGen.create(); + nodes[i] = NodeInliningBenchmarkFactory.InlinedNodeGen.create(); } } @@ -140,7 +140,7 @@ public void createInlined(BenchmarkState state) { public void createCached(BenchmarkState state) { CachedNode[] nodes = state.cachedNodes; for (int i = 0; i < nodes.length; i++) { - nodes[i] = com.oracle.truffle.api.benchmark.NodeInliningBenchmarkFactory.CachedNodeGen.create(); + nodes[i] = NodeInliningBenchmarkFactory.CachedNodeGen.create(); } } diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java index a8ed7c0d06c5..160cc70114e7 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeCostTest.java @@ -56,7 +56,7 @@ public class NodeCostTest { @Test public void testNodeCost() { - TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostTestNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(NodeCostTestFactory.CostTestNodeFactory.getInstance()); assertEquals(NodeCost.UNINITIALIZED, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.MONOMORPHIC, node.getNode().getCost()); @@ -88,7 +88,7 @@ Object cost(Object left) { @Test public void testNodeCostViaMethodOverride() { - TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostViaMethodOverrideNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(NodeCostTestFactory.CostViaMethodOverrideNodeFactory.getInstance()); assertEquals(NodeCost.NONE, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.NONE, node.getNode().getCost()); @@ -111,7 +111,7 @@ public final NodeCost getCost() { @Test public void testNodeCostWithNodeInfo() { - TestRootNode node = TestHelper.createRoot(com.oracle.truffle.api.dsl.test.NodeCostTestFactory.CostWithNodeInfoNodeFactory.getInstance()); + TestRootNode node = TestHelper.createRoot(NodeCostTestFactory.CostWithNodeInfoNodeFactory.getInstance()); assertEquals(NodeCost.NONE, node.getNode().getCost()); assertEquals(21, executeWith(node, 21)); assertEquals(NodeCost.NONE, node.getNode().getCost()); diff --git a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java index 5a1b9ef7374b..2ce3b0259753 100644 --- a/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java +++ b/truffle/src/com.oracle.truffle.api.dsl.test/src/com/oracle/truffle/api/dsl/test/NodeFieldTest.java @@ -66,7 +66,7 @@ public class NodeFieldTest { @Test public void testIntField() { - assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldTestNodeFactory.create(42)).call()); + assertEquals(42, createCallTarget(NodeFieldTestFactory.IntFieldTestNodeFactory.create(42)).call()); } @NodeField(name = "field", type = int.class) @@ -83,7 +83,7 @@ int intField() { @Test public void testIntFieldNoGetter() { - assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory.create(42)).call()); + assertEquals(42, createCallTarget(NodeFieldTestFactory.IntFieldNoGetterTestNodeFactory.create(42)).call()); } @NodeField(name = "field", type = int.class) @@ -98,7 +98,7 @@ int intField(int field) { @Test public void testMultipleFields() { - assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.MultipleFieldsTestNodeFactory.create(21, 21)).call()); + assertEquals(42, createCallTarget(NodeFieldTestFactory.MultipleFieldsTestNodeFactory.create(21, 21)).call()); } @NodeField(name = "field0", type = int.class) @@ -117,7 +117,7 @@ int intField() { @Test public void testStringField() { - assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.StringFieldTestNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(NodeFieldTestFactory.StringFieldTestNodeFactory.create("42")).call()); } @NodeField(name = "field", type = String.class) @@ -134,7 +134,7 @@ String stringField() { @Test public void testRewrite() { - assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.RewriteTestNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(NodeFieldTestFactory.RewriteTestNodeFactory.create("42")).call()); } @NodeField(name = "field", type = String.class) @@ -155,7 +155,7 @@ Object returnField() { @Test public void testStringContainer() { - assertEquals(42, createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.TestContainerFactory.create("42")).call()); + assertEquals(42, createCallTarget(NodeFieldTestFactory.TestContainerFactory.create("42")).call()); } @NodeField(name = "field", type = int.class) @@ -177,7 +177,7 @@ int containerField(String field) { @Test public void testObjectContainer() { - assertEquals("42", createCallTarget(com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ObjectContainerNodeFactory.create("42")).call()); + assertEquals("42", createCallTarget(NodeFieldTestFactory.ObjectContainerNodeFactory.create("42")).call()); } @NodeField(name = "object", type = Object.class) @@ -194,8 +194,8 @@ Object containerField() { @Test public void testUncachedNodeIntFieldTest() { - assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldTestNodeGen.create(42).execute()); - assertFails(() -> com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); + assertEquals(42, NodeFieldTestFactory.UncachedNodeIntFieldTestNodeGen.create(42).execute()); + assertFails(() -> NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); } @GenerateUncached @@ -221,8 +221,8 @@ public SourceSection getSourceSection() { @Test public void testUncachedNodeObjectFieldTest() { Object instance = new Object(); - assertSame(instance, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.create(instance).execute()); - assertFails(() -> com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); + assertSame(instance, NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.create(instance).execute()); + assertFails(() -> NodeFieldTestFactory.UncachedNodeObjectFieldTestNodeGen.getUncached().execute(), UnsupportedOperationException.class); } @GenerateUncached @@ -247,8 +247,8 @@ public SourceSection getSourceSection() { @Test public void testUncachedNodeIntFieldRef() { - assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.create(42).execute()); - assertEquals(0, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.getUncached().execute()); + assertEquals(42, NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.create(42).execute()); + assertEquals(0, NodeFieldTestFactory.UncachedNodeIntFieldRefNodeGen.getUncached().execute()); } @GenerateUncached @@ -265,7 +265,7 @@ static Object s0(int foo) { @Test public void testUncachedNodeSettableIntFieldRef() throws Exception { - UncachedNodeSettableIntFieldRef cached = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.create(); + UncachedNodeSettableIntFieldRef cached = NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.create(); assertEquals(0, cached.execute()); assertEquals(0, cached.getFoo()); cached.setFoo(42); @@ -274,7 +274,7 @@ public void testUncachedNodeSettableIntFieldRef() throws Exception { assertNull(cached.getClass().getDeclaredMethod("getFoo").getAnnotation(TruffleBoundary.class)); assertNull(cached.getClass().getDeclaredMethod("setFoo", int.class).getAnnotation(TruffleBoundary.class)); - UncachedNodeSettableIntFieldRef uncached = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.getUncached(); + UncachedNodeSettableIntFieldRef uncached = NodeFieldTestFactory.UncachedNodeSettableIntFieldRefNodeGen.getUncached(); assertFails(() -> uncached.execute(), UnsupportedOperationException.class); assertFails(() -> uncached.getFoo(), UnsupportedOperationException.class); assertFails(() -> uncached.setFoo(42), UnsupportedOperationException.class); @@ -356,8 +356,8 @@ int s0() { @Test public void testConstructorAnnotations() throws NoSuchMethodException, SecurityException { - assertEquals(42, com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.create(21, 21).execute()); - Method method = com.oracle.truffle.api.dsl.test.NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.class.getMethod("create", int.class, int.class); + assertEquals(42, NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.create(21, 21).execute()); + Method method = NodeFieldTestFactory.ConstructorAnnotationsTestNodeGen.class.getMethod("create", int.class, int.class); MyAnnotation annotation = method.getParameters()[0].getAnnotation(MyAnnotation.class); assertEquals("42", annotation.string()); assertEquals("41", annotation.stringArray()[0]); From e434fdb2fe2aa74de92373905a063d2f32c154fa Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Fri, 19 Jan 2024 21:58:36 +0100 Subject: [PATCH 53/75] Apply the static method inheritance bug workaround only for versions of ECJ that have the bug. --- .../processor/java/compiler/JDTCompiler.java | 50 ++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java index 30aa6b4de8a4..37ce02ca3930 100644 --- a/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java +++ b/truffle/src/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/java/compiler/JDTCompiler.java @@ -40,6 +40,8 @@ */ package com.oracle.truffle.dsl.processor.java.compiler; +import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Arrays; @@ -48,7 +50,10 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.TreeMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.AnnotationMirror; @@ -94,17 +99,50 @@ public List getAllMembersInDeclarationOrder(ProcessingEnviron return cache.computeIfAbsent(type, (t) -> sortBySourceOrder(newElementList(getAllMembers(environment, type)))); } + private static volatile boolean HASSTATICMEMBERINHERITANCEBUG = false; + private static volatile boolean HASSTATICMEMBERINHERITANCEBUGASSIGNED = false; + + static boolean hasStaticMemberInheritanceBug() { + if (HASSTATICMEMBERINHERITANCEBUGASSIGNED) { + return HASSTATICMEMBERINHERITANCEBUG; + } + try (InputStream eclipseCompilerPropertiesStream = JDTCompiler.class.getResourceAsStream("/org/eclipse/jdt/internal/compiler/batch/messages.properties")) { + Properties properties = new Properties(); + if (eclipseCompilerPropertiesStream != null) { + properties.load(eclipseCompilerPropertiesStream); + } + int compilerVersion1 = 0; + int compilerVersion2 = 0; + String compilerVersionRawString = properties.getProperty("compiler.version"); + if (compilerVersionRawString != null) { + Pattern compilerVersionPattern = Pattern.compile("^.*(\\d+)\\.(\\d+).\\d+$"); + Matcher compilerVersionMatcher = compilerVersionPattern.matcher(compilerVersionRawString); + if (compilerVersionMatcher.find()) { + compilerVersion1 = Integer.parseInt(compilerVersionMatcher.group(1)); + compilerVersion2 = Integer.parseInt(compilerVersionMatcher.group(2)); + } + } + HASSTATICMEMBERINHERITANCEBUG = (compilerVersion1 > 3 || (compilerVersion1 == 3 && compilerVersion2 >= 34)); + HASSTATICMEMBERINHERITANCEBUGASSIGNED = true; + return HASSTATICMEMBERINHERITANCEBUG; + } catch (IOException ioe) { + throw new RuntimeException(ioe); + } + } + private static List getAllMembers(ProcessingEnvironment environment, TypeElement type) { Elements elements = environment.getElementUtils(); List allMembers = new ArrayList<>(elements.getAllMembers(type)); - TypeElement superTypeElement = type.getSuperclass() != null ? ElementUtils.castTypeElement(type.getSuperclass()) : null; - while (superTypeElement != null) { - for (ExecutableElement method : ElementFilter.methodsIn(superTypeElement.getEnclosedElements())) { - if (method.getModifiers().contains(Modifier.STATIC)) { - allMembers.add(method); + if (hasStaticMemberInheritanceBug()) { + TypeElement superTypeElement = type.getSuperclass() != null ? ElementUtils.castTypeElement(type.getSuperclass()) : null; + while (superTypeElement != null) { + for (ExecutableElement method : ElementFilter.methodsIn(superTypeElement.getEnclosedElements())) { + if (method.getModifiers().contains(Modifier.STATIC)) { + allMembers.add(method); + } } + superTypeElement = superTypeElement.getSuperclass() != null ? ElementUtils.castTypeElement(superTypeElement.getSuperclass()) : null; } - superTypeElement = superTypeElement.getSuperclass() != null ? ElementUtils.castTypeElement(superTypeElement.getSuperclass()) : null; } return allMembers; } From d6a3be3e119e5ab7e8339e62578298803871d288 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Wed, 24 Jan 2024 13:53:39 +0100 Subject: [PATCH 54/75] Fix ECJ warnings for SVM. --- compiler/mx.compiler/suite.py | 3 + .../lir/processor/IntrinsicStubProcessor.java | 4 +- .../core/test/CheckGraalInvariants.java | 2 +- .../test/InstanceOfCanonicalizationTest.java | 2 + .../hotspot/test/CompileTheWorld.java | 2 +- .../test/HotSpotGraalCompilerTest.java | 12 ++-- .../compiler/hotspot/test/MonitorPEATest.java | 1 + .../test/IntegerShuffleBitsStampTest.java | 4 +- .../nodes/test/OptimizationLogTest.java | 12 ++-- .../StringIntrinsicAVX3ThresholdTest.java | 1 + .../test/ClassLinkedByCompilerTest.java | 1 + .../truffle/test/HostInliningTest.java | 45 +++++++------- .../SLTestTruffleBoundary01Builtin.java | 2 +- .../asm/amd64/AMD64MacroAssembler.java | 3 + .../compiler/core/phases/EconomyLowTier.java | 2 +- .../phases/fuzzing/FullFuzzedTierPlan.java | 2 +- .../hotspot/SymbolicSnippetEncoder.java | 1 - .../hotspot/replacements/MonitorSnippets.java | 1 + .../jdk/graal/compiler/lir/LIRValueUtil.java | 2 +- .../lir/alloc/SaveCalleeSaveRegisters.java | 2 +- .../LinearScanOptimizeSpillPositionPhase.java | 2 +- .../lsra/LinearScanResolveDataFlowPhase.java | 4 +- .../lir/alloc/lsra/LinearScanWalker.java | 3 +- .../constopt/ConstantLoadOptimization.java | 3 +- .../compiler/lir/gen/LIRGenerationResult.java | 2 +- .../lir/profiling/MethodProfilingPhase.java | 2 +- .../lir/profiling/MoveProfilingPhase.java | 2 +- .../nodes/cfg/ControlFlowGraphBuilder.java | 24 ++++---- .../test/ArrayNewInstancePluginCase.java | 1 + .../com/oracle/graal/pointsto/BigBang.java | 1 + .../com/oracle/graal/pointsto/api/HostVM.java | 2 +- .../graal/pointsto/heap/ImageHeapScanner.java | 1 + .../pointsto/reports/StatisticsPrinter.java | 4 +- .../DefaultVirtualInvokeTypeFlow.java | 1 + .../pointsto/util/CompletionExecutor.java | 9 +-- .../src/com/oracle/objectfile/ObjectFile.java | 4 +- .../pecoff/PECoffRelocTableStruct.java | 2 +- .../oracle/svm/agent/NativeImageAgent.java | 4 +- .../agent/NativeImageAgentJNIHandleSet.java | 8 +-- .../ChunkedImageHeapPartition.java | 7 ++- .../oracle/svm/core/genscavenge/HeapImpl.java | 24 +++----- .../posix/linux/LinuxImageHeapProvider.java | 3 +- .../svm/core/SubstrateSegfaultHandler.java | 1 + .../svm/core/code/FrameInfoDecoder.java | 2 +- .../graal/replacements/SubstrateGraphKit.java | 30 +++++----- .../core/heap/StoredContinuationAccess.java | 58 ++----------------- .../com/oracle/svm/core/hub/DynamicHub.java | 4 +- .../svm/core/image/ImageHeapLayouter.java | 1 + .../svm/core/jdk/DeferredCommonPool.java | 2 +- .../jdk/ForeignDisabledSubstitutions.java | 6 ++ .../com/oracle/svm/core/jdk/JRTSupport.java | 1 + .../svm/core/jdk/JavaLangSubstitutions.java | 14 +++-- .../svm/core/jdk/NativeLibrarySupport.java | 1 + .../svm/core/jdk/Target_java_lang_Module.java | 1 + .../svm/core/jdk/Target_java_nio_Bits.java | 1 + .../jdk/Target_java_nio_DirectByteBuffer.java | 1 + ...arget_jdk_internal_reflect_Reflection.java | 1 + .../jdk/localization/LocalizationSupport.java | 2 +- .../JfrRecurringCallbackExecutionSampler.java | 1 + .../svm/core/jni/JNIThreadOwnedMonitors.java | 2 +- .../src/com/oracle/svm/core/log/RealLog.java | 6 +- ...dk_internal_reflect_AccessorGenerator.java | 4 +- .../core/thread/Target_java_lang_Thread.java | 1 + .../Target_java_lang_VirtualThread.java | 1 + .../com/oracle/svm/driver/NativeImage.java | 4 +- .../hotspot/libgraal/LibGraalEntryPoints.java | 2 +- .../RuntimeCompilationCandidate.java | 1 + .../RuntimeCompiledMethodSupport.java | 13 +++-- .../SubstrateRuntimeConfigurationBuilder.java | 8 +-- .../oracle/svm/hosted/ImageClassLoader.java | 8 ++- .../hosted/ReachabilityRegistrationNode.java | 17 +++--- .../src/com/oracle/svm/hosted/SVMHost.java | 4 +- .../hosted/c/codegen/CCompilerInvoker.java | 2 +- .../SimulateClassInitializerGraphDecoder.java | 2 +- .../HostedRuntimeConfigurationBuilder.java | 4 +- .../SharedRuntimeConfigurationBuilder.java | 4 +- .../hosted/config/HybridLayoutSupport.java | 1 + .../DisallowedImageHeapObjectFeature.java | 4 ++ .../oracle/svm/hosted/image/NativeImage.java | 12 ++-- .../image/NativeImageBFDNameProvider.java | 2 +- .../hosted/image/NativeImageCodeCache.java | 9 ++- .../hosted/jdk/JNIRegistrationJavaNet.java | 9 +++ .../hosted/jdk/JNIRegistrationJavaNio.java | 1 + .../svm/hosted/jfr/JfrEventSubstitution.java | 1 + .../phases/CInterfaceInvocationPlugin.java | 2 +- ...trinsifyMethodHandlesInvocationPlugin.java | 7 +-- .../phases/SharedGraphBuilderPhase.java | 12 ++-- .../hosted/reflect/ReflectionDataBuilder.java | 2 +- .../hosted/reflect/ReflectionGraphKit.java | 1 + .../hosted/snippets/ReflectionPlugins.java | 2 +- .../SubstrateGraphBuilderPlugins.java | 2 + .../AutomaticUnsafeTransformationSupport.java | 7 +-- .../hosted/substitute/ComputedValueField.java | 1 - .../test/clinit/TestClassInitialization.java | 4 +- .../oracle/svm/test/debug/CStructTests.java | 1 + .../svm/truffle/tck/PermissionsFeature.java | 12 ++-- .../oracle/svm/truffle/TruffleFeature.java | 2 +- 97 files changed, 261 insertions(+), 260 deletions(-) diff --git a/compiler/mx.compiler/suite.py b/compiler/mx.compiler/suite.py index f89ddf6b4abc..e8582784d0f8 100644 --- a/compiler/mx.compiler/suite.py +++ b/compiler/mx.compiler/suite.py @@ -316,6 +316,9 @@ "java.base" : [ "jdk.internal.util", ], + "jdk.internal.vm.ci" : [ + "jdk.vm.ci.meta", + ], }, "checkstyle": "jdk.graal.compiler", "javaCompliance" : "21+", diff --git a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/lir/processor/IntrinsicStubProcessor.java b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/lir/processor/IntrinsicStubProcessor.java index 0ba8bc48417d..31852acf1e13 100644 --- a/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/lir/processor/IntrinsicStubProcessor.java +++ b/compiler/src/jdk.graal.compiler.processor/src/jdk/graal/compiler/lir/processor/IntrinsicStubProcessor.java @@ -331,8 +331,8 @@ private void createStubs(AbstractProcessor processor, TargetVM targetVM, TypeEle out.printf(" super(linkage.getDescriptor().getName(), options, providers, linkage);\n"); out.printf(" }\n"); } else { - out.printf(" private static final EnumSet EMPTY_CPU_FEATURES_AMD64 = EnumSet.noneOf(AMD64.CPUFeature.class);\n"); - out.printf(" private static final EnumSet EMPTY_CPU_FEATURES_AARCH64 = EnumSet.noneOf(AArch64.CPUFeature.class);\n"); + out.printf(" @SuppressWarnings(\"unused\") private static final EnumSet EMPTY_CPU_FEATURES_AMD64 = EnumSet.noneOf(AMD64.CPUFeature.class);\n"); + out.printf(" @SuppressWarnings(\"unused\") private static final EnumSet EMPTY_CPU_FEATURES_AARCH64 = EnumSet.noneOf(AArch64.CPUFeature.class);\n"); } out.printf("\n"); for (GenerateStubClass genClass : classes) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java index 49aae7ac88a4..abdfe60858ff 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CheckGraalInvariants.java @@ -309,7 +309,7 @@ public static void runTest(InvariantsTool tool) { OptionValues options = getInitialOptions(); CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread"); int availableProcessors = Runtime.getRuntime().availableProcessors(); - ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), factory); + ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), factory); List errors = Collections.synchronizedList(new ArrayList<>()); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/InstanceOfCanonicalizationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/InstanceOfCanonicalizationTest.java index ea222bdefd64..d7ff4abe170b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/InstanceOfCanonicalizationTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/InstanceOfCanonicalizationTest.java @@ -34,6 +34,7 @@ public class InstanceOfCanonicalizationTest extends GraalCompilerTest { + @SuppressWarnings("unused") public static boolean checkCastIncompatibleTypes(Object arr) { // Cast first to a byte array, then to a boolean array. This only succeeds if arr is null. byte[] barr = (byte[]) arr; @@ -41,6 +42,7 @@ public static boolean checkCastIncompatibleTypes(Object arr) { return true; } + @SuppressWarnings("cast") public static int unsatisfiableInstanceOf(byte[] barr) { // Plain instanceof does not allow null, so this will never succeed. if ((Object) barr instanceof boolean[]) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/CompileTheWorld.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/CompileTheWorld.java index 0b1eb8a4cbb2..e169731cc76b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/CompileTheWorld.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/CompileTheWorld.java @@ -1099,7 +1099,7 @@ private void compile(LibGraalParams libgraal) { } } else { compileTimes = new ConcurrentHashMap<>(); - ThreadPoolExecutor threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), new CTWThreadFactory(libgraal)); + ThreadPoolExecutor threadPool = new ThreadPoolExecutor(threadCount, threadCount, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(), new CTWThreadFactory(libgraal)); for (Compilation task : tasks) { threadPool.submit(new Runnable() { @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java index 9a32bc54e1fe..d5384542b592 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java @@ -24,16 +24,18 @@ */ package jdk.graal.compiler.hotspot.test; +import org.junit.Assume; +import org.junit.AssumptionViolatedException; + import jdk.graal.compiler.api.test.Graal; -import jdk.graal.compiler.core.test.GraalCompilerTest; import jdk.graal.compiler.bytecode.Bytecode; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.test.GraalCompilerTest; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.hotspot.HotSpotBackend; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.nodes.Cancellable; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.StructuredGraph.AllowAssumptions; @@ -41,9 +43,6 @@ import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.runtime.RuntimeProvider; -import org.junit.Assume; -import org.junit.AssumptionViolatedException; - import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; @@ -81,7 +80,7 @@ protected InstalledCode compileAndInstallSubstitution(Class c, String methodN protected InstalledCode compileAndInstallSubstitution(ResolvedJavaMethod method) { HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); - HotSpotProviders providers = rt.getHostBackend().getProviders(); + rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); OptionValues options = getInitialOptions(); StructuredGraph graph = getIntrinsicGraph(method, compilationId, getDebugContext(options), AllowAssumptions.YES, null); @@ -91,6 +90,7 @@ protected InstalledCode compileAndInstallSubstitution(ResolvedJavaMethod method) return null; } + @SuppressWarnings("unused") public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationIdentifier compilationId, DebugContext debug, AllowAssumptions allowAssumptions, Cancellable cancellable) { GraphBuilderConfiguration.Plugins graphBuilderPlugins = getReplacements().getGraphBuilderPlugins(); InvocationPlugin plugin = graphBuilderPlugins.getInvocationPlugins().lookupInvocation(method, debug.getOptions()); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/MonitorPEATest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/MonitorPEATest.java index c82fcf36eed5..be9e87e0dee1 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/MonitorPEATest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/MonitorPEATest.java @@ -139,6 +139,7 @@ static class A { Object o = new Object(); } + @SuppressWarnings("unused") public static void snippet4(Object external, boolean flag, boolean flag1) { A escaped = new A(); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/IntegerShuffleBitsStampTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/IntegerShuffleBitsStampTest.java index 6b12465d2c94..bced848d6326 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/IntegerShuffleBitsStampTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/IntegerShuffleBitsStampTest.java @@ -49,12 +49,12 @@ public void testICompress() { Stamp value0Stamp = StampFactory.forInteger(JavaKind.Int, value0, value0, value0 & INT_MASK, value0 & INT_MASK); for (int value1 : inputs) { Stamp value1Stamp = StampFactory.forInteger(JavaKind.Int, value1, value1, value1 & INT_MASK, value1 & INT_MASK); - Stamp valueStamp = (IntegerStamp) value0Stamp.meet(value1Stamp); + Stamp valueStamp = value0Stamp.meet(value1Stamp); for (int mask0 : inputs) { Stamp mask0Stamp = StampFactory.forInteger(JavaKind.Int, mask0, mask0, mask0 & INT_MASK, mask0 & INT_MASK); for (int mask1 : inputs) { Stamp mask1Stamp = StampFactory.forInteger(JavaKind.Int, mask1, mask1, mask1 & INT_MASK, mask1 & INT_MASK); - Stamp maskStamp = (IntegerStamp) mask0Stamp.meet(mask1Stamp); + Stamp maskStamp = mask0Stamp.meet(mask1Stamp); IntegerStamp newStamp = (IntegerStamp) compressOp.foldStamp(valueStamp, maskStamp); assertTrue(newStamp.contains(Integer.compress(value0, mask0))); assertTrue(newStamp.contains(Integer.compress(value0, mask1))); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java index 8e7c1b578e06..ea2489fa3d89 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java @@ -27,10 +27,13 @@ import java.util.Optional; import java.util.function.Supplier; -import jdk.graal.compiler.core.test.GraalCompilerTest; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; +import org.junit.Assert; +import org.junit.Test; + import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.test.GraalCompilerTest; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.nodes.GraphState; @@ -45,9 +48,6 @@ import jdk.graal.compiler.phases.BasePhase; import jdk.graal.compiler.phases.ClassTypeSequence; import jdk.graal.compiler.phases.util.Providers; -import org.junit.Assert; -import org.junit.Test; - import jdk.vm.ci.meta.ResolvedJavaMethod; /** @@ -150,8 +150,8 @@ public void buildOptimizationTreeWhenEnabled() { /** * Tests that there is no reporting going on when the optimization log is disabled. In * particular, the optimization tree shall not be built and - * {@link OptimizationLog.OptimizationEntry#withLazyProperty(String, Supplier) lazy properties} - * shall not be consumed. + * {@link jdk.graal.compiler.nodes.OptimizationLog.OptimizationEntry#withLazyProperty(String, Supplier) + * lazy properties} shall not be consumed. */ @Test public void noReportingWhenDisabled() { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StringIntrinsicAVX3ThresholdTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StringIntrinsicAVX3ThresholdTest.java index c60d2920903a..7fdc04073c1c 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StringIntrinsicAVX3ThresholdTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StringIntrinsicAVX3ThresholdTest.java @@ -52,6 +52,7 @@ public void before() { */ } + @SuppressWarnings("unused") public void testWithAVX3Threshold(String testSelector, Class testClass) { Runnable nopRunnable = () -> { /* diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/ClassLinkedByCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/ClassLinkedByCompilerTest.java index 65b98032de96..6344e686a54d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/ClassLinkedByCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/ClassLinkedByCompilerTest.java @@ -52,6 +52,7 @@ static final class RootNodeImpl extends RootNode { super(null); } + @Override public Object execute(VirtualFrame frame) { return Unlinked.call(); } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/HostInliningTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/HostInliningTest.java index 1dfaeee1788e..19c7e9635d3b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/HostInliningTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/HostInliningTest.java @@ -36,27 +36,6 @@ import java.util.Map; import org.graalvm.collections.EconomicMap; -import jdk.graal.compiler.api.directives.GraalDirectives; -import jdk.graal.compiler.core.phases.HighTier; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; -import jdk.graal.compiler.nodes.ConstantNode; -import jdk.graal.compiler.nodes.Invoke; -import jdk.graal.compiler.nodes.InvokeNode; -import jdk.graal.compiler.nodes.InvokeWithExceptionNode; -import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.nodes.ValueNode; -import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; -import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; -import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; -import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; -import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.common.CanonicalizerPhase; -import jdk.graal.compiler.phases.tiers.HighTierContext; -import jdk.graal.compiler.truffle.host.HostInliningPhase; -import jdk.graal.compiler.truffle.test.HostInliningTestFactory.IfNodeGen; import org.graalvm.polyglot.Context; import org.junit.Assert; import org.junit.BeforeClass; @@ -67,10 +46,10 @@ import org.junit.runners.Parameterized.Parameters; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.HostCompilerDirectives.BytecodeInterpreterSwitch; import com.oracle.truffle.api.HostCompilerDirectives.InliningCutoff; +import com.oracle.truffle.api.Truffle; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.Specialization; @@ -83,6 +62,26 @@ import com.oracle.truffle.runtime.OptimizedCallTarget; import com.oracle.truffle.runtime.OptimizedDirectCallNode; +import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.core.phases.HighTier; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; +import jdk.graal.compiler.nodes.ConstantNode; +import jdk.graal.compiler.nodes.Invoke; +import jdk.graal.compiler.nodes.InvokeNode; +import jdk.graal.compiler.nodes.InvokeWithExceptionNode; +import jdk.graal.compiler.nodes.StructuredGraph; +import jdk.graal.compiler.nodes.ValueNode; +import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderContext; +import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.Receiver; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; +import jdk.graal.compiler.options.OptionKey; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.common.CanonicalizerPhase; +import jdk.graal.compiler.phases.tiers.HighTierContext; +import jdk.graal.compiler.truffle.host.HostInliningPhase; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -869,7 +868,7 @@ int doDefault(boolean condition, @Cached InlinedCountingConditionProfile profile } - static final IfNode IF_NODE = IfNodeGen.create(); + static final IfNode IF_NODE = HostInliningTestFactory.IfNodeGen.create(); @BytecodeInterpreterSwitch @ExpectNotInlined(name = "traceTransferToInterpreter", count = -1 /* any number of calls ok */) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/builtins/SLTestTruffleBoundary01Builtin.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/builtins/SLTestTruffleBoundary01Builtin.java index c50a7e4a4d84..3bcfdc7e4217 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/builtins/SLTestTruffleBoundary01Builtin.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/truffle/test/builtins/SLTestTruffleBoundary01Builtin.java @@ -58,7 +58,7 @@ public Object testTruffleBoundary() { throw new AssertionError(); } try { - int result = (int) CompilerDirectives.interpreterOnly(new Callable() { + int result = (int) CompilerDirectives.interpreterOnly(new Callable<>() { @Override public Object call() throws Exception { return 1; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java index c0f391e73dd7..5110aa9e2bcb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java @@ -420,6 +420,7 @@ private void emitAlignmentForDirectCall(boolean align, int additionalInstruction * * @return the position of the emitted call instruction */ + @SuppressWarnings("unused") public int indirectCall(PostCallAction postCallAction, Register callReg, boolean mitigateDecodingAsDirectCall, InvokeTarget callTarget, CallingConvention.Type callingConventionType) { int indirectCallSize = needsRex(callReg) ? 3 : 2; @@ -455,6 +456,7 @@ public int indirectCall(PostCallAction postCallAction, Register callReg, boolean return beforeCall; } + @SuppressWarnings("unused") public int directCall(PostCallAction postCallAction, long address, Register scratch, InvokeTarget callTarget) { int bytesToEmit = needsRex(scratch) ? 13 : 12; mitigateJCCErratum(bytesToEmit); @@ -480,6 +482,7 @@ public int directJmp(long address, Register scratch) { return beforeJmp; } + @SuppressWarnings("unused") public int call(PostCallAction postCallAction, InvokeTarget callTarget) { int beforeCall = position(); call(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyLowTier.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyLowTier.java index 8b3e52460920..9a9509c0591d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyLowTier.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/EconomyLowTier.java @@ -51,7 +51,7 @@ public EconomyLowTier() { * specific to the target architecture for this compilation. This should be done by the * backend or the target specific suites provider. */ - appendPhase(new PlaceholderPhase(AddressLoweringPhase.class)); + appendPhase(new PlaceholderPhase<>(AddressLoweringPhase.class)); appendPhase(new SchedulePhase(SchedulePhase.SchedulingStrategy.LATEST_OUT_OF_LOOPS)); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/fuzzing/FullFuzzedTierPlan.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/fuzzing/FullFuzzedTierPlan.java index 0fe9a0554192..c304e459ba9b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/fuzzing/FullFuzzedTierPlan.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/fuzzing/FullFuzzedTierPlan.java @@ -60,7 +60,7 @@ private FullFuzzedTierPlan(MinimalFuzzedTierPlan minimalTierPlan, long randomSeed, int phaseSkipOdds, String tierName) { - this(minimalTierPlan.getSingleApplyPhases(), minimalTierPlan.getMultiApplyPhases(), minimalTierPlan.getIgnoredPhases(), new PhaseSuite(), minimalTierPlan, randomSeed, + this(minimalTierPlan.getSingleApplyPhases(), minimalTierPlan.getMultiApplyPhases(), minimalTierPlan.getIgnoredPhases(), new PhaseSuite<>(), minimalTierPlan, randomSeed, phaseSkipOdds, tierName); computeFullFuzzedTierPlan(graphState); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java index c60f1cfba3fc..557bf1e60a92 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java @@ -833,7 +833,6 @@ private Object filterStamp(DebugContext debug, Stamp stamp) { throw new InternalError(stamp.toString()); } ResolvedJavaType elementalType = type.getElementalType(); - String elementalTypeName = elementalType.getName(); if (isGraalClass(elementalType)) { if (!type.equals(elementalType)) { // Ensure that the underlying type is available diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java index f4c377f212b9..a96e6909ab42 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/MonitorSnippets.java @@ -332,6 +332,7 @@ private static boolean tryStackLocking(Object object, Word lock, Word mark, Word @SyncPort(from = "https://github.com/openjdk/jdk/blob/c5e72450966ad50d57a8d22e9d634bfcb319aee9/src/hotspot/cpu/x86/macroAssembler_x86.cpp#L9877-L9911", sha1 = "7a02d52b6b621959389e574984ca20b52100fe5e") // @formatter:on + @SuppressWarnings("unused") private static boolean tryLightweightLocking(Object object, Word lock, Word mark, Word thread, boolean trace, Counters counters, Register stackPointerRegister) { if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorMask(INJECTED_VMCONFIG)).notEqual(0))) { // Inflated case diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRValueUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRValueUtil.java index 51ba71539465..56fb392fa848 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRValueUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/LIRValueUtil.java @@ -139,7 +139,7 @@ public static Value stripCast(Value value) { * are not {@link RegisterValue registers} are ignored. */ public static boolean differentRegisters(Object... values) { - List registers = collectRegisters(values, new ArrayList()); + List registers = collectRegisters(values, new ArrayList<>()); for (int i = 1; i < registers.size(); i++) { Register r1 = registers.get(i); for (int j = 0; j < i; j++) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java index 1ad2606e73c6..4b4baee2f135 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java @@ -71,7 +71,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) { BasicBlock startBlock = lir.getControlFlowGraph().getStartBlock(); ArrayList instructions = lir.getLIRforBlock(startBlock); - int insertionIndex = lirGenRes.getFirstInsertPosition(); + int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); LIRInsertionBuffer buffer = new LIRInsertionBuffer(); buffer.init(instructions); StandardOp.LabelOp entry = (StandardOp.LabelOp) instructions.get(insertionIndex - 1); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java index 5f3e57256338..a5767cadf2fe 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java @@ -171,7 +171,7 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in debug.log(DebugContext.VERBOSE_LEVEL, "Insert spill move %s", move); move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID); - int insertionIndex = res.getFirstInsertPosition(); + int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); insertionBuffer.append(insertionIndex, move); betterSpillPosWithLowerProbability.increment(debug); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java index 9e0fe5cbf326..640affdffe94 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java @@ -118,7 +118,7 @@ void resolveFindInsertPos(BasicBlock fromBlock, BasicBlock toBlock, MoveRe } } - moveResolver.setInsertPosition(allocator.getLIR().getLIRforBlock(toBlock), allocator.getLIRGenerationResult().getFirstInsertPosition()); + moveResolver.setInsertPosition(allocator.getLIR().getLIRforBlock(toBlock), LIRGenerationResult.getFirstInsertPosition()); } } @@ -170,7 +170,7 @@ protected void optimizeEmptyBlocks(MoveResolver moveResolver, BitSet blockComple */ resolveCollectMappings(pred, sux, block, moveResolver); if (moveResolver.hasMappings()) { - moveResolver.setInsertPosition(instructions, allocator.getLIRGenerationResult().getFirstInsertPosition()); + moveResolver.setInsertPosition(instructions, LIRGenerationResult.getFirstInsertPosition()); moveResolver.resolveAndAppendMoves(); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java index 7a96378f9b28..a1110afb52ac 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java @@ -49,6 +49,7 @@ import jdk.graal.compiler.lir.alloc.lsra.Interval.SpillState; import jdk.graal.compiler.lir.alloc.lsra.Interval.State; +import jdk.graal.compiler.lir.gen.LIRGenerationResult; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.Value; @@ -277,7 +278,7 @@ void insertMove(int operandId, Interval srcIt, Interval dstIt) { index++; assert 0 <= index && index < instructions.size() : "index out of bounds"; } - assert allocator.getLIRGenerationResult().getFirstInsertPosition() <= index && index < instructions.size() : "index out of bounds"; + assert LIRGenerationResult.getFirstInsertPosition() <= index && index < instructions.size() : "index out of bounds"; assert instructions.get(index).id() == opId : "error in calculation"; // insert new instruction before instruction at position index diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java index 65f5e2362300..8b964de8654e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java @@ -356,7 +356,8 @@ private void insertLoad(Constant constant, ValueKind kind, BasicBlock bloc // create move LIRInstruction move = lirGen.getSpillMoveFactory().createLoad(variable, constant); // insert instruction - int insertionIndex = lirGen.getResult().getFirstInsertPosition(); + lirGen.getResult(); + int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); getInsertionBuffer(block).append(insertionIndex, move); debug.log("new move (%s) and inserted in block %s", move, block); // update usages diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java index cfd5b89ed58a..3d73368b19b0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java @@ -165,7 +165,7 @@ public String getCompilationUnitName() { * * @return index of the first insert position */ - public final int getFirstInsertPosition() { + public static int getFirstInsertPosition() { return 1; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java index 2e936e88cc56..70804ead5b80 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java @@ -86,7 +86,7 @@ public void doBlock(BasicBlock block, String group) { LIRInstruction op = diagnosticLirGenTool.createBenchmarkCounter(lirGenRes.getCompilationUnitName(), group, increment); buffer.init(instructions); - int insertionIndex = lirGenRes.getFirstInsertPosition(); + int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); buffer.append(insertionIndex, op); buffer.finish(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java index e611a0775e9b..d9b05af645b4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java @@ -131,7 +131,7 @@ protected final void insertBenchmarkCounter(BasicBlock block) { increments.toArray(new Value[size])); assert inst != null; buffer.init(instructions); - int insertionIndex = lirGenRes.getFirstInsertPosition(); + int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); buffer.append(insertionIndex, inst); buffer.finish(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/cfg/ControlFlowGraphBuilder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/cfg/ControlFlowGraphBuilder.java index f91c6aac87ed..ae87162ef808 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/cfg/ControlFlowGraphBuilder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/cfg/ControlFlowGraphBuilder.java @@ -39,33 +39,33 @@ public ControlFlowGraphBuilder(StructuredGraph structuredGraph) { this.structuredGraph = structuredGraph; } - public ControlFlowGraphBuilder backendBlocks(boolean backendBlocks) { - this.backendBlocks = backendBlocks; + public ControlFlowGraphBuilder backendBlocks(boolean backendBlocksParam) { + this.backendBlocks = backendBlocksParam; return this; } - public ControlFlowGraphBuilder connectBlocks(boolean connectBlocks) { - this.connectBlocks = connectBlocks; + public ControlFlowGraphBuilder connectBlocks(boolean connectBlocksParam) { + this.connectBlocks = connectBlocksParam; return this; } - public ControlFlowGraphBuilder computeFrequency(boolean computeFrequency) { - this.computeFrequency = computeFrequency; + public ControlFlowGraphBuilder computeFrequency(boolean computeFrequencyParam) { + this.computeFrequency = computeFrequencyParam; return this; } - public ControlFlowGraphBuilder computeLoops(boolean computeLoops) { - this.computeLoops = computeLoops; + public ControlFlowGraphBuilder computeLoops(boolean computeLoopsParam) { + this.computeLoops = computeLoopsParam; return this; } - public ControlFlowGraphBuilder computeDominators(boolean computeDominators) { - this.computeDominators = computeDominators; + public ControlFlowGraphBuilder computeDominators(boolean computeDominatorsParam) { + this.computeDominators = computeDominatorsParam; return this; } - public ControlFlowGraphBuilder computePostdominators(boolean computePostdominators) { - this.computePostdominators = computePostdominators; + public ControlFlowGraphBuilder computePostdominators(boolean computePostdominatorsParam) { + this.computePostdominators = computePostdominatorsParam; return this; } diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone.test/src/com/oracle/graal/pointsto/standalone/test/ArrayNewInstancePluginCase.java b/substratevm/src/com.oracle.graal.pointsto.standalone.test/src/com/oracle/graal/pointsto/standalone/test/ArrayNewInstancePluginCase.java index 2ce2f82eaf56..e4c418804cf2 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone.test/src/com/oracle/graal/pointsto/standalone/test/ArrayNewInstancePluginCase.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone.test/src/com/oracle/graal/pointsto/standalone/test/ArrayNewInstancePluginCase.java @@ -35,6 +35,7 @@ * This case is for * {@link jdk.graal.compiler.replacements.StandardGraphBuilderPlugins#registerArrayPlugins(InvocationPlugins, Replacements)}. */ +@SuppressWarnings({"javadoc"}) public class ArrayNewInstancePluginCase { public static void main(String[] args) { int size = 3; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java index 612ad177b792..4e192e69a85e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/BigBang.java @@ -137,6 +137,7 @@ default AnalysisMethod fallbackResolveConcreteMethod(AnalysisType resolvingType, return null; } + @SuppressWarnings("unused") default void registerTypeForBaseImage(Class cls) { } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java index da1233406b79..1cea42fc5b70 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java @@ -89,7 +89,6 @@ public OptionValues options() { /** * Check if the provided object is a relocated pointer. * - * @param metaAccess the meta-access provider * @param constant the constant to check */ public boolean isRelocatedPointer(JavaConstant constant) { @@ -314,6 +313,7 @@ public HostedProviders getProviders(MultiMethod.MultiMethodKey key) { return providers; } + @SuppressWarnings("unused") public boolean isFieldIncluded(BigBang bb, Field field) { return true; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index c890bb3ef20a..7b0348afe6dc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -545,6 +545,7 @@ private void updateInstanceField(AnalysisField field, ImageHeapInstance imageHea } } + @SuppressWarnings("unused") public boolean isValueAvailable(AnalysisField field) { return true; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java index fb20b23148f4..773a553512bd 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/reports/StatisticsPrinter.java @@ -31,7 +31,6 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; -import com.oracle.graal.pointsto.flow.MethodFlowsGraph; import com.oracle.graal.pointsto.flow.MethodTypeFlow; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; @@ -180,12 +179,11 @@ private static long[] getTypeCheckStats(BigBang bb) { continue; } - boolean runtimeMethod = isRuntimeLibraryType(method.getDeclaringClass()); MethodTypeFlow methodFlow = PointsToAnalysis.assertPointsToAnalysisMethod(method).getTypeFlow(); if (!methodFlow.flowsGraphCreated()) { continue; } - MethodFlowsGraph originalFlows = methodFlow.getMethodFlowsGraph(); + methodFlow.getMethodFlowsGraph(); } return new long[]{totalFilters, totalRemovableFilters, appTotalFilters, appTotalRemovableFilters}; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/DefaultVirtualInvokeTypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/DefaultVirtualInvokeTypeFlow.java index 796b0e8e6d3b..5b4516829356 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/DefaultVirtualInvokeTypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/typestate/DefaultVirtualInvokeTypeFlow.java @@ -215,6 +215,7 @@ public Collection getAllCallees() { } } + @Override public Collection getCalleesForReturnLinking() { if (isSaturated()) { /* If the invoke has saturated, then it is not necessary to link the callees. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java index a57aa9dda6c1..5bfa86089125 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java @@ -163,10 +163,10 @@ private void executeCommand(DebugContextRunnable command) { } bb.getHostVM().recordActivity(); Throwable thrown = null; - try (DebugContext debug = command.getDebug(bb.getOptions(), bb.getDebugHandlerFactories()); - Scope s = debug.scope("Operation"); - Activation a = debug.activate()) { - command.run(debug); + try (DebugContext debugLocal = command.getDebug(bb.getOptions(), bb.getDebugHandlerFactories()); + Scope s = debugLocal.scope("Operation"); + Activation a = debugLocal.activate()) { + command.run(debugLocal); } catch (Throwable x) { thrown = x; } finally { @@ -195,6 +195,7 @@ private void setState(State newState) { state.set(newState); } + @SuppressWarnings("unused") public long complete() throws InterruptedException { long lastPrint = 0; if (timing != null) { diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java index 636429db224b..616ab7dd9b6d 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/ObjectFile.java @@ -1557,8 +1557,8 @@ public int bake(List sortedObjectFileElements) { Map> removedEdgesDependingOn = new HashMap<>(); Map> removedEdgesDependedOnBy = new HashMap<>(); for (LayoutDecision l : allDecisions) { - removedEdgesDependingOn.put(l, new ArrayList()); - removedEdgesDependedOnBy.put(l, new ArrayList()); + removedEdgesDependingOn.put(l, new ArrayList<>()); + removedEdgesDependedOnBy.put(l, new ArrayList<>()); } // 2. run Kahn's algorithm diff --git a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocTableStruct.java b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocTableStruct.java index 6e63b99ecf12..0f8e6c66a309 100644 --- a/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocTableStruct.java +++ b/substratevm/src/com.oracle.objectfile/src/com/oracle/objectfile/pecoff/PECoffRelocTableStruct.java @@ -36,7 +36,7 @@ final class PECoffRelocTableStruct { PECoffRelocTableStruct(int numsects) { relocEntries = new ArrayList<>(numsects); for (int i = 0; i < numsects; i++) { - relocEntries.add(new ArrayList()); + relocEntries.add(new ArrayList<>()); } } diff --git a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java index 1de088372e64..89714b434bdd 100644 --- a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java +++ b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java @@ -487,8 +487,8 @@ private static void ignoreConfigFromClasspath(JvmtiEnv jvmti, ConfigurationFileC } } - private static final Pattern propertyBlacklist = Pattern.compile("(java\\..*)|(sun\\..*)|(jvmci\\..*)"); - private static final Pattern propertyWhitelist = Pattern.compile("(java\\.library\\.path)|(java\\.io\\.tmpdir)"); + @SuppressWarnings("unused") private static final Pattern propertyBlacklist = Pattern.compile("(java\\..*)|(sun\\..*)|(jvmci\\..*)"); + @SuppressWarnings("unused") private static final Pattern propertyWhitelist = Pattern.compile("(java\\.library\\.path)|(java\\.io\\.tmpdir)"); private static String transformPath(String path) { String result = path; diff --git a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgentJNIHandleSet.java b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgentJNIHandleSet.java index defd3436ffee..cd32aba734f1 100644 --- a/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgentJNIHandleSet.java +++ b/substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgentJNIHandleSet.java @@ -177,9 +177,9 @@ JNIObjectHandle getJavaIOObjectStreamClass(JNIEnvironment env) { return javaIoObjectStreamClass; } - JNIMethodId getJavaIoObjectStreamClassForClass(JNIEnvironment env, JNIObjectHandle javaIoObjectStreamClass) { + JNIMethodId getJavaIoObjectStreamClassForClass(JNIEnvironment env, JNIObjectHandle javaIoObjectStreamClassParam) { if (javaIoObjectStreamClassForClass.equal(nullHandle())) { - javaIoObjectStreamClassForClass = getMethodId(env, javaIoObjectStreamClass, "forClass", "()Ljava/lang/Class;", false); + javaIoObjectStreamClassForClass = getMethodId(env, javaIoObjectStreamClassParam, "forClass", "()Ljava/lang/Class;", false); } return javaIoObjectStreamClassForClass; } @@ -191,9 +191,9 @@ JNIMethodId getJavaIoObjectStreamClassGetName(JNIEnvironment env) { return javaIoObjectStreamClassGetName; } - JNIMethodId getJavaIoObjectStreamClassGetClassDataLayout0(JNIEnvironment env, JNIObjectHandle javaIoObjectStreamClass) { + JNIMethodId getJavaIoObjectStreamClassGetClassDataLayout0(JNIEnvironment env, JNIObjectHandle javaIoObjectStreamClassParam) { if (javaIoObjectStreamClassGetClassDataLayout0.equal(nullHandle())) { - javaIoObjectStreamClassGetClassDataLayout0 = getMethodId(env, javaIoObjectStreamClass, "getClassDataLayout0", "()[Ljava/io/ObjectStreamClass$ClassDataSlot;", false); + javaIoObjectStreamClassGetClassDataLayout0 = getMethodId(env, javaIoObjectStreamClassParam, "getClassDataLayout0", "()[Ljava/io/ObjectStreamClass$ClassDataSlot;", false); } return javaIoObjectStreamClassGetClassDataLayout0; } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapPartition.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapPartition.java index 93ba44499e1b..0c0fa409e478 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapPartition.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ChunkedImageHeapPartition.java @@ -120,18 +120,18 @@ private void allocateObjectsInAlignedChunks(ChunkedImageHeapAllocator allocator) } } - private ImageHeapObject dequeueBestFit(NavigableMap> objects, long nbytes) { + private ImageHeapObject dequeueBestFit(NavigableMap> objectsParam, long nbytes) { if (nbytes < minimumObjectSize) { return null; } - Map.Entry> entry = objects.floorEntry(nbytes); + Map.Entry> entry = objectsParam.floorEntry(nbytes); if (entry == null) { return null; } Queue queue = entry.getValue(); ImageHeapObject info = queue.remove(); if (queue.isEmpty()) { - objects.remove(entry.getKey()); + objectsParam.remove(entry.getKey()); } return info; } @@ -220,6 +220,7 @@ public long getSize() { return getEndOffset() - getStartOffset(); } + @Override public String toString() { return name; } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index 02673fac6945..bd7f77fe11bc 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -304,24 +304,16 @@ static void logZapValues(Log log) { if (HeapParameters.getZapProducedHeapChunks() || HeapParameters.getZapConsumedHeapChunks()) { /* Padded with spaces so the columns line up between the int and word variants. */ if (HeapParameters.getZapProducedHeapChunks()) { - log.string("producedHeapChunkZapInt: ") - .string(" hex: ").spaces(8).hex(HeapParameters.getProducedHeapChunkZapInt()) - .string(" signed: ").spaces(9).signed(HeapParameters.getProducedHeapChunkZapInt()) - .string(" unsigned: ").spaces(10).unsigned(HeapParameters.getProducedHeapChunkZapInt()).newline(); - log.string("producedHeapChunkZapWord:") - .string(" hex: ").hex(HeapParameters.getProducedHeapChunkZapWord()) - .string(" signed: ").signed(HeapParameters.getProducedHeapChunkZapWord()) - .string(" unsigned: ").unsigned(HeapParameters.getProducedHeapChunkZapWord()).newline(); + log.string("producedHeapChunkZapInt: ").string(" hex: ").spaces(8).hex(HeapParameters.getProducedHeapChunkZapInt()).string(" signed: ").spaces(9).signed( + HeapParameters.getProducedHeapChunkZapInt()).string(" unsigned: ").spaces(10).unsigned(HeapParameters.getProducedHeapChunkZapInt()).newline(); + log.string("producedHeapChunkZapWord:").string(" hex: ").hex(HeapParameters.getProducedHeapChunkZapWord()).string(" signed: ").signed( + HeapParameters.getProducedHeapChunkZapWord()).string(" unsigned: ").unsigned(HeapParameters.getProducedHeapChunkZapWord()).newline(); } if (HeapParameters.getZapConsumedHeapChunks()) { - log.string("consumedHeapChunkZapInt: ") - .string(" hex: ").spaces(8).hex(HeapParameters.getConsumedHeapChunkZapInt()) - .string(" signed: ").spaces(10).signed(HeapParameters.getConsumedHeapChunkZapInt()) - .string(" unsigned: ").spaces(10).unsigned(HeapParameters.getConsumedHeapChunkZapInt()).newline(); - log.string("consumedHeapChunkZapWord:") - .string(" hex: ").hex(HeapParameters.getConsumedHeapChunkZapWord()) - .string(" signed: ").signed(HeapParameters.getConsumedHeapChunkZapWord()) - .string(" unsigned: ").unsigned(HeapParameters.getConsumedHeapChunkZapWord()).newline(); + log.string("consumedHeapChunkZapInt: ").string(" hex: ").spaces(8).hex(HeapParameters.getConsumedHeapChunkZapInt()).string(" signed: ").spaces(10).signed( + HeapParameters.getConsumedHeapChunkZapInt()).string(" unsigned: ").spaces(10).unsigned(HeapParameters.getConsumedHeapChunkZapInt()).newline(); + log.string("consumedHeapChunkZapWord:").string(" hex: ").hex(HeapParameters.getConsumedHeapChunkZapWord()).string(" signed: ").signed( + HeapParameters.getConsumedHeapChunkZapWord()).string(" unsigned: ").unsigned(HeapParameters.getConsumedHeapChunkZapWord()).newline(); } } } diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java index 9c076d5daef7..6cf761106d60 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java @@ -162,12 +162,13 @@ public int initialize(Pointer reservedAddressSpace, UnsignedWord reservedSize, W } @Uninterruptible(reason = "Called during isolate initialization.") - private int initializeImageHeap(Pointer imageHeap, UnsignedWord reservedSize, WordPointer endPointer, WordPointer cachedFd, WordPointer cachedOffsetInFile, + private static int initializeImageHeap(Pointer imageHeapParam, UnsignedWord reservedSize, WordPointer endPointer, WordPointer cachedFd, WordPointer cachedOffsetInFile, Pointer magicAddress, Word heapBeginSym, Word heapEndSym, Word heapRelocsSym, Pointer heapAnyRelocPointer, Word heapRelocsEndSym, Word heapWritableSym, Word heapWritableEndSym) { assert heapBeginSym.belowOrEqual(heapWritableSym) && heapWritableSym.belowOrEqual(heapWritableEndSym) && heapWritableEndSym.belowOrEqual(heapEndSym); assert heapBeginSym.belowOrEqual(heapRelocsSym) && heapRelocsSym.belowOrEqual(heapRelocsEndSym) && heapRelocsEndSym.belowOrEqual(heapEndSym); assert heapAnyRelocPointer.isNull() || (heapRelocsSym.belowOrEqual(heapAnyRelocPointer) && heapAnyRelocPointer.belowThan(heapRelocsEndSym)); + Pointer imageHeap = imageHeapParam; SignedWord fd = cachedFd.read(); /* diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java index e84606ddf7ae..7a4edd12ee0a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java @@ -127,6 +127,7 @@ public static class Options { private static final long MARKER_VALUE = 0x0123456789ABCDEFL; @UnknownPrimitiveField(availability = ReadyForCompilation.class) // static long offsetOfStaticFieldWithWellKnownValue; + @SuppressWarnings("unused") private static long staticFieldWithWellKnownValue = MARKER_VALUE; private boolean installed; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java index 9635ce183f0d..6415d10314aa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java @@ -63,7 +63,7 @@ public class FrameInfoDecoder { */ protected static final int ENCODED_BCI_ADDEND = 4; /** - * Flag in the encoded bci to preserve {@link FrameState#duringCall()} information. + * Flag in the encoded bci to preserve {@link jdk.graal.compiler.nodes.FrameState.StackState#duringCall} information. */ protected static final int ENCODED_BCI_DURING_CALL_MASK = 2; /** diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/replacements/SubstrateGraphKit.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/replacements/SubstrateGraphKit.java index 6ce0a602447c..84c30e4b4d3e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/replacements/SubstrateGraphKit.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/replacements/SubstrateGraphKit.java @@ -169,24 +169,24 @@ public ValueNode createInvokeWithExceptionAndUnwind(Class declaringClass, Str return createInvokeWithExceptionAndUnwind(findMethod(declaringClass, name, invokeKind == InvokeKind.Static), invokeKind, frameState, bci(), args); } - public InvokeWithExceptionNode createJavaCallWithException(InvokeKind kind, ResolvedJavaMethod targetMethod, ValueNode... arguments) { - return startInvokeWithException(targetMethod, kind, frameState, bci(), arguments); + public InvokeWithExceptionNode createJavaCallWithException(InvokeKind kind, ResolvedJavaMethod targetMethod, ValueNode... argumentsParam) { + return startInvokeWithException(targetMethod, kind, frameState, bci(), argumentsParam); } - public InvokeWithExceptionNode createJavaCallWithExceptionAndUnwind(InvokeKind kind, ResolvedJavaMethod targetMethod, ValueNode... arguments) { - return createInvokeWithExceptionAndUnwind(targetMethod, kind, frameState, bci(), arguments); + public InvokeWithExceptionNode createJavaCallWithExceptionAndUnwind(InvokeKind kind, ResolvedJavaMethod targetMethod, ValueNode... argumentsParam) { + return createInvokeWithExceptionAndUnwind(targetMethod, kind, frameState, bci(), argumentsParam); } public ConstantNode createConstant(Constant value, JavaKind kind) { return ConstantNode.forConstant(StampFactory.forKind(kind), value, getMetaAccess(), getGraph()); } - public ValueNode createCFunctionCall(ValueNode targetAddress, List arguments, Signature signature, int newThreadStatus, boolean emitDeoptTarget) { - return createCFunctionCallWithCapture(targetAddress, arguments, signature, newThreadStatus, emitDeoptTarget, SubstrateCallingConventionKind.Native.toType(true), + public ValueNode createCFunctionCall(ValueNode targetAddress, List argumentsParam, Signature signature, int newThreadStatus, boolean emitDeoptTarget) { + return createCFunctionCallWithCapture(targetAddress, argumentsParam, signature, newThreadStatus, emitDeoptTarget, SubstrateCallingConventionKind.Native.toType(true), null, null, null); } - public ValueNode createCFunctionCallWithCapture(ValueNode targetAddress, List arguments, Signature signature, int newThreadStatus, boolean emitDeoptTarget, + public ValueNode createCFunctionCallWithCapture(ValueNode targetAddress, List argumentsParam, Signature signature, int newThreadStatus, boolean emitDeoptTarget, CallingConvention.Type convention, ForeignCallDescriptor captureFunction, ValueNode statesToCapture, ValueNode captureBuffer) { assert ((captureFunction == null) && (statesToCapture == null) && (captureBuffer == null)) || ((captureFunction != null) && (statesToCapture != null) && (captureBuffer != null)); @@ -212,7 +212,7 @@ public ValueNode createCFunctionCallWithCapture(ValueNode targetAddress, List arguments, Signature signature, SubstrateCallingConventionKind callKind) { - assert arguments.size() == signature.getParameterCount(false); + public InvokeNode createIndirectCall(ValueNode targetAddress, List argumentsParam, Signature signature, SubstrateCallingConventionKind callKind) { + assert argumentsParam.size() == signature.getParameterCount(false); assert callKind != SubstrateCallingConventionKind.Native : "return kind and stamp would be incorrect"; JavaKind returnKind = signature.getReturnKind().getStackKind(); Stamp returnStamp = returnStamp(signature.getReturnType(null), returnKind); - return createIndirectCall(targetAddress, arguments, signature.toParameterTypes(null), returnStamp, returnKind, callKind); + return createIndirectCall(targetAddress, argumentsParam, signature.toParameterTypes(null), returnStamp, returnKind, callKind); } - private InvokeNode createIndirectCall(ValueNode targetAddress, List arguments, JavaType[] parameterTypes, Stamp returnStamp, JavaKind returnKind, + private InvokeNode createIndirectCall(ValueNode targetAddress, List argumentsParam, JavaType[] parameterTypes, Stamp returnStamp, JavaKind returnKind, SubstrateCallingConventionKind callKind) { - return createIndirectCall(targetAddress, arguments, parameterTypes, returnStamp, returnKind, callKind.toType(true)); + return createIndirectCall(targetAddress, argumentsParam, parameterTypes, returnStamp, returnKind, callKind.toType(true)); } - private InvokeNode createIndirectCall(ValueNode targetAddress, List arguments, JavaType[] parameterTypes, Stamp returnStamp, JavaKind returnKind, + private InvokeNode createIndirectCall(ValueNode targetAddress, List argumentsParam, JavaType[] parameterTypes, Stamp returnStamp, JavaKind returnKind, CallingConvention.Type convention) { frameState.clearStack(); int bci = bci(); CallTargetNode callTarget = getGraph().add( - new IndirectCallTargetNode(targetAddress, arguments.toArray(new ValueNode[arguments.size()]), StampPair.createSingle(returnStamp), parameterTypes, null, + new IndirectCallTargetNode(targetAddress, argumentsParam.toArray(new ValueNode[argumentsParam.size()]), StampPair.createSingle(returnStamp), parameterTypes, null, convention, InvokeKind.Static)); InvokeNode invoke = append(new InvokeNode(callTarget, bci)); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java index 88d39fd13825..e98d1be98c90 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java @@ -24,11 +24,6 @@ */ package com.oracle.svm.core.heap; -import jdk.graal.compiler.api.directives.GraalDirectives; -import jdk.graal.compiler.graph.Node.NodeIntrinsic; -import jdk.graal.compiler.nodes.extended.MembarNode; -import jdk.graal.compiler.nodes.java.ArrayLengthNode; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.StackValue; import org.graalvm.nativeimage.c.function.CodePointer; @@ -45,25 +40,27 @@ import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.CodeInfoTable; -import com.oracle.svm.core.code.FrameInfoQueryResult; import com.oracle.svm.core.code.SimpleCodeInfoQueryResult; import com.oracle.svm.core.code.UntetheredCodeInfo; import com.oracle.svm.core.config.ConfigurationValues; -import com.oracle.svm.core.deopt.DeoptimizedFrame; import com.oracle.svm.core.deopt.Deoptimizer; import com.oracle.svm.core.graal.nodes.NewStoredContinuationNode; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.stack.JavaStackWalk; import com.oracle.svm.core.stack.JavaStackWalker; -import com.oracle.svm.core.stack.StackFrameVisitor; import com.oracle.svm.core.thread.ContinuationInternals; import com.oracle.svm.core.thread.ContinuationSupport; -import com.oracle.svm.core.thread.Safepoint; import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.graph.Node.NodeIntrinsic; +import jdk.graal.compiler.nodes.extended.MembarNode; +import jdk.graal.compiler.nodes.java.ArrayLengthNode; +import jdk.graal.compiler.word.Word; + /** Helper for allocating and accessing {@link StoredContinuation} instances. */ public final class StoredContinuationAccess { private StoredContinuationAccess() { @@ -269,47 +266,4 @@ public abstract static class ContinuationStackFrameVisitor { public interface ContinuationStackFrameVisitorData extends PointerBase { } - private static final class PreemptVisitor extends StackFrameVisitor { - private final Pointer endSP; - private boolean startFromNextFrame = false; - - Pointer leafSP; - CodePointer leafIP; - int preemptStatus = ContinuationSupport.FREEZE_OK; - - PreemptVisitor(Pointer endSP) { - this.endSP = endSP; - } - - @Override - protected boolean visitFrame(Pointer sp, CodePointer ip, CodeInfo codeInfo, DeoptimizedFrame deoptimizedFrame) { - if (sp.aboveOrEqual(endSP)) { - return false; - } - - FrameInfoQueryResult frameInfo = CodeInfoTable.lookupCodeInfoQueryResult(codeInfo, ip).getFrameInfo(); - if (frameInfo.getSourceClass().equals(StoredContinuationAccess.class) && frameInfo.getSourceMethodName().equals("allocateToYield")) { - // Continuation is already in the process of yielding, cancel preemption. - preemptStatus = ContinuationSupport.FREEZE_YIELDING; - return false; - } - - if (leafSP.isNull()) { - // Should start from the method calling `enterSlowPathSafepointCheck`. - if (startFromNextFrame) { - leafSP = sp; - leafIP = ip; - } else { - if (frameInfo.getSourceClass().equals(Safepoint.class) && frameInfo.getSourceMethodName().equals("enterSlowPathSafepointCheck")) { - startFromNextFrame = true; - } - return true; - } - } - - VMError.guarantee(codeInfo.equal(CodeInfoTable.getImageCodeInfo())); - - return true; - } - } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index 4f97504a6afe..da8fbf084262 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -1456,7 +1456,7 @@ public String toString() { @KeepOriginal @TargetElement(onlyWith = JDK23OrLater.class) - private native void addSealingInfo(int modifiers, StringBuilder sb); + private native void addSealingInfo(int modifiersParam, StringBuilder sb); @KeepOriginal @TargetElement(onlyWith = JDK23OrLater.class) @@ -1771,7 +1771,7 @@ private Class[] getPermittedSubclasses0() { @KeepOriginal @TargetElement(onlyWith = JDK22OrLater.class) - native Method findMethod(boolean publicOnly, String name, Class... parameterTypes); + native Method findMethod(boolean publicOnly, String nameParam, Class... parameterTypes); @KeepOriginal private native Method getMethod0(String methodName, Class[] parameterTypes); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/ImageHeapLayouter.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/ImageHeapLayouter.java index ca4e4bfd9fc8..b9fd85f31d34 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/ImageHeapLayouter.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/ImageHeapLayouter.java @@ -48,6 +48,7 @@ public interface ImageHeapLayouter { ImageHeapLayoutInfo layout(ImageHeap imageHeap, int pageSize); /** Hook to run tasks after heap layout is finished. */ + @SuppressWarnings("unused") default void afterLayout(ImageHeap imageHeap) { } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java index ce32220a781b..5f30baf58225 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java @@ -84,7 +84,7 @@ public ForkJoinTask submit(Runnable task) { return ForkJoinPool.commonPool().submit(task); } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked","static-method"}) public List> invokeAllUninterruptibly(Collection> tasks) { VMError.guarantee(JavaVersionUtil.JAVA_SPEC >= 22, "invokeAllUninterruptibly only exists in JDK 22+"); var m = ReflectionUtil.lookupMethod(ForkJoinPool.class, "invokeAllUninterruptibly", Collection.class); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java index f0eb0b704ff4..6d99731a9978 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java @@ -51,6 +51,7 @@ public boolean getAsBoolean() { @TargetClass(className = "jdk.internal.foreign.MemorySessionImpl", onlyWith = ForeignDisabled.class) final class Target_jdk_internal_foreign_MemorySessionImpl { @Substitute + @SuppressWarnings("static-method") Target_java_lang_foreign_Arena asArena() { throw ForeignDisabledSubstitutions.fail(); } @@ -67,6 +68,7 @@ final class Target_java_lang_foreign_Linker { @TargetClass(className = "jdk.internal.foreign.abi.SharedUtils", onlyWith = ForeignDisabled.class) final class Target_jdk_internal_foreign_abi_SharedUtils { @Substitute + @SuppressWarnings("unused") static Target_java_lang_foreign_Arena newBoundedArena(long size) { throw ForeignDisabledSubstitutions.fail(); } @@ -89,6 +91,7 @@ final class Target_java_lang_foreign_MemoryLayout { @TargetClass(className = "jdk.internal.foreign.FunctionDescriptorImpl", onlyWith = ForeignDisabled.class) final class Target_jdk_internal_foreign_FunctionDescriptorImpl { @Substitute + @SuppressWarnings("unused") Target_jdk_internal_foreign_FunctionDescriptorImpl(Target_java_lang_foreign_MemoryLayout resLayout, List argLayouts) { throw ForeignDisabledSubstitutions.fail(); } @@ -106,6 +109,7 @@ static void ensureInitialized() { @TargetClass(className = "sun.nio.ch.FileChannelImpl", onlyWith = ForeignDisabled.class) final class Target_sun_nio_ch_FileChannelImpl { @Substitute + @SuppressWarnings({"unused","static-method"}) Target_java_lang_foreign_MemorySegment map(FileChannel.MapMode mode, long offset, long size, Target_java_lang_foreign_Arena arena) throws IOException { throw ForeignDisabledSubstitutions.fail(); } @@ -123,11 +127,13 @@ final class Target_java_lang_foreign_MemoryLayout_PathElement { final class Target_jdk_internal_foreign_layout_AbstractLayout { @Substitute @AlwaysInline("Make remaining code in callers unreachable.") + @SuppressWarnings({"unused","static-method"}) VarHandle varHandle(Target_java_lang_foreign_MemoryLayout_PathElement... elements) { throw ForeignDisabledSubstitutions.fail(); } @Substitute + @SuppressWarnings("unused") static Z computePathOp(Target_jdk_internal_foreign_LayoutPath path, Function finalizer, Set badKinds, Target_java_lang_foreign_MemoryLayout_PathElement... elements) { throw ForeignDisabledSubstitutions.fail(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JRTSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JRTSupport.java index 8757de6e5005..55f9ce289a4d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JRTSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JRTSupport.java @@ -197,6 +197,7 @@ final class Target_jdk_internal_jimage_BasicImageReader { @Substitute final class Target_jdk_internal_jimage_NativeImageBuffer { @Substitute + @SuppressWarnings("unused") static ByteBuffer getNativeMap(String imagePath) { throw VMError.unsupportedFeature("Using jdk.internal.jimage.NativeImageBuffer is not supported"); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java index a68c7ea8346a..4d93a51110c3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java @@ -416,13 +416,17 @@ private static String getProperty(String key, String def) { private static int allowSecurityManager = 1; /** - * We do not support the {@link SecurityManager} so this method must throw a - * {@link SecurityException} when 'java.security.manager' is set to anything but - * disallow. + * We do not support the SecurityManager + * so this method must throw a {@link SecurityException} when 'java.security.manager' is set to + * anything but disallow. * - * @see System#setSecurityManager(SecurityManager) - * @see SecurityManager + * @see System#setSecurityManager(SecurityManager) + * @see SecurityManager */ + @SuppressWarnings("removal") @Substitute private static void setSecurityManager(SecurityManager sm) { if (sm != null) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java index 68d338387808..44984e18f96a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NativeLibrarySupport.java @@ -140,6 +140,7 @@ private boolean addLibrary(boolean asBuiltin, String canonical, boolean initiali } } + @Override public PointerBase findSymbol(String name) { lock.lock(); try { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_Module.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_Module.java index 0238aac44e55..ab1b98e77722 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_Module.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_Module.java @@ -39,6 +39,7 @@ public final class Target_java_lang_Module { @Substitute @TargetElement(onlyWith = ForeignDisabled.class) + @SuppressWarnings("static-method") public boolean isNativeAccessEnabled() { throw ForeignDisabledSubstitutions.fail(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_Bits.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_Bits.java index 24d193ba1be0..8f7ef8445213 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_Bits.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_Bits.java @@ -69,6 +69,7 @@ static long getMAX_MEMORY() { return DirectMemoryAccessors.getDirectMemory(); } + @SuppressWarnings("unused") static void setMAX_MEMORY(long value) { /* Nothing to do. */ } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_DirectByteBuffer.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_DirectByteBuffer.java index e414b25706de..c680cd8cdf7f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_DirectByteBuffer.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_nio_DirectByteBuffer.java @@ -57,6 +57,7 @@ public final class Target_java_nio_DirectByteBuffer { } @Alias + @SuppressWarnings("unused") Target_java_nio_DirectByteBuffer(int cap, long addr, FileDescriptor fd, Runnable unmapper, boolean isSync, Target_java_lang_foreign_MemorySegment segment) { throw VMError.shouldNotReachHere("This is an alias to the original constructor in the target class, so this code is unreachable"); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_reflect_Reflection.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_reflect_Reflection.java index d63d006adb4e..9083014ae4f2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_reflect_Reflection.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_reflect_Reflection.java @@ -41,6 +41,7 @@ final class Target_jdk_internal_reflect_Reflection { @TargetElement(onlyWith = ForeignDisabled.class) @Substitute @AlwaysInline("Make remaining code in callers unreachable.") + @SuppressWarnings("unused") static void ensureNativeAccess(Class currentClass, Class owner, String methodName) { throw ForeignDisabledSubstitutions.fail(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java index fe2cb8dd2720..db339beac710 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/LocalizationSupport.java @@ -262,7 +262,7 @@ public void prepareClassResourceBundle(@SuppressWarnings("unused") String basena * default constructor as invoked if it exists, and as queried if it doesn't, which we know will * result in a negative query. */ - private void registerNullaryConstructor(Class bundleClass) { + private static void registerNullaryConstructor(Class bundleClass) { RuntimeReflection.register(bundleClass); Constructor nullaryConstructor; try { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java index edf7d1ce6f99..362f876b41a2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java @@ -108,6 +108,7 @@ private static void install(IsolateThread thread, RecurringCallbackTimer callbac @Override @Uninterruptible(reason = "Prevent VM operations that modify the recurring callbacks.") + @Override protected void uninstall(IsolateThread thread) { assert thread == CurrentIsolate.getCurrentThread() || VMOperation.isInProgressAtSafepoint(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIThreadOwnedMonitors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIThreadOwnedMonitors.java index 9f903787ba49..0ea3b32108dd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIThreadOwnedMonitors.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jni/JNIThreadOwnedMonitors.java @@ -41,7 +41,7 @@ public class JNIThreadOwnedMonitors { @SuppressWarnings("unchecked") private static IdentityHashMap mutableMap() { if (ownedMonitors.get() == null) { - ownedMonitors.set(new IdentityHashMap()); + ownedMonitors.set(new IdentityHashMap<>()); } return ownedMonitors.get(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/RealLog.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/RealLog.java index 5cfacb066bf2..aba1533922df 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/RealLog.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/log/RealLog.java @@ -27,8 +27,6 @@ import java.nio.charset.StandardCharsets; -import jdk.graal.compiler.core.common.calc.UnsignedMath; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.LogHandler; import org.graalvm.nativeimage.c.type.CCharPointer; @@ -52,6 +50,9 @@ import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.core.common.calc.UnsignedMath; +import jdk.graal.compiler.word.Word; + public class RealLog extends Log { private boolean autoflush = false; @@ -187,6 +188,7 @@ public Log string(CCharPointer value) { return this; } + @Override @RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not allocate when logging.") public Log string(CCharPointer bytes, int length) { if (length == 0) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_AccessorGenerator.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_AccessorGenerator.java index 1247b80bb3bf..c918d64711c2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_AccessorGenerator.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/target/Target_jdk_internal_reflect_AccessorGenerator.java @@ -26,7 +26,6 @@ import java.util.function.Function; -import jdk.graal.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -35,6 +34,8 @@ import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.reflect.serialize.SerializationRegistry; +import jdk.graal.compiler.serviceprovider.JavaVersionUtil; + @TargetClass(className = "jdk.internal.reflect.AccessorGenerator") public final class Target_jdk_internal_reflect_AccessorGenerator { } @@ -43,6 +44,7 @@ public final class Target_jdk_internal_reflect_AccessorGenerator { final class Target_jdk_internal_reflect_SerializationConstructorAccessorGenerator { @Substitute + @SuppressWarnings("static-method") public Target_jdk_internal_reflect_SerializationConstructorAccessorImpl generateSerializationConstructor(Class declaringClass, @SuppressWarnings("unused") Class[] parameterTypes, @SuppressWarnings("unused") int modifiers, diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java index a6b21fdf0b26..25563c9b78c3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java @@ -516,6 +516,7 @@ static void blockedOnJDK22(Target_sun_nio_ch_Interruptible b) { @Substitute @TargetElement(onlyWith = JDK23OrLater.class) + @SuppressWarnings("static-method") void blockedOn(Target_sun_nio_ch_Interruptible b) { JavaThreads.blockedOn(b); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java index d8de56243df6..438f7adee31e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_VirtualThread.java @@ -138,6 +138,7 @@ private static synchronized ForkJoinPool initializeDefaultScheduler() { private static final class UnparkerAccessor { private static volatile ScheduledExecutorService delayedTaskScheduler; + @SuppressWarnings("unused") public static ScheduledExecutorService get() { ScheduledExecutorService result = delayedTaskScheduler; if (result == null) { diff --git a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java index d072815b12cb..b6ae3472254e 100644 --- a/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java +++ b/substratevm/src/com.oracle.svm.driver/src/com/oracle/svm/driver/NativeImage.java @@ -1554,8 +1554,8 @@ protected int buildImage(List javaArgs, LinkedHashSet cp, LinkedHa List finalImageClassPath = imagecp.stream().map(substituteClassPath).collect(Collectors.toList()); Function substituteModulePath = useBundle() ? bundleSupport::substituteModulePath : Function.identity(); - List imageModulePath = imagemp.stream().map(substituteModulePath).collect(Collectors.toList()); - Map applicationModules = getModulesFromPath(imageModulePath); + List localImageModulePath = imagemp.stream().map(substituteModulePath).collect(Collectors.toList()); + Map applicationModules = getModulesFromPath(localImageModulePath); if (!applicationModules.isEmpty()) { // Remove modules that we already have built-in diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java index 9d0e007a3d1d..adba40cd20c4 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java @@ -342,7 +342,7 @@ private static long hashConstantOopFields(JNIEnv jniEnv, * @param timeAndMemBufferAddress 16-byte native buffer to store result of time and memory * measurements of the compilation * @param profilePathBufferAddress native buffer containing a 0-terminated C string representing - * {@link ProfileReplaySupport.Options#LoadProfiles} path. + * {@link jdk.graal.compiler.hotspot.ProfileReplaySupport.Options#LoadProfiles} path. * @return a handle to a {@link InstalledCode} in HotSpot's heap or 0 if compilation failed */ @SuppressWarnings({"unused", "try"}) diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationCandidate.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationCandidate.java index 361cd8532c46..d88759b939e2 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationCandidate.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationCandidate.java @@ -45,6 +45,7 @@ public AnalysisMethod getTargetMethod() { return targetMethod; } + @Override public boolean equals(Object o) { if (this == o) { return true; diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java index 9ef831f88e4a..a273962eab59 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java @@ -201,10 +201,10 @@ public void run(DebugContext debug) { } @SuppressWarnings("try") - private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod method) { - assert method.getMultiMethodKey() == RUNTIME_COMPILED_METHOD; + private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod hostedMethod) { + assert hostedMethod.getMultiMethodKey() == RUNTIME_COMPILED_METHOD; - AnalysisMethod aMethod = method.getWrapped(); + AnalysisMethod aMethod = hostedMethod.getWrapped(); StructuredGraph graph = aMethod.decodeAnalyzedGraph(debug, null, false, (arch, analyzedGraph) -> new RuntimeCompilationGraphDecoder(arch, analyzedGraph, compilationState.heapScanner)); if (graph == null) { @@ -216,7 +216,7 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho */ aMethod.setAnalyzedGraph(null); - try (DebugContext.Scope s = debug.scope("RuntimeOptimize", graph, method, this)) { + try (DebugContext.Scope s = debug.scope("RuntimeOptimize", graph, hostedMethod, this)) { CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); canonicalizer.apply(graph, compilationState.runtimeCompilationProviders); @@ -241,7 +241,7 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho * Registering all deopt entries seen within the optimized graph. This should be * strictly a subset of the deopt entrypoints seen during evaluation. */ - AnalysisMethod origMethod = method.getMultiMethod(ORIGINAL_METHOD).getWrapped(); + AnalysisMethod origMethod = hostedMethod.getMultiMethod(ORIGINAL_METHOD).getWrapped(); DeoptimizationUtils.registerDeoptEntries(graph, compilationState.registeredRuntimeCompilations.contains(origMethod), (deoptEntryMethod -> { PointsToAnalysisMethod deoptMethod = (PointsToAnalysisMethod) ((PointsToAnalysisMethod) deoptEntryMethod).getMultiMethod(DEOPT_TARGET_METHOD); @@ -250,7 +250,7 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho })); assert verifyNodes(graph); - var previous = compilationState.runtimeGraphs.put(method, graph); + var previous = compilationState.runtimeGraphs.put(hostedMethod, graph); assert previous == null; // graph encoder is not currently threadsafe @@ -349,6 +349,7 @@ public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receive * {@link GraphEncoder#objectsArray} are captured in GraalSupport#graphObjects and * SubstrateReplacements#snippetObjects which are then scanned. */ + @SuppressWarnings("javadoc") public static class RuntimeCompilationGraphEncoder extends GraphEncoder { private final ImageHeapScanner heapScanner; diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java index 0a98617836da..18caa7e11901 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java @@ -74,10 +74,10 @@ public SubstrateRuntimeConfigurationBuilder(OptionValues options, SVMHost hostVM @Override protected Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, - LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider snippetReflection, + LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider) { return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider); + metaAccessExtensionProvider, reflectionProvider, wordTypes, loopsDataProvider); } @Override @@ -96,9 +96,9 @@ protected LoweringProvider createLoweringProvider(ForeignCallsProvider foreignCa } @Override - protected Replacements createReplacements(Providers p, SnippetReflectionProvider snippetReflection) { + protected Replacements createReplacements(Providers p, SnippetReflectionProvider reflectionProvider) { BytecodeProvider bytecodeProvider = new ResolvedJavaMethodBytecodeProvider(); - return new SubstrateReplacements(p, snippetReflection, bytecodeProvider, ConfigurationValues.getTarget(), new SubstrateGraphMakerFactory()); + return new SubstrateReplacements(p, reflectionProvider, bytecodeProvider, ConfigurationValues.getTarget(), new SubstrateGraphMakerFactory()); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java index 624b129bf195..687c45a11e9d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageClassLoader.java @@ -41,17 +41,18 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import com.oracle.svm.util.LogUtils; import org.graalvm.collections.EconomicSet; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.word.Word; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.TypeResult; +import com.oracle.svm.util.LogUtils; import com.oracle.svm.util.ReflectionUtil; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.word.Word; + public final class ImageClassLoader { static { @@ -80,6 +81,7 @@ public final class ImageClassLoader { this.watchdog = new DeadlockWatchdog(watchdogInterval, watchdogExitOnTimeout); } + @SuppressWarnings("unused") public void loadAllClasses() throws InterruptedException { ForkJoinPool executor = ForkJoinPool.commonPool(); try { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java index 94d12db5fdec..dd73d4fc260e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java @@ -24,22 +24,21 @@ */ package com.oracle.svm.hosted; +import com.oracle.graal.pointsto.util.AnalysisFuture; +import com.oracle.svm.core.BuildPhaseProvider; +import com.oracle.svm.core.ParsingReason; +import com.oracle.svm.core.util.VMError; + import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.nodeinfo.NodeCycles; import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodeinfo.NodeSize; -import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; import jdk.graal.compiler.nodes.FixedWithNextNode; import jdk.graal.compiler.nodes.spi.Canonicalizable; import jdk.graal.compiler.nodes.spi.CanonicalizerTool; -import com.oracle.graal.pointsto.util.AnalysisFuture; -import com.oracle.svm.core.BuildPhaseProvider; -import com.oracle.svm.core.ParsingReason; -import com.oracle.svm.core.util.VMError; - /** * Allows a custom callback to be executed when this node is reachable. * @@ -59,8 +58,10 @@ * * To use: *
    - *
  1. Create a subclass of {@link InvocationPlugin.RequiredInvocationPlugin} that is also a - * decorator (override @{@link InvocationPlugin.RequiredInvocationPlugin#isDecorator()})
  2. + *
  3. Create a subclass of + * {@link jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin} that + * is also a decorator + * (override @{@link jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin#isDecorator()})
  4. *
  5. When applying the plugin, add this node to the graph with a @{link {@link Runnable} that * registers the metadata.}
  6. *
diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index b284202c1e69..8705ac5b5703 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -339,7 +339,7 @@ public GraphBuilderConfiguration updateGraphBuilderConfiguration(GraphBuilderCon return updatedConfig; } - private boolean retainLocalVariables() { + private static boolean retainLocalVariables() { /* * Disabling liveness analysis preserves the values of local variables beyond the * bytecode-liveness. This greatly helps debugging. Note that when local variable numbers @@ -422,7 +422,7 @@ private DynamicHub createHub(AnalysisType type) { private static final Method getSignature = ReflectionUtil.lookupMethod(Class.class, "getGenericSignature0"); - private String getSignature(Class javaClass) { + private static String getSignature(Class javaClass) { try { return (String) getSignature.invoke(javaClass); } catch (IllegalAccessException | InvocationTargetException e) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java index 12aeeb068cc2..4902e98e8b6e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/codegen/CCompilerInvoker.java @@ -177,7 +177,7 @@ protected CompilerInfo createCompilerInfo(Path compilerPath, Scanner scanner) { } } - private void skipLineIfHasNext(Scanner scanner, String expectedToken) { + private static void skipLineIfHasNext(Scanner scanner, String expectedToken) { if (scanner.hasNext(expectedToken)) { scanner.nextLine(); } else { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java index 5f91af0d4802..bc5a2dc3e32f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java @@ -744,7 +744,7 @@ protected static int asIntegerOrMinusOne(ValueNode node) { * sub-integer types are often just integer constants in the Graal IR, i.e., we cannot rely on * the JavaKind of the constant to match the type of the field or array. */ - private JavaConstant adaptForImageHeap(JavaConstant value, JavaKind storageKind) { + private static JavaConstant adaptForImageHeap(JavaConstant value, JavaKind storageKind) { if (value.getJavaKind() != storageKind) { assert value instanceof PrimitiveConstant && value.getJavaKind().getStackKind() == storageKind.getStackKind() : "only sub-int values can have a mismatch of the JavaKind: " + value.getJavaKind() + ", " + storageKind; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java index 168bad0e2b3c..3001707c40ee 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java @@ -69,9 +69,9 @@ public HostedRuntimeConfigurationBuilder(OptionValues options, SVMHost hostVM, H @Override protected Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, - LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider snippetReflection, + LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider) { - return new HostedProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, snippetReflection, + return new HostedProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, reflectionProvider, wordTypes, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java index 8e01f6c70462..3aa829140df4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java @@ -151,7 +151,7 @@ public final RuntimeConfiguration build() { protected abstract Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, - LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider snippetReflection, + LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider); protected abstract ConstantReflectionProvider createConstantReflectionProvider(); @@ -168,7 +168,7 @@ private StampProvider createStampProvider() { protected abstract LoweringProvider createLoweringProvider(ForeignCallsProvider foreignCalls, MetaAccessExtensionProvider metaAccessExtensionProvider); - protected abstract Replacements createReplacements(Providers p, SnippetReflectionProvider snippetReflection); + protected abstract Replacements createReplacements(Providers p, SnippetReflectionProvider reflectionProvider); protected abstract CodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/HybridLayoutSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/HybridLayoutSupport.java index ffd5a89a1413..89a320ecd33a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/HybridLayoutSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/config/HybridLayoutSupport.java @@ -47,6 +47,7 @@ public boolean isHybrid(ResolvedJavaType clazz) { return clazz.isAnnotationPresent(Hybrid.class); } + @SuppressWarnings("unused") public boolean isHybridField(HostedField field) { return false; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/DisallowedImageHeapObjectFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/DisallowedImageHeapObjectFeature.java index 3739b8c57a99..2b85e64ce026 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/DisallowedImageHeapObjectFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/DisallowedImageHeapObjectFeature.java @@ -123,6 +123,7 @@ private static String[] getDisallowedSubstrings(String... substrings) { }).toArray(String[]::new); } + @SuppressWarnings("unused") private void onStringReachable(DuringAnalysisAccess a, String string) { if (disallowedSubstrings != null) { for (String disallowedSubstring : disallowedSubstrings) { @@ -137,6 +138,7 @@ private void onStringReachable(DuringAnalysisAccess a, String string) { } } + @SuppressWarnings("unused") private void onByteArrayReachable(DuringAnalysisAccess a, byte[] bytes) { if (disallowedByteSubstrings != null) { for (Map.Entry entry : disallowedByteSubstrings.entrySet()) { @@ -156,6 +158,7 @@ private void onByteArrayReachable(DuringAnalysisAccess a, byte[] bytes) { /** * See {@link ManagementSupport} for details why these objects are not allowed. */ + @SuppressWarnings("unused") private void onMBeanServerConnectionReachable(DuringAnalysisAccess a, MBeanServerConnection serverConnection) { throw error("Detected a MBean server in the image heap. This is currently not supported, but could be changed in the future. " + "Management beans are registered in many global caches that would need to be cleared and properly re-built at image build time. " + @@ -166,6 +169,7 @@ private void onMBeanServerConnectionReachable(DuringAnalysisAccess a, MBeanServe /** * See {@link ManagementSupport} for details why these objects are not allowed. */ + @SuppressWarnings("unused") private void onPlatformManagedObjectReachable(DuringAnalysisAccess a, PlatformManagedObject platformManagedObject) { if (!ManagementSupport.getSingleton().isAllowedPlatformManagedObject(platformManagedObject)) { throw error("Detected a PlatformManagedObject (a MXBean defined by the virtual machine) in the image heap. " + diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index 3d9db20447b3..bafbe2d8c665 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -185,10 +185,8 @@ protected final void write(DebugContext context, Path outputFile) { void writeHeaderFiles(Path outputDir, String imageName, boolean dynamic) { /* Group methods by header files. */ - Map, List> hostedMethods = uniqueEntryPoints.stream() - .filter(this::shouldWriteHeader) - .map(m -> Pair.create(cHeader(m), m)) - .collect(Collectors.groupingBy(Pair::getLeft, Collectors.mapping(Pair::getRight, Collectors.toList()))); + Map, List> hostedMethods = uniqueEntryPoints.stream().filter(this::shouldWriteHeader).map(m -> Pair.create(cHeader(m), m)).collect( + Collectors.groupingBy(Pair::getLeft, Collectors.mapping(Pair::getRight, Collectors.toList()))); hostedMethods.forEach((headerClass, methods) -> { methods.sort(NativeImage::sortMethodsByFileNameAndPosition); @@ -209,9 +207,7 @@ private void writeHeaderFile(Path outDir, Header header, List meth writer.writeCStandardHeaders(); - List dependencies = header.dependsOn().stream() - .map(NativeImage::instantiateCHeader) - .map(depHeader -> "<" + depHeader.name() + dynamicSuffix + ">").collect(Collectors.toList()); + List dependencies = header.dependsOn().stream().map(NativeImage::instantiateCHeader).map(depHeader -> "<" + depHeader.name() + dynamicSuffix + ">").collect(Collectors.toList()); writer.includeFiles(dependencies); ByteArrayOutputStream baos = new ByteArrayOutputStream(); @@ -570,7 +566,7 @@ private static boolean checkEmbeddedOffset(ProgbitsSectionImpl sectionImpl, fina return true; } - private void validateNoDirectRelocationsInTextSection(RelocatableBuffer.Info info) { + private static void validateNoDirectRelocationsInTextSection(RelocatableBuffer.Info info) { if (SubstrateOptions.NoDirectRelocationsInText.getValue() && RelocationKind.isDirect(info.getRelocationKind())) { String message = "%nFound direct relocation in text section. This means that the resulting generated image will have relocations present within the text section. If this is okay, you can skip this check by setting the flag %s"; throw VMError.shouldNotReachHere(message, SubstrateOptionsParser.commandArgument(SubstrateOptions.NoDirectRelocationsInText, "-")); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageBFDNameProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageBFDNameProvider.java index 681c17a8a712..39bcc2b5438a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageBFDNameProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageBFDNameProvider.java @@ -815,7 +815,7 @@ private void mangleArrayPointer(String loaderName, String baseName, int dims) { mangleClassPointer(loaderName, makeArrayName(baseName, dims)); } - private String makeArrayName(String baseName, int dims) { + private static String makeArrayName(String baseName, int dims) { StringBuilder sb1 = new StringBuilder(); sb1.append(baseName); for (int i = 0; i < dims; i++) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index 90c5ddf576c6..d1e54567d0bb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -182,8 +182,8 @@ public Pair getLastCompilation() { } protected List> computeCompilationOrder(Map compilationMap) { - return compilationMap.entrySet().stream().map(e -> Pair.create(e.getKey(), e.getValue())).sorted(Comparator.comparing(o -> o.getLeft().wrapped.format("%H.%n(%P):%R"))) - .collect(Collectors.toList()); + return compilationMap.entrySet().stream().map(e -> Pair.create(e.getKey(), e.getValue())).sorted(Comparator.comparing(o -> o.getLeft().wrapped.format("%H.%n(%P):%R"))).collect( + Collectors.toList()); } public List> getOrderedCompilations() { @@ -401,9 +401,7 @@ protected void buildRuntimeMetadata(DebugContext debug, SnippetReflectionProvide if (includedMethods.add(analysisMethod)) { HostedType declaringType = hUniverse.lookup(analysisMethod.getDeclaringClass()); String name = analysisMethod.getName(); - HostedType[] parameterTypes = analysisMethod.getSignature().toParameterList(null).stream() - .map(aType -> hUniverse.lookup(aType)) - .toArray(HostedType[]::new); + HostedType[] parameterTypes = analysisMethod.getSignature().toParameterList(null).stream().map(aType -> hUniverse.lookup(aType)).toArray(HostedType[]::new); int modifiers = analysisMethod.getModifiers(); HostedType returnType = hUniverse.lookup(analysisMethod.getSignature().getReturnType()); reflectionMetadataEncoder.addHidingMethodMetadata(analysisMethod, declaringType, name, parameterTypes, modifiers, returnType); @@ -625,6 +623,7 @@ private static boolean error(HostedMethod method, long encodedBci, String msg) { return true; } + @SuppressWarnings("unused") protected boolean verifyMethods(DebugContext debug, HostedUniverse hUniverse, CodeInfoEncoder codeInfoEncoder, CodeInfo codeInfo, ConstantAccess constantAccess) { /* * Run method verification in parallel to reduce computation time. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNet.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNet.java index d8fbc0877e53..7c93f0af6715 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNet.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNet.java @@ -116,6 +116,7 @@ static void registerInitInetAddressIDs(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.Inet6Address$Inet6AddressHolder", "ipaddress", "scope_id", "scope_id_set", "scope_ifname")); } + @SuppressWarnings("unused") private static void registerInetAddressLoadImpl(DuringAnalysisAccess a) { RuntimeReflection.register(clazz(a, "java.net.Inet4AddressImpl")); RuntimeReflection.register(constructor(a, "java.net.Inet4AddressImpl")); @@ -140,10 +141,12 @@ private static void registerNetworkInterfaceInit(DuringAnalysisAccess a) { registerInitInetAddressIDs(a); } + @SuppressWarnings("unused") private static void registerDatagramPacketInit(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.DatagramPacket", "address", "port", "buf", "offset", "length", "bufLength")); } + @SuppressWarnings("unused") private static void registerPlainDatagramSocketImplInit(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.DatagramSocketImpl", "fd", "localPort")); RuntimeJNIAccess.register(fields(a, "java.net.AbstractPlainDatagramSocketImpl", "timeout", "trafficClass", "connected")); @@ -156,16 +159,19 @@ private static void registerPlainDatagramSocketImplInit(DuringAnalysisAccess a) } } + @SuppressWarnings("unused") private static void registerPlainDatagramSocketImplSocketGetOption(DuringAnalysisAccess a) { RuntimeJNIAccess.register(method(a, "java.net.InetAddress", "anyLocalAddress")); RuntimeReflection.register(clazz(a, "[Ljava.net.Inet4Address;")); /* Created via JNI. */ } + @SuppressWarnings("unused") private static void registerDualStackPlainDatagramSocketImplInitIDs(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.DatagramSocketImpl", "fd")); registerInitInetAddressIDs(a); } + @SuppressWarnings("unused") private static void registerPlainSocketImplInitProto(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.SocketImpl", "fd", "address", "port", "localport", "serverSocket")); RuntimeJNIAccess.register(fields(a, "java.net.AbstractPlainSocketImpl", "timeout", "trafficClass")); @@ -177,15 +183,18 @@ private static void registerPlainSocketImplInitProto(DuringAnalysisAccess a) { } } + @SuppressWarnings("unused") private static void registerPlainSocketImplSocketGetOption(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.InetAddressContainer", "addr")); } + @SuppressWarnings("unused") private static void registerDualStackPlainSocketImplInitIDs(DuringAnalysisAccess a) { RuntimeJNIAccess.register(constructor(a, "java.net.InetSocketAddress", InetAddress.class, int.class)); registerInitInetAddressIDs(a); } + @SuppressWarnings("unused") private static void registerDualStackPlainSocketImplLocalAddress(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "java.net.InetAddressContainer", "addr")); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNio.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNio.java index 236eec27d5ee..a0ac0fb23337 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNio.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/JNIRegistrationJavaNio.java @@ -129,6 +129,7 @@ private static void registerNetInitIDs(DuringAnalysisAccess a) { RuntimeJNIAccess.register(constructor(a, "java.net.InetSocketAddress", InetAddress.class, int.class)); } + @SuppressWarnings("unused") private static void registerFileChannelImplInitIDs(DuringAnalysisAccess a) { RuntimeJNIAccess.register(fields(a, "sun.nio.ch.FileChannelImpl", "fd")); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventSubstitution.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventSubstitution.java index 02ee0fcb91ef..372ad55e2a33 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventSubstitution.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jfr/JfrEventSubstitution.java @@ -66,6 +66,7 @@ public class JfrEventSubstitution extends SubstitutionProcessor { private static final Method registerMirror = JavaVersionUtil.JAVA_SPEC < 22 ? ReflectionUtil.lookupMethod(SecuritySupport.class, "registerMirror", Class.class) : null; + @SuppressWarnings("unused") JfrEventSubstitution(MetaAccessProvider metaAccess) { baseEventType = metaAccess.lookupJavaType(jdk.internal.event.Event.class); ResolvedJavaType jdkJfrEventWriter = metaAccess.lookupJavaType(EventWriter.class); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java index 696bf2363e04..d9a40b1887d6 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/CInterfaceInvocationPlugin.java @@ -146,7 +146,7 @@ public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod m, ValueNo } } - private boolean replaceOffsetOf(GraphBuilderContext b, AnalysisMethod method, ValueNode[] args, AccessorInfo accessorInfo, int displacement) { + private static boolean replaceOffsetOf(GraphBuilderContext b, AnalysisMethod method, ValueNode[] args, AccessorInfo accessorInfo, int displacement) { /* * A method annotated with @OffsetOf can be static, but does not need to be. If it is * non-static, we just ignore the receiver. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index a58d87ec9c2f..e610bdf0d5cb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -173,7 +173,7 @@ */ public class IntrinsifyMethodHandlesInvocationPlugin implements NodePlugin { - private final ParsingReason reason; + @SuppressWarnings("unused") private final ParsingReason reason; private final Providers parsingProviders; private final HostedProviders universeProviders; private final AnalysisUniverse aUniverse; @@ -545,10 +545,7 @@ private boolean processInvokeWithMethodHandle(GraphBuilderContext b, Replacement GraphBuilderPhase.Instance graphBuilder = new HotSpotGraphBuilderInstance(parsingProviders, graphBuilderConfig, OptimisticOptimizations.NONE, null); DebugContext debug = b.getDebug(); - StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug) - .method(toOriginal(methodHandleMethod)) - .recordInlinedMethods(false) - .build(); + StructuredGraph graph = new StructuredGraph.Builder(b.getOptions(), debug).method(toOriginal(methodHandleMethod)).recordInlinedMethods(false).build(); try (DebugContext.Scope s = debug.scope("IntrinsifyMethodHandles", graph)) { graphBuilder.apply(graph); /* diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java index 13dbcf8e2c05..eab318e9e0fd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/SharedGraphBuilderPhase.java @@ -1059,7 +1059,7 @@ protected Object resolveLinkedObject(int bci, int cpi, int opcode, BootstrapMeth System.arraycopy(oldArguments, 0, arguments, 1, oldArguments.length); } - Class returnClass = OriginalClassProvider.getJavaClass((ResolvedJavaType) bootstrapMethod.getSignature().getReturnType(null)); + Class returnClass = OriginalClassProvider.getJavaClass(bootstrapMethod.getSignature().getReturnType(null)); InvokeWithExceptionNode bootstrapObject; ValueNode bootstrapObjectNode; @@ -1195,10 +1195,10 @@ protected InvokeWithExceptionNode throwBootstrapMethodError(int bci, ValueNode e * {@link java.lang.invoke.MethodHandle#invoke(Object...)}. */ private boolean isBootstrapInvocationInvalid(BootstrapMethodIntrospection bootstrap, int parameterLength, List staticArgumentsList, boolean isVarargs, Class typeClass) { - ResolvedJavaMethod method = bootstrap.getMethod(); + ResolvedJavaMethod resolvedMethod = bootstrap.getMethod(); return (isVarargs && parameterLength > (3 + staticArgumentsList.size())) || (!isVarargs && parameterLength != (3 + staticArgumentsList.size())) || - !(OriginalClassProvider.getJavaClass((ResolvedJavaType) method.getSignature().getReturnType(null)).isAssignableFrom(typeClass) || method.isConstructor()) || - !checkBootstrapParameters(method, bootstrap.getStaticArguments(), true); + !(OriginalClassProvider.getJavaClass(resolvedMethod.getSignature().getReturnType(null)).isAssignableFrom(typeClass) || resolvedMethod.isConstructor()) || + !checkBootstrapParameters(resolvedMethod, bootstrap.getStaticArguments(), true); } protected boolean checkBootstrapParameters(ResolvedJavaMethod bootstrapMethod, List staticArguments, boolean condy) { @@ -1283,8 +1283,8 @@ protected InvokeWithExceptionNode invokeMethodAndAdd(int bci, Class clazz, Cl protected InvokeWithExceptionNode invokeMethodAndAdd(int bci, Class returnClass, InvokeKind invokeKind, ValueNode[] arguments, ResolvedJavaMethod invokedMethod) { CallTargetNode callTarget = graph.add(createMethodCallTarget(invokeKind, invokedMethod, arguments, returnClass, null)); - InvokeWithExceptionNode invoke = graph - .add(createInvokeWithException(bci, callTarget, callTarget.returnStamp().getTrustedStamp().getStackKind(), ExceptionEdgeAction.INCLUDE_AND_HANDLE)); + InvokeWithExceptionNode invoke = graph.add( + createInvokeWithException(bci, callTarget, callTarget.returnStamp().getTrustedStamp().getStackKind(), ExceptionEdgeAction.INCLUDE_AND_HANDLE)); invoke.setStateAfter(createFrameState(stream.nextBCI(), invoke)); return invoke; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java index ddbff63a6361..16844f504757 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionDataBuilder.java @@ -940,7 +940,7 @@ private void maybeRegisterRecordComponents(Class clazz) { } } - private void registerLinkageError(Class clazz, LinkageError error, Map, Throwable> errorMap) { + private static void registerLinkageError(Class clazz, LinkageError error, Map, Throwable> errorMap) { if (LinkAtBuildTimeSupport.singleton().linkAtBuildTime(clazz)) { throw error; } else { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionGraphKit.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionGraphKit.java index d929194fd4b9..ac674b770957 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionGraphKit.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionGraphKit.java @@ -103,6 +103,7 @@ public class ReflectionGraphKit extends HostedGraphKit { private final List illegalArgumentExceptionPaths = new ArrayList<>(); private final List invocationTargetExceptionPaths = new ArrayList<>(); + @SuppressWarnings("unused") public ReflectionGraphKit(DebugContext debug, HostedProviders providers, ResolvedJavaMethod method, GraphProvider.Purpose purpose) { super(debug, providers, method); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java index b7a0ed3474a2..5c9a9f5edecd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/ReflectionPlugins.java @@ -641,7 +641,7 @@ private Object unboxObjectConstant(GraphBuilderContext b, JavaConstant argConsta return null; } - private boolean isAllowedConstant(Class clazz) { + private static boolean isAllowedConstant(Class clazz) { for (var allowed : ALLOWED_CONSTANT_CLASSES) { if (allowed.isAssignableFrom(clazz)) { return true; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index d84e2c24ed04..0168ee434ffa 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -703,6 +703,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec * Intercept the invoke to newUpdater. If the holder class and field name are constant register * them for reflection/unsafe access. */ + @SuppressWarnings("unused") private static void interceptUpdaterInvoke(GraphBuilderContext b, SnippetReflectionProvider snippetReflection, ValueNode tclassNode, ValueNode fieldNameNode) { if (tclassNode.isConstant() && fieldNameNode.isConstant()) { Class tclass = snippetReflection.asObject(Class.class, tclassNode.asJavaConstant()); @@ -879,6 +880,7 @@ private static boolean processStaticFieldBase(GraphBuilderContext b, Field targe return true; } + @SuppressWarnings("unused") private static void registerArrayPlugins(InvocationPlugins plugins, SnippetReflectionProvider snippetReflection, ParsingReason reason) { Registration r = new Registration(plugins, Array.class).setAllowOverwrite(true); r.register(new RequiredInvocationPlugin("newInstance", Class.class, int[].class) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AutomaticUnsafeTransformationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AutomaticUnsafeTransformationSupport.java index a74f88ef7e18..c4c3b498a18e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AutomaticUnsafeTransformationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/AutomaticUnsafeTransformationSupport.java @@ -275,7 +275,7 @@ public AutomaticUnsafeTransformationSupport(OptionValues options, AnnotationSubs * we need to convert it to a {@link FieldValueTransformer}, because that is the only mechanism * we can install late while the analysis is already running. */ - private void addTransformation(BigBang bb, ResolvedJavaField original, ComputedValueField transformation) { + private static void addTransformation(BigBang bb, ResolvedJavaField original, ComputedValueField transformation) { JavaKind returnKind = original.getType().getJavaKind(); FieldValueTransformer transformer = switch (transformation.getRecomputeValueKind()) { @@ -1086,10 +1086,7 @@ private StructuredGraph getStaticInitializerGraph(ResolvedJavaMethod clinit, Deb assert clinit.hasBytecodes(); HighTierContext context = new HighTierContext(GraalAccess.getOriginalProviders(), null, OptimisticOptimizations.NONE); - StructuredGraph graph = new StructuredGraph.Builder(options, debug) - .method(clinit) - .recordInlinedMethods(false) - .build(); + StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(clinit).recordInlinedMethods(false).build(); graph.getGraphState().configureExplicitExceptionsNoDeopt(); GraphBuilderPhase.Instance builderPhase = new ClassInitializerGraphBuilderPhase(context, GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true), diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java index 9062a321892b..ecf6b4c952be 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/substitute/ComputedValueField.java @@ -119,7 +119,6 @@ public static ComputedValueField create(ResolvedJavaField original, ResolvedJava break; case StaticFieldBase: f = getField(annotated, targetClass, targetName); - Object[] args = new Object[]{}; if (!Modifier.isStatic(f.getModifiers())) { throw UserError.abort("Target field must be static for " + StaticFieldBase + " computation of field " + original.format("%H.%n") + (annotated != null ? " specified by alias " + annotated.format("%H.%n") : "")); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/clinit/TestClassInitialization.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/clinit/TestClassInitialization.java index 0eb3cf8a072d..75773878cfc4 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/clinit/TestClassInitialization.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/clinit/TestClassInitialization.java @@ -829,7 +829,7 @@ public void afterRegistration(AfterRegistrationAccess access) { } } - private void assertNotInitialized(Class... classes) { + private static void assertNotInitialized(Class... classes) { for (var clazz : classes) { if (!Unsafe.getUnsafe().shouldBeInitialized(clazz)) { throw new AssertionError("Already initialized: " + clazz); @@ -837,7 +837,7 @@ private void assertNotInitialized(Class... classes) { } } - private void assertInitialized(Class... classes) { + private static void assertInitialized(Class... classes) { for (var clazz : classes) { if (Unsafe.getUnsafe().shouldBeInitialized(clazz)) { throw new AssertionError("Not initialized: " + clazz); diff --git a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/CStructTests.java b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/CStructTests.java index c6c7ccedf83c..c35dbca03e57 100644 --- a/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/CStructTests.java +++ b/substratevm/src/com.oracle.svm.test/src/com/oracle/svm/test/debug/CStructTests.java @@ -232,6 +232,7 @@ public void mixedArguments() { free(ss2); } + @SuppressWarnings("unused") public void testMixedArguments(String m1, short s, SimpleStruct ss1, long l, String m2, SimpleStruct2 ss2, String m3) { System.out.println("You find " + m1); System.out.println("You find " + m2); diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java index 5479c7a25471..f3a98f3d8a32 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/PermissionsFeature.java @@ -444,7 +444,7 @@ private static boolean isBackTraceOverLanguageMethod(AnalysisMethodNode method, * @param maxReports maximal number of reports * @param callGraph call graph obtained from * {@link PermissionsFeature#callGraph(BigBang, Set, DebugContext, SVMHost)} - * @param contextFilters filters removing known valid calls + * @param contextFiltersParam filters removing known valid calls * @param currentPath current path from a privileged method in a call graph * @param visited set of already visited methods, these methods are already part of an existing * report or do not lead to language class @@ -456,7 +456,7 @@ private int collectViolations( int maxDepth, int maxReports, Map> callGraph, - Set contextFilters, + Set contextFiltersParam, List currentPath, Set visited, int depth, @@ -482,7 +482,7 @@ private int collectViolations( Set callers = callGraph.get(mNode); if (depth > maxDepth) { if (!callers.isEmpty()) { - numReports = collectViolations(report, callers.iterator().next(), maxDepth, maxReports, callGraph, contextFilters, currentPath, visited, depth + 1, numReports); + numReports = collectViolations(report, callers.iterator().next(), maxDepth, maxReports, callGraph, contextFiltersParam, currentPath, visited, depth + 1, numReports); } } else if (!isSystemClass(mNode)) { List callPath = new ArrayList<>(currentPath); @@ -490,8 +490,8 @@ private int collectViolations( numReports++; } else { for (BaseMethodNode caller : callers) { - if (contextFilters.stream().noneMatch((f) -> f.test(mNode, caller, currentPath))) { - numReports = collectViolations(report, caller, maxDepth, maxReports, callGraph, contextFilters, currentPath, visited, depth + 1, numReports); + if (contextFiltersParam.stream().noneMatch((f) -> f.test(mNode, caller, currentPath))) { + numReports = collectViolations(report, caller, maxDepth, maxReports, callGraph, contextFiltersParam, currentPath, visited, depth + 1, numReports); } } } @@ -737,7 +737,7 @@ public boolean test(BaseMethodNode methodNode, BaseMethodNode callerNode, List trace) { + private static ResolvedJavaMethod findPrivilegedEntryPoint(ResolvedJavaMethod doPrivilegedMethod, List trace) { ResolvedJavaMethod ep = null; for (BaseMethodNode mNode : trace) { AnalysisMethod m = mNode.getMethod(); diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java index ccfcb70d1838..b0a93c8d40cd 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java @@ -782,7 +782,7 @@ private void warnAllMethods(MetaAccessProvider metaAccess, Class clazz) { } private record BlocklistViolationInfo(RuntimeCompilationCandidate candidate, String[] callTrace) { - }; + } private void checkBlockList(CallTreeInfo treeInfo) { RuntimeCompilationFeature runtimeCompilation = RuntimeCompilationFeature.singleton(); From 22b6043d7fd005518eb1aef34839f364bd183a93 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Wed, 24 Jan 2024 14:17:50 +0100 Subject: [PATCH 55/75] Fix additional ECJ warnings after rebase. --- .../jdk/graal/compiler/nodes/java/ArrayLengthNode.java | 8 ++++---- .../com/oracle/graal/pointsto/heap/ImageHeapScanner.java | 1 + .../FieldValueTransformerWithAvailability.java | 1 + .../com/oracle/svm/core/graal/nodes/FieldOffsetNode.java | 1 + .../runtimecompilation/RuntimeCompiledMethodSupport.java | 7 ++++--- .../src/com/oracle/svm/hosted/NativeImageGenerator.java | 5 +++-- .../hosted/ameta/AnalysisConstantReflectionProvider.java | 2 +- .../svm/hosted/ameta/FieldValueInterceptionSupport.java | 2 +- .../svm/hosted/snippets/SubstrateGraphBuilderPlugins.java | 1 + 9 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/ArrayLengthNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/ArrayLengthNode.java index 5bb5f1ccf1a6..ddb99672feda 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/ArrayLengthNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/java/ArrayLengthNode.java @@ -187,12 +187,12 @@ public void simplify(SimplifierTool tool) { */ public static ValueNode maybeAddPositivePi(ValueNode length, FixedWithNextNode insertionPosition) { StructuredGraph graph = insertionPosition.graph(); - length = graph.addOrUnique(length); - ValueNode replacement = length; - if (!length.isConstant() && length.stamp(NodeView.DEFAULT).canBeImprovedWith(StampFactory.positiveInt())) { + ValueNode localLength = graph.addOrUnique(length); + ValueNode replacement = localLength; + if (!localLength.isConstant() && localLength.stamp(NodeView.DEFAULT).canBeImprovedWith(StampFactory.positiveInt())) { ValueAnchorNode g = graph.add(new ValueAnchorNode()); graph.addAfterFixed(insertionPosition, g); - replacement = graph.addWithoutUnique(new PiNode(length, StampFactory.positiveInt(), g)); + replacement = graph.addWithoutUnique(new PiNode(localLength, StampFactory.positiveInt(), g)); } return replacement; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index 7b0348afe6dc..55b77e0418ed 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -396,6 +396,7 @@ protected JavaConstant createFieldValue(AnalysisField field, ValueSupplier rawValue, ScanReason reason) { /* * Check if the field value is available. If not, trying to access it is an error. This diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java index 4c8cf6701dd4..e81708142197 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/fieldvaluetransformer/FieldValueTransformerWithAvailability.java @@ -70,6 +70,7 @@ enum ValueAvailability { * This allows the compiler to optimize field values that are not available yet, as long as * there is a dedicated high-level node available. */ + @SuppressWarnings("unused") default ValueNode intrinsify(CoreProviders providers, JavaConstant receiver) { return null; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/FieldOffsetNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/FieldOffsetNode.java index be4e20f0fc69..581192e0c020 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/FieldOffsetNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/nodes/FieldOffsetNode.java @@ -85,6 +85,7 @@ protected FieldOffsetNode(ResolvedJavaField field) { this.field = field; } + @Override public ResolvedJavaField getField() { return field; } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java index a273962eab59..53d4775c5d7c 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java @@ -131,9 +131,9 @@ public static void onCompileQueueCreation(BigBang bb, HostedUniverse hUniverse, ImageHeapScanner imageScanner = bb.getUniverse().getHeapScanner(); GraphEncoder graphEncoder = new RuntimeCompiledMethodSupport.RuntimeCompilationGraphEncoder(ConfigurationValues.getTarget().arch, imageScanner); - HostedProviders runtimeCompilationProviders = hostedProviders - .copyWith(constantFieldProviderWrapper.apply(new RuntimeCompilationFieldProvider(hostedProviders.getMetaAccess(), hUniverse))) - .copyWith(new RuntimeCompilationReflectionProvider(bb, hUniverse.hostVM().getClassInitializationSupport())); + HostedProviders runtimeCompilationProviders = hostedProviders.copyWith( + constantFieldProviderWrapper.apply(new RuntimeCompilationFieldProvider(hostedProviders.getMetaAccess(), hUniverse))).copyWith( + new RuntimeCompilationReflectionProvider(bb, hUniverse.hostVM().getClassInitializationSupport())); SubstrateCompilationDirectives.singleton().resetDeoptEntries(); @@ -324,6 +324,7 @@ public boolean isFinalField(ResolvedJavaField f, ConstantFieldTool tool) { static class RuntimeCompilationReflectionProvider extends AnalysisConstantReflectionProvider { + @SuppressWarnings("unused") RuntimeCompilationReflectionProvider(BigBang bb, ClassInitializationSupport classInitializationSupport) { super(bb.getUniverse(), bb.getMetaAccess()); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 69173ab29279..bd3560a9f4c7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -1165,6 +1165,7 @@ public static void performSnippetGraphAnalysis(BigBang bb, SubstrateReplacements } } + @SuppressWarnings("unused") private static HostedProviders createHostedProviders(TargetDescription target, AnalysisUniverse aUniverse, Providers originalProviders, SubstratePlatformConfigurationProvider platformConfig, ClassInitializationSupport classInitializationSupport, AnalysisMetaAccess aMetaAccess) { @@ -1327,8 +1328,8 @@ public void notifyNoPlugin(ResolvedJavaMethod targetMethod, OptionValues options while (cursor.advance()) { data.add(Pair.create(cursor.getKey(), cursor.getValue())); } - data.stream().sorted(Comparator.comparing(Pair::getRight, Comparator.reverseOrder())) - .forEach(pair -> System.out.format(" - %d occurrences during parsing: %s%n", pair.getRight(), pair.getLeft())); + data.stream().sorted(Comparator.comparing(Pair::getRight, Comparator.reverseOrder())).forEach( + pair -> System.out.format(" - %d occurrences during parsing: %s%n", pair.getRight(), pair.getLeft())); } })); } catch (IllegalStateException e) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index 3ed1d634911d..b4b26333fc4e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -292,7 +292,7 @@ public JavaConstant forString(String value) { return universe.getHeapScanner().createImageHeapConstant(asConstant(value), ObjectScanner.OtherReason.UNKNOWN); } - private JavaConstant asConstant(Object object) { + private static JavaConstant asConstant(Object object) { return SubstrateObjectConstant.forObject(object); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java index 6a21e0cd5141..07e3eeb39ed8 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/FieldValueInterceptionSupport.java @@ -306,7 +306,7 @@ JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) { return interceptValue(field, value); } - private JavaConstant interceptValue(AnalysisField field, JavaConstant value) { + private static JavaConstant interceptValue(AnalysisField field, JavaConstant value) { JavaConstant result = value; if (result != null) { result = filterInjectedAccessor(field, result); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 0168ee434ffa..dd1a0d382922 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -1294,6 +1294,7 @@ protected ResolvedJavaType getTypeAESCrypt(MetaAccessProvider metaAccess, Resolv } } + @SuppressWarnings("unused") private static Object nonNullReason(NodeSourcePosition position) { return position == null ? "Unknown graph builder location." : position; } From 2c55b5f45352335258f46722f12cbc20a418444d Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Wed, 24 Jan 2024 15:36:55 +0100 Subject: [PATCH 56/75] Further improvements of the changes addressing ECJ warnings. --- .../nodes/test/OptimizationLogTest.java | 5 +- .../compiler/core/phases/CEOptimization.java | 3 +- .../stubs/AbstractForeignCallStub.java | 6 +- .../hotspot/stubs/ForeignCallStub.java | 6 +- .../jdk/graal/compiler/lir/GenerateStub.java | 15 ++--- .../amd64/AMD64CalcStringAttributesOp.java | 59 ++++++++++--------- .../phases/StackMoveOptimizationPhase.java | 9 +-- .../stackslotalloc/LSStackSlotAllocator.java | 6 +- .../compiler/nodes/extended/RawLoadNode.java | 3 +- .../phases/common/HighTierLoweringPhase.java | 8 +-- .../phases/common/LowTierLoweringPhase.java | 6 +- .../phases/common/MidTierLoweringPhase.java | 8 +-- .../replacements/NonNullParameterPlugin.java | 3 +- .../replacements/ReplacementsImpl.java | 14 ++--- .../replacements/nodes/MethodHandleNode.java | 6 +- .../pointsto/util/CompletionExecutor.java | 8 +-- .../svm/core/SubstrateSegfaultHandler.java | 8 +-- .../svm/core/code/FrameInfoDecoder.java | 3 +- .../core/heap/StoredContinuationAccess.java | 48 +++++++++++++++ .../svm/core/jdk/DeferredCommonPool.java | 2 +- .../jdk/ForeignDisabledSubstitutions.java | 4 +- .../svm/core/jdk/JavaLangSubstitutions.java | 15 ++--- .../hotspot/libgraal/LibGraalEntryPoints.java | 6 +- .../hosted/ReachabilityRegistrationNode.java | 7 +-- 24 files changed, 153 insertions(+), 105 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java index ea2489fa3d89..f0b1ffe6241e 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/nodes/test/OptimizationLogTest.java @@ -38,6 +38,7 @@ import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.nodes.GraphState; import jdk.graal.compiler.nodes.OptimizationLog; +import jdk.graal.compiler.nodes.OptimizationLog.OptimizationEntry; import jdk.graal.compiler.nodes.OptimizationLogImpl; import jdk.graal.compiler.nodes.ReturnNode; import jdk.graal.compiler.nodes.StructuredGraph; @@ -150,8 +151,8 @@ public void buildOptimizationTreeWhenEnabled() { /** * Tests that there is no reporting going on when the optimization log is disabled. In * particular, the optimization tree shall not be built and - * {@link jdk.graal.compiler.nodes.OptimizationLog.OptimizationEntry#withLazyProperty(String, Supplier) - * lazy properties} shall not be consumed. + * {@link OptimizationEntry#withLazyProperty(String, Supplier) lazy properties} shall not be + * consumed. */ @Test public void noReportingWhenDisabled() { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java index 71a1e989f84b..b86d96fc2872 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/phases/CEOptimization.java @@ -25,6 +25,7 @@ package jdk.graal.compiler.core.phases; import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.graph.Node.ValueNumberable; import jdk.graal.compiler.loop.phases.ConvertDeoptimizeToGuardPhase; import jdk.graal.compiler.loop.phases.LoopFullUnrollPhase; import jdk.graal.compiler.loop.phases.LoopPartialUnrollPhase; @@ -73,7 +74,7 @@ public enum CEOptimization { * * @see Canonicalizable#canonical(CanonicalizerTool) * @see Simplifiable#simplify(SimplifierTool) - * @see jdk.graal.compiler.graph.Node.ValueNumberable + * @see ValueNumberable * */ Canonicalization(null, CanonicalizerPhase.class), diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java index 54f5fe2362a9..ebdef5040b5c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/AbstractForeignCallStub.java @@ -41,6 +41,7 @@ import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkageImpl; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; +import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition; import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.nodes.ParameterNode; @@ -60,9 +61,8 @@ import jdk.vm.ci.meta.Signature; /** - * A {@linkplain #getGraph generated} stub for a - * {@link jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition non-leaf} foreign - * call from compiled code. A stub is required for such calls as the caller may be scheduled for + * A {@linkplain #getGraph generated} stub for a {@link Transition non-leaf} foreign call from + * compiled code. A stub is required for such calls as the caller may be scheduled for * deoptimization while the call is in progress. And since these are foreign/runtime calls on slow * paths, we don't want to force the register allocator to spill around the call. As such, this stub * saves and restores all allocatable registers. It also diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java index 82445cc1905f..1a8c52e8f79a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/ForeignCallStub.java @@ -30,6 +30,7 @@ import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; +import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.nodes.StubForeignCallNode; import jdk.graal.compiler.nodes.ParameterNode; @@ -42,9 +43,8 @@ import jdk.vm.ci.meta.JavaKind; /** - * A {@linkplain #getGraph generated} stub for a - * {@link jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition non-leaf} foreign - * call from compiled code. A stub is required for such calls as the caller may be scheduled for + * A {@linkplain #getGraph generated} stub for a {@link Transition non-leaf} foreign call from + * compiled code. A stub is required for such calls as the caller may be scheduled for * deoptimization while the call is in progress. And since these are foreign/runtime calls on slow * paths, we don't want to force the register allocator to spill around the call. As such, this stub * saves and restores all allocatable registers. It also diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java index 47259ff267b5..5297b9aa4d76 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/GenerateStub.java @@ -30,11 +30,13 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import jdk.graal.compiler.graph.Node.ConstantNodeParameter; +import jdk.graal.compiler.graph.Node.NodeIntrinsic; + /** * Generate a stub to be called via foreign call. This annotation is valid for methods annotated - * with {@link jdk.graal.compiler.graph.Node.NodeIntrinsic} only. To trigger stub generation, a - * marker class annotated with {@link GeneratedStubsHolder} is required. Processed by - * {@code IntrinsicStubProcessor}. + * with {@link NodeIntrinsic} only. To trigger stub generation, a marker class annotated with + * {@link GeneratedStubsHolder} is required. Processed by {@code IntrinsicStubProcessor}. */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.CLASS) @@ -47,10 +49,9 @@ String name() default ""; /** - * Optional values for parameters annotated with - * {@link jdk.graal.compiler.graph.Node.ConstantNodeParameter}. The string content is pasted - * as-is into the generated code, with the only exception being enum values - in that case, the - * enum class name and a dot is prepended to the string. + * Optional values for parameters annotated with {@link ConstantNodeParameter}. The string + * content is pasted as-is into the generated code, with the only exception being enum values - + * in that case, the enum class name and a dot is prepended to the string. */ String[] parameters() default {}; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java index 063a169815dd..9d6fae4cb2d7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64CalcStringAttributesOp.java @@ -56,6 +56,7 @@ import jdk.graal.compiler.lir.Opcode; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import jdk.graal.compiler.lir.gen.LIRGeneratorTool; +import jdk.graal.compiler.lir.gen.LIRGeneratorTool.CalcStringAttributesEncoding; import jdk.vm.ci.amd64.AMD64.CPUFeature; import jdk.vm.ci.amd64.AMD64Kind; import jdk.vm.ci.code.Register; @@ -80,7 +81,7 @@ public final class AMD64CalcStringAttributesOp extends AMD64ComplexVectorOp { // The following fields must be kept in sync with com.oracle.truffle.api.strings.TSCodeRange, // TStringOpsCalcStringAttributesReturnValuesInSyncTest verifies this. - private final LIRGeneratorTool.CalcStringAttributesEncoding encoding; + private final CalcStringAttributesEncoding encoding; private final Stride stride; private final int vectorLength; @@ -101,7 +102,7 @@ public final class AMD64CalcStringAttributesOp extends AMD64ComplexVectorOp { @Temp({OperandFlag.REG}) private Value[] temp; @Temp({OperandFlag.REG}) private Value[] vectorTemp; - private AMD64CalcStringAttributesOp(LIRGeneratorTool tool, LIRGeneratorTool.CalcStringAttributesEncoding encoding, EnumSet runtimeCheckedCPUFeatures, Value array, Value offset, + private AMD64CalcStringAttributesOp(LIRGeneratorTool tool, CalcStringAttributesEncoding encoding, EnumSet runtimeCheckedCPUFeatures, Value array, Value offset, Value length, Value result, boolean assumeValid) { super(TYPE, tool, runtimeCheckedCPUFeatures, YMM); this.encoding = encoding; @@ -127,7 +128,7 @@ private AMD64CalcStringAttributesOp(LIRGeneratorTool tool, LIRGeneratorTool.Calc } } - private static int getNumberOfTempRegisters(LIRGeneratorTool.CalcStringAttributesEncoding encoding, boolean assumeValid) { + private static int getNumberOfTempRegisters(CalcStringAttributesEncoding encoding, boolean assumeValid) { switch (encoding) { case UTF_8: return assumeValid ? 1 : 3; @@ -138,7 +139,7 @@ private static int getNumberOfTempRegisters(LIRGeneratorTool.CalcStringAttribute } } - private static int getNumberOfRequiredVectorRegisters(LIRGeneratorTool.CalcStringAttributesEncoding encoding, boolean isAVX, boolean assumeValid) { + private static int getNumberOfRequiredVectorRegisters(CalcStringAttributesEncoding encoding, boolean isAVX, boolean assumeValid) { switch (encoding) { case LATIN1: return isAVX ? 1 : 2; @@ -171,10 +172,10 @@ private int elementsPerVector(AMD64BaseAssembler.OperandSize size) { * @param array arbitrary array. * @param byteOffset byteOffset to start from. Must include array base byteOffset! * @param length length of the array region to consider, scaled to - * {@link jdk.graal.compiler.lir.gen.LIRGeneratorTool.CalcStringAttributesEncoding#stride}. + * {@link CalcStringAttributesEncoding#stride}. * @param assumeValid assume that the string is encoded correctly. */ - public static AMD64CalcStringAttributesOp movParamsAndCreate(LIRGeneratorTool tool, LIRGeneratorTool.CalcStringAttributesEncoding encoding, EnumSet runtimeCheckedCPUFeatures, + public static AMD64CalcStringAttributesOp movParamsAndCreate(LIRGeneratorTool tool, CalcStringAttributesEncoding encoding, EnumSet runtimeCheckedCPUFeatures, Value array, Value byteOffset, Value length, Value result, boolean assumeValid) { @@ -252,7 +253,7 @@ private void emitLatin1(CompilationResultBuilder crb, AMD64MacroAssembler asm, R emitPTestTail(asm, XMM, arr, lengthTail, vecArray, vecMask, null, returnLatin1, returnAscii); } - emitExit(asm, ret, returnLatin1, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_8BIT); + emitExit(asm, ret, returnLatin1, end, CalcStringAttributesEncoding.CR_8BIT); asm.bind(tailLessThan16); // move mask into general purpose register for regular TEST instructions @@ -271,7 +272,7 @@ private void emitLatin1(CompilationResultBuilder crb, AMD64MacroAssembler asm, R asm.testAndJcc(AMD64BaseAssembler.OperandSize.QWORD, len, 0x80, NotZero, returnLatin1, true); asm.jmpb(returnAscii); - emitExitAtEnd(asm, ret, returnAscii, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_7BIT); + emitExitAtEnd(asm, ret, returnAscii, end, CalcStringAttributesEncoding.CR_7BIT); } private void latin1Tail(AMD64MacroAssembler asm, AMD64BaseAssembler.OperandSize size, @@ -397,9 +398,9 @@ private void emitBMP(CompilationResultBuilder crb, AMD64MacroAssembler asm, Regi bmpTail(asm, arr, lengthTail, vecArray, vecMaskAscii, vecMaskBMP, tailLessThan32, tailLessThan16, returnBMP, returnLatin1, returnAscii); } - emitExit(asm, ret, returnAscii, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_7BIT); - emitExit(asm, ret, returnLatin1, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_8BIT); - emitExit(asm, ret, returnBMP, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_16BIT); + emitExit(asm, ret, returnAscii, end, CalcStringAttributesEncoding.CR_7BIT); + emitExit(asm, ret, returnLatin1, end, CalcStringAttributesEncoding.CR_8BIT); + emitExit(asm, ret, returnBMP, end, CalcStringAttributesEncoding.CR_16BIT); asm.bind(tailLessThan16); // move masks into general purpose registers for regular TEST instructions @@ -798,7 +799,7 @@ private void emitUTF8(CompilationResultBuilder crb, AMD64MacroAssembler asm, Reg asm.ptest(vectorSize, vecError, vecError); asm.jcc(Zero, returnValid); asm.shlq(ret, 32); - asm.orq(ret, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.orq(ret, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.jmp(end); asm.bind(tailLessThan32); @@ -872,12 +873,12 @@ private void emitUTF8(CompilationResultBuilder crb, AMD64MacroAssembler asm, Reg asm.testqAndJcc(state, state, Zero, returnValid, true); asm.shlq(ret, 32); - asm.orq(ret, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.orq(ret, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.jmpb(end); } - emitExitMultiByte(asm, ret, returnValid, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); - emitExitMultiByteAtEnd(asm, ret, returnAscii, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_7BIT); + emitExitMultiByte(asm, ret, returnValid, end, CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); + emitExitMultiByteAtEnd(asm, ret, returnAscii, end, CalcStringAttributesEncoding.CR_7BIT); } /** @@ -987,7 +988,7 @@ private void emitUTF16(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re asm.movl(ret, len); if (!assumeValid) { - asm.movl(retBroken, LIRGeneratorTool.CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); + asm.movl(retBroken, CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); asm.pxor(vectorSize, vecResult, vecResult); } @@ -1055,7 +1056,7 @@ private void emitUTF16(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re asm.movzwl(tmp, new AMD64Address(arr, len, stride)); asm.shrl(tmp, 10); asm.cmpl(tmp, 0x37); - asm.movl(tmp, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.movl(tmp, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.cmovl(Equal, retBroken, tmp); // high surrogate mask: 0x1b << 1 == 0x36 asm.psllw(vectorSize, vecMaskSurrogate, vecMaskSurrogate, 1); @@ -1100,7 +1101,7 @@ private void emitUTF16(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re asm.shrl(tmp, 10); // if last char is a high surrogate, return BROKEN asm.cmpl(tmp, 0x36); - asm.movl(tmp, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.movl(tmp, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.cmovl(Equal, retBroken, tmp); asm.jmp(returnValidOrBroken); } @@ -1167,7 +1168,7 @@ private void emitUTF16(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re asm.movzwl(tmp, new AMD64Address(arr, -2)); asm.shrl(tmp, 10); asm.cmpl(tmp, 0x36); - asm.movl(tmp, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.movl(tmp, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.cmovl(Equal, retBroken, tmp); asm.bind(tailSingleVectorSurrogate); @@ -1185,17 +1186,17 @@ private void emitUTF16(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re utf16ValidateSurrogates(asm, ret, vecArrayTail, vecArray, vecMaskSurrogate, vecMaskAscii, vecTmp, vecResult, tmp); asm.jmpb(returnValidOrBroken); } - emitExitMultiByte(asm, ret, returnAscii, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_7BIT); - emitExitMultiByte(asm, ret, returnLatin1, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_8BIT); - emitExitMultiByte(asm, ret, returnBMP, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_16BIT); + emitExitMultiByte(asm, ret, returnAscii, end, CalcStringAttributesEncoding.CR_7BIT); + emitExitMultiByte(asm, ret, returnLatin1, end, CalcStringAttributesEncoding.CR_8BIT); + emitExitMultiByte(asm, ret, returnBMP, end, CalcStringAttributesEncoding.CR_16BIT); asm.bind(returnValidOrBroken); asm.shlq(ret, 32); if (assumeValid) { - asm.orq(ret, LIRGeneratorTool.CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); + asm.orq(ret, CalcStringAttributesEncoding.CR_VALID_MULTIBYTE); } else { asm.ptest(vectorSize, vecResult, vecResult); - asm.movl(tmp, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); + asm.movl(tmp, CalcStringAttributesEncoding.CR_BROKEN_MULTIBYTE); asm.cmovl(NotZero, retBroken, tmp); asm.orq(ret, retBroken); } @@ -1312,8 +1313,8 @@ private void emitUTF32(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re utf32CheckInvalid(asm, vecArrayTail, vecArrayTail, vecArrayTmp, vecMaskSurrogate, vecMaskOutOfRange, returnBroken, true); asm.jmpb(returnBMP); - emitExit(asm, ret, returnBroken, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_BROKEN, false); - emitExit(asm, ret, returnBMP, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_16BIT, false); + emitExit(asm, ret, returnBroken, end, CalcStringAttributesEncoding.CR_BROKEN, false); + emitExit(asm, ret, returnBMP, end, CalcStringAttributesEncoding.CR_16BIT, false); // astral loop: check if any codepoints are in the forbidden UTF-16 surrogate range; // if so, break immediately and return BROKEN @@ -1362,10 +1363,10 @@ private void emitUTF32(CompilationResultBuilder crb, AMD64MacroAssembler asm, Re asm.ptest(vectorSize, vecArray, vecMaskBMP); asm.jcc(Zero, returnBMP); - emitExit(asm, ret, returnAstral, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_VALID); + emitExit(asm, ret, returnAstral, end, CalcStringAttributesEncoding.CR_VALID); - emitExit(asm, ret, returnLatin1, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_8BIT); - emitExitAtEnd(asm, ret, returnAscii, end, LIRGeneratorTool.CalcStringAttributesEncoding.CR_7BIT); + emitExit(asm, ret, returnLatin1, end, CalcStringAttributesEncoding.CR_8BIT); + emitExitAtEnd(asm, ret, returnAscii, end, CalcStringAttributesEncoding.CR_7BIT); } private void utf32CheckInvalid(AMD64MacroAssembler asm, Register vecArrayDst, Register vecArraySrc, Register vecArrayTmp, Register vecMaskBroken, Register vecMaskOutOfRange, Label returnBroken, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java index adcf6a249ed7..b9841c4e4778 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/phases/StackMoveOptimizationPhase.java @@ -35,6 +35,8 @@ import jdk.graal.compiler.lir.LIRInstruction; import jdk.graal.compiler.lir.RedundantMoveElimination; import jdk.graal.compiler.lir.amd64.AMD64Move; +import jdk.graal.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove; +import jdk.graal.compiler.lir.amd64.AMD64Move.AMD64StackMove; import jdk.graal.compiler.lir.gen.LIRGenerationResult; import jdk.graal.compiler.lir.phases.LIRPhase; import jdk.graal.compiler.lir.phases.PostAllocationOptimizationPhase; @@ -47,12 +49,11 @@ import jdk.vm.ci.meta.Value; /** - * Replaces sequential {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64StackMove}s of the same - * type with a single {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove} to avoid - * storing/restoring the scratch register multiple times. + * Replaces sequential {@link AMD64StackMove}s of the same type with a single + * {@link AMD64MultiStackMove} to avoid storing/restoring the scratch register multiple times. * * Note: this phase must be inserted after {@link RedundantMoveElimination} phase because - * {@link jdk.graal.compiler.lir.amd64.AMD64Move.AMD64MultiStackMove} are not probably detected. + * {@link AMD64MultiStackMove} are not probably detected. */ public class StackMoveOptimizationPhase extends PostAllocationOptimizationPhase { public static class Options { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java index d163ca151431..5db644bd210e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/stackslotalloc/LSStackSlotAllocator.java @@ -50,6 +50,7 @@ import jdk.graal.compiler.lir.LIRInstruction; import jdk.graal.compiler.lir.LIRInstruction.OperandFlag; import jdk.graal.compiler.lir.LIRInstruction.OperandMode; +import jdk.graal.compiler.lir.LIRInstruction.Use; import jdk.graal.compiler.lir.ValueProcedure; import jdk.graal.compiler.lir.VirtualStackSlot; import jdk.graal.compiler.lir.framemap.FrameMap; @@ -74,9 +75,8 @@ * Remark: The analysis works under the assumption that a stack slot is no longer live after * its last usage. If an {@link LIRInstruction instruction} transfers the raw address of the stack * slot to another location, e.g. a registers, and this location is referenced later on, the - * {@link jdk.graal.compiler.lir.LIRInstruction.Use usage} of the stack slot must be marked with the - * {@link OperandFlag#UNINITIALIZED}. Otherwise the stack slot might be reused and its content - * destroyed. + * {@link Use usage} of the stack slot must be marked with the {@link OperandFlag#UNINITIALIZED}. + * Otherwise, the stack slot might be reused and its content destroyed. */ public final class LSStackSlotAllocator extends AllocationPhase { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java index b2f2d8baaada..4fb4906db327 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/extended/RawLoadNode.java @@ -36,6 +36,7 @@ import jdk.graal.compiler.core.common.type.TypeReference; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.graph.Node; +import jdk.graal.compiler.graph.Node.NodeIntrinsic; import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodes.GraphState; @@ -82,7 +83,7 @@ public RawLoadNode(ValueNode object, ValueNode offset, JavaKind accessKind, Loca /** * This constructor exists for node intrinsics that need a stamp based on the return type of the - * {@link jdk.graal.compiler.graph.Node.NodeIntrinsic} annotated method. + * {@link NodeIntrinsic} annotated method. */ public RawLoadNode(@InjectedNodeParameter Stamp stamp, ValueNode object, ValueNode offset, LocationIdentity locationIdentity, JavaKind accessKind) { super(TYPE, stamp, object, offset, accessKind, locationIdentity, false, MemoryOrderMode.PLAIN); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java index f7fdbcb9dd0c..8022ad138aec 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/HighTierLoweringPhase.java @@ -29,20 +29,20 @@ import jdk.graal.compiler.nodes.GraphState; import jdk.graal.compiler.nodes.GraphState.StageFlag; import jdk.graal.compiler.nodes.spi.Lowerable; -import jdk.graal.compiler.nodes.spi.LoweringTool; +import jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage; /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#HIGH_TIER} stage. + * {@link StandardLoweringStage#HIGH_TIER} stage. */ public class HighTierLoweringPhase extends LoweringPhase { public HighTierLoweringPhase(CanonicalizerPhase canonicalizer, boolean lowerOptimizableMacroNodes) { - super(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER, lowerOptimizableMacroNodes, StageFlag.HIGH_TIER_LOWERING); + super(canonicalizer, StandardLoweringStage.HIGH_TIER, lowerOptimizableMacroNodes, StageFlag.HIGH_TIER_LOWERING); } public HighTierLoweringPhase(CanonicalizerPhase canonicalizer) { - super(canonicalizer, LoweringTool.StandardLoweringStage.HIGH_TIER, StageFlag.HIGH_TIER_LOWERING); + super(canonicalizer, StandardLoweringStage.HIGH_TIER, StageFlag.HIGH_TIER_LOWERING); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java index 00856c5b1917..3fde1e9383d0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/LowTierLoweringPhase.java @@ -29,16 +29,16 @@ import jdk.graal.compiler.nodes.GraphState; import jdk.graal.compiler.nodes.GraphState.StageFlag; import jdk.graal.compiler.nodes.spi.Lowerable; -import jdk.graal.compiler.nodes.spi.LoweringTool; +import jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage; /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#LOW_TIER} stage. + * {@link StandardLoweringStage#LOW_TIER} stage. */ public class LowTierLoweringPhase extends LoweringPhase { public LowTierLoweringPhase(CanonicalizerPhase canonicalizer) { - super(canonicalizer, LoweringTool.StandardLoweringStage.LOW_TIER, StageFlag.LOW_TIER_LOWERING); + super(canonicalizer, StandardLoweringStage.LOW_TIER, StageFlag.LOW_TIER_LOWERING); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java index 62c1a85674ba..fcfec7c9bde8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/MidTierLoweringPhase.java @@ -29,20 +29,20 @@ import jdk.graal.compiler.nodes.GraphState; import jdk.graal.compiler.nodes.GraphState.StageFlag; import jdk.graal.compiler.nodes.spi.Lowerable; -import jdk.graal.compiler.nodes.spi.LoweringTool; +import jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage; /** * A {@link LoweringPhase} used to lower {@link Lowerable} nodes when the graph is in - * {@link jdk.graal.compiler.nodes.spi.LoweringTool.StandardLoweringStage#MID_TIER} stage. + * {@link StandardLoweringStage#MID_TIER} stage. */ public class MidTierLoweringPhase extends LoweringPhase { public MidTierLoweringPhase(CanonicalizerPhase canonicalizer, boolean lowerOptimizableMacroNodes) { - super(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER, lowerOptimizableMacroNodes, StageFlag.MID_TIER_LOWERING); + super(canonicalizer, StandardLoweringStage.MID_TIER, lowerOptimizableMacroNodes, StageFlag.MID_TIER_LOWERING); } public MidTierLoweringPhase(CanonicalizerPhase canonicalizer) { - super(canonicalizer, LoweringTool.StandardLoweringStage.MID_TIER, StageFlag.MID_TIER_LOWERING); + super(canonicalizer, StandardLoweringStage.MID_TIER, StageFlag.MID_TIER_LOWERING); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java index d7789b26b924..37bcab334996 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/NonNullParameterPlugin.java @@ -26,6 +26,7 @@ import java.util.BitSet; +import jdk.graal.compiler.api.replacements.Snippet.NonNullParameter; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.common.type.StampPair; @@ -37,7 +38,7 @@ /** * A {@link ParameterPlugin} that sets non-null stamps for parameters annotated with - * {@link jdk.graal.compiler.api.replacements.Snippet.NonNullParameter}. + * {@link NonNullParameter}. */ public class NonNullParameterPlugin implements ParameterPlugin { private final BitSet nonNullParameters; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java index aad168b9d028..1c47fb7f92f8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/ReplacementsImpl.java @@ -77,6 +77,7 @@ import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderPlugin; import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin; import jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext; +import jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; import jdk.graal.compiler.nodes.spi.Replacements; @@ -353,19 +354,16 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo * @param nonNullParameters * @param original XXX always null? * @param trackNodeSourcePosition record source information - * @param context - * {@link jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext - * compilation context} for the graph + * @param context {@link CompilationContext compilation context} for the graph */ public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, ResolvedJavaMethod method, Object[] args, BitSet nonNullParameters, ResolvedJavaMethod original, - boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { + boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, CompilationContext context) { return createGraphMaker(method, original).makeGraph(debug, bytecodeProvider, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, context); } /** * Creates a preprocessed graph for a snippet or method substitution with a context of . - * {@link jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext#INLINE_AFTER_PARSING} - * . + * {@link CompilationContext#INLINE_AFTER_PARSING} . * * @param bytecodeProvider how to access the bytecode of {@code method} * @param method the snippet or method substitution for which a graph will be created @@ -412,7 +410,7 @@ public GraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, @SuppressWarnings("try") public StructuredGraph makeGraph(DebugContext debug, BytecodeProvider bytecodeProvider, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, - NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { + NodeSourcePosition replaceePosition, CompilationContext context) { try (DebugContext.Scope s = debug.scope("BuildSnippetGraph", method)) { assert method.hasBytecodes() : method; StructuredGraph graph = buildInitialGraph(debug, bytecodeProvider, method, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, context); @@ -516,7 +514,7 @@ public boolean isDeferredInvoke(StateSplit stateSplit) { */ @SuppressWarnings("try") protected StructuredGraph buildInitialGraph(DebugContext debug, BytecodeProvider bytecodeProvider, final ResolvedJavaMethod methodToParse, Object[] args, BitSet nonNullParameters, - boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, IntrinsicContext.CompilationContext context) { + boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, CompilationContext context) { // @formatter:off // Replacements cannot have optimistic assumptions since they have // to be valid for the entire run of the VM. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java index 9fea27f94a34..86779280730a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/MethodHandleNode.java @@ -35,6 +35,7 @@ import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.TypeReference; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.Node; import jdk.graal.compiler.graph.NodeClass; import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodes.CallTargetNode; @@ -126,9 +127,8 @@ public GraphAdder(StructuredGraph graph) { } /** - * Call - * {@link jdk.graal.compiler.nodes.StructuredGraph#addOrUnique(jdk.graal.compiler.graph.Node)} - * on {@code node} and link any {@link FixedWithNextNode}s into the current control flow. + * Call {@link jdk.graal.compiler.nodes.StructuredGraph#addOrUnique(Node)} on {@code node} + * and link any {@link FixedWithNextNode}s into the current control flow. * * @return the newly added node */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java index 5bfa86089125..b301ea2b7787 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/util/CompletionExecutor.java @@ -163,10 +163,10 @@ private void executeCommand(DebugContextRunnable command) { } bb.getHostVM().recordActivity(); Throwable thrown = null; - try (DebugContext debugLocal = command.getDebug(bb.getOptions(), bb.getDebugHandlerFactories()); - Scope s = debugLocal.scope("Operation"); - Activation a = debugLocal.activate()) { - command.run(debugLocal); + try (DebugContext localDebug = command.getDebug(bb.getOptions(), bb.getDebugHandlerFactories()); + Scope s = localDebug.scope("Operation"); + Activation a = localDebug.activate()) { + command.run(localDebug); } catch (Throwable x) { thrown = x; } finally { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java index 7a4edd12ee0a..f65e928ca8ec 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateSegfaultHandler.java @@ -127,8 +127,7 @@ public static class Options { private static final long MARKER_VALUE = 0x0123456789ABCDEFL; @UnknownPrimitiveField(availability = ReadyForCompilation.class) // static long offsetOfStaticFieldWithWellKnownValue; - @SuppressWarnings("unused") - private static long staticFieldWithWellKnownValue = MARKER_VALUE; + @SuppressWarnings("unused") private static long staticFieldWithWellKnownValue = MARKER_VALUE; private boolean installed; @@ -280,9 +279,8 @@ private static void dumpInterruptibly(Pointer sp, CodePointer ip, PointerBase si boolean printedDiagnostics = SubstrateDiagnostics.printFatalError(log, sp, ip, context, false); if (SubstrateSegfaultHandler.isInstalled() && printedDiagnostics) { - log.string("Segfault detected, aborting process. ") - .string("Use '-XX:-InstallSegfaultHandler' to disable the segfault handler at run time and create a core dump instead. ") - .string("Rebuild with '-R:-InstallSegfaultHandler' to disable the handler permanently at build time.") // + log.string("Segfault detected, aborting process. ").string("Use '-XX:-InstallSegfaultHandler' to disable the segfault handler at run time and create a core dump instead. ").string( + "Rebuild with '-R:-InstallSegfaultHandler' to disable the handler permanently at build time.") // .newline().newline(); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java index 6415d10314aa..a9f1f10db86c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/FrameInfoDecoder.java @@ -45,6 +45,7 @@ import jdk.graal.compiler.core.common.util.TypeConversion; import jdk.graal.compiler.nodes.FrameState; +import jdk.graal.compiler.nodes.FrameState.StackState; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -63,7 +64,7 @@ public class FrameInfoDecoder { */ protected static final int ENCODED_BCI_ADDEND = 4; /** - * Flag in the encoded bci to preserve {@link jdk.graal.compiler.nodes.FrameState.StackState#duringCall} information. + * Flag in the encoded bci to preserve {@link StackState#duringCall} information. */ protected static final int ENCODED_BCI_DURING_CALL_MASK = 2; /** diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java index e98d1be98c90..8bc574fc082b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java @@ -40,17 +40,21 @@ import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.CodeInfoTable; +import com.oracle.svm.core.code.FrameInfoQueryResult; import com.oracle.svm.core.code.SimpleCodeInfoQueryResult; import com.oracle.svm.core.code.UntetheredCodeInfo; import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.deopt.DeoptimizedFrame; import com.oracle.svm.core.deopt.Deoptimizer; import com.oracle.svm.core.graal.nodes.NewStoredContinuationNode; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.stack.JavaStackWalk; import com.oracle.svm.core.stack.JavaStackWalker; +import com.oracle.svm.core.stack.StackFrameVisitor; import com.oracle.svm.core.thread.ContinuationInternals; import com.oracle.svm.core.thread.ContinuationSupport; +import com.oracle.svm.core.thread.Safepoint; import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; @@ -266,4 +270,48 @@ public abstract static class ContinuationStackFrameVisitor { public interface ContinuationStackFrameVisitorData extends PointerBase { } + @SuppressWarnings("unused") + private static final class PreemptVisitor extends StackFrameVisitor { + private final Pointer endSP; + private boolean startFromNextFrame = false; + + Pointer leafSP; + CodePointer leafIP; + int preemptStatus = ContinuationSupport.FREEZE_OK; + + PreemptVisitor(Pointer endSP) { + this.endSP = endSP; + } + + @Override + protected boolean visitFrame(Pointer sp, CodePointer ip, CodeInfo codeInfo, DeoptimizedFrame deoptimizedFrame) { + if (sp.aboveOrEqual(endSP)) { + return false; + } + + FrameInfoQueryResult frameInfo = CodeInfoTable.lookupCodeInfoQueryResult(codeInfo, ip).getFrameInfo(); + if (frameInfo.getSourceClass().equals(StoredContinuationAccess.class) && frameInfo.getSourceMethodName().equals("allocateToYield")) { + // Continuation is already in the process of yielding, cancel preemption. + preemptStatus = ContinuationSupport.FREEZE_YIELDING; + return false; + } + + if (leafSP.isNull()) { + // Should start from the method calling `enterSlowPathSafepointCheck`. + if (startFromNextFrame) { + leafSP = sp; + leafIP = ip; + } else { + if (frameInfo.getSourceClass().equals(Safepoint.class) && frameInfo.getSourceMethodName().equals("enterSlowPathSafepointCheck")) { + startFromNextFrame = true; + } + return true; + } + } + + VMError.guarantee(codeInfo.equal(CodeInfoTable.getImageCodeInfo())); + + return true; + } + } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java index 5f30baf58225..2c9d09d11564 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java @@ -84,7 +84,7 @@ public ForkJoinTask submit(Runnable task) { return ForkJoinPool.commonPool().submit(task); } - @SuppressWarnings({"unchecked","static-method"}) + @SuppressWarnings({"unchecked", "static-method"}) public List> invokeAllUninterruptibly(Collection> tasks) { VMError.guarantee(JavaVersionUtil.JAVA_SPEC >= 22, "invokeAllUninterruptibly only exists in JDK 22+"); var m = ReflectionUtil.lookupMethod(ForkJoinPool.class, "invokeAllUninterruptibly", Collection.class); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java index 6d99731a9978..79d5aea9a7cd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ForeignDisabledSubstitutions.java @@ -109,7 +109,7 @@ static void ensureInitialized() { @TargetClass(className = "sun.nio.ch.FileChannelImpl", onlyWith = ForeignDisabled.class) final class Target_sun_nio_ch_FileChannelImpl { @Substitute - @SuppressWarnings({"unused","static-method"}) + @SuppressWarnings({"unused", "static-method"}) Target_java_lang_foreign_MemorySegment map(FileChannel.MapMode mode, long offset, long size, Target_java_lang_foreign_Arena arena) throws IOException { throw ForeignDisabledSubstitutions.fail(); } @@ -127,7 +127,7 @@ final class Target_java_lang_foreign_MemoryLayout_PathElement { final class Target_jdk_internal_foreign_layout_AbstractLayout { @Substitute @AlwaysInline("Make remaining code in callers unreachable.") - @SuppressWarnings({"unused","static-method"}) + @SuppressWarnings({"unused", "static-method"}) VarHandle varHandle(Target_java_lang_foreign_MemoryLayout_PathElement... elements) { throw ForeignDisabledSubstitutions.fail(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java index 4d93a51110c3..6b2aedda8b47 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/JavaLangSubstitutions.java @@ -416,18 +416,15 @@ private static String getProperty(String key, String def) { private static int allowSecurityManager = 1; /** - * We do not support the SecurityManager - * so this method must throw a {@link SecurityException} when 'java.security.manager' is set to - * anything but disallow. + * We do not support the {@link SecurityManager} so this method must throw a + * {@link SecurityException} when 'java.security.manager' is set to anything but + * disallow. * - * @see System#setSecurityManager(SecurityManager) - * @see SecurityManager + * @see System#setSecurityManager(SecurityManager) + * @see SecurityManager */ - @SuppressWarnings("removal") @Substitute + @SuppressWarnings({"removal", "javadoc"}) private static void setSecurityManager(SecurityManager sm) { if (sm != null) { /* Read the property collected at isolate creation as that is what happens on the JVM */ diff --git a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java index adba40cd20c4..37bdddd9f051 100644 --- a/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java +++ b/substratevm/src/com.oracle.svm.graal.hotspot.libgraal/src/com/oracle/svm/graal/hotspot/libgraal/LibGraalEntryPoints.java @@ -62,7 +62,7 @@ import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotGraalRuntime; import jdk.graal.compiler.hotspot.HotSpotGraalServices; -import jdk.graal.compiler.hotspot.ProfileReplaySupport; +import jdk.graal.compiler.hotspot.ProfileReplaySupport.Options; import jdk.graal.compiler.hotspot.stubs.Stub; import jdk.graal.compiler.options.OptionDescriptors; import jdk.graal.compiler.options.OptionKey; @@ -342,7 +342,7 @@ private static long hashConstantOopFields(JNIEnv jniEnv, * @param timeAndMemBufferAddress 16-byte native buffer to store result of time and memory * measurements of the compilation * @param profilePathBufferAddress native buffer containing a 0-terminated C string representing - * {@link jdk.graal.compiler.hotspot.ProfileReplaySupport.Options#LoadProfiles} path. + * {@link Options#LoadProfiles} path. * @return a handle to a {@link InstalledCode} in HotSpot's heap or 0 if compilation failed */ @SuppressWarnings({"unused", "try"}) @@ -377,7 +377,7 @@ private static long compileMethod(JNIEnv jniEnv, CompilationTask task = new CompilationTask(runtime, compiler, request, useProfilingInfo, false, eagerResolving, installAsDefault); if (profilePathBufferAddress > 0) { String profileLoadPath = CTypeConversion.toJavaString(WordFactory.pointer(profilePathBufferAddress)); - options = new OptionValues(options, ProfileReplaySupport.Options.LoadProfiles, profileLoadPath); + options = new OptionValues(options, Options.LoadProfiles, profileLoadPath); } long allocatedBytesBefore = 0; ThreadMXBean threadMXBean = null; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java index dd73d4fc260e..cfef16116b1b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ReachabilityRegistrationNode.java @@ -36,6 +36,7 @@ import jdk.graal.compiler.nodeinfo.NodeInfo; import jdk.graal.compiler.nodeinfo.NodeSize; import jdk.graal.compiler.nodes.FixedWithNextNode; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin; import jdk.graal.compiler.nodes.spi.Canonicalizable; import jdk.graal.compiler.nodes.spi.CanonicalizerTool; @@ -58,10 +59,8 @@ * * To use: *
    - *
  1. Create a subclass of - * {@link jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin} that - * is also a decorator - * (override @{@link jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin.RequiredInvocationPlugin#isDecorator()})
  2. + *
  3. Create a subclass of {@link RequiredInvocationPlugin} that is also a decorator + * (override @{@link RequiredInvocationPlugin#isDecorator()})
  4. *
  5. When applying the plugin, add this node to the graph with a @{link {@link Runnable} that * registers the metadata.}
  6. *
From b3f1794331463ad4429cd7661761d8f620a7df1e Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Wed, 24 Jan 2024 18:07:53 +0100 Subject: [PATCH 57/75] Change LIRGenerationResult#getFirstInsertPosition back to non-static. --- .../compiler/hotspot/test/HotSpotGraalCompilerTest.java | 4 ---- .../graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java | 3 +-- .../lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java | 2 +- .../lir/alloc/lsra/LinearScanResolveDataFlowPhase.java | 5 ++--- .../jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java | 4 +--- .../compiler/lir/constopt/ConstantLoadOptimization.java | 4 +--- .../src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java | 3 ++- .../graal/compiler/lir/profiling/MethodProfilingPhase.java | 2 +- .../jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java | 2 +- 9 files changed, 10 insertions(+), 19 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java index d5384542b592..313a7b65b6a7 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotGraalCompilerTest.java @@ -27,7 +27,6 @@ import org.junit.Assume; import org.junit.AssumptionViolatedException; -import jdk.graal.compiler.api.test.Graal; import jdk.graal.compiler.bytecode.Bytecode; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.common.CompilationIdentifier; @@ -42,7 +41,6 @@ import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugin; import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; @@ -79,8 +77,6 @@ protected InstalledCode compileAndInstallSubstitution(Class c, String methodN } protected InstalledCode compileAndInstallSubstitution(ResolvedJavaMethod method) { - HotSpotGraalRuntimeProvider rt = (HotSpotGraalRuntimeProvider) Graal.getRequiredCapability(RuntimeProvider.class); - rt.getHostBackend().getProviders(); CompilationIdentifier compilationId = runtime().getHostBackend().getCompilationIdentifier(method); OptionValues options = getInitialOptions(); StructuredGraph graph = getIntrinsicGraph(method, compilationId, getDebugContext(options), AllowAssumptions.YES, null); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java index 4b4baee2f135..e61fbbdf7ce7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/SaveCalleeSaveRegisters.java @@ -38,7 +38,6 @@ import jdk.graal.compiler.lir.gen.MoveFactory; import jdk.graal.compiler.lir.phases.PreAllocationOptimizationPhase; import jdk.graal.compiler.lir.util.RegisterMap; - import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.Register; import jdk.vm.ci.code.RegisterArray; @@ -71,7 +70,7 @@ protected void run(TargetDescription target, LIRGenerationResult lirGenRes, PreA private static RegisterMap saveAtEntry(LIR lir, LIRGeneratorTool lirGen, LIRGenerationResult lirGenRes, RegisterArray calleeSaveRegisters, Architecture arch) { BasicBlock startBlock = lir.getControlFlowGraph().getStartBlock(); ArrayList instructions = lir.getLIRforBlock(startBlock); - int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); + int insertionIndex = lirGenRes.getFirstInsertPosition(); LIRInsertionBuffer buffer = new LIRInsertionBuffer(); buffer.init(instructions); StandardOp.LabelOp entry = (StandardOp.LabelOp) instructions.get(insertionIndex - 1); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java index a5767cadf2fe..5f3e57256338 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanOptimizeSpillPositionPhase.java @@ -171,7 +171,7 @@ private void optimizeInterval(LIRInsertionBuffer[] insertionBuffers, Interval in debug.log(DebugContext.VERBOSE_LEVEL, "Insert spill move %s", move); move.setId(LinearScan.DOMINATOR_SPILL_MOVE_ID); - int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); + int insertionIndex = res.getFirstInsertPosition(); insertionBuffer.append(insertionIndex, move); betterSpillPosWithLowerProbability.increment(debug); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java index 640affdffe94..84d033bcb0ed 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanResolveDataFlowPhase.java @@ -35,7 +35,6 @@ import jdk.graal.compiler.lir.StandardOp; import jdk.graal.compiler.lir.gen.LIRGenerationResult; import jdk.graal.compiler.lir.phases.AllocationPhase; - import jdk.vm.ci.code.TargetDescription; /** @@ -118,7 +117,7 @@ void resolveFindInsertPos(BasicBlock fromBlock, BasicBlock toBlock, MoveRe } } - moveResolver.setInsertPosition(allocator.getLIR().getLIRforBlock(toBlock), LIRGenerationResult.getFirstInsertPosition()); + moveResolver.setInsertPosition(allocator.getLIR().getLIRforBlock(toBlock), allocator.getLIRGenerationResult().getFirstInsertPosition()); } } @@ -170,7 +169,7 @@ protected void optimizeEmptyBlocks(MoveResolver moveResolver, BitSet blockComple */ resolveCollectMappings(pred, sux, block, moveResolver); if (moveResolver.hasMappings()) { - moveResolver.setInsertPosition(instructions, LIRGenerationResult.getFirstInsertPosition()); + moveResolver.setInsertPosition(instructions, allocator.getLIRGenerationResult().getFirstInsertPosition()); moveResolver.resolveAndAppendMoves(); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java index a1110afb52ac..872e048ea3b1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/alloc/lsra/LinearScanWalker.java @@ -48,8 +48,6 @@ import jdk.graal.compiler.lir.alloc.lsra.Interval.RegisterPriority; import jdk.graal.compiler.lir.alloc.lsra.Interval.SpillState; import jdk.graal.compiler.lir.alloc.lsra.Interval.State; - -import jdk.graal.compiler.lir.gen.LIRGenerationResult; import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.Value; @@ -278,7 +276,7 @@ void insertMove(int operandId, Interval srcIt, Interval dstIt) { index++; assert 0 <= index && index < instructions.size() : "index out of bounds"; } - assert LIRGenerationResult.getFirstInsertPosition() <= index && index < instructions.size() : "index out of bounds"; + assert allocator.getLIRGenerationResult().getFirstInsertPosition() <= index && index < instructions.size() : "index out of bounds"; assert instructions.get(index).id() == opId : "error in calculation"; // insert new instruction before instruction at position index diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java index 8b964de8654e..d58fc875d25b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/constopt/ConstantLoadOptimization.java @@ -58,7 +58,6 @@ import jdk.graal.compiler.options.NestedBooleanOptionKey; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionType; - import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.AllocatableValue; import jdk.vm.ci.meta.Constant; @@ -356,8 +355,7 @@ private void insertLoad(Constant constant, ValueKind kind, BasicBlock bloc // create move LIRInstruction move = lirGen.getSpillMoveFactory().createLoad(variable, constant); // insert instruction - lirGen.getResult(); - int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); + int insertionIndex = lirGen.getResult().getFirstInsertPosition(); getInsertionBuffer(block).append(insertionIndex, move); debug.log("new move (%s) and inserted in block %s", move, block); // update usages diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java index 3d73368b19b0..c595300a0175 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/gen/LIRGenerationResult.java @@ -165,7 +165,8 @@ public String getCompilationUnitName() { * * @return index of the first insert position */ - public static int getFirstInsertPosition() { + @SuppressWarnings("static-method") + public final int getFirstInsertPosition() { return 1; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java index 70804ead5b80..2e936e88cc56 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MethodProfilingPhase.java @@ -86,7 +86,7 @@ public void doBlock(BasicBlock block, String group) { LIRInstruction op = diagnosticLirGenTool.createBenchmarkCounter(lirGenRes.getCompilationUnitName(), group, increment); buffer.init(instructions); - int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); + int insertionIndex = lirGenRes.getFirstInsertPosition(); buffer.append(insertionIndex, op); buffer.finish(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java index d9b05af645b4..e611a0775e9b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/profiling/MoveProfilingPhase.java @@ -131,7 +131,7 @@ protected final void insertBenchmarkCounter(BasicBlock block) { increments.toArray(new Value[size])); assert inst != null; buffer.init(instructions); - int insertionIndex = LIRGenerationResult.getFirstInsertPosition(); + int insertionIndex = lirGenRes.getFirstInsertPosition(); buffer.append(insertionIndex, inst); buffer.finish(); } From 6ddb21cdebd87c9af0b95cd732dc3b276495d7e5 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Thu, 25 Jan 2024 15:16:07 +0100 Subject: [PATCH 58/75] Fix after another rebase. --- .../core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java index 362f876b41a2..184a84e1cdf2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/sampler/JfrRecurringCallbackExecutionSampler.java @@ -30,6 +30,7 @@ import java.util.Collections; import java.util.List; +import com.oracle.svm.core.jfr.JfrExecutionSamplerSupported; import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; @@ -44,7 +45,6 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; -import com.oracle.svm.core.jfr.JfrExecutionSamplerSupported; import com.oracle.svm.core.jfr.JfrFeature; import com.oracle.svm.core.jfr.SubstrateJVM; import com.oracle.svm.core.thread.ThreadListenerSupport; @@ -108,7 +108,6 @@ private static void install(IsolateThread thread, RecurringCallbackTimer callbac @Override @Uninterruptible(reason = "Prevent VM operations that modify the recurring callbacks.") - @Override protected void uninstall(IsolateThread thread) { assert thread == CurrentIsolate.getCurrentThread() || VMOperation.isInProgressAtSafepoint(); From 0e2edeb6153a8477325296f91cc19030052e02d9 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 25 Jan 2024 15:50:56 +0100 Subject: [PATCH 59/75] Simplifications and cleanups. --- .../doc-files/FlightRecorderOptionsHelp.txt | 68 +++++++------------ .../com/oracle/svm/core/jfr/JfrManager.java | 14 ++-- .../com/oracle/svm/core/jfr/JfrOptionSet.java | 6 +- .../com/oracle/svm/core/jfr/SubstrateJVM.java | 4 +- 4 files changed, 37 insertions(+), 55 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt index 06b737e77da7..c6e3bfbee71f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/doc-files/FlightRecorderOptionsHelp.txt @@ -2,45 +2,29 @@ Usage: -XX:FlightRecorderOptions=[option[=value][,...]] This option expects a comma separated list of key-value pairs. None of the options are mandatory. Possible option keys are as follows: -globalbuffercount (Optional) Number of global buffers. This option is a legacy - option: change the memorysize parameter to alter the number of - global buffers. This value cannot be changed once JFR has been - initialized. (LONG, default determined by the value for - memorysize) - -globalbuffersize (Optional) Size of the global buffers, in bytes. This option is a - legacy option: change the memorysize parameter to alter the size - of the global buffers. This value cannot be changed once JFR has - been initialized. (STRING, default determined by the value for - memorysize) - -maxchunksize (Optional) Maximum size of an individual data chunk in bytes if - one of the following suffixes is not used: 'm' or 'M' for - megabytes OR 'g' or 'G' for gigabytes. This value cannot be - changed once JFR has been initialized. (STRING, 12M) - -memorysize (Optional) Overall memory size, in bytes if one of the following - suffixes is not used: 'm' or 'M' for megabytes OR 'g' or 'G' for - gigabytes. This value cannot be changed once JFR has been - initialized. (STRING, 10M) - -repositorypath (Optional) Path to the location where recordings are stored until - they are written to a permanent file. (STRING, The default - location is the temporary directory for the operating system. On - Linux operating systems, the temporary directory is /tmp. On - Windows, the temporary directory is specified by the TMP - environment variable) - -stackdepth (Optional) Stack depth for stack traces. Setting this value - greater than the default of 64 may cause a performance - degradation. This value cannot be changed once JFR has been - initialized. (LONG, 64) - -thread_buffer_size (Optional) Local buffer size for each thread in bytes if one of - the following suffixes is not used: 'k' or 'K' for kilobytes or - 'm' or 'M' for megabytes. Overriding this parameter could reduce - performance and is not recommended. This value cannot be changed - once JFR has been initialized. (STRING, 8k) - -preserve-repository (Optional) Preserve files stored in the disk repository after the - Java Virtual Machine has exited. (BOOLEAN, false) \ No newline at end of file +globalbuffercount=20 (Optional) Number of global JFR buffers. This is a legacy option. + This value cannot be changed once JFR has been initialized. + The default value is determined by the values for memorysize and globalbuffersize. + +globalbuffersize=512k (Optional) Size of each global JFR buffer. This is a legacy option. + This value cannot be changed once JFR has been initialized. + The default value is determined by the values for memorysize and globalbuffercount. + +maxchunksize=12m (Optional) Maximum size of each individual JFR data chunk. + This value cannot be changed once JFR has been initialized. + +memorysize=10m (Optional) Total size of all global JFR buffers. + This value cannot be changed once JFR has been initialized. + +repositorypath=... (Optional) Path to the location where JFR recordings are stored until they are + written to a permanent file. + The default location is the temporary directory for the operating system. + +stackdepth=64 (Optional) Stack depth for stack traces. + Setting this value greater than the default may cause a performance degradation. + This value cannot be changed once JFR has been initialized. + +thread_buffer_size=8k (Optional) Size of each thread-local JFR buffer. + This value cannot be changed once JFR has been initialized. + +preserve-repository=false (Optional) Preserve files stored in the disk repository after the process exits. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java index c066c82b5354..12946f0c6ecb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrManager.java @@ -36,8 +36,6 @@ import java.util.HashMap; import java.util.Map; -import jdk.graal.compiler.api.replacements.Fold; -import jdk.graal.compiler.core.common.SuppressFBWarnings; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -49,6 +47,8 @@ import com.oracle.svm.core.util.UserError.UserException; import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.api.replacements.Fold; +import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.jfr.FlightRecorder; import jdk.jfr.Recording; import jdk.jfr.internal.LogLevel; @@ -57,9 +57,9 @@ import jdk.jfr.internal.OldObjectSample; import jdk.jfr.internal.Options; import jdk.jfr.internal.PrivateAccess; +import jdk.jfr.internal.Repository; import jdk.jfr.internal.SecuritySupport; import jdk.jfr.internal.jfc.JFC; -import jdk.jfr.internal.Repository; /** * Called during VM startup and teardown. Also triggers the JFR argument parsing. @@ -75,10 +75,6 @@ public JfrManager(boolean hostedEnabled) { this.hostedEnabled = hostedEnabled; } - public static boolean shouldBeginRecordingAtLaunch() { - return SubstrateOptions.FlightRecorder.getValue() || !SubstrateOptions.StartFlightRecording.getValue().isEmpty(); - } - @Fold public static JfrManager get() { return ImageSingletons.lookup(JfrManager.class); @@ -88,7 +84,9 @@ public RuntimeSupport.Hook startupHook() { return isFirstIsolate -> { parseFlightRecorderLogging(SubstrateOptions.FlightRecorderLogging.getValue()); periodicEventSetup(); - if (shouldBeginRecordingAtLaunch()) { + + boolean startRecording = SubstrateOptions.FlightRecorder.getValue() || !SubstrateOptions.StartFlightRecording.getValue().isEmpty(); + if (startRecording) { initRecording(); } }; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java index 8f0a0b9674ab..9cfc0740c5a5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java @@ -24,12 +24,12 @@ */ package com.oracle.svm.core.jfr; -import jdk.graal.compiler.core.common.NumUtil; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.os.VirtualMemoryProvider; +import jdk.graal.compiler.core.common.NumUtil; import jdk.jfr.internal.Options; /** @@ -37,8 +37,8 @@ * the option values as needed. * * Similar to OpenJDK, the options available by -XX:FlightRecorderOptions cannot be set after JFR is - * initialized. This means this that after {@link SubstrateJVM#createJFR(boolean)} is called, this - * class is no longer needed. + * initialized. This means that after {@link SubstrateJVM#createJFR(boolean)} is called, this class + * is no longer needed. * * This class is used to store options set at the OpenJDK Java-level which propagate down to the VM * level via {@link jdk.jfr.internal.JVM}. The option values are stored here until they are diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java index ad4eef6add53..0a5a241e3f40 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/SubstrateJVM.java @@ -26,7 +26,6 @@ import java.util.List; -import com.oracle.svm.core.log.Log; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.IsolateThread; import org.graalvm.nativeimage.Platform; @@ -39,6 +38,7 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jfr.logging.JfrLogging; import com.oracle.svm.core.jfr.sampler.JfrExecutionSampler; +import com.oracle.svm.core.log.Log; import com.oracle.svm.core.sampler.SamplerBufferPool; import com.oracle.svm.core.sampler.SubstrateSigprofHandler; import com.oracle.svm.core.thread.JavaThreads; @@ -209,7 +209,7 @@ public boolean createJFR(boolean simulateFailure) { threadLocal.initialize(options.threadBufferSize.getValue()); globalMemory.initialize(options.globalBufferSize.getValue(), options.globalBufferCount.getValue()); unlockedChunkWriter.initialize(options.maxChunkSize.getValue()); - stackTraceRepo.setStackTraceDepth((int) options.stackDepth.getValue()); + stackTraceRepo.setStackTraceDepth(NumUtil.safeToInt(options.stackDepth.getValue())); recorderThread.start(); From 928c6bdfba8b49bca988ff318779a74cbc016d45 Mon Sep 17 00:00:00 2001 From: Martin Entlicher Date: Tue, 16 Jan 2024 23:41:57 +0100 Subject: [PATCH 60/75] Instrumentation and Debugger API extended to ignore unavailable source sections. (GR-51385) --- .../UnavailableSectionInspectDebugTest.java | 96 +++++++++++++ .../chromeinspector/InspectorDebugger.java | 5 +- .../dap/test/UnavailableSectionDAPTest.java | 86 ++++++++++++ .../dap/server/DebugProtocolServerImpl.java | 5 +- truffle/CHANGELOG.md | 5 + .../api/debug/test/SuspensionFilterTest.java | 130 +++++++++++++++++- .../snapshot.sigtest | 7 +- .../truffle/api/debug/DebuggerSession.java | 6 +- .../truffle/api/debug/SuspensionFilter.java | 35 ++++- .../test/SourceSectionFilterTest.java | 20 ++- .../snapshot.sigtest | 5 +- .../instrumentation/SourceSectionFilter.java | 50 ++++++- .../api/interop/DefaultNodeExports.java | 8 +- .../com.oracle.truffle.tck/snapshot.sigtest | 1 + .../oracle/truffle/tck/DebuggerTester.java | 29 +++- 15 files changed, 466 insertions(+), 22 deletions(-) create mode 100644 tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/UnavailableSectionInspectDebugTest.java create mode 100644 tools/src/com.oracle.truffle.tools.dap.test/src/com/oracle/truffle/tools/dap/test/UnavailableSectionDAPTest.java diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/UnavailableSectionInspectDebugTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/UnavailableSectionInspectDebugTest.java new file mode 100644 index 000000000000..57be6289b169 --- /dev/null +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/UnavailableSectionInspectDebugTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tools.chromeinspector.test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +import org.graalvm.polyglot.Source; + +import com.oracle.truffle.api.debug.test.SuspensionFilterTest; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; + +/** + * Test that we do not suspend on unavailable source sections. + */ +public class UnavailableSectionInspectDebugTest { + + @Test + public void testNoStopInUnavailable() throws InterruptedException { + ProxyLanguage.setDelegate(SuspensionFilterTest.createSectionAvailabilityTestLanguage()); + InspectorTester tester = InspectorTester.start(true, false, false); + + tester.sendMessage("{\"id\":1,\"method\":\"Runtime.enable\"}"); + assertEquals("{\"result\":{},\"id\":1}", tester.getMessages(true).trim()); + tester.sendMessage("{\"id\":2,\"method\":\"Debugger.enable\"}"); + tester.receiveMessages( + "{\"result\":{\"debuggerId\":\"UniqueDebuggerId.", "},\"id\":2}\n"); + tester.sendMessage("{\"id\":3,\"method\":\"Runtime.runIfWaitingForDebugger\"}"); + // @formatter:off The default formatting makes unnecessarily big indents and illogical line breaks + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":3}\n" + + "{\"method\":\"Runtime.executionContextCreated\",\"params\":{\"context\":{\"origin\":\"\",\"name\":\"test\",\"id\":1}}}\n")); + // @formatter:on + + long cid = tester.getContextId(); + int cmdId = 1; + String[] hashes = new String[]{"fc4f434affffffffffffffffffffffffffffffff", "daaab888ffffffffffffffffffffffffffffffff"}; + for (int i = 0; i < 3; i++) { + String sourceName = i + ".test"; + // Create RootWithUnavailableSection.sectionAvailability = i: + Source source = Source.newBuilder(ProxyLanguage.ID, Integer.toString(i), sourceName).buildLiteral(); + tester.eval(source); + // @formatter:off + if (i < 2) { // No Source when SourceSection is null + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.scriptParsed\",\"params\":{\"endLine\":0,\"scriptId\":\"" + i + "\",\"endColumn\":1,\"startColumn\":0,\"startLine\":0,\"length\":1," + + "\"executionContextId\":" + cid + ",\"url\":\"" + sourceName + "\",\"hash\":\"" + hashes[i] + "\"}}\n")); + } + if (i == 0) { + assertTrue(tester.compareReceivedMessages( + "{\"method\":\"Debugger.paused\",\"params\":{\"reason\":\"other\",\"hitBreakpoints\":[]," + + "\"callFrames\":[{\"callFrameId\":\"0\"," + + "\"returnValue\":{\"description\":\"42\",\"type\":\"number\",\"value\":42}," + + "\"functionName\":\"\"," + + "\"scopeChain\":[]," + + "\"this\":null," + + "\"location\":{\"scriptId\":\"" + i + "\",\"columnNumber\":1,\"lineNumber\":0}," + + "\"url\":\"" + sourceName + "\"}]}}\n")); + cmdId++; + tester.sendMessage("{\"id\":" + cmdId + ",\"method\":\"Debugger.stepOver\"}"); + assertTrue(tester.compareReceivedMessages( + "{\"result\":{},\"id\":" + cmdId + "}\n" + + "{\"method\":\"Debugger.resumed\"}\n")); + } + // @formatter:on + } + // Wait for evals to finish, since there may be no protocol communication from some of them. + tester.finishNoGC(); + // Reset the delegate so that we can GC the tested Engine + ProxyLanguage.setDelegate(new ProxyLanguage()); + tester.finish(); + } +} diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java index 9ce349cdcc5d..d4ac6f51ddff 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector/src/com/oracle/truffle/tools/chromeinspector/InspectorDebugger.java @@ -169,7 +169,10 @@ private void startSession() { suspendedCallback = new SuspendedCallbackImpl(); debuggerSession = tdbg.startSession(suspendedCallback, SourceElement.ROOT, SourceElement.STATEMENT); debuggerSession.setSourcePath(context.getSourcePath()); - debuggerSession.setSteppingFilter(SuspensionFilter.newBuilder().ignoreLanguageContextInitialization(!context.isInspectInitialization()).includeInternal(context.isInspectInternal()).build()); + debuggerSession.setSteppingFilter(SuspensionFilter.newBuilder() // + .ignoreLanguageContextInitialization(!context.isInspectInitialization()) // + .includeInternal(context.isInspectInternal()) // + .sourceSectionAvailableOnly(true).build()); scriptsHandler = context.acquireScriptsHandler(debuggerSession); breakpointsHandler = new BreakpointsHandler(debuggerSession, scriptsHandler, () -> eventHandler); } diff --git a/tools/src/com.oracle.truffle.tools.dap.test/src/com/oracle/truffle/tools/dap/test/UnavailableSectionDAPTest.java b/tools/src/com.oracle.truffle.tools.dap.test/src/com/oracle/truffle/tools/dap/test/UnavailableSectionDAPTest.java new file mode 100644 index 000000000000..577be2f0b086 --- /dev/null +++ b/tools/src/com.oracle.truffle.tools.dap.test/src/com/oracle/truffle/tools/dap/test/UnavailableSectionDAPTest.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.tools.dap.test; + +import org.junit.Test; + +import org.graalvm.polyglot.Source; + +import com.oracle.truffle.api.debug.test.SuspensionFilterTest; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; + +/** + * Test that we do not suspend on unavailable source sections. + */ +public class UnavailableSectionDAPTest { + + @Test + public void testNoStopInUnavailable() throws Exception { + ProxyLanguage.setDelegate(SuspensionFilterTest.createSectionAvailabilityTestLanguage()); + DAPTester tester = DAPTester.start(true, null); + + tester.sendMessage( + "{\"command\":\"initialize\",\"arguments\":{\"clientID\":\"DAPTester\",\"clientName\":\"DAP Tester\",\"adapterID\":\"graalvm\",\"pathFormat\":\"path\",\"linesStartAt1\":true,\"columnsStartAt1\":true," + + "\"supportsVariableType\":true,\"supportsVariablePaging\":true,\"supportsRunInTerminalRequest\":true,\"locale\":\"en-us\",\"supportsProgressReporting\":true},\"type\":\"request\",\"seq\":1}"); + tester.compareReceivedMessages( + "{\"event\":\"initialized\",\"type\":\"event\"}", + "{\"success\":true,\"type\":\"response\",\"body\":{\"supportsConditionalBreakpoints\":true,\"supportsLoadedSourcesRequest\":true,\"supportsFunctionBreakpoints\":true,\"supportsExceptionInfoRequest\":true," + + "\"supportsBreakpointLocationsRequest\":true,\"supportsHitConditionalBreakpoints\":true,\"supportsLogPoints\":true,\"supportsSetVariable\":true,\"supportsConfigurationDoneRequest\":true," + + "\"exceptionBreakpointFilters\":[{\"filter\":\"all\",\"label\":\"All Exceptions\"},{\"filter\":\"uncaught\",\"label\":\"Uncaught Exceptions\"}]},\"request_seq\":1,\"command\":\"initialize\"}"); + tester.sendMessage( + "{\"command\":\"attach\",\"arguments\":{\"type\":\"graalvm\",\"request\":\"attach\",\"name\":\"Attach\",\"port\":9229,\"protocol\":\"debugAdapter\"},\"type\":\"request\",\"seq\":2}"); + tester.compareReceivedMessages("{\"event\":\"output\",\"body\":{\"output\":\"Debugger attached.\",\"category\":\"stderr\"},\"type\":\"event\"}", + "{\"success\":true,\"type\":\"response\",\"request_seq\":2,\"command\":\"attach\"}"); + tester.sendMessage("{\"command\":\"configurationDone\",\"type\":\"request\",\"seq\":5}"); + tester.compareReceivedMessages("{\"success\":true,\"type\":\"response\",\"request_seq\":5,\"command\":\"configurationDone\",\"seq\":5}"); + + int seq = 6; + for (int i = 0; i < 3; i++) { + String sourceName = i + ".test"; + // Create RootWithUnavailableSection.sectionAvailability = i: + Source source = Source.newBuilder(ProxyLanguage.ID, Integer.toString(i), sourceName).buildLiteral(); + tester.eval(source); + if (i == 0) { + tester.compareReceivedMessages("{\"event\":\"thread\",\"body\":{\"threadId\":1,\"reason\":\"started\"},\"type\":\"event\",\"seq\":" + (seq++) + "}"); + } + if (i < 2) { // No Source when SourceSection is null + String sourceJson = "{\"sourceReference\":" + (i + 1) + ",\"name\":\"" + sourceName + "\"}"; + tester.compareReceivedMessages( + "{\"event\":\"loadedSource\",\"body\":{\"reason\":\"new\",\"source\":" + sourceJson + "},\"type\":\"event\",\"seq\":" + (seq++) + "}"); + } + if (i == 0) { + tester.compareReceivedMessages( + "{\"event\":\"stopped\",\"body\":{\"threadId\":1,\"reason\":\"debugger_statement\",\"description\":\"Paused on debugger statement\"},\"type\":\"event\",\"seq\":" + + (seq++) + "}"); + tester.sendMessage("{\"command\":\"next\",\"arguments\":{\"threadId\":1},\"type\":\"request\",\"seq\":7}"); + tester.compareReceivedMessages( + "{\"success\":true,\"type\":\"response\",\"request_seq\":7,\"command\":\"next\",\"seq\":" + (seq++) + "}"); + tester.compareReceivedMessages( + "{\"event\":\"continued\",\"body\":{\"threadId\":1,\"allThreadsContinued\":false},\"type\":\"event\",\"seq\":" + (seq++) + "}"); + } + } + tester.finish(); + } +} diff --git a/tools/src/com.oracle.truffle.tools.dap/src/com/oracle/truffle/tools/dap/server/DebugProtocolServerImpl.java b/tools/src/com.oracle.truffle.tools.dap/src/com/oracle/truffle/tools/dap/server/DebugProtocolServerImpl.java index 28a149eb16c7..f5c89d2b63a3 100644 --- a/tools/src/com.oracle.truffle.tools.dap/src/com/oracle/truffle/tools/dap/server/DebugProtocolServerImpl.java +++ b/tools/src/com.oracle.truffle.tools.dap/src/com/oracle/truffle/tools/dap/server/DebugProtocolServerImpl.java @@ -699,7 +699,10 @@ private DebuggerSession startDebuggerSession() { Debugger tdbg = context.getEnv().lookup(context.getEnv().getInstruments().get("debugger"), Debugger.class); DebuggerSession session = tdbg.startSession(new SuspendedCallbackImpl(), SourceElement.ROOT, SourceElement.STATEMENT); session.setSourcePath(sourcePath); - session.setSteppingFilter(SuspensionFilter.newBuilder().ignoreLanguageContextInitialization(!context.isInspectInitialization()).includeInternal(context.isInspectInternal()).build()); + session.setSteppingFilter(SuspensionFilter.newBuilder() // + .ignoreLanguageContextInitialization(!context.isInspectInitialization()) // + .includeInternal(context.isInspectInternal()) // + .sourceSectionAvailableOnly(true).build()); return session; } diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 27188be870a1..1766c00f3ffa 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -2,6 +2,11 @@ This changelog summarizes major changes between Truffle versions relevant to languages implementors building upon the Truffle framework. The main focus is on APIs exported by Truffle. +## Version 24.1.0 + +* GR-51385 Added an instrumentation filter to include available source sections only: `SourceSectionFilter.Builder#sourceSectionAvailableOnly(boolean)` +* GR-51385 Added a debugger filter to suspend in available source sections only: `SuspensionFilter.Builder#sourceSectionAvailableOnly(boolean)`. + ## Version 24.0.0 * GR-45863 Yield and resume events added to the instrumentation: diff --git a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/SuspensionFilterTest.java b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/SuspensionFilterTest.java index 2b76c7036ae1..15e92365525d 100644 --- a/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/SuspensionFilterTest.java +++ b/truffle/src/com.oracle.truffle.api.debug.test/src/com/oracle/truffle/api/debug/test/SuspensionFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -48,11 +48,26 @@ import org.junit.Assert; import org.junit.Test; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.debug.Breakpoint; import com.oracle.truffle.api.debug.DebuggerSession; +import com.oracle.truffle.api.debug.SourceElement; +import com.oracle.truffle.api.debug.SuspendAnchor; import com.oracle.truffle.api.debug.SuspendedEvent; import com.oracle.truffle.api.debug.SuspensionFilter; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.instrumentation.GenerateWrapper; +import com.oracle.truffle.api.instrumentation.InstrumentableNode; +import com.oracle.truffle.api.instrumentation.ProbeNode; +import com.oracle.truffle.api.instrumentation.StandardTags; +import com.oracle.truffle.api.instrumentation.Tag; import com.oracle.truffle.api.instrumentation.test.InstrumentationTestLanguage; +import com.oracle.truffle.api.nodes.Node; +import com.oracle.truffle.api.nodes.RootNode; +import com.oracle.truffle.api.source.SourceSection; +import com.oracle.truffle.api.test.polyglot.ProxyLanguage; +import java.util.List; import org.graalvm.polyglot.Source; @@ -531,4 +546,117 @@ public void testSourceFilterBreakpoints() { } } } + + @Test + public void testUnavailableSourceSection() { + ProxyLanguage.setDelegate(createSectionAvailabilityTestLanguage()); + try (DebuggerSession session = tester.startSession(SourceElement.ROOT)) { + session.suspendNextExecution(); + for (Boolean availableOnly : List.of(Boolean.FALSE, Boolean.TRUE)) { + session.setSteppingFilter(SuspensionFilter.newBuilder().sourceSectionAvailableOnly(availableOnly).build()); + for (int i = 0; i < 3; i++) { + // Create RootWithUnavailableSection.sectionAvailability = i: + Source source = Source.create(ProxyLanguage.ID, Integer.toString(i)); + tester.startEval(source); + boolean suspends = !availableOnly || i == 0; + if (suspends) { + for (SuspendAnchor anchor : List.of(SuspendAnchor.BEFORE, SuspendAnchor.AFTER)) { + final SuspendAnchor suspendAnchor = anchor; + final int sectionAvailability = i; + tester.expectSuspended((SuspendedEvent event) -> { + Assert.assertEquals(suspendAnchor, event.getSuspendAnchor()); + SourceSection section = event.getSourceSection(); + switch (sectionAvailability) { + case 0: + Assert.assertTrue(section.isAvailable()); + break; + case 1: + Assert.assertFalse(section.isAvailable()); + break; + case 2: + Assert.assertNull(section); + break; + } + event.prepareStepOver(1); + }, error -> error.contains("has null SourceSection")); + } + } + tester.expectDone(); + } + } + } + } + + public static ProxyLanguage createSectionAvailabilityTestLanguage() { + return new ProxyLanguage() { + @Override + protected CallTarget parse(TruffleLanguage.ParsingRequest request) throws Exception { + return new TestRootNode(languageInstance, request.getSource()).getCallTarget(); + } + + final class TestRootNode extends RootNode { + @Node.Child RootWithUnavailableSection node; + + TestRootNode(TruffleLanguage language, com.oracle.truffle.api.source.Source source) { + super(language); + node = new RootWithUnavailableSection(source); + } + + @Override + public Object execute(VirtualFrame frame) { + return node.execute(frame); + } + } + }; + } + + @GenerateWrapper + static class RootWithUnavailableSection extends Node implements InstrumentableNode { + + private final int sectionAvailability; + private final com.oracle.truffle.api.source.Source source; + + RootWithUnavailableSection(com.oracle.truffle.api.source.Source source) { + this.sectionAvailability = Character.digit(source.getCharacters().charAt(0), 10); + this.source = source; + } + + RootWithUnavailableSection(RootWithUnavailableSection root) { + this.sectionAvailability = root.sectionAvailability; + this.source = root.source; + } + + @Override + public boolean isInstrumentable() { + return true; + } + + @Override + public boolean hasTag(Class tag) { + return StandardTags.RootTag.class.equals(tag); + } + + @Override + public InstrumentableNode.WrapperNode createWrapper(ProbeNode probe) { + return new RootWithUnavailableSectionWrapper(this, this, probe); + } + + @Override + public SourceSection getSourceSection() { + switch (sectionAvailability) { + case 0: // Available + return source.createSection(1); + case 1: // Unavailable + return source.createUnavailableSection(); + case 2: // null + return null; + default: + throw new IllegalStateException(String.format("Unknown sectionAvailability %d", sectionAvailability)); + } + } + + public int execute(@SuppressWarnings("unused") VirtualFrame frame) { + return 42; + } + } } diff --git a/truffle/src/com.oracle.truffle.api.debug/snapshot.sigtest b/truffle/src/com.oracle.truffle.api.debug/snapshot.sigtest index a22a989cc230..40984ec61f38 100644 --- a/truffle/src/com.oracle.truffle.api.debug/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api.debug/snapshot.sigtest @@ -290,7 +290,7 @@ meth public void suspend(java.lang.Thread) meth public void suspendAll() meth public void suspendNextExecution() supr java.lang.Object -hfds ANCHOR_SET_AFTER,ANCHOR_SET_ALL,ANCHOR_SET_BEFORE,SESSIONS,allBindings,alwaysHaltBreakpointsActive,breakpoints,callback,closed,currentSuspendedEventMap,debugger,exceptionBreakpointsActive,executionLifecycle,hasExpressionElement,hasRootElement,ignoreLanguageContextInitialization,inEvalInContext,includeInternal,locationBreakpointsActive,sessionId,showHostStackFrames,sourceElements,sourceFilter,sources,stepping,steppingEnabledSlots,strategyMap,suspendAll,suspendNext,suspensionFilterUnchanged,syntaxElementsBinding,threadSuspensions +hfds ANCHOR_SET_AFTER,ANCHOR_SET_ALL,ANCHOR_SET_BEFORE,SESSIONS,allBindings,alwaysHaltBreakpointsActive,breakpoints,callback,closed,currentSuspendedEventMap,debugger,exceptionBreakpointsActive,executionLifecycle,hasExpressionElement,hasRootElement,ignoreLanguageContextInitialization,inEvalInContext,includeAvailableSourceSectionsOnly,includeInternal,locationBreakpointsActive,sessionId,showHostStackFrames,sourceElements,sourceFilter,sources,stepping,steppingEnabledSlots,strategyMap,suspendAll,suspendNext,suspensionFilterUnchanged,syntaxElementsBinding,threadSuspensions hcls Caller,RootSteppingDepthNode,StableBoolean,SteppingNode,SuspendContextAndFrame,ThreadSuspension CLSS public final com.oracle.truffle.api.debug.DebuggerTags @@ -370,7 +370,7 @@ innr public final Builder meth public boolean isIgnoreLanguageContextInitialization() meth public static com.oracle.truffle.api.debug.SuspensionFilter$Builder newBuilder() supr java.lang.Object -hfds ignoreLanguageContextInitialization,includeInternal,sourcePredicate +hfds ignoreLanguageContextInitialization,includeAvailableSourceSectionsOnly,includeInternal,sourcePredicate CLSS public final com.oracle.truffle.api.debug.SuspensionFilter$Builder outer com.oracle.truffle.api.debug.SuspensionFilter @@ -378,8 +378,9 @@ meth public com.oracle.truffle.api.debug.SuspensionFilter build() meth public com.oracle.truffle.api.debug.SuspensionFilter$Builder ignoreLanguageContextInitialization(boolean) meth public com.oracle.truffle.api.debug.SuspensionFilter$Builder includeInternal(boolean) meth public com.oracle.truffle.api.debug.SuspensionFilter$Builder sourceIs(java.util.function.Predicate) +meth public com.oracle.truffle.api.debug.SuspensionFilter$Builder sourceSectionAvailableOnly(boolean) supr java.lang.Object -hfds ignoreLanguageContextInitialization,includeInternal,sourcePredicate +hfds ignoreLanguageContextInitialization,includeAvailableSourceSectionsOnly,includeInternal,sourcePredicate CLSS public abstract com.oracle.truffle.api.instrumentation.Tag cons protected init() diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java index 3e14616522b9..58459c8466d1 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/DebuggerSession.java @@ -205,6 +205,7 @@ public final class DebuggerSession implements Closeable { private final StableBoolean stepping = new StableBoolean(false); private final StableBoolean ignoreLanguageContextInitialization = new StableBoolean(false); private volatile boolean includeInternal = false; + private volatile boolean includeAvailableSourceSectionsOnly = false; private volatile boolean showHostStackFrames = false; private Predicate sourceFilter; @CompilationFinal private volatile Assumption suspensionFilterUnchanged = Truffle.getRuntime().createAssumption("Unchanged suspension filter"); @@ -350,11 +351,13 @@ public void setSteppingFilter(SuspensionFilter steppingFilter) { synchronized (this) { boolean oldIncludeInternal = this.includeInternal; this.includeInternal = steppingFilter.isInternalIncluded(); + boolean oldIncludeOnlyAvailableSourceSections = this.includeAvailableSourceSectionsOnly; + this.includeAvailableSourceSectionsOnly = steppingFilter.isIncludeAvailableSourceSectionsOnly(); Predicate oldSourceFilter = this.sourceFilter; this.sourceFilter = steppingFilter.getSourcePredicate(); this.suspensionFilterUnchanged.invalidate(); this.suspensionFilterUnchanged = Truffle.getRuntime().createAssumption("Unchanged suspension filter"); - if (oldIncludeInternal != this.includeInternal || oldSourceFilter != this.sourceFilter) { + if (oldIncludeInternal != this.includeInternal || oldIncludeOnlyAvailableSourceSections != this.includeAvailableSourceSectionsOnly || oldSourceFilter != this.sourceFilter) { removeBindings(); addBindings(this.includeInternal, this.sourceFilter); } @@ -687,6 +690,7 @@ private EventBinding createBinding(boolean Class... tags) { Builder builder = SourceSectionFilter.newBuilder().tagIs(tags); builder.includeInternal(includeInternalCode); + builder.sourceSectionAvailableOnly(includeAvailableSourceSectionsOnly); if (sFilter != null) { builder.sourceIs(new SourceSectionFilter.SourcePredicate() { @Override diff --git a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspensionFilter.java b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspensionFilter.java index b9ceb3a4327d..3a6102ab00b4 100644 --- a/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspensionFilter.java +++ b/truffle/src/com.oracle.truffle.api.debug/src/com/oracle/truffle/api/debug/SuspensionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -44,6 +44,7 @@ import com.oracle.truffle.api.nodes.RootNode; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.source.SourceSection; /** * A filter to limit the suspension locations. An instance of this filter can be provided to @@ -57,17 +58,20 @@ public final class SuspensionFilter { private final boolean ignoreLanguageContextInitialization; private final boolean includeInternal; + private final boolean includeAvailableSourceSectionsOnly; private final Predicate sourcePredicate; private SuspensionFilter() { this.ignoreLanguageContextInitialization = false; this.includeInternal = false; + this.includeAvailableSourceSectionsOnly = false; this.sourcePredicate = null; } - private SuspensionFilter(boolean ignoreLanguageContextInitialization, boolean includeInternal, Predicate sourcePredicate) { + private SuspensionFilter(boolean ignoreLanguageContextInitialization, boolean includeInternal, boolean includeAvailableSourceSectionsOnly, Predicate sourcePredicate) { this.ignoreLanguageContextInitialization = ignoreLanguageContextInitialization; this.includeInternal = includeInternal; + this.includeAvailableSourceSectionsOnly = includeAvailableSourceSectionsOnly; this.sourcePredicate = sourcePredicate; } @@ -96,6 +100,13 @@ boolean isInternalIncluded() { return includeInternal; } + /** + * Test if only available source sections are included. + */ + boolean isIncludeAvailableSourceSectionsOnly() { + return includeAvailableSourceSectionsOnly; + } + /** * Get a {@link Predicate} that filters based on a {@link Source}. */ @@ -112,6 +123,7 @@ public final class Builder { private boolean ignoreLanguageContextInitialization; private boolean includeInternal = false; + private boolean includeAvailableSourceSectionsOnly = false; private Predicate sourcePredicate; private Builder() { @@ -143,6 +155,23 @@ public Builder includeInternal(boolean internal) { return this; } + /** + * Set to suspend on available source sections only. By default all locations with or + * without available source sections are suspended. If this flag is set to {@code true} then + * {@code null} and not {@link SourceSection#isAvailable() available} source sections are + * not suspended. + * + * @param availableOnly true to include only non-null and + * {@link SourceSection#isAvailable() available} + * {@link SuspendedEvent#getSourceSection() SourceSection}, false to + * include all. + * @since 24.1 + */ + public Builder sourceSectionAvailableOnly(boolean availableOnly) { + this.includeAvailableSourceSectionsOnly = availableOnly; + return this; + } + /** * Set a {@link Predicate} that filters based on a {@link Source}. The predicate must always * return the same result for a source instance otherwise the behavior is undefined. The @@ -162,7 +191,7 @@ public Builder sourceIs(Predicate filter) { * @since 0.26 */ public SuspensionFilter build() { - return new SuspensionFilter(ignoreLanguageContextInitialization, includeInternal, sourcePredicate); + return new SuspensionFilter(ignoreLanguageContextInitialization, includeInternal, includeAvailableSourceSectionsOnly, sourcePredicate); } } } diff --git a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java index c175261ec5ef..870d0e9a1c70 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation.test/src/com/oracle/truffle/api/instrumentation/test/SourceSectionFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -954,6 +954,24 @@ public void testIgnoreInternal() throws Exception { isInstrumented(internalFilter, root, createNode(internalSource.createSection(1)))); } + @Test + public void testAvailableSections() throws Exception { + SourceSectionFilter availableFilter = SourceSectionFilter.newBuilder().sourceSectionAvailableOnly(true).build(); + // Available-only filter instruments available source sections + Assert.assertTrue(isInstrumented(availableFilter, null, source())); + + SourceSection unavailableSourceSection = Source.newBuilder(InstrumentationTestLanguage.ID, "foo", "sampleSource1").build().createUnavailableSection(); + Node unavailableNode = createNode(unavailableSourceSection); + + // Available-only filter does not instrument unavailable or null source sections + Assert.assertFalse(isInstrumented(availableFilter, null, unavailableNode)); + Assert.assertFalse(isInstrumented(availableFilter, null, null)); + + // Any root source section does not affect available filter + Assert.assertTrue(isInstrumented(availableFilter, new SourceSectionRootNode(null, null), source())); + Assert.assertTrue(isInstrumented(availableFilter, new SourceSectionRootNode(unavailableSourceSection, null), source())); + } + @Test public void testComplexFilter() { Source sampleSource1 = Source.newBuilder(InstrumentationTestLanguage.ID, "line1\nline2\nline3\nline4", "sampleSource1").mimeType("text/mime2").build(); diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/snapshot.sigtest b/truffle/src/com.oracle.truffle.api.instrumentation/snapshot.sigtest index b237c2a7e95b..0ab378b7dfbc 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.api.instrumentation/snapshot.sigtest @@ -236,7 +236,7 @@ meth public void onResume(com.oracle.truffle.api.frame.VirtualFrame) meth public void onReturnValue(com.oracle.truffle.api.frame.VirtualFrame,java.lang.Object) meth public void onYield(com.oracle.truffle.api.frame.VirtualFrame,java.lang.Object) supr com.oracle.truffle.api.nodes.Node -hfds SEEN_REENTER,SEEN_RETURN,SEEN_UNWIND,SEEN_UNWIND_NEXT,UNWIND_ACTION_IGNORED,chain,context,handler,retiredNodeReference,seen,version +hfds ASSERT_ENTER_RETURN_PARITY,SEEN_REENTER,SEEN_RETURN,SEEN_UNWIND,SEEN_UNWIND_NEXT,UNWIND_ACTION_IGNORED,chain,context,handler,retiredNodeReference,seen,version hcls EventChainNode,EventFilterChainNode,EventProviderChainNode,EventProviderWithInputChainNode,InputChildContextLookup,InputChildIndexLookup,InputValueChainNode,InstrumentableChildVisitor,RetiredNodeReference CLSS public abstract interface !annotation com.oracle.truffle.api.instrumentation.ProvidedTags @@ -303,8 +303,9 @@ meth public com.oracle.truffle.api.instrumentation.SourceSectionFilter$Builder l meth public com.oracle.truffle.api.instrumentation.SourceSectionFilter$Builder rootNameIs(java.util.function.Predicate) meth public com.oracle.truffle.api.instrumentation.SourceSectionFilter$Builder sourceFilter(com.oracle.truffle.api.instrumentation.SourceFilter) meth public com.oracle.truffle.api.instrumentation.SourceSectionFilter$Builder sourceIs(com.oracle.truffle.api.instrumentation.SourceSectionFilter$SourcePredicate) +meth public com.oracle.truffle.api.instrumentation.SourceSectionFilter$Builder sourceSectionAvailableOnly(boolean) supr java.lang.Object -hfds expressions,includeInternal +hfds availableSections,expressions,includeInternal CLSS public final static com.oracle.truffle.api.instrumentation.SourceSectionFilter$IndexRange outer com.oracle.truffle.api.instrumentation.SourceSectionFilter diff --git a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/SourceSectionFilter.java b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/SourceSectionFilter.java index 3fd804e99834..467fd3267d00 100644 --- a/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/SourceSectionFilter.java +++ b/truffle/src/com.oracle.truffle.api.instrumentation/src/com/oracle/truffle/api/instrumentation/SourceSectionFilter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -311,6 +311,7 @@ boolean isInstrumentedSource(Source source) { public final class Builder { private List expressions = new ArrayList<>(); private boolean includeInternal = true; + private boolean availableSections = false; private Builder() { } @@ -425,6 +426,23 @@ public Builder sourceSectionEquals(SourceSection... section) { return this; } + /** + * Add a filter for available source sections. By default all locations with or without + * available source sections are provided. If this flag is set to {@code true} then + * {@code null} and not {@link SourceSection#isAvailable() available} source sections are + * filtered out. + * + * @param availableOnly {@code true} to include only non-null and + * {@link SourceSection#isAvailable() available} source sections, {@code false} + * to include all. + * @return the builder to chain calls + * @since 24.1 + */ + public Builder sourceSectionAvailableOnly(boolean availableOnly) { + this.availableSections = availableOnly; + return this; + } + /** * Add a filter for all root source sections that equal one of the given source sections. * All descendant source sections of a matching root source section are included in the @@ -685,6 +703,9 @@ public SourceSectionFilter build() { if (!includeInternal) { expressions.add(new EventFilterExpression.IgnoreInternal()); } + if (availableSections) { + expressions.add(new EventFilterExpression.AvailableSections()); + } Collections.sort(expressions); return new SourceSectionFilter(expressions.toArray(new EventFilterExpression[0])); } @@ -1601,6 +1622,33 @@ public String toString() { } + private static final class AvailableSections extends EventFilterExpression { + + AvailableSections() { + } + + @Override + boolean isIncluded(Set> providedTags, Node instrumentedNode, SourceSection s) { + return s != null && s.isAvailable(); + } + + @Override + boolean isRootIncluded(Set> providedTags, SourceSection rootSection, RootNode rootNode, int rootNodeBits) { + return true; + } + + @Override + protected int getOrder() { + return 1; + } + + @Override + public String toString() { + return "available source sections"; + } + + } + } private static final class Not extends EventFilterExpression { diff --git a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/DefaultNodeExports.java b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/DefaultNodeExports.java index 75d8a2375422..15713649c9da 100644 --- a/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/DefaultNodeExports.java +++ b/truffle/src/com.oracle.truffle.api.interop/src/com/oracle/truffle/api/interop/DefaultNodeExports.java @@ -216,8 +216,12 @@ boolean hasSourceLocation() { @ExportMessage @TruffleBoundary - SourceSection getSourceLocation() { - return root.getSourceSection(); + SourceSection getSourceLocation() throws UnsupportedMessageException { + SourceSection section = root.getSourceSection(); + if (section == null) { + throw UnsupportedMessageException.create(); + } + return section; } @ExportMessage diff --git a/truffle/src/com.oracle.truffle.tck/snapshot.sigtest b/truffle/src/com.oracle.truffle.tck/snapshot.sigtest index e4efbf64f87b..3a779d23270c 100644 --- a/truffle/src/com.oracle.truffle.tck/snapshot.sigtest +++ b/truffle/src/com.oracle.truffle.tck/snapshot.sigtest @@ -112,6 +112,7 @@ meth public void close() meth public void closeEngine() meth public void expectKilled() meth public void expectSuspended(com.oracle.truffle.api.debug.SuspendedCallback) +meth public void expectSuspended(com.oracle.truffle.api.debug.SuspendedCallback,java.util.function.Function) meth public void startEval(org.graalvm.polyglot.Source) meth public void startExecute(java.util.function.Function) supr java.lang.Object diff --git a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java index 4eb001ce0b87..9462bc03d057 100644 --- a/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java +++ b/truffle/src/com.oracle.truffle.tck/src/com/oracle/truffle/tck/DebuggerTester.java @@ -269,16 +269,28 @@ public void startExecute(Function script) { } /** - * Expects an suspended event and returns it for potential assertions. If the execution - * completed or was killed instead then an assertion error is thrown. The returned suspended - * event is only valid until on of {@link #expectKilled()}, - * {@link #expectSuspended(SuspendedCallback)} or {@link #expectDone()} is called again. Throws - * an {@link IllegalStateException} if the tester is already closed. + * Expects a suspended event and returns it for potential assertions. If the execution completed + * or was killed instead then an assertion error is thrown. The returned suspended event is only + * valid until on of {@link #expectKilled()}, {@link #expectSuspended(SuspendedCallback)} or + * {@link #expectDone()} is called again. Throws an {@link IllegalStateException} if the tester + * is already closed. * * @param callback handler to be called when the execution is suspended * @since 0.16 */ public void expectSuspended(SuspendedCallback callback) { + expectSuspended(callback, null); + } + + /** + * Expects a suspended event and returns it for potential assertions, allows to verify errors + * printed to the error output. + * + * @param callback handler to be called when the execution is suspended + * @param errorVerifier handler, which returns true when the error is expected + * @since 24.1 + */ + public void expectSuspended(SuspendedCallback callback, Function errorVerifier) { if (closed) { throw new IllegalStateException("Already closed."); } @@ -290,7 +302,12 @@ public void expectSuspended(SuspendedCallback callback) { event = takeEvent(); String e = getErr(); if (!e.isEmpty()) { - throw new AssertionError("Error output is not empty: " + e); + if (errorVerifier != null) { + Assert.assertTrue(e, errorVerifier.apply(e)); + err.reset(); + } else { + throw new AssertionError("Error output is not empty: " + e); + } } } catch (InterruptedException e) { throw new AssertionError(e); From 0be5eea779f58461d9bc8faf2f09d385218cc9ac Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 22 Jan 2024 19:48:02 +0100 Subject: [PATCH 61/75] Shadow JCodings for truffle module from source using mx. --- truffle/mx.truffle/suite.py | 53 ++++++++++++++++++- .../native-image.properties | 1 + 2 files changed, 53 insertions(+), 1 deletion(-) create mode 100644 truffle/src/org.graalvm.shadowed.org.jcodings/src/META-INF/native-image/org.graalvm.shadowed.org.jcodings/native-image.properties diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index cc75c7b12872..435b42674578 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -97,6 +97,17 @@ "digest": "sha512:f92f976375421ef117a97cb4298b7478b849370334a1eaf2efb243bd510e79358f258f47327deb2b9441843e7061acc67add2d034259f3136d97da8a09e545a4", }, + "JCODINGS_1.0.58": { + "digest" : "sha512:625210aa07d1e08bf2f5fdc9da6c491a4e5a56e7db297cba1aa73636670ac1d62f3fd763716ef6ede862456b17169272ed9c8461d07100f95262163dc9c18ef8", + "sourceDigest" : "sha512:d0f883f658310f7ad091aea08df28f1f5fe12080d6cb266cd91aec7e34cda1d57736d32618e8632b329854367d6e4d5fc91b5eb8ac9b823b26113fae3f75f50c", + "maven": { + "groupId": "org.jruby.jcodings", + "artifactId": "jcodings", + "version": "1.0.58", + }, + "license": ["MIT"], + }, + "TRUFFLE_JCODINGS": { "digest" : "sha512:455f3dc287181c185ab87c03e88cc89615f3da262358f44ea01bb3cc9f04d8e3cee7911f8a14a6403d3285d9b54812aaa48ade093a0b3ec4e594adbbda1d5387", "version" : "1.0.58.1", @@ -648,7 +659,7 @@ "sourceDirs" : ["src"], "dependencies" : [ "com.oracle.truffle.api.profiles", - "TRUFFLE_JCODINGS", + "org.graalvm.shadowed.org.jcodings", ], "requires" : [ "jdk.unsupported", # sun.misc.Unsafe @@ -1387,6 +1398,46 @@ "jacoco" : "exclude", "graalCompilerSourceEdition": "ignore", }, + + "org.graalvm.shadowed.org.jcodings" : { + # Shadowed JCODINGS library (org.jruby.jcodings:jcodings) + "subDir" : "src", + "sourceDirs" : ["src"], + "javaCompliance" : "17+", + "spotbugs" : "false", + "shadedDependencies" : [ + "truffle:JCODINGS_1.0.58", + ], + "class" : "ShadedLibraryProject", + "shade" : { + "packages" : { + "org.jcodings" : "org.graalvm.shadowed.org.jcodings", + }, + "exclude" : [ + "module-info.java", + "META-INF/MANIFEST.MF", + "META-INF/services/java.nio.charset.spi.CharsetProvider", + "META-INF/maven/org.jruby.jcodings/jcodings/*", # pom.xml, pom.properties + ], + "include" : { + "tables/*.bin" : { + "tables/" : "org/graalvm/shadowed/org/jcodings/tables/", + }, + }, + "patch" : { + "org/jcodings/util/ArrayReader.java" : { + "\"/tables/\"" : "\"/org/graalvm/shadowed/org/jcodings/tables/\"", + }, + }, + }, + "description" : "JCodings library shadowed for Truffle.", + "allowsJavadocWarnings": True, + # We need to force javac because the generated sources in this project produce warnings in JDT. + "forceJavac" : "true", + "javac.lint.overrides" : "none", + "jacoco" : "exclude", + "graalCompilerSourceEdition": "ignore", + }, }, "licenses" : { diff --git a/truffle/src/org.graalvm.shadowed.org.jcodings/src/META-INF/native-image/org.graalvm.shadowed.org.jcodings/native-image.properties b/truffle/src/org.graalvm.shadowed.org.jcodings/src/META-INF/native-image/org.graalvm.shadowed.org.jcodings/native-image.properties new file mode 100644 index 000000000000..da47ea3f2e20 --- /dev/null +++ b/truffle/src/org.graalvm.shadowed.org.jcodings/src/META-INF/native-image/org.graalvm.shadowed.org.jcodings/native-image.properties @@ -0,0 +1 @@ +Args = --initialize-at-build-time=org.graalvm.shadowed.org.jcodings From 009c051004dcfc139b1bb38669dad8cedb6fe5e7 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 23 Jan 2024 03:47:14 +0100 Subject: [PATCH 62/75] Apply JCodings patch fixing CESU8Encoding.leftAdjustCharHead. --- truffle/mx.truffle/suite.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 435b42674578..5cd2eb169616 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -1428,6 +1428,34 @@ "org/jcodings/util/ArrayReader.java" : { "\"/tables/\"" : "\"/org/graalvm/shadowed/org/jcodings/tables/\"", }, + # Fix CESU8Encoding.leftAdjustCharHead by applying a stripped down version of: + # https://github.com/jruby/jcodings/pull/61/ (not in 1.0.58; remove when updating to a newer version). + "org/jcodings/specific/CESU8Encoding.java" : { +""" + (public int leftAdjustCharHead\\(byte\\[\\] bytes, int p, int s, int end\\) { + if \\(s <= p\\) + return s; + int p_ = s; + while \\(!utf8IsLead\\(bytes\\[p_\\] & 0xff\\) && p_ > p\\) + p_--;)( + return p_; + }) +""" : """ + \\1 + if (p_ > p && s - p_ == 2 && Character.isLowSurrogate((char) utf8Decode3ByteSequence(bytes, p_))) { + int pSurrogatePair = p_ - 1; + while (!utf8IsLead(bytes[pSurrogatePair] & 0xff) && pSurrogatePair > p) + pSurrogatePair--; + if (p_ - pSurrogatePair == 3 && Character.isHighSurrogate((char) utf8Decode3ByteSequence(bytes, pSurrogatePair))) { + return pSurrogatePair; + } + }\\2 + + private static int utf8Decode3ByteSequence(byte[] bytes, int p) { + return ((bytes[p] & 0xF) << 12) | ((bytes[p + 1] & 0xff & 0x3f) << 6) | (bytes[p + 2] & 0xff & 0x3f); + } +""" + }, }, }, "description" : "JCodings library shadowed for Truffle.", From 19a64c84c8910b7ab1f44bc51c171929c4ec32f3 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 23 Jan 2024 15:14:39 +0100 Subject: [PATCH 63/75] Remove TRUFFLE_JCODINGS library definition. --- truffle/mx.truffle/suite.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 5cd2eb169616..6c06a87b7d24 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -108,14 +108,6 @@ "license": ["MIT"], }, - "TRUFFLE_JCODINGS": { - "digest" : "sha512:455f3dc287181c185ab87c03e88cc89615f3da262358f44ea01bb3cc9f04d8e3cee7911f8a14a6403d3285d9b54812aaa48ade093a0b3ec4e594adbbda1d5387", - "version" : "1.0.58.1", - "urls" : ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/graalvm-shadowed-jcodings-{version}.jar"], - "exports" : [], - "license": ["MIT"], - }, - "ASM_9.5": { "digest": "sha512:9e65f2983783725bae196ca939b45246958731246df1c495089c8ea5ce646de77c4e01a5a9ba10642016bb3258e1727e9ebcece6e74d9e3c32f528025d76b955", "sourceDigest": "sha512:64262b68c1acd473a49be3c8a89190200be66808034c55fb23ed08d8a977111c234b6dc77b6ca95310e1f1cbc43437cdc863aadb6217976cc1720d63ef01e937", From b3b83abdcec1c26f7e740144aabc991636e7cb20 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 23 Jan 2024 04:16:39 +0100 Subject: [PATCH 64/75] Espresso should use its own shadowed copy of ASM rather than Truffle's. --- espresso/mx.espresso/mx_espresso.py | 3 + espresso/mx.espresso/suite.py | 30 +++++++- .../EspressoForeignProxyGenerator.java | 70 +++++++++---------- .../truffle/espresso/ref/ClassAssembler.java | 46 ++++++------ 4 files changed, 90 insertions(+), 59 deletions(-) diff --git a/espresso/mx.espresso/mx_espresso.py b/espresso/mx.espresso/mx_espresso.py index fbcf6e3fbf69..c4e918fdc864 100644 --- a/espresso/mx.espresso/mx_espresso.py +++ b/espresso/mx.espresso/mx_espresso.py @@ -35,6 +35,9 @@ _suite = mx.suite('espresso') +# re-export custom mx project classes, so they can be used from suite.py +from mx_sdk_shaded import ShadedLibraryProject # pylint: disable=unused-import + # JDK compiled with the Sulong toolchain. espresso_llvm_java_home = mx.get_env('ESPRESSO_LLVM_JAVA_HOME') or mx.get_env('LLVM_JAVA_HOME') diff --git a/espresso/mx.espresso/suite.py b/espresso/mx.espresso/suite.py index 0dbec84b0664..9165e325a05b 100644 --- a/espresso/mx.espresso/suite.py +++ b/espresso/mx.espresso/suite.py @@ -112,8 +112,8 @@ "dependencies": [ "truffle:TRUFFLE_API", "truffle:TRUFFLE_NFI", - "truffle:TRUFFLE_ASM_9.5", "com.oracle.truffle.espresso.jdwp", + "com.oracle.truffle.espresso.shadowed.asm", ], "requires": [ "java.logging", @@ -321,6 +321,34 @@ "checkstyle": "com.oracle.truffle.espresso", "testProject" : True, }, + + "com.oracle.truffle.espresso.shadowed.asm" : { + # Shadowed ASM library (org.ow2.asm:asm) + "subDir" : "src", + "sourceDirs" : ["src"], + "javaCompliance" : "17+", + "spotbugs" : "false", + "shadedDependencies" : [ + "truffle:ASM_9.5", + ], + "class" : "ShadedLibraryProject", + "shade" : { + "packages" : { + "org.objectweb.asm" : "com.oracle.truffle.espresso.shadowed.asm", + }, + "exclude" : [ + "META-INF/MANIFEST.MF", + "**/package.html", + ], + }, + "description" : "ASM library shadowed for Espresso.", + "allowsJavadocWarnings": True, + # We need to force javac because the generated sources in this project produce warnings in JDT. + "forceJavac" : "true", + "javac.lint.overrides" : "none", + "jacoco" : "exclude", + "graalCompilerSourceEdition": "ignore", + }, }, # ------------- distributions diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/EspressoForeignProxyGenerator.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/EspressoForeignProxyGenerator.java index f856e2f0bcf9..80fc78b36a40 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/EspressoForeignProxyGenerator.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/nodes/interop/EspressoForeignProxyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,36 +22,36 @@ */ package com.oracle.truffle.espresso.nodes.interop; -import static com.oracle.truffle.api.impl.asm.Opcodes.AASTORE; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_FINAL; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_PUBLIC; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_SUPER; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_VARARGS; -import static com.oracle.truffle.api.impl.asm.Opcodes.ALOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.ANEWARRAY; -import static com.oracle.truffle.api.impl.asm.Opcodes.ARETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.ASTORE; -import static com.oracle.truffle.api.impl.asm.Opcodes.ATHROW; -import static com.oracle.truffle.api.impl.asm.Opcodes.BIPUSH; -import static com.oracle.truffle.api.impl.asm.Opcodes.CHECKCAST; -import static com.oracle.truffle.api.impl.asm.Opcodes.DLOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.DRETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.DUP; -import static com.oracle.truffle.api.impl.asm.Opcodes.FLOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.FRETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.ICONST_0; -import static com.oracle.truffle.api.impl.asm.Opcodes.ILOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.INVOKESPECIAL; -import static com.oracle.truffle.api.impl.asm.Opcodes.INVOKESTATIC; -import static com.oracle.truffle.api.impl.asm.Opcodes.INVOKEVIRTUAL; -import static com.oracle.truffle.api.impl.asm.Opcodes.IRETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.LLOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.LRETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.NEW; -import static com.oracle.truffle.api.impl.asm.Opcodes.POP; -import static com.oracle.truffle.api.impl.asm.Opcodes.RETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.SIPUSH; -import static com.oracle.truffle.api.impl.asm.Opcodes.V1_8; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.AASTORE; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_FINAL; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_PUBLIC; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_SUPER; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_VARARGS; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ALOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ANEWARRAY; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ARETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ASTORE; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ATHROW; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.BIPUSH; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.CHECKCAST; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.DLOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.DRETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.DUP; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.FLOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.FRETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ICONST_0; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ILOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.INVOKESPECIAL; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.INVOKESTATIC; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.INVOKEVIRTUAL; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.IRETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.LLOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.LRETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.NEW; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.POP; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.RETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.SIPUSH; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.V1_8; import java.lang.reflect.Modifier; import java.util.ArrayList; @@ -66,10 +66,6 @@ import java.util.concurrent.atomic.AtomicLong; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; -import com.oracle.truffle.api.impl.asm.ClassWriter; -import com.oracle.truffle.api.impl.asm.Label; -import com.oracle.truffle.api.impl.asm.MethodVisitor; -import com.oracle.truffle.api.impl.asm.Type; import com.oracle.truffle.espresso.descriptors.Symbol; import com.oracle.truffle.espresso.impl.ArrayKlass; import com.oracle.truffle.espresso.impl.ClassRegistry; @@ -85,6 +81,10 @@ import com.oracle.truffle.espresso.runtime.EspressoContext; import com.oracle.truffle.espresso.runtime.EspressoException; import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; +import com.oracle.truffle.espresso.shadowed.asm.ClassWriter; +import com.oracle.truffle.espresso.shadowed.asm.Label; +import com.oracle.truffle.espresso.shadowed.asm.MethodVisitor; +import com.oracle.truffle.espresso.shadowed.asm.Type; import com.oracle.truffle.espresso.vm.ModulesHelperVM; /** diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ref/ClassAssembler.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ref/ClassAssembler.java index eac80a5f2c9e..5ff9a21447be 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ref/ClassAssembler.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/ref/ClassAssembler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,28 +22,28 @@ */ package com.oracle.truffle.espresso.ref; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_ABSTRACT; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_BRIDGE; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_FINAL; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_PRIVATE; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_PROTECTED; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_PUBLIC; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_SUPER; -import static com.oracle.truffle.api.impl.asm.Opcodes.ACC_SYNTHETIC; -import static com.oracle.truffle.api.impl.asm.Opcodes.ALOAD; -import static com.oracle.truffle.api.impl.asm.Opcodes.ARETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.CHECKCAST; -import static com.oracle.truffle.api.impl.asm.Opcodes.GETFIELD; -import static com.oracle.truffle.api.impl.asm.Opcodes.INVOKESPECIAL; -import static com.oracle.truffle.api.impl.asm.Opcodes.PUTFIELD; -import static com.oracle.truffle.api.impl.asm.Opcodes.RETURN; -import static com.oracle.truffle.api.impl.asm.Opcodes.V1_8; - -import com.oracle.truffle.api.impl.asm.AnnotationVisitor; -import com.oracle.truffle.api.impl.asm.ClassWriter; -import com.oracle.truffle.api.impl.asm.FieldVisitor; -import com.oracle.truffle.api.impl.asm.MethodVisitor; -import com.oracle.truffle.api.impl.asm.Type; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_ABSTRACT; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_BRIDGE; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_FINAL; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_PRIVATE; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_PROTECTED; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_PUBLIC; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_SUPER; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ACC_SYNTHETIC; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ALOAD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.ARETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.CHECKCAST; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.GETFIELD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.INVOKESPECIAL; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.PUTFIELD; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.RETURN; +import static com.oracle.truffle.espresso.shadowed.asm.Opcodes.V1_8; + +import com.oracle.truffle.espresso.shadowed.asm.AnnotationVisitor; +import com.oracle.truffle.espresso.shadowed.asm.ClassWriter; +import com.oracle.truffle.espresso.shadowed.asm.FieldVisitor; +import com.oracle.truffle.espresso.shadowed.asm.MethodVisitor; +import com.oracle.truffle.espresso.shadowed.asm.Type; final class ClassAssembler { From ae096d815d6c5d613390940e692751c68240bfb3 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Tue, 23 Jan 2024 15:14:30 +0100 Subject: [PATCH 65/75] Remove TRUFFLE_ASM_9.5 library definition. --- truffle/mx.truffle/suite.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 6c06a87b7d24..ca4e71879741 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -143,11 +143,6 @@ "license": "BSD-new", }, - "TRUFFLE_ASM_9.5" : { - "digest" : "sha512:7a49aaa0c4b513ca54ce684a74a3848ba4caf486320125f08cb8872720dc1e789538729f45c46d6ccf1b1ea54f7c3770dc9682d13a3f1813a348168ee5c40b82", - "urls": ["https://lafo.ssw.uni-linz.ac.at/pub/graal-external-deps/com.oracle.truffle.api.impl.asm-9.5.0.jar"], - }, - "ICU4J" : { "moduleName" : "com.ibm.icu", "digest" : "sha512:08720318b2d175ad8379306caacea7da181e51ce9e7410318dae11008ab4a8d6d7b1723136a1fd17b02b11efd24ce87cbe24413c1d5f8d7cb0d00c9d32c1b267", From 0e91ab7b1f2e896481714e0e12ba3a4af5635fcf Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Mon, 22 Jan 2024 20:01:43 +0100 Subject: [PATCH 66/75] Compress truffle-icu4j.jar. --- truffle/mx.truffle/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index ca4e71879741..6000fce99f5e 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -2304,6 +2304,7 @@ "artifactId" : "icu4j", "tag": ["default", "public"], }, + "compress" : True, "graalCompilerSourceEdition": "ignore", }, From 9688b6792b53cdc91217dde713beb20658da1ba4 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 25 Jan 2024 17:21:59 +0100 Subject: [PATCH 67/75] Patch out Encoding and Transcoder loading using reflection. --- truffle/mx.truffle/suite.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 6000fce99f5e..9f6b7f2027cd 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -1441,7 +1441,13 @@ private static int utf8Decode3ByteSequence(byte[] bytes, int p) { return ((bytes[p] & 0xF) << 12) | ((bytes[p + 1] & 0xff & 0x3f) << 6) | (bytes[p + 2] & 0xff & 0x3f); } -""" +""", + }, + "org/jcodings/Encoding.java" : { + "(public static Encoding load\\([^()]*\\) \\{\\s*)[^{}]*(?:\\{[^{}]*\\}[^{}]*)*(\\s*\\})" : "\\1throw new InternalException(ErrorMessages.ERR_ENCODING_CLASS_DEF_NOT_FOUND, name);\\2" + }, + "org/jcodings/transcode/Transcoder.java" : { + "(public static Transcoder load\\([^()]*\\) \\{\\s*)[^{}]*(?:\\{[^{}]*\\}[^{}]*)*(\\s*\\})" : "\\1throw new InternalException(ErrorMessages.ERR_TRANSCODER_CLASS_DEF_NOT_FOUND, name);\\2" }, }, }, From 1cae029a09e18364541038dab606b757d0b74586 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 25 Jan 2024 17:33:24 +0100 Subject: [PATCH 68/75] Exclude CharsetProvider implementation classes from shadowed jcodings. --- truffle/mx.truffle/suite.py | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 9f6b7f2027cd..ace8901d2226 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -1405,6 +1405,7 @@ "META-INF/MANIFEST.MF", "META-INF/services/java.nio.charset.spi.CharsetProvider", "META-INF/maven/org.jruby.jcodings/jcodings/*", # pom.xml, pom.properties + "org/jcodings/spi/*.java", # CharsetProvider implementation classes (Charsets.java, ISO_8859_16.java) ], "include" : { "tables/*.bin" : { From 81dc9cd2cf4b254e5bc4834c89d429f332cd3bd6 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 25 Jan 2024 18:12:12 +0100 Subject: [PATCH 69/75] Minor JavaDoc change. --- .../src/com/oracle/svm/core/jfr/JfrOptionSet.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java index 9cfc0740c5a5..a4a73eb3eb24 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrOptionSet.java @@ -36,7 +36,7 @@ * Holds all JFR-related options that can be set by the user. It is also used to validate and adjust * the option values as needed. * - * Similar to OpenJDK, the options available by -XX:FlightRecorderOptions cannot be set after JFR is + * Similar to OpenJDK, the options set via -XX:FlightRecorderOptions cannot be changed after JFR is * initialized. This means that after {@link SubstrateJVM#createJFR(boolean)} is called, this class * is no longer needed. * From 682642bbe4cc03f0abbc3528251507c498fef3de Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Wed, 13 Dec 2023 15:53:19 +0100 Subject: [PATCH 70/75] [GR-42882] No longer expose bridge methods in Java host interop. --- .../truffle/api/test/host/VisibilityTest.java | 8 +++--- .../oracle/truffle/host/HostClassDesc.java | 26 +++---------------- 2 files changed, 8 insertions(+), 26 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/VisibilityTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/VisibilityTest.java index 6c1cb9db1790..a769522a6549 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/VisibilityTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/host/VisibilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -256,8 +256,10 @@ public void testStaticMethodNotInherited() throws InteropException { } @Test - public void testPublicClassBridgeMethod() throws InteropException { - invokeRun(new B1(), A3.class); + public void testPublicClassBridgeMethod() { + // GR-42882: public bridge method B1.run() for A3.run() no longer exposed. + // invokeRun(new B1(), A3.class); + Assert.assertFalse(INTEROP.isMemberExisting(asTruffleObject(new B1()), "run")); } @Test diff --git a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassDesc.java b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassDesc.java index 491728fe02bc..4f996de96f18 100644 --- a/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassDesc.java +++ b/truffle/src/com.oracle.truffle.host/src/com/oracle/truffle/host/HostClassDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -217,7 +217,6 @@ private static void collectPublicMethods(HostClassCache hostAccess, Class typ Class startType) { boolean isPublicType = getLookupForPublicClass(type, hostAccess) != null && !Proxy.isProxyClass(type); boolean includeInherited = hostAccess.allowsPublicAccess || hostAccess.allowsAccessInheritance; - List bridgeMethods = null; /** * If we do not allow inheriting access, we discover all accessible methods through the * public methods of this class. That way, (possibly inaccessible) method overrides hide @@ -232,19 +231,8 @@ private static void collectPublicMethods(HostClassCache hostAccess, Class typ } else if (getLookupForPublicClass(declaringClass, hostAccess) == null && !Proxy.isProxyClass(declaringClass)) { // the declaring class and the method itself must be public and accessible continue; - } else if (m.isBridge() && hostAccess.allowsAccess(m)) { - /* - * Bridge methods for varargs methods generated by javac may not have the - * varargs modifier, so we must not use the bridge method in that case since - * it would be then treated as non-varargs. - * - * As a workaround, stash away all bridge methods and only consider them at - * the end if no equivalent public non-bridge method was found. - */ - if (bridgeMethods == null) { - bridgeMethods = new ArrayList<>(); - } - bridgeMethods.add(m); + } else if (m.isBridge()) { + // skip all bridge methods continue; } if (hostAccess.allowsAccess(m)) { @@ -267,14 +255,6 @@ private static void collectPublicMethods(HostClassCache hostAccess, Class typ } } } - // Add bridge methods for public methods inherited from non-public superclasses. - // See https://bugs.openjdk.java.net/browse/JDK-6342411 - if (bridgeMethods != null && !bridgeMethods.isEmpty()) { - for (Method m : bridgeMethods) { - assert hostAccess.allowsAccess(m); // already checked above - collectPublicMethod(hostAccess, methodMap, staticMethodMap, visited, m); - } - } } private static void collectPublicMethod(HostClassCache hostAccess, Map methodMap, Map staticMethodMap, Map visited, Method m) { From 59673355a455c9e6b0adaeb2df4d31590ee2f976 Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 25 Jan 2024 16:12:08 +0100 Subject: [PATCH 71/75] [GR-42882] Update testOverloadedFunctionalMethod() for the new expected behavior around bridge methods. --- .../api/test/polyglot/HostAccessTest.java | 29 +++++++++++-------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java index 54c142d7ae18..8b379ad2add1 100644 --- a/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java +++ b/truffle/src/com.oracle.truffle.api.test/src/com/oracle/truffle/api/test/polyglot/HostAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -978,17 +978,8 @@ public void testOverloadedFunctionalMethod() throws Exception { // when calling a functional interface implementation, only dispatch to implementations of // the single abstract method and not other methods with the same name in the subclass. assertFails(() -> function.execute(42), Exception.class, e -> { - // TODO GR-42882 investigate why this fails differently depending on Java compiler - if (e instanceof PolyglotException) { - // javac - PolyglotException p = (PolyglotException) e; - assertTrue(p.toString(), p.isHostException()); - assertTrue(p.asHostException().toString(), p.asHostException() instanceof ClassCastException); - } else { - // jdt - assertTrue(e instanceof IllegalArgumentException); - assertTrue(e.getMessage(), e.getMessage().contains("Cannot convert '42'(language: Java, type: java.lang.Integer)")); - } + assertTrue(e instanceof IllegalArgumentException); + assertTrue(e.getMessage(), e.getMessage().contains("Cannot convert '42'(language: Java, type: java.lang.Integer)")); }); assertFails(() -> function.execute("ok", "not ok"), IllegalArgumentException.class); @@ -996,6 +987,20 @@ public void testOverloadedFunctionalMethod() throws Exception { assertEquals("ok", function.invokeMember("apply", "ok").asString()); assertEquals(42, function.invokeMember("apply", 42).asInt()); assertEquals("also ok", function.invokeMember("apply", "ok", "also ok").asString()); + + // explicitly invoke overloads using qualified parameter types + for (String methodNameWithParams : new String[]{ + "apply(java.lang.String)", + "apply(int)", + "apply(java.lang.String,java.lang.Object)"}) { + assertTrue(methodNameWithParams, function.canInvokeMember(methodNameWithParams)); + } + assertEquals("ok", function.invokeMember("apply(java.lang.String)", "ok").asString()); + assertEquals(42, function.invokeMember("apply(int)", 42).asInt()); + assertEquals("also ok", function.invokeMember("apply(java.lang.String,java.lang.Object)", "ok", "also ok").asString()); + + // [GR-42882] bridge method apply(Object) for Function.apply(T) not exposed anymore. + assertFalse("apply(java.lang.Object)", function.hasMember("apply(java.lang.Object)")); } static class CountingPredicate implements Predicate { From 5d2878bf4e01ac29304a3ca8ad6f0ddf1aa3662b Mon Sep 17 00:00:00 2001 From: Andreas Woess Date: Thu, 25 Jan 2024 20:00:25 +0100 Subject: [PATCH 72/75] Update truffle changelog. --- truffle/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/truffle/CHANGELOG.md b/truffle/CHANGELOG.md index 7dadce19272c..8b6d339c0980 100644 --- a/truffle/CHANGELOG.md +++ b/truffle/CHANGELOG.md @@ -4,6 +4,7 @@ This changelog summarizes major changes between Truffle versions relevant to lan ## Version 24.1.0 * GR-51253 Extend allowed DynamicObject shape flags from 8 to 16 bits. +* GR-42882 Changed behavior: Java host interop no longer exposes bridge methods. ## Version 24.0.0 From a5bd1fde65b66aca94ab75c3e834b85f007458b7 Mon Sep 17 00:00:00 2001 From: Fabio Niephaus Date: Thu, 25 Jan 2024 11:27:32 +0100 Subject: [PATCH 73/75] Minor edits. --- substratevm/src/com.oracle.svm.agent/README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/substratevm/src/com.oracle.svm.agent/README.md b/substratevm/src/com.oracle.svm.agent/README.md index 5e44254a1903..2589dbe5dd4c 100644 --- a/substratevm/src/com.oracle.svm.agent/README.md +++ b/substratevm/src/com.oracle.svm.agent/README.md @@ -10,9 +10,7 @@ To do that, execute: $ native-image -g --macro:native-image-agent-library ``` -Next, in order to debug the agent, -the java process that runs agent needs to be executed from within GDB, -assuming that the `java` executable is located in the same `JAVA_HOME` as `native-image`, the agent and its debug symbols: +Next, in order to debug the agent, the Java process that runs agent needs to be executed from within GDB, assuming that the `java` executable is located in the same `JAVA_HOME` as `native-image`, the agent and its debug symbols: ```bash $ gdb java --args -agentlib:native-image-agent=config-output-dir=./native-image-config -jar app.jar @@ -51,7 +49,7 @@ Put a breakpoint: Breakpoint 2 at 0x7ffff4cdf550: file com/oracle/svm/agent/NativeImageAgent.java, line 134. ``` -Optionally, disabling `SIGSEGV` signal is recommended to avoid signal handlers that HotSpot uses for safepoints: +Disabling handling `SIGSEGV` signals in the debugger is highly recommended because HotSpot intentionally and frequently uses them for safepoints: ```bash (gdb) handle SIGSEGV nostop noprint From 6c2b6040fcc59bbd01f71169cb8285322c1263ea Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Thu, 25 Jan 2024 21:28:55 +0100 Subject: [PATCH 74/75] Bump the mx version to start compiling with ECJ 3.36. --- common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common.json b/common.json index 6799e780db29..128c7da99adc 100644 --- a/common.json +++ b/common.json @@ -4,7 +4,7 @@ "Jsonnet files should not include this file directly but use ci/common.jsonnet instead." ], - "mx_version": "7.6.1", + "mx_version": "7.7.3", "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { From f24c0490094b65d5e8c9b10486a7c4fc587f9261 Mon Sep 17 00:00:00 2001 From: Jakub Chaloupka Date: Fri, 26 Jan 2024 09:10:13 +0100 Subject: [PATCH 75/75] Fix remaining ECJ warnings. --- .../core/common/type/ArithmeticOpTable.java | 1 + substratevm/mx.substratevm/suite.py | 2 ++ .../svm/core/jdk/DeferredCommonPool.java | 2 +- .../truffle/llvm/runtime/LLVMLanguage.java | 34 +++++++++---------- .../llvm/tests/harness/TestHarness.java | 10 +++--- .../tools/profiler/JoinableExecutors.java | 2 +- truffle/mx.truffle/suite.py | 2 ++ 7 files changed, 29 insertions(+), 24 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java index 7a2ffa20373c..2407b6db9a45 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/type/ArithmeticOpTable.java @@ -917,6 +917,7 @@ public boolean inputCanBeNaN(Stamp inputStamp) { * Determine if this is a floating-point to integer conversion whose result may be outside * the range of the target type. */ + @SuppressWarnings("unused") public boolean canOverflowInteger(Stamp inputStamp) { if (op.getCategory().equals(FloatConvertCategory.FloatingPointToInteger)) { throw GraalError.unimplementedOverride(); diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 509f42ce1483..51fdf8e58150 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -690,6 +690,7 @@ ], }, "javaCompliance" : "22+", + "forceJavac": True, "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", "SVM_PROCESSOR", @@ -718,6 +719,7 @@ ], }, "javaCompliance" : "22+", + "forceJavac": True, "annotationProcessors": [ "compiler:GRAAL_PROCESSOR", "SVM_PROCESSOR", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java index 2c9d09d11564..3286eabd697d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/DeferredCommonPool.java @@ -84,7 +84,7 @@ public ForkJoinTask submit(Runnable task) { return ForkJoinPool.commonPool().submit(task); } - @SuppressWarnings({"unchecked", "static-method"}) + @SuppressWarnings({"unchecked", "static-method", "all"}) public List> invokeAllUninterruptibly(Collection> tasks) { VMError.guarantee(JavaVersionUtil.JAVA_SPEC >= 22, "invokeAllUninterruptibly only exists in JDK 22+"); var m = ReflectionUtil.lookupMethod(ForkJoinPool.class, "invokeAllUninterruptibly", Collection.class); diff --git a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java index d2e96ddb2ce4..73a0bc5d34b6 100644 --- a/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java +++ b/sulong/projects/com.oracle.truffle.llvm.runtime/src/com/oracle/truffle/llvm/runtime/LLVMLanguage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. * * All rights reserved. * @@ -29,6 +29,21 @@ */ package com.oracle.truffle.llvm.runtime; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Function; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Pair; +import org.graalvm.options.OptionDescriptors; +import org.graalvm.options.OptionValues; + import com.oracle.truffle.api.Assumption; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerAsserts; @@ -54,7 +69,6 @@ import com.oracle.truffle.llvm.api.Toolchain; import com.oracle.truffle.llvm.runtime.IDGenerater.BitcodeID; import com.oracle.truffle.llvm.runtime.LLVMContext.TLSInitializerAccess; -import com.oracle.truffle.llvm.runtime.LLVMLanguageFactory.InitializeContextNodeGen; import com.oracle.truffle.llvm.runtime.config.Configuration; import com.oracle.truffle.llvm.runtime.config.Configurations; import com.oracle.truffle.llvm.runtime.config.LLVMCapability; @@ -77,20 +91,6 @@ import com.oracle.truffle.llvm.runtime.pointer.LLVMPointer; import com.oracle.truffle.llvm.runtime.target.TargetTriple; import com.oracle.truffle.llvm.runtime.types.Type; -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Pair; -import org.graalvm.options.OptionDescriptors; -import org.graalvm.options.OptionValues; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Function; @TruffleLanguage.Registration(id = LLVMLanguage.ID, name = LLVMLanguage.NAME, internal = false, interactive = false, defaultMimeType = LLVMLanguage.LLVM_BITCODE_MIME_TYPE, // byteMimeTypes = {LLVMLanguage.LLVM_BITCODE_MIME_TYPE, LLVMLanguage.LLVM_ELF_SHARED_MIME_TYPE, LLVMLanguage.LLVM_ELF_EXEC_MIME_TYPE, LLVMLanguage.LLVM_MACHO_MIME_TYPE, @@ -745,7 +745,7 @@ public LLVMStatementNode createInitializeContextNode() { if (sulongInitContextCode == null) { throw new IllegalStateException("Context cannot be initialized:" + LLVMContext.SULONG_INIT_CONTEXT + " was not found"); } - return InitializeContextNodeGen.create(sulongInitContextCode); + return LLVMLanguageFactory.InitializeContextNodeGen.create(sulongInitContextCode); } /** diff --git a/sulong/tests/com.oracle.truffle.llvm.tests.harness/src/com/oracle/truffle/llvm/tests/harness/TestHarness.java b/sulong/tests/com.oracle.truffle.llvm.tests.harness/src/com/oracle/truffle/llvm/tests/harness/TestHarness.java index 4911abd9345a..63e376bb5a7e 100644 --- a/sulong/tests/com.oracle.truffle.llvm.tests.harness/src/com/oracle/truffle/llvm/tests/harness/TestHarness.java +++ b/sulong/tests/com.oracle.truffle.llvm.tests.harness/src/com/oracle/truffle/llvm/tests/harness/TestHarness.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. * * All rights reserved. * @@ -38,15 +38,15 @@ import java.util.Map; import java.util.TreeMap; -import com.oracle.truffle.llvm.tests.pipe.CaptureNativeOutput; - import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Context.Builder; import org.graalvm.polyglot.Engine; import org.graalvm.polyglot.Source; import org.graalvm.polyglot.Value; -import org.graalvm.polyglot.Context.Builder; import org.junit.Assert; +import com.oracle.truffle.llvm.tests.pipe.CaptureNativeOutput; + public class TestHarness { private static Engine testEngine = Engine.newBuilder().allowExperimentalOptions(true).build(); @@ -76,7 +76,7 @@ private static int runBitcode(File bitcodeFile, String[] args, Map()); + return runBitcode(bitcodeFile, args, new TreeMap<>()); } private static void run(String[] runargs) throws IOException { diff --git a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/JoinableExecutors.java b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/JoinableExecutors.java index 3c3040fc95ba..1c455d0afa63 100644 --- a/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/JoinableExecutors.java +++ b/tools/src/com.oracle.truffle.tools.profiler/src/com/oracle/truffle/tools/profiler/JoinableExecutors.java @@ -43,7 +43,7 @@ private JoinableExecutors() { static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new JoinableThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, - new LinkedBlockingQueue(), + new LinkedBlockingQueue<>(), threadFactory); } diff --git a/truffle/mx.truffle/suite.py b/truffle/mx.truffle/suite.py index 1b27d87f08d6..624f4649eb59 100644 --- a/truffle/mx.truffle/suite.py +++ b/truffle/mx.truffle/suite.py @@ -906,6 +906,7 @@ ], "checkstyle" : "com.oracle.truffle.api", "javaCompliance" : "22+", + "forceJavac": True, "annotationProcessors" : ["TRUFFLE_DSL_PROCESSOR"], "workingSets" : "Truffle", # disable SpotBugs and Jacoco as long as JDK 22 is unsupported [GR-49566] @@ -1826,6 +1827,7 @@ }, "subDir" : "src", "javaCompliance" : "22+", + "forceJavac": True, "dependencies" : [ "com.oracle.truffle.nfi.backend.panama", ],