From 8f89c3d8cca01167ac57bfc0f972594e9cff054d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 15 Sep 2025 09:34:50 +0200 Subject: [PATCH 01/49] Revert "[GR-69145] Update labsjdk to 26+13-jvmci-b01" This reverts commit 451808a29a04f07268e741e69382fea1ad9212d5, reversing changes made to c331944f938a7dadd6b6158ed728350984ac37ce. --- common.json | 14 +- .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- ...get_jdk_internal_reflect_ConstantPool.java | 171 ++++++++++++ .../espresso/substitutions/VersionFilter.java | 12 - ...get_jdk_internal_reflect_ConstantPool.java | 254 ------------------ .../com/oracle/truffle/espresso/vm/VM.java | 35 +-- .../svm/core/amd64/AMD64LibCHelper.java | 6 +- .../svm/core/container/ContainerLibrary.java | 2 +- ...arget_sun_nio_fs_UnixNativeDispatcher.java | 55 ---- .../src/UnixNativeDispatcherHelper.c | 48 ---- .../include/amd64cpufeatures.h | 1 - .../include/amd64hotspotcpuinfo.h | 7 +- .../src/cpuid.c | 7 +- 13 files changed, 200 insertions(+), 416 deletions(-) create mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_ConstantPool.java delete mode 100644 espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_jdk_internal_reflect_ConstantPool.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_sun_nio_fs_UnixNativeDispatcher.java delete mode 100644 substratevm/src/com.oracle.svm.native.jvm.posix/src/UnixNativeDispatcherHelper.c diff --git a/common.json b/common.json index 3f88e17674a6..7a9d6bf5a8dc 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+13", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+13-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+13-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+13-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+13-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+13-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+13-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+12", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 08555caffa09..23b6ec572f0c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+13", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+13", 1))); + "Oracle Corporation", createLabsJDKVersion("26+12", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+12", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_ConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_ConstantPool.java new file mode 100644 index 000000000000..676de96822f0 --- /dev/null +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_ConstantPool.java @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.espresso.libs.libjava.impl; + +import java.lang.reflect.Field; +import java.lang.reflect.Member; + +import com.oracle.truffle.espresso.libs.libjava.LibJava; +import com.oracle.truffle.espresso.meta.Meta; +import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; +import com.oracle.truffle.espresso.substitutions.EspressoSubstitutions; +import com.oracle.truffle.espresso.substitutions.Inject; +import com.oracle.truffle.espresso.substitutions.JavaSubstitution; +import com.oracle.truffle.espresso.substitutions.JavaType; +import com.oracle.truffle.espresso.substitutions.Substitution; +import com.oracle.truffle.espresso.substitutions.SubstitutionProfiler; +import com.oracle.truffle.espresso.vm.VM; + +@EspressoSubstitutions(type = "Ljdk/internal/reflect/ConstantPool;", group = LibJava.class) +public final class Target_jdk_internal_reflect_ConstantPool { + @Substitution(hasReceiver = true) + public static int getSize0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, @Inject VM vm) { + return vm.JVM_ConstantPoolGetSize(unused, jcpool); + } + + @Substitution(hasReceiver = true) + public static @JavaType(Class.class) StaticObject getClassAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetClassAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(Class.class) StaticObject getClassAtIfLoaded0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static int getClassRefIndexAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(Member.class) StaticObject getMethodAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(Member.class) StaticObject getMethodAtIfLoaded0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(Field.class) StaticObject getFieldAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(Field.class) StaticObject getFieldAtIfLoaded0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(String[].class) StaticObject getMemberRefInfoAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static int getNameAndTypeRefIndexAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static @JavaType(String[].class) StaticObject getNameAndTypeRefInfoAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } + + @Substitution(hasReceiver = true) + public static int getIntAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetIntAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + public static long getLongAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetLongAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + public static float getFloatAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetFloatAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + public static double getDoubleAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetDoubleAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + public static @JavaType(String.class) StaticObject getStringAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetStringAt(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + public static @JavaType(String.class) StaticObject getUTF8At0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, + @Inject VM vm, + @Inject Meta meta, + @Inject SubstitutionProfiler profiler) { + return vm.JVM_ConstantPoolGetUTF8At(unused, jcpool, index, meta, profiler); + } + + @Substitution(hasReceiver = true) + @SuppressWarnings("unused") + public static byte getTagAt0(@JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { + throw JavaSubstitution.unimplemented(); + + } +} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java index e5058028c170..607fda3739ef 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java @@ -237,16 +237,4 @@ public boolean isValidFor(JavaVersion version) { return version.java25OrEarlier(); } } - - final class Java26OrLater implements VersionFilter { - public static final Java26OrLater INSTANCE = new Java26OrLater(); - - private Java26OrLater() { - } - - @Override - public boolean isValidFor(JavaVersion version) { - return version.java26OrLater(); - } - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_jdk_internal_reflect_ConstantPool.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_jdk_internal_reflect_ConstantPool.java deleted file mode 100644 index cc4b6bb8429b..000000000000 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_jdk_internal_reflect_ConstantPool.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.truffle.espresso.substitutions.standard; - -import java.lang.reflect.Field; -import java.lang.reflect.Member; - -import com.oracle.truffle.espresso.meta.Meta; -import com.oracle.truffle.espresso.runtime.staticobject.StaticObject; -import com.oracle.truffle.espresso.substitutions.EspressoSubstitutions; -import com.oracle.truffle.espresso.substitutions.Inject; -import com.oracle.truffle.espresso.substitutions.JavaSubstitution; -import com.oracle.truffle.espresso.substitutions.JavaType; -import com.oracle.truffle.espresso.substitutions.Substitution; -import com.oracle.truffle.espresso.substitutions.SubstitutionProfiler; -import com.oracle.truffle.espresso.substitutions.VersionFilter; -import com.oracle.truffle.espresso.vm.VM; - -@EspressoSubstitutions -public final class Target_jdk_internal_reflect_ConstantPool { - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static int getSize0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, @Inject VM vm) { - return vm.JVM_ConstantPoolGetSize(unused, jcpool); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static int getSize0(StaticObject self, @Inject VM vm, @Inject Meta meta) { - return vm.JVM_ConstantPoolGetSize(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self)); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static @JavaType(Class.class) StaticObject getClassAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetClassAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static @JavaType(Class.class) StaticObject getClassAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetClassAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(Class.class) StaticObject getClassAtIfLoaded0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(Class.class) StaticObject getClassAtIfLoaded0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static int getClassRefIndexAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static int getClassRefIndexAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(Member.class) StaticObject getMethodAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(Member.class) StaticObject getMethodAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(Member.class) StaticObject getMethodAtIfLoaded0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(Member.class) StaticObject getMethodAtIfLoaded0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(Field.class) StaticObject getFieldAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(Field.class) StaticObject getFieldAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(Field.class) StaticObject getFieldAtIfLoaded0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(Field.class) StaticObject getFieldAtIfLoaded0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(String[].class) StaticObject getMemberRefInfoAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(String[].class) StaticObject getMemberRefInfoAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static int getNameAndTypeRefIndexAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static int getNameAndTypeRefIndexAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static @JavaType(String[].class) StaticObject getNameAndTypeRefInfoAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static @JavaType(String[].class) StaticObject getNameAndTypeRefInfoAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static int getIntAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetIntAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static int getIntAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetIntAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static long getLongAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetLongAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static long getLongAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetLongAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static float getFloatAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetFloatAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static float getFloatAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetFloatAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static double getDoubleAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetDoubleAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static double getDoubleAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetDoubleAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static @JavaType(String.class) StaticObject getStringAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetStringAt(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static @JavaType(String.class) StaticObject getStringAt0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetStringAt(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - public static @JavaType(String.class) StaticObject getUTF8At0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetUTF8At(unused, jcpool, index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - public static @JavaType(String.class) StaticObject getUTF8At0(StaticObject self, int index, - @Inject VM vm, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - return vm.JVM_ConstantPoolGetUTF8At(null, meta.sun_reflect_ConstantPool_constantPoolOop.getObject(self), index, meta, profiler); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java25OrEarlier.class) - @SuppressWarnings("unused") - public static byte getTagAt0(StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index) { - throw JavaSubstitution.unimplemented(); - } - - @Substitution(hasReceiver = true, languageFilter = VersionFilter.Java26OrLater.class) - @SuppressWarnings("unused") - public static byte getTagAt0(StaticObject self, int index) { - throw JavaSubstitution.unimplemented(); - } -} diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index 3480e81765bc..322d124c151b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -1896,59 +1896,52 @@ public int JVM_ConstantPoolGetSize(@SuppressWarnings("unused") @JavaType(Object. public @JavaType(Class.class) StaticObject JVM_ConstantPoolGetClassAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.CLASS, meta, profiler); - return constantPool.resolvedKlassAt(null, index).mirror(); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.CLASS, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().resolvedKlassAt(null, index).mirror(); } @VmImpl(isJni = true) public double JVM_ConstantPoolGetDoubleAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.DOUBLE, meta, profiler); - return constantPool.doubleAt(index); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.DOUBLE, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().doubleAt(index); } @VmImpl(isJni = true) public float JVM_ConstantPoolGetFloatAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.FLOAT, meta, profiler); - return constantPool.floatAt(index); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.FLOAT, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().floatAt(index); } @VmImpl(isJni = true) public @JavaType(String.class) StaticObject JVM_ConstantPoolGetStringAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.STRING, meta, profiler); - return constantPool.resolvedStringAt(index); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.STRING, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().resolvedStringAt(index); } @VmImpl(isJni = true) public @JavaType(String.class) StaticObject JVM_ConstantPoolGetUTF8At(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.UTF8, meta, profiler); - return getMeta().toGuestString(constantPool.utf8At(index).toString()); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.UTF8, meta, profiler); + return getMeta().toGuestString(jcpool.getMirrorKlass(getMeta()).getConstantPool().utf8At(index).toString()); } @VmImpl(isJni = true) public int JVM_ConstantPoolGetIntAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.INTEGER, meta, profiler); - return constantPool.intAt(index); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.INTEGER, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().intAt(index); } @VmImpl(isJni = true) public long JVM_ConstantPoolGetLongAt(@SuppressWarnings("unused") @JavaType(Object.class) StaticObject unused, @JavaType(Object.class) StaticObject jcpool, int index, @Inject Meta meta, @Inject SubstitutionProfiler profiler) { - RuntimeConstantPool constantPool = jcpool.getMirrorKlass(getMeta()).getConstantPool(); - checkTag(constantPool, index, ConstantPool.Tag.LONG, meta, profiler); - return constantPool.longAt(index); + checkTag(jcpool.getMirrorKlass(getMeta()).getConstantPool(), index, ConstantPool.Tag.LONG, meta, profiler); + return jcpool.getMirrorKlass(getMeta()).getConstantPool().longAt(index); } // endregion ConstantPool diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java index 151cc44fca00..53e493159002 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/amd64/AMD64LibCHelper.java @@ -43,7 +43,7 @@ * - substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h * - substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c */ -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+13/src/hotspot/cpu/x86/vm_version_x86.hpp#L43-L351") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/cpu/x86/vm_version_x86.hpp#L41-L348") @CLibrary(value = "libchelper", requireStatic = true) public class AMD64LibCHelper { @Platforms(Platform.AMD64.class) @@ -322,10 +322,6 @@ public interface CPUFeatures extends PointerBase { @AllowNarrowingCast @CField boolean fAVX10_2(); - - @AllowNarrowingCast - @CField - boolean fHYBRID(); } // Checkstyle: resume } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 0d699114aaf2..81640730cea8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -84,7 +84,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+11/src/hotspot/share/utilities/ostream.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/permitForbiddenFunctions.hpp") // The following annotations are for files in `src/svm`, which are completely customized for SVM -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+13/src/hotspot/share/logging/log.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+12/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/debug.cpp") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_sun_nio_fs_UnixNativeDispatcher.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_sun_nio_fs_UnixNativeDispatcher.java deleted file mode 100644 index 88b2a910cf68..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_sun_nio_fs_UnixNativeDispatcher.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.jdk; - -import static com.oracle.svm.core.jdk.Helper_sun_nio_fs_UnixNativeDispatcher.init1; - -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.annotate.TargetClass; - -@TargetClass(className = "sun.nio.fs.UnixNativeDispatcher", onlyWith = NonWindowsOS.class) -final class Target_sun_nio_fs_UnixNativeDispatcher { - - /** - * Wraps the original native {@code init()} call with a pthread mutex. This is a workaround for - * GR-69415. The assumption is that there is a race condition when multiple isolates call the - * static initializer of {@code UnixNativeDispatcher} and thus the native {@code init} function - * concurrently. All those calls operate on the same global C variables so multiple isolates can - * interfere with each other. - */ - @Substitute - static int init() { - return init1(Target_sun_nio_fs_UnixNativeDispatcher.class); - } -} - -final class Helper_sun_nio_fs_UnixNativeDispatcher { - /** - * A C-level thread-safe wrapper for the original - * {@link Target_sun_nio_fs_UnixNativeDispatcher#init()}. Implementation is in - * {@code UnixNativeDispatcher.c}. - */ - static native int init1(Class targetSunNioFsUnixNativeDispatcherClass); -} diff --git a/substratevm/src/com.oracle.svm.native.jvm.posix/src/UnixNativeDispatcherHelper.c b/substratevm/src/com.oracle.svm.native.jvm.posix/src/UnixNativeDispatcherHelper.c deleted file mode 100644 index df88b8ab73c7..000000000000 --- a/substratevm/src/com.oracle.svm.native.jvm.posix/src/UnixNativeDispatcherHelper.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include - -// The original init function -jint JNICALL Java_sun_nio_fs_UnixNativeDispatcher_init(JNIEnv* env, jclass this); - -// cached capabilities -static jint capabilities = 0; - -// Global/static initialization flag and mutex -static jboolean initialized = JNI_FALSE; -static pthread_mutex_t init_mutex = PTHREAD_MUTEX_INITIALIZER; - -JNIEXPORT jint JNICALL Java_com_oracle_svm_core_jdk_Helper_1sun_1nio_1fs_1UnixNativeDispatcher_init1(JNIEnv* env, jclass this, jclass unixNativeDispatcherClass) { - pthread_mutex_lock(&init_mutex); - if (initialized == JNI_FALSE) { - capabilities = Java_sun_nio_fs_UnixNativeDispatcher_init(env, unixNativeDispatcherClass); - // initialization done - initialized = JNI_TRUE; - } - pthread_mutex_unlock(&init_mutex); - return capabilities; -} diff --git a/substratevm/src/com.oracle.svm.native.libchelper/include/amd64cpufeatures.h b/substratevm/src/com.oracle.svm.native.libchelper/include/amd64cpufeatures.h index dfbe6f46555f..e975876cb771 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/include/amd64cpufeatures.h +++ b/substratevm/src/com.oracle.svm.native.libchelper/include/amd64cpufeatures.h @@ -91,5 +91,4 @@ typedef struct { uint8_t fAVX512_FP16; uint8_t fAVX10_1; uint8_t fAVX10_2; - uint8_t fHYBRID; } CPUFeatures; diff --git a/substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h b/substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h index 687aa4e1bd8f..92f2b08be7ca 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h +++ b/substratevm/src/com.oracle.svm.native.libchelper/include/amd64hotspotcpuinfo.h @@ -188,8 +188,8 @@ typedef union { typedef union { uint32_t value; struct { - uint32_t threads_per_cpu : 8, - : 24; + uint32_t cores_per_cpu : 8, + : 24; } bits; } ExtCpuid8Ecx; @@ -265,8 +265,7 @@ typedef union { fast_short_rep_mov : 1, : 9, serialize : 1, - hybrid : 1, - : 4, + : 5, cet_ibt : 1, : 2, avx512_fp16 : 1, diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c index c2f8f09cd190..2316e248fc02 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c @@ -211,10 +211,7 @@ static uint32_t cores_per_cpu(CpuidInfo *_cpuid_info) { } else if (is_amd_family(_cpuid_info)) { - result = _cpuid_info->ext_cpuid8_ecx.bits.threads_per_cpu + 1; - if (cpu_family(_cpuid_info) >= 0x17) { // Zen or later - result /= _cpuid_info->ext_cpuid1E_ebx.bits.threads_per_core + 1; - } + result = (_cpuid_info->ext_cpuid8_ecx.bits.cores_per_cpu + 1); } else if (is_zx(_cpuid_info)) { @@ -580,8 +577,6 @@ NO_INLINE static void set_cpufeatures(CPUFeatures *features, CpuidInfo *_cpuid_i { if (_cpuid_info->sef_cpuid7_edx.bits.serialize != 0) features->fSERIALIZE = 1; - if (_cpuid_info->sef_cpuid7_edx.bits.hybrid != 0) - features->fHYBRID = 1; if (_cpuid_info->sef_cpuid7_edx.bits.avx512_fp16 != 0) features->fAVX512_FP16 = 1; } From 01e817884ef515b1e191ccc72f4aa6a08f27e59b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 15 Sep 2025 09:57:54 +0200 Subject: [PATCH 02/49] Revert "[GR-68961] Update labsjdk to 26+12-jvmci-b01" This reverts commit 2a65da51f0d03aab0f5ec14877c1310019d007f7, reversing changes made to 58ebbc8cc57a46f31979a8a4604df7e8e165b8b6. --- common.json | 14 +++++++------- .../replacements/test/EncodeArrayTest.java | 6 +++--- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../replacements/StandardGraphBuilderPlugins.java | 15 +++++++++++---- .../svm/core/container/ContainerLibrary.java | 4 ++-- 5 files changed, 25 insertions(+), 18 deletions(-) diff --git a/common.json b/common.json index 7a9d6bf5a8dc..217f81c370d4 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+12", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+12-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+12-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+11", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/EncodeArrayTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/EncodeArrayTest.java index adb88f18167a..2369450f5be4 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/EncodeArrayTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/EncodeArrayTest.java @@ -67,7 +67,7 @@ private static Result executeCompiledMethod(InstalledCode compiledMethod, Object @Test public void testStringCodingISO() throws ClassNotFoundException { Class klass = Class.forName("java.lang.StringCoding"); - ResolvedJavaMethod method = getResolvedJavaMethod(klass, "encodeISOArray0"); + ResolvedJavaMethod method = getResolvedJavaMethod(klass, "implEncodeISOArray"); StructuredGraph graph = getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), StructuredGraph.AllowAssumptions.YES, null); InstalledCode compiledMethod = getCode(method, graph); @@ -100,7 +100,7 @@ public void testStringCodingISO() throws ClassNotFoundException { @Test public void testStringCodingAscii() throws ClassNotFoundException { Class klass = Class.forName("java.lang.StringCoding"); - ResolvedJavaMethod method = getResolvedJavaMethod(klass, "encodeAsciiArray0"); + ResolvedJavaMethod method = getResolvedJavaMethod(klass, "implEncodeAsciiArray"); StructuredGraph graph = getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), StructuredGraph.AllowAssumptions.YES, null); InstalledCode compiledMethod = getCode(method, graph); @@ -133,7 +133,7 @@ public void testStringCodingAscii() throws ClassNotFoundException { @Test public void testISOEncoding() throws ClassNotFoundException { Class klass = Class.forName("sun.nio.cs.ISO_8859_1$Encoder"); - ResolvedJavaMethod method = getResolvedJavaMethod(klass, "encodeISOArray0"); + ResolvedJavaMethod method = getResolvedJavaMethod(klass, "implEncodeISOArray"); StructuredGraph graph = getIntrinsicGraph(method, CompilationIdentifier.INVALID_COMPILATION_ID, getDebugContext(), StructuredGraph.AllowAssumptions.YES, null); InstalledCode compiledMethod = getCode(method, graph); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 23b6ec572f0c..d82f1ab33e94 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+12", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+12", 1))); + "Oracle Corporation", createLabsJDKVersion("26+11", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+11", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java index 7c509daa6c64..ec6c03dc0365 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/StandardGraphBuilderPlugins.java @@ -2622,7 +2622,7 @@ public boolean isApplicable(Architecture arch) { private static void registerStringCodingPlugins(InvocationPlugins plugins) { Registration r = new Registration(plugins, "java.lang.StringCoding"); - r.register(new InvocationPlugin("encodeISOArray0", byte[].class, int.class, byte[].class, int.class, int.class) { + r.register(new InvocationPlugin("implEncodeISOArray", byte[].class, int.class, byte[].class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode sa, ValueNode sp, ValueNode da, ValueNode dp, ValueNode len) { @@ -2635,7 +2635,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } } }); - r.register(new InvocationPlugin("encodeAsciiArray0", char[].class, int.class, byte[].class, int.class, int.class) { + r.register(new InvocationPlugin("implEncodeAsciiArray", char[].class, int.class, byte[].class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode sa, ValueNode sp, ValueNode da, ValueNode dp, ValueNode len) { @@ -2647,10 +2647,17 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec } } }); - r.register(new InvocationPlugin("countPositives0", byte[].class, int.class, int.class) { + r.register(new InvocationPlugin("countPositives", byte[].class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode ba, ValueNode off, ValueNode len) { try (InvocationPluginHelper helper = new InvocationPluginHelper(b, targetMethod)) { + helper.intrinsicRangeCheck(off, Condition.LT, ConstantNode.forInt(0)); + helper.intrinsicRangeCheck(len, Condition.LT, ConstantNode.forInt(0)); + + ValueNode arrayLength = b.add(new ArrayLengthNode(ba)); + ValueNode limit = b.add(AddNode.create(off, len, NodeView.DEFAULT)); + helper.intrinsicRangeCheck(arrayLength, Condition.LT, limit); + ValueNode array = helper.arrayElementPointer(ba, JavaKind.Byte, off); b.addPush(JavaKind.Int, new CountPositivesNode(array, len)); return true; @@ -2659,7 +2666,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec }); r = new Registration(plugins, "sun.nio.cs.ISO_8859_1$Encoder"); - r.register(new InvocationPlugin("encodeISOArray0", char[].class, int.class, byte[].class, int.class, int.class) { + r.register(new InvocationPlugin("implEncodeISOArray", char[].class, int.class, byte[].class, int.class, int.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode sa, ValueNode sp, ValueNode da, ValueNode dp, ValueNode len) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 81640730cea8..0c7d04d1d94e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -71,7 +71,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allStatic.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/nmt/memTag.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+12/src/hotspot/share/runtime/os.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/os.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/runtime/os.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") @@ -86,7 +86,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+12/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { From 940d2b2d2f96863ee725beb2570f433ba715994d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 15 Sep 2025 10:16:04 +0200 Subject: [PATCH 03/49] Revert "[GR-68735] Update labsjdk to 26+11-jvmci-b01" This reverts commit 0008303b74a410346b58c9b1ca4d6ef45ba4f711, reversing changes made to 2385a9691e7937c0f4eb5e29caa38c946d7255a6. --- common.json | 16 ++++++------ .../compiler/hotspot/JVMCIVersionCheck.java | 4 +-- .../standard/Target_sun_misc_Unsafe.java | 26 ------------------- .../svm/core/container/ContainerLibrary.java | 6 ++--- .../heap/Target_java_nio_BufferCleaner.java | 6 ++--- .../oracle/svm/core/jdk/RecomputedFields.java | 9 ------- .../svm/core/jdk/SunMiscSubstitutions.java | 2 +- .../com/oracle/svm/driver/NativeImage.java | 2 +- 8 files changed, 18 insertions(+), 53 deletions(-) diff --git a/common.json b/common.json index 217f81c370d4..b82135fdd17f 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+11-1117", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+10-1012", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+11", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+11-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+11-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+10", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index d82f1ab33e94..cc708e9b8f3b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+11", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+11", 1))); + "Oracle Corporation", createLabsJDKVersion("26+10", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+10", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java index 3b851cfd4989..d65e0de44e1b 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/standard/Target_sun_misc_Unsafe.java @@ -913,32 +913,6 @@ public static long objectFieldOffset1(@JavaType(Unsafe.class) StaticObject self, throw meta.throwException(meta.java_lang_InternalError); } - @Substitution(hasReceiver = true, nameProvider = Unsafe11.class) - static long knownObjectFieldOffset0(@SuppressWarnings("unused") StaticObject self, @JavaType(Class.class) StaticObject c, @JavaType(String.class) StaticObject guestName, - @Inject Meta meta, @Inject EspressoLanguage language) { - // Error code -1 is not found, -2 is static field - Klass k = c.getMirrorKlass(meta); - if (!(k instanceof ObjectKlass kl)) { - return -1; - } - String hostName = meta.toHostString(guestName); - Symbol name = meta.getNames().lookup(hostName); - if (name == null) { - return -1; - } - for (Field f : kl.getFieldTable()) { - if (!f.isRemoved() && f.getName() == name) { - return getGuestFieldOffset(f, language); - } - } - for (Field f : kl.getStaticFieldTable()) { - if (!f.isRemoved() && f.getName() == name) { - return -2; - } - } - return -1; - } - // region UnsafeAccessors @GenerateInline diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 0c7d04d1d94e..52517c20f395 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -60,7 +60,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+11/src/hotspot/os/linux/os_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/os/linux/os_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") @@ -78,10 +78,10 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+11/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/utilities/globalDefinitions.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+11/src/hotspot/share/utilities/ostream.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/permitForbiddenFunctions.hpp") // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java index 802856ef2ba6..e796e8d115d2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java @@ -43,11 +43,11 @@ public final class Target_java_nio_BufferCleaner { static ReferenceQueue queue; @Alias // @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // - static Thread cleaningThread; + static Target_java_nio_BufferCleaner_CleaningThread cleaningThread; } -@TargetClass(className = "java.nio.BufferCleaner", innerClass = "CleaningRunnable") -final class Target_java_nio_BufferCleaner_CleaningRunnable { +@TargetClass(className = "java.nio.BufferCleaner", innerClass = "CleaningThread") +final class Target_java_nio_BufferCleaner_CleaningThread { @SuppressWarnings("static-method") @Substitute public void run() { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java index 9a9358b81ca3..721b4867c78e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/RecomputedFields.java @@ -104,9 +104,6 @@ final class Target_java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Atomi if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - if (Modifier.isStatic(modifiers)) - throw new IllegalArgumentException("Must not be a static field"); - // access checks are disabled this.cclass = tclass; this.tclass = tclass; @@ -145,9 +142,6 @@ final class Target_java_util_concurrent_atomic_AtomicIntegerFieldUpdater_AtomicI if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - if (Modifier.isStatic(modifiers)) - throw new IllegalArgumentException("Must not be a static field"); - // access checks are disabled this.cclass = tclass; this.tclass = tclass; @@ -185,9 +179,6 @@ final class Target_java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater if (!Modifier.isVolatile(modifiers)) throw new IllegalArgumentException("Must be volatile type"); - if (Modifier.isStatic(modifiers)) - throw new IllegalArgumentException("Must not be a static field"); - // access checks are disabled this.cclass = tclass; this.tclass = tclass; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java index 683bd71d02fc..709bebde4abf 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java @@ -166,7 +166,7 @@ public Object getUncompressedObject(long address) { private native long objectFieldOffset0(Field f); @Delete - private native long knownObjectFieldOffset0(Class c, String name); + private native long objectFieldOffset1(Class c, String name); @Delete private native long staticFieldOffset0(Field f); 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 8989d33dbf88..f12c73108354 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 @@ -1969,7 +1969,7 @@ private Set getBuiltInModules() { Path jdkRoot = config.rootDir; try { var reader = ImageReader.open(jdkRoot.resolve("lib/modules")); - return new LinkedHashSet<>(reader.findNode("/modules").getChildNames().map(s -> s.substring("/modules/".length())).toList()); + return new LinkedHashSet<>(List.of(reader.getModuleNames())); } catch (IOException e) { throw showError("Unable to determine builtin modules of JDK in " + jdkRoot, e); } From b20d0dfb1dd3be70e36b879e015f0cf4907bcf61 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 15 Sep 2025 11:42:39 +0200 Subject: [PATCH 04/49] Revert "[GR-68712] Port Math.sinh stub on x64" This reverts commit e5276df8ae72af4407c80395ed873fb3fd416fa7, reversing changes made to 1c92b92c6127f1a305672be0d4825388efab992a. --- .../replacements/test/MathSinhTest.java | 49 -- .../test/StandardMethodSubstitutionsTest.java | 8 - .../compiler/asm/amd64/AMD64Assembler.java | 28 +- .../amd64/AMD64ArithmeticLIRGenerator.java | 6 - .../hotspot/GraalHotSpotVMConfig.java | 1 - .../AMD64HotSpotForeignCallsProvider.java | 2 - .../compiler/hotspot/amd64/AMD64MathStub.java | 6 - .../meta/HotSpotHostForeignCallsProvider.java | 4 - .../meta/UnimplementedGraalIntrinsics.java | 4 +- .../compiler/lir/amd64/AMD64MathSinhOp.java | 593 ------------------ .../lir/gen/ArithmeticLIRGeneratorTool.java | 5 - .../amd64/AMD64GraphBuilderPlugins.java | 2 - .../nodes/UnaryMathIntrinsicNode.java | 4 - .../svm/core/snippets/SnippetRuntime.java | 5 +- .../svm/hosted/webimage/wasm/WasmImports.java | 1 - .../wasm/codegen/WebImageWasmNodeLowerer.java | 1 - .../wasm/codegen/runtime/wasm-bootstrap.js | 1 - 17 files changed, 13 insertions(+), 707 deletions(-) delete mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathSinhTest.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathSinhOp.java diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathSinhTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathSinhTest.java deleted file mode 100644 index 9c35be8ec6f3..000000000000 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/MathSinhTest.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.replacements.test; - -import org.junit.Test; - -import jdk.graal.compiler.jtt.JTTTest; - -public class MathSinhTest extends JTTTest { - - public double sinh(double d) { - return Math.sinh(d); - } - - @Test - public void testSinh() { - for (double d = -3.0d; d <= 3.0D; d += 0.01D) { - test("sinh", d); - } - - double[] inputs = {Math.PI / 2, Math.PI, -1.0D, Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, - Double.longBitsToDouble(0x7fffffffffffffffL), Double.longBitsToDouble(0xffffffffffffffffL)}; - for (double d : inputs) { - test("sinh", d); - } - } -} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java index 991b646ad29f..97e5697fac42 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/StandardMethodSubstitutionsTest.java @@ -60,9 +60,6 @@ public void testMathSubstitutions() { testGraph("mathSqrt"); testGraph("mathTan"); testGraph("mathAll"); - if (getReplacements().hasSubstitution(getResolvedJavaMethod(Math.class, "sinh"), getInitialOptions())) { - testGraph("mathSinh"); - } if (getReplacements().hasSubstitution(getResolvedJavaMethod(Math.class, "tanh"), getInitialOptions())) { testGraph("mathTanh"); } @@ -75,7 +72,6 @@ public void testMathSubstitutions() { test("mathLog", value); test("mathLog10", value); test("mathSin", value); - test("mathSinh", value); test("mathSqrt", value); test("mathTan", value); test("mathTanh", value); @@ -137,10 +133,6 @@ public static double mathSin(double value) { return Math.sin(value); } - public static double mathSinh(double value) { - return Math.sinh(value); - } - public static double mathCos(double value) { return Math.cos(value); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java index b8c005ff315e..01d8941166ce 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64Assembler.java @@ -950,24 +950,22 @@ public final void emit(AMD64Assembler asm, OperandSize size, Register dst, int i public static class SSERMIOp extends AMD64RMIOp { // @formatter:off - public static final SSERMIOp ROUNDSS = new SSERMIOp("ROUNDSS", true, P_0F3A, 0x0A, PreferredNDS.SRC, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); - public static final SSERMIOp ROUNDSD = new SSERMIOp("ROUNDSD", true, P_0F3A, 0x0B, PreferredNDS.SRC, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); + public static final SSERMIOp ROUNDSS = new SSERMIOp("ROUNDSS", true, P_0F3A, 0x0A, PreferredNDS.SRC, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); + public static final SSERMIOp ROUNDSD = new SSERMIOp("ROUNDSD", true, P_0F3A, 0x0B, PreferredNDS.SRC, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); - public static final SSERMIOp PCMPESTRI = new SSERMIOp("PCMPESTRI", true, P_0F3A, 0x61, PreferredNDS.NONE, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_2); - public static final SSERMIOp PCLMULQDQ = new SSERMIOp("PCLMULQDQ", true, P_0F3A, 0x44, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.CLMUL); - public static final SSERMIOp GF2P8AFFINEQB = new SSERMIOp("GF2P8AFFINEQB", true, P_0F3A, true, 0xCE, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.GFNI); + public static final SSERMIOp PCMPESTRI = new SSERMIOp("PCMPESTRI", true, P_0F3A, 0x61, PreferredNDS.NONE, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_2); + public static final SSERMIOp PCLMULQDQ = new SSERMIOp("PCLMULQDQ", true, P_0F3A, 0x44, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.CLMUL); + public static final SSERMIOp GF2P8AFFINEQB = new SSERMIOp("GF2P8AFFINEQB", true, P_0F3A, true, 0xCE, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.GFNI); public static final SSERMIOp PINSRB = new SSERMIOp("PINSRB", true, P_0F3A, 0x20, PreferredNDS.DST, OpAssertion.PackedDoubleIntToFloatAssertion, CPUFeature.SSE4_1); public static final SSERMIOp PINSRW = new SSERMIOp("PINSRW", true, P_0F, 0xC4, PreferredNDS.DST, OpAssertion.PackedDoubleIntToFloatAssertion, CPUFeature.SSE2); public static final SSERMIOp PINSRD = new SSERMIOp("PINSRD", true, P_0F3A, 0x22, PreferredNDS.DST, OpAssertion.PackedDoubleIntToFloatAssertion, CPUFeature.SSE4_1); public static final SSERMIOp PINSRQ = new SSERMIOp("PINSRQ", true, P_0F3A, true, 0x22, PreferredNDS.DST, OpAssertion.PackedDoubleIntToFloatAssertion, CPUFeature.SSE4_1); - public static final SSERMIOp PALIGNR = new SSERMIOp("PALIGNR", true, P_0F3A, 0x0F, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.SSSE3); - public static final SSERMIOp PBLENDW = new SSERMIOp("PBLENDW", true, P_0F3A, 0x0E, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); - public static final SSERMIOp PSHUFD = new SSERMIOp("PSHUFD", true, P_0F, 0x70, PreferredNDS.NONE, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE2); - public static final SSERMIOp PSHUFLW = new SSERMIOp("PSHUFLW", true, P_0F, 0x70, PreferredNDS.NONE, OpAssertion.DoubleAssertion, CPUFeature.SSE2); - - public static final SSERMIOp SHUFPD = new SSERMIOp("SHUFPD", true, P_0F, 0xC6, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE2); + public static final SSERMIOp PALIGNR = new SSERMIOp("PALIGNR", true, P_0F3A, 0x0F, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.SSSE3); + public static final SSERMIOp PBLENDW = new SSERMIOp("PBLENDW", true, P_0F3A, 0x0E, PreferredNDS.DST, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE4_1); + public static final SSERMIOp PSHUFD = new SSERMIOp("PSHUFD", true, P_0F, 0x70, PreferredNDS.NONE, OpAssertion.PackedDoubleAssertion, CPUFeature.SSE2); + public static final SSERMIOp PSHUFLW = new SSERMIOp("PSHUFLW", true, P_0F, 0x70, PreferredNDS.NONE, OpAssertion.DoubleAssertion, CPUFeature.SSE2); // @formatter:on private final PreferredNDS preferredNDS; @@ -5691,10 +5689,6 @@ public final void psubusw(Register dst, AMD64Address src) { SSEOp.PSUBUSW.emit(this, OperandSize.PD, dst, src); } - public final void psubw(Register dst, Register src) { - SSEOp.PSUBW.emit(this, OperandSize.PD, dst, src); - } - public final void ptest(Register dst, Register src) { SSEOp.PTEST.emit(this, OperandSize.PD, dst, src); } @@ -5865,10 +5859,6 @@ public final void shrq(Register dst) { AMD64MOp.SHR.emit(this, OperandSize.QWORD, dst); } - public final void shufpd(Register dst, Register src, int imm8) { - SSERMIOp.SHUFPD.emit(this, OperandSize.PD, dst, src, imm8); - } - public final void sqrtsd(Register dst, Register src) { SSEOp.SQRT.emit(this, OperandSize.SD, dst, src); } 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 1bec2f482e48..2d080d422c5e 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 @@ -144,7 +144,6 @@ import jdk.graal.compiler.lir.amd64.AMD64MathPowOp; import jdk.graal.compiler.lir.amd64.AMD64MathSignumOp; import jdk.graal.compiler.lir.amd64.AMD64MathSinOp; -import jdk.graal.compiler.lir.amd64.AMD64MathSinhOp; import jdk.graal.compiler.lir.amd64.AMD64MathTanOp; import jdk.graal.compiler.lir.amd64.AMD64MathTanhOp; import jdk.graal.compiler.lir.amd64.AMD64Move; @@ -1308,11 +1307,6 @@ public Value emitMathSin(Value input) { return new AMD64MathSinOp().emitLIRWrapper(getLIRGen(), input); } - @Override - public Value emitMathSinh(Value input) { - return new AMD64MathSinhOp().emitLIRWrapper(getLIRGen(), input); - } - @Override public Value emitMathTan(Value input) { return new AMD64MathTanOp().emitLIRWrapper(getLIRGen(), input); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index b1542e93cff0..9575f0e566e9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -703,7 +703,6 @@ private long getZGCAddressField(String name) { public final long javaTimeMillisAddress = getAddress("os::javaTimeMillis"); public final long javaTimeNanosAddress = getAddress("os::javaTimeNanos"); public final long arithmeticSinAddress = getFieldValue("CompilerToVM::Data::dsin", Long.class, "address"); - public final long arithmeticSinhAddress = getFieldValue("CompilerToVM::Data::dsinh", Long.class, "address"); public final long arithmeticCosAddress = getFieldValue("CompilerToVM::Data::dcos", Long.class, "address"); public final long arithmeticTanAddress = getFieldValue("CompilerToVM::Data::dtan", Long.class, "address"); public final long arithmeticTanhAddress = getFieldValue("CompilerToVM::Data::dtanh", Long.class, "address"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java index 5d03e8d2774f..03ea6b157f54 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotForeignCallsProvider.java @@ -39,7 +39,6 @@ import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; -import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SINH; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TANH; import static jdk.vm.ci.amd64.AMD64.rax; @@ -105,7 +104,6 @@ public Value[] getNativeABICallerSaveRegisters() { protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotProviders providers, OptionValues options) { if (GraalArithmeticStubs.getValue(options)) { link(new AMD64MathStub(SIN, options, providers, registerStubCall(SIN.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS))); - link(new AMD64MathStub(SINH, options, providers, registerStubCall(SINH.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS))); link(new AMD64MathStub(COS, options, providers, registerStubCall(COS.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS))); link(new AMD64MathStub(TAN, options, providers, registerStubCall(TAN.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS))); link(new AMD64MathStub(TANH, options, providers, registerStubCall(TANH.foreignCallSignature, LEAF, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED, NO_LOCATIONS))); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java index 921c564a47d9..4c70633a354b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64MathStub.java @@ -51,7 +51,6 @@ public AMD64MathStub(BinaryOperation operation, OptionValues options, HotSpotPro private static String snippetName(UnaryOperation operation) { return switch (operation) { case SIN -> "sin"; - case SINH -> "sinh"; case COS -> "cos"; case TAN -> "tan"; case TANH -> "tanh"; @@ -84,11 +83,6 @@ private static double sin(double value) { return UnaryMathIntrinsicNode.compute(value, UnaryOperation.SIN); } - @Snippet - private static double sinh(double value) { - return UnaryMathIntrinsicNode.compute(value, UnaryOperation.SINH); - } - @Snippet private static double cos(double value) { return UnaryMathIntrinsicNode.compute(value, UnaryOperation.COS); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index ffe1f317f04f..483a94a160ad 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -111,7 +111,6 @@ import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; -import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SINH; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TANH; import static jdk.vm.ci.hotspot.HotSpotCallingConventionType.NativeCall; @@ -741,9 +740,6 @@ protected void registerMathStubs(GraalHotSpotVMConfig hotSpotVMConfig, HotSpotPr registerForeignCall(createDescriptor(LOG.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticLogAddress, NativeCall); registerForeignCall(createDescriptor(LOG10.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticLog10Address, NativeCall); registerForeignCall(createDescriptor(POW.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticPowAddress, NativeCall); - if (hotSpotVMConfig.arithmeticSinhAddress != 0L) { - registerForeignCall(createDescriptor(SINH.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticSinhAddress, NativeCall); - } if (hotSpotVMConfig.arithmeticTanhAddress != 0L) { registerForeignCall(createDescriptor(TANH.foreignCallSignature, LEAF, NO_SIDE_EFFECT, NO_LOCATIONS), hotSpotVMConfig.arithmeticTanhAddress, NativeCall); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index 49da510e9a1e..f4071eea460e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -87,6 +87,8 @@ private static void add(Collection c, String... elements) { public UnimplementedGraalIntrinsics(Architecture arch) { add(toBeInvestigated, // @formatter:off + // JDK-8360559: Optimize Math.sinh for x86 64 bit platforms + "java/lang/Math.sinh(D)D", // JDK-8342103: C2 compiler support for Float16 type and associated // scalar operations "jdk/internal/vm/vector/Float16Math.fma(Ljava/lang/Class;Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;Ljdk/internal/vm/vector/Float16Math$TernaryOperator;)Ljava/lang/Object;", @@ -153,8 +155,6 @@ public UnimplementedGraalIntrinsics(Architecture arch) { add(ignore, // JDK-8355644 "java/lang/Math.cbrt(D)D", - // JDK-8360559 - "java/lang/Math.sinh(D)D", // JDK-8338694 "java/lang/Math.tanh(D)D", // JDK-8309130 diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathSinhOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathSinhOp.java deleted file mode 100644 index 70f386ad4227..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/amd64/AMD64MathSinhOp.java +++ /dev/null @@ -1,593 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.lir.amd64; - -import static jdk.graal.compiler.lir.amd64.AMD64LIRHelper.pointerConstant; -import static jdk.graal.compiler.lir.amd64.AMD64LIRHelper.recordExternalAddress; -import static jdk.vm.ci.amd64.AMD64.r10; -import static jdk.vm.ci.amd64.AMD64.r11; -import static jdk.vm.ci.amd64.AMD64.r8; -import static jdk.vm.ci.amd64.AMD64.r9; -import static jdk.vm.ci.amd64.AMD64.rax; -import static jdk.vm.ci.amd64.AMD64.rcx; -import static jdk.vm.ci.amd64.AMD64.rdx; -import static jdk.vm.ci.amd64.AMD64.xmm0; -import static jdk.vm.ci.amd64.AMD64.xmm1; -import static jdk.vm.ci.amd64.AMD64.xmm2; -import static jdk.vm.ci.amd64.AMD64.xmm3; -import static jdk.vm.ci.amd64.AMD64.xmm4; -import static jdk.vm.ci.amd64.AMD64.xmm5; -import static jdk.vm.ci.amd64.AMD64.xmm6; -import static jdk.vm.ci.amd64.AMD64.xmm7; - -import jdk.graal.compiler.asm.Label; -import jdk.graal.compiler.asm.amd64.AMD64Address; -import jdk.graal.compiler.asm.amd64.AMD64Assembler.ConditionFlag; -import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; -import jdk.graal.compiler.core.common.Stride; -import jdk.graal.compiler.lir.LIRInstructionClass; -import jdk.graal.compiler.lir.SyncPort; -import jdk.graal.compiler.lir.asm.ArrayDataPointerConstant; -import jdk.graal.compiler.lir.asm.CompilationResultBuilder; - -/** - *
- *                     ALGORITHM DESCRIPTION
- *                     ---------------------
- *
- * sinh(x)=(exp(x)-exp(-x))/2
- *
- * Let |x|=xH+xL (upper 26 bits, lower 27 bits)
- * log2(e) rounded to 26 bits (high part) plus a double precision low part is
- *         L2EH+L2EL (upper 26, lower 53 bits)
- *
- * Let xH*L2EH=k+f+r`, where (k+f)*2^7=int(xH*L2EH*2^7),
- *                             f=0.b1 b2 ... b7, k integer
- * 2^f is approximated as Tp[f]+Dp[f], and 2^{-f} as Tn[f]+Dn[f]
- * Tp stores the high 53 bits, Dp stores (2^f-Tp[f]) rounded to double precision
- *
- * e^|x|=2^{k+f}*2^r, r=r`+xL*L2EH+|x|*L2EL, |r|<2^{-8}+2^{-14},
- *                      for |x| in [23/64,3*2^7)
- * e^{-|x|}=2^{-k-f}*2^{-r}
- *
- * e^|x| is approximated as 2^k*Tp+2^k*Tp*c1*r(1+c2*r+..+c5*r^4)+2^k*Dp=
- *                          =2^k*Tp+2^k*Tp*P15+2^k*Dp
- * e^{-|x|} approximated as 2^{-k}*Tn-2^{-k}*Tn*c1*r(1-c2*r+..+c5*r^4)+2^{-k}*Dn
- *
- * For |x| in [1/8, 3*2^7), sinh(x) is formed as
- *     RN(2^k*Tp-2^{-k}*Tn)+2^k*Tp*P15-2^{-k}*Tn*P`15-2^{-k}*TnL-2^{-k}*Dn+2^k*Dp
- *
- * For x in (3*2^7, 3*2^8), sign(x)*(e^|x|)/2 is returned, and
- * the result is checked for overflow.
- *
- * For |x|<23/64, a Taylor polynomial expansion is used (degree 13)
- * To reduce rounding errors, the p3*x^3 term is computed as
- *    (p3*xh^3)_high+[(p3*xl*(3*x*xh+xl^2))+(p3*xh^3)_low],
- * where x=xh+xl, (xh are the leading 17 bits of x), and
- *    (p3*xh^3)_high=RN(x+p3*xh^3)-x
- *
- * Error bound:
- *  0.51 ulp
- *
- * Special cases:
- *  sinh(NaN) = quiet NaN, and raise invalid exception
- *  sinh(+/-INF) = +/-INF
- *  sinh(+/-0) = +/-0
- * 
- */ -// @formatter:off -@SyncPort(from = "https://github.com/openjdk/jdk/blob/001aaa1e49f2692061cad44d68c9e81a27ea3b98/src/hotspot/cpu/x86/stubGenerator_x86_64_sinh.cpp#L30-L523", - sha1 = "ec41339ad6dcdce94d6e288a56c0502fa59bf5ec") -// @formatter:on -public final class AMD64MathSinhOp extends AMD64MathIntrinsicUnaryOp { - - public static final LIRInstructionClass TYPE = LIRInstructionClass.create(AMD64MathSinhOp.class); - - public AMD64MathSinhOp() { - super(TYPE, /* GPR */ rax, rcx, rdx, r8, r9, r10, r11, - /* XMM */ xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7); - } - - private static ArrayDataPointerConstant halfMask = pointerConstant(16, new int[]{ - // @formatter:off - 0xF8000000, 0x7FFFFFFF - // @formatter:on - }); - - private static ArrayDataPointerConstant mask3 = pointerConstant(16, new int[]{ - // @formatter:off - 0x00000000, 0xFFFFFFF0, 0x00000000, 0xFFFFFFF0 - // @formatter:on - }); - - private static ArrayDataPointerConstant l2E = pointerConstant(16, new int[]{ - // @formatter:off - 0x60000000, 0x40671547 - // @formatter:on - }); - - private static ArrayDataPointerConstant l2E8 = pointerConstant(16, new int[]{ - // @formatter:off - 0xF85DDF44, 0x3EC4AE0B - // @formatter:on - }); - - private static ArrayDataPointerConstant shifter = pointerConstant(16, new int[]{ - // @formatter:off - 0x00000000, 0x43380000, 0x00000000, 0xC3380000 - // @formatter:on - }); - - private static ArrayDataPointerConstant cv = pointerConstant(16, new int[]{ - // @formatter:off - 0xD704A0C0, 0x3E3C6B08, 0xD704A0C0, 0xBE3C6B08, - // @formatter:on - }); - - private static ArrayDataPointerConstant cv16 = pointerConstant(16, new int[]{ - // @formatter:off - 0xFEFA39EF, 0x3F662E42, 0xFEFA39EF, 0xBF662E42, - // @formatter:on - }); - - private static ArrayDataPointerConstant cv32 = pointerConstant(16, new int[]{ - // @formatter:off - 0x7F907D8B, 0x3D9F8445, 0x7F907D8B, 0x3D9F8445, - // @formatter:on - }); - - private static ArrayDataPointerConstant cv48 = pointerConstant(16, new int[]{ - // @formatter:off - 0xFFAC83B4, 0x3ED47FD3, 0xFFAC83B4, 0x3ED47FD3, - // @formatter:on - }); - - private static ArrayDataPointerConstant cv64 = pointerConstant(16, new int[]{ - // @formatter:off - 0xFEFA39EF, 0x3F762E42, 0xFEFA39EF, 0x3F762E42 - // @formatter:on - }); - - private static ArrayDataPointerConstant pv = pointerConstant(16, new int[]{ - // @formatter:off - 0x13A86D08, 0x3DE61246, 0xA556C732, 0x3EC71DE3, - // @formatter:on - }); - - private static ArrayDataPointerConstant pv16 = pointerConstant(16, new int[]{ - // @formatter:off - 0x11111111, 0x3F811111, 0x55555555, 0x3FC55555, - // @formatter:on - }); - - private static ArrayDataPointerConstant pv32 = pointerConstant(16, new int[]{ - // @formatter:off - 0x67F544E1, 0x3E5AE645, 0x1A01A019, 0x3F2A01A0 - // @formatter:on - }); - - private static ArrayDataPointerConstant t2F = pointerConstant(16, new int[]{ - // @formatter:off - 0x00000000, 0x3FF00000, 0x00000000, 0x00000000, 0xA9FB3335, 0x3FF0163D, - 0x9AB8CDB7, 0x3C9B6129, 0x3E778061, 0x3FF02C9A, 0x535B085D, 0xBC719083, - 0xE86E7F85, 0x3FF04315, 0x1977C96E, 0xBC90A31C, 0xD3158574, 0x3FF059B0, - 0xA475B465, 0x3C8D73E2, 0x29DDF6DE, 0x3FF0706B, 0xE2B13C27, 0xBC8C91DF, - 0x18759BC8, 0x3FF08745, 0x4BB284FF, 0x3C6186BE, 0xCAC6F383, 0x3FF09E3E, - 0x18316136, 0x3C914878, 0x6CF9890F, 0x3FF0B558, 0x4ADC610B, 0x3C98A62E, - 0x2B7247F7, 0x3FF0CC92, 0x16E24F71, 0x3C901EDC, 0x32D3D1A2, 0x3FF0E3EC, - 0x27C57B52, 0x3C403A17, 0xAFFED31B, 0x3FF0FB66, 0xC44EBD7B, 0xBC6B9BED, - 0xD0125B51, 0x3FF11301, 0x39449B3A, 0xBC96C510, 0xC06C31CC, 0x3FF12ABD, - 0xB36CA5C7, 0xBC51B514, 0xAEA92DE0, 0x3FF1429A, 0x9AF1369E, 0xBC932FBF, - 0xC8A58E51, 0x3FF15A98, 0xB9EEAB0A, 0x3C82406A, 0x3C7D517B, 0x3FF172B8, - 0xB9D78A76, 0xBC819041, 0x388C8DEA, 0x3FF18AF9, 0xD1970F6C, 0xBC911023, - 0xEB6FCB75, 0x3FF1A35B, 0x7B4968E4, 0x3C8E5B4C, 0x84045CD4, 0x3FF1BBE0, - 0x352EF607, 0xBC995386, 0x3168B9AA, 0x3FF1D487, 0x00A2643C, 0x3C9E016E, - 0x22FCD91D, 0x3FF1ED50, 0x027BB78C, 0xBC91DF98, 0x88628CD6, 0x3FF2063B, - 0x814A8495, 0x3C8DC775, 0x917DDC96, 0x3FF21F49, 0x9494A5EE, 0x3C82A97E, - 0x6E756238, 0x3FF2387A, 0xB6C70573, 0x3C99B07E, 0x4FB2A63F, 0x3FF251CE, - 0xBEF4F4A4, 0x3C8AC155, 0x65E27CDD, 0x3FF26B45, 0x9940E9D9, 0x3C82BD33, - 0xE1F56381, 0x3FF284DF, 0x8C3F0D7E, 0xBC9A4C3A, 0xF51FDEE1, 0x3FF29E9D, - 0xAFAD1255, 0x3C8612E8, 0xD0DAD990, 0x3FF2B87F, 0xD6381AA4, 0xBC410ADC, - 0xA6E4030B, 0x3FF2D285, 0x54DB41D5, 0x3C900247, 0xA93E2F56, 0x3FF2ECAF, - 0x45D52383, 0x3C71CA0F, 0x0A31B715, 0x3FF306FE, 0xD23182E4, 0x3C86F46A, - 0xFC4CD831, 0x3FF32170, 0x8E18047C, 0x3C8A9CE7, 0xB26416FF, 0x3FF33C08, - 0x843659A6, 0x3C932721, 0x5F929FF1, 0x3FF356C5, 0x5C4E4628, 0xBC8B5CEE, - 0x373AA9CB, 0x3FF371A7, 0xBF42EAE2, 0xBC963AEA, 0x6D05D866, 0x3FF38CAE, - 0x3C9904BD, 0xBC9E958D, 0x34E59FF7, 0x3FF3A7DB, 0xD661F5E3, 0xBC75E436, - 0xC313A8E5, 0x3FF3C32D, 0x375D29C3, 0xBC9EFFF8, 0x4C123422, 0x3FF3DEA6, - 0x11F09EBC, 0x3C8ADA09, 0x04AC801C, 0x3FF3FA45, 0xF956F9F3, 0xBC97D023, - 0x21F72E2A, 0x3FF4160A, 0x1C309278, 0xBC5EF369, 0xD950A897, 0x3FF431F5, - 0xE35F7999, 0xBC81C7DD, 0x6061892D, 0x3FF44E08, 0x04EF80D0, 0x3C489B7A, - 0xED1D0057, 0x3FF46A41, 0xD1648A76, 0x3C9C944B, 0xB5C13CD0, 0x3FF486A2, - 0xB69062F0, 0x3C73C1A3, 0xF0D7D3DE, 0x3FF4A32A, 0xF3D1BE56, 0x3C99CB62, - 0xD5362A27, 0x3FF4BFDA, 0xAFEC42E2, 0x3C7D4397, 0x99FDDD0D, 0x3FF4DCB2, - 0xBC6A7833, 0x3C98ECDB, 0x769D2CA7, 0x3FF4F9B2, 0xD25957E3, 0xBC94B309, - 0xA2CF6642, 0x3FF516DA, 0x69BD93EF, 0xBC8F7685, 0x569D4F82, 0x3FF5342B, - 0x1DB13CAD, 0xBC807ABE, 0xCA5D920F, 0x3FF551A4, 0xEFEDE59B, 0xBC8D689C, - 0x36B527DA, 0x3FF56F47, 0x011D93AD, 0x3C99BB2C, 0xD497C7FD, 0x3FF58D12, - 0x5B9A1DE8, 0x3C8295E1, 0xDD485429, 0x3FF5AB07, 0x054647AD, 0x3C96324C, - 0x8A5946B7, 0x3FF5C926, 0x816986A2, 0x3C3C4B1B, 0x15AD2148, 0x3FF5E76F, - 0x3080E65E, 0x3C9BA6F9, 0xB976DC09, 0x3FF605E1, 0x9B56DE47, 0xBC93E242, - 0xB03A5585, 0x3FF6247E, 0x7E40B497, 0xBC9383C1, 0x34CCC320, 0x3FF64346, - 0x759D8933, 0xBC8C483C, 0x82552225, 0x3FF66238, 0x87591C34, 0xBC9BB609, - 0xD44CA973, 0x3FF68155, 0x44F73E65, 0x3C6038AE, 0x667F3BCD, 0x3FF6A09E, - 0x13B26456, 0xBC9BDD34, 0x750BDABF, 0x3FF6C012, 0x67FF0B0D, 0xBC728956, - 0x3C651A2F, 0x3FF6DFB2, 0x683C88AB, 0xBC6BBE3A, 0xF9519484, 0x3FF6FF7D, - 0x25860EF6, 0xBC883C0F, 0xE8EC5F74, 0x3FF71F75, 0x86887A99, 0xBC816E47, - 0x48A58174, 0x3FF73F9A, 0x6C65D53C, 0xBC90A8D9, 0x564267C9, 0x3FF75FEB, - 0x57316DD3, 0xBC902459, 0x4FDE5D3F, 0x3FF78069, 0x0A02162D, 0x3C9866B8, - 0x73EB0187, 0x3FF7A114, 0xEE04992F, 0xBC841577, 0x0130C132, 0x3FF7C1ED, - 0xD1164DD6, 0x3C9F124C, 0x36CF4E62, 0x3FF7E2F3, 0xBA15797E, 0x3C705D02, - 0x543E1A12, 0x3FF80427, 0x626D972B, 0xBC927C86, 0x994CCE13, 0x3FF82589, - 0xD41532D8, 0xBC9D4C1D, 0x4623C7AD, 0x3FF8471A, 0xA341CDFB, 0xBC88D684, - 0x9B4492ED, 0x3FF868D9, 0x9BD4F6BA, 0xBC9FC6F8, 0xD98A6699, 0x3FF88AC7, - 0xF37CB53A, 0x3C9994C2, 0x422AA0DB, 0x3FF8ACE5, 0x56864B27, 0x3C96E9F1, - 0x16B5448C, 0x3FF8CF32, 0x32E9E3AA, 0xBC70D55E, 0x99157736, 0x3FF8F1AE, - 0xA2E3976C, 0x3C85CC13, 0x0B91FFC6, 0x3FF9145B, 0x2E582524, 0xBC9DD679, - 0xB0CDC5E5, 0x3FF93737, 0x81B57EBC, 0xBC675FC7, 0xCBC8520F, 0x3FF95A44, - 0x96A5F039, 0xBC764B7C, 0x9FDE4E50, 0x3FF97D82, 0x7C1B85D1, 0xBC9D185B, - 0x70CA07BA, 0x3FF9A0F1, 0x91CEE632, 0xBC9173BD, 0x82A3F090, 0x3FF9C491, - 0xB071F2BE, 0x3C7C7C46, 0x19E32323, 0x3FF9E863, 0x78E64C6E, 0x3C7824CA, - 0x7B5DE565, 0x3FFA0C66, 0x5D1CD533, 0xBC935949, 0xEC4A2D33, 0x3FFA309B, - 0x7DDC36AB, 0x3C96305C, 0xB23E255D, 0x3FFA5503, 0xDB8D41E1, 0xBC9D2F6E, - 0x1330B358, 0x3FFA799E, 0xCAC563C7, 0x3C9BCB7E, 0x5579FDBF, 0x3FFA9E6B, - 0x0EF7FD31, 0x3C90FAC9, 0xBFD3F37A, 0x3FFAC36B, 0xCAE76CD0, 0xBC8F9234, - 0x995AD3AD, 0x3FFAE89F, 0x345DCC81, 0x3C97A1CD, 0x298DB666, 0x3FFB0E07, - 0x4C80E425, 0xBC9BDEF5, 0xB84F15FB, 0x3FFB33A2, 0x3084D708, 0xBC62805E, - 0x8DE5593A, 0x3FFB5972, 0xBBBA6DE3, 0xBC9C71DF, 0xF2FB5E47, 0x3FFB7F76, - 0x7E54AC3B, 0xBC75584F, 0x30A1064A, 0x3FFBA5B0, 0x0E54292E, 0xBC9EFCD3, - 0x904BC1D2, 0x3FFBCC1E, 0x7A2D9E84, 0x3C823DD0, 0x5BD71E09, 0x3FFBF2C2, - 0x3F6B9C73, 0xBC9EFDCA, 0xDD85529C, 0x3FFC199B, 0x895048DD, 0x3C811065, - 0x5FFFD07A, 0x3FFC40AB, 0xE083C60A, 0x3C9B4537, 0x2E57D14B, 0x3FFC67F1, - 0xFF483CAD, 0x3C92884D, 0x9406E7B5, 0x3FFC8F6D, 0x48805C44, 0x3C71ACBC, - 0xDCEF9069, 0x3FFCB720, 0xD1E949DC, 0x3C7503CB, 0x555DC3FA, 0x3FFCDF0B, - 0x53829D72, 0xBC8DD83B, 0x4A07897C, 0x3FFD072D, 0x43797A9C, 0xBC9CBC37, - 0x080D89F2, 0x3FFD2F87, 0x719D8578, 0xBC9D487B, 0xDCFBA487, 0x3FFD5818, - 0xD75B3707, 0x3C82ED02, 0x16C98398, 0x3FFD80E3, 0x8BEDDFE8, 0xBC911EC1, - 0x03DB3285, 0x3FFDA9E6, 0x696DB532, 0x3C9C2300, 0xF301B460, 0x3FFDD321, - 0x78F018C3, 0x3C92DA57, 0x337B9B5F, 0x3FFDFC97, 0x4F184B5C, 0xBC91A5CD, - 0x14F5A129, 0x3FFE2646, 0x817A1496, 0xBC97B627, 0xE78B3FF6, 0x3FFE502E, - 0x80A9CC8F, 0x3C839E89, 0xFBC74C83, 0x3FFE7A51, 0xCA0C8DE2, 0x3C92D522, - 0xA2A490DA, 0x3FFEA4AF, 0x179C2893, 0xBC9E9C23, 0x2D8E67F1, 0x3FFECF48, - 0xB411AD8C, 0xBC9C93F3, 0xEE615A27, 0x3FFEFA1B, 0x86A4B6B0, 0x3C9DC7F4, - 0x376BBA97, 0x3FFF252B, 0xBF0D8E43, 0x3C93A1A5, 0x5B6E4540, 0x3FFF5076, - 0x2DD8A18B, 0x3C99D3E1, 0xAD9CBE14, 0x3FFF7BFD, 0xD006350A, 0xBC9DBB12, - 0x819E90D8, 0x3FFFA7C1, 0xF3A5931E, 0x3C874853, 0x2B8F71F1, 0x3FFFD3C2, - 0x966579E7, 0x3C62EB74 - // @formatter:on - }); - - private static ArrayDataPointerConstant t2NegF = pointerConstant(16, new int[]{ - // @formatter:off - 0x00000000, 0x3FF00000, 0x00000000, 0x00000000, 0x2B8F71F1, 0x3FEFD3C2, - 0x966579E7, 0x3C52EB74, 0x819E90D8, 0x3FEFA7C1, 0xF3A5931E, 0x3C774853, - 0xAD9CBE14, 0x3FEF7BFD, 0xD006350A, 0xBC8DBB12, 0x5B6E4540, 0x3FEF5076, - 0x2DD8A18B, 0x3C89D3E1, 0x376BBA97, 0x3FEF252B, 0xBF0D8E43, 0x3C83A1A5, - 0xEE615A27, 0x3FEEFA1B, 0x86A4B6B0, 0x3C8DC7F4, 0x2D8E67F1, 0x3FEECF48, - 0xB411AD8C, 0xBC8C93F3, 0xA2A490DA, 0x3FEEA4AF, 0x179C2893, 0xBC8E9C23, - 0xFBC74C83, 0x3FEE7A51, 0xCA0C8DE2, 0x3C82D522, 0xE78B3FF6, 0x3FEE502E, - 0x80A9CC8F, 0x3C739E89, 0x14F5A129, 0x3FEE2646, 0x817A1496, 0xBC87B627, - 0x337B9B5F, 0x3FEDFC97, 0x4F184B5C, 0xBC81A5CD, 0xF301B460, 0x3FEDD321, - 0x78F018C3, 0x3C82DA57, 0x03DB3285, 0x3FEDA9E6, 0x696DB532, 0x3C8C2300, - 0x16C98398, 0x3FED80E3, 0x8BEDDFE8, 0xBC811EC1, 0xDCFBA487, 0x3FED5818, - 0xD75B3707, 0x3C72ED02, 0x080D89F2, 0x3FED2F87, 0x719D8578, 0xBC8D487B, - 0x4A07897C, 0x3FED072D, 0x43797A9C, 0xBC8CBC37, 0x555DC3FA, 0x3FECDF0B, - 0x53829D72, 0xBC7DD83B, 0xDCEF9069, 0x3FECB720, 0xD1E949DC, 0x3C6503CB, - 0x9406E7B5, 0x3FEC8F6D, 0x48805C44, 0x3C61ACBC, 0x2E57D14B, 0x3FEC67F1, - 0xFF483CAD, 0x3C82884D, 0x5FFFD07A, 0x3FEC40AB, 0xE083C60A, 0x3C8B4537, - 0xDD85529C, 0x3FEC199B, 0x895048DD, 0x3C711065, 0x5BD71E09, 0x3FEBF2C2, - 0x3F6B9C73, 0xBC8EFDCA, 0x904BC1D2, 0x3FEBCC1E, 0x7A2D9E84, 0x3C723DD0, - 0x30A1064A, 0x3FEBA5B0, 0x0E54292E, 0xBC8EFCD3, 0xF2FB5E47, 0x3FEB7F76, - 0x7E54AC3B, 0xBC65584F, 0x8DE5593A, 0x3FEB5972, 0xBBBA6DE3, 0xBC8C71DF, - 0xB84F15FB, 0x3FEB33A2, 0x3084D708, 0xBC52805E, 0x298DB666, 0x3FEB0E07, - 0x4C80E425, 0xBC8BDEF5, 0x995AD3AD, 0x3FEAE89F, 0x345DCC81, 0x3C87A1CD, - 0xBFD3F37A, 0x3FEAC36B, 0xCAE76CD0, 0xBC7F9234, 0x5579FDBF, 0x3FEA9E6B, - 0x0EF7FD31, 0x3C80FAC9, 0x1330B358, 0x3FEA799E, 0xCAC563C7, 0x3C8BCB7E, - 0xB23E255D, 0x3FEA5503, 0xDB8D41E1, 0xBC8D2F6E, 0xEC4A2D33, 0x3FEA309B, - 0x7DDC36AB, 0x3C86305C, 0x7B5DE565, 0x3FEA0C66, 0x5D1CD533, 0xBC835949, - 0x19E32323, 0x3FE9E863, 0x78E64C6E, 0x3C6824CA, 0x82A3F090, 0x3FE9C491, - 0xB071F2BE, 0x3C6C7C46, 0x70CA07BA, 0x3FE9A0F1, 0x91CEE632, 0xBC8173BD, - 0x9FDE4E50, 0x3FE97D82, 0x7C1B85D1, 0xBC8D185B, 0xCBC8520F, 0x3FE95A44, - 0x96A5F039, 0xBC664B7C, 0xB0CDC5E5, 0x3FE93737, 0x81B57EBC, 0xBC575FC7, - 0x0B91FFC6, 0x3FE9145B, 0x2E582524, 0xBC8DD679, 0x99157736, 0x3FE8F1AE, - 0xA2E3976C, 0x3C75CC13, 0x16B5448C, 0x3FE8CF32, 0x32E9E3AA, 0xBC60D55E, - 0x422AA0DB, 0x3FE8ACE5, 0x56864B27, 0x3C86E9F1, 0xD98A6699, 0x3FE88AC7, - 0xF37CB53A, 0x3C8994C2, 0x9B4492ED, 0x3FE868D9, 0x9BD4F6BA, 0xBC8FC6F8, - 0x4623C7AD, 0x3FE8471A, 0xA341CDFB, 0xBC78D684, 0x994CCE13, 0x3FE82589, - 0xD41532D8, 0xBC8D4C1D, 0x543E1A12, 0x3FE80427, 0x626D972B, 0xBC827C86, - 0x36CF4E62, 0x3FE7E2F3, 0xBA15797E, 0x3C605D02, 0x0130C132, 0x3FE7C1ED, - 0xD1164DD6, 0x3C8F124C, 0x73EB0187, 0x3FE7A114, 0xEE04992F, 0xBC741577, - 0x4FDE5D3F, 0x3FE78069, 0x0A02162D, 0x3C8866B8, 0x564267C9, 0x3FE75FEB, - 0x57316DD3, 0xBC802459, 0x48A58174, 0x3FE73F9A, 0x6C65D53C, 0xBC80A8D9, - 0xE8EC5F74, 0x3FE71F75, 0x86887A99, 0xBC716E47, 0xF9519484, 0x3FE6FF7D, - 0x25860EF6, 0xBC783C0F, 0x3C651A2F, 0x3FE6DFB2, 0x683C88AB, 0xBC5BBE3A, - 0x750BDABF, 0x3FE6C012, 0x67FF0B0D, 0xBC628956, 0x667F3BCD, 0x3FE6A09E, - 0x13B26456, 0xBC8BDD34, 0xD44CA973, 0x3FE68155, 0x44F73E65, 0x3C5038AE, - 0x82552225, 0x3FE66238, 0x87591C34, 0xBC8BB609, 0x34CCC320, 0x3FE64346, - 0x759D8933, 0xBC7C483C, 0xB03A5585, 0x3FE6247E, 0x7E40B497, 0xBC8383C1, - 0xB976DC09, 0x3FE605E1, 0x9B56DE47, 0xBC83E242, 0x15AD2148, 0x3FE5E76F, - 0x3080E65E, 0x3C8BA6F9, 0x8A5946B7, 0x3FE5C926, 0x816986A2, 0x3C2C4B1B, - 0xDD485429, 0x3FE5AB07, 0x054647AD, 0x3C86324C, 0xD497C7FD, 0x3FE58D12, - 0x5B9A1DE8, 0x3C7295E1, 0x36B527DA, 0x3FE56F47, 0x011D93AD, 0x3C89BB2C, - 0xCA5D920F, 0x3FE551A4, 0xEFEDE59B, 0xBC7D689C, 0x569D4F82, 0x3FE5342B, - 0x1DB13CAD, 0xBC707ABE, 0xA2CF6642, 0x3FE516DA, 0x69BD93EF, 0xBC7F7685, - 0x769D2CA7, 0x3FE4F9B2, 0xD25957E3, 0xBC84B309, 0x99FDDD0D, 0x3FE4DCB2, - 0xBC6A7833, 0x3C88ECDB, 0xD5362A27, 0x3FE4BFDA, 0xAFEC42E2, 0x3C6D4397, - 0xF0D7D3DE, 0x3FE4A32A, 0xF3D1BE56, 0x3C89CB62, 0xB5C13CD0, 0x3FE486A2, - 0xB69062F0, 0x3C63C1A3, 0xED1D0057, 0x3FE46A41, 0xD1648A76, 0x3C8C944B, - 0x6061892D, 0x3FE44E08, 0x04EF80D0, 0x3C389B7A, 0xD950A897, 0x3FE431F5, - 0xE35F7999, 0xBC71C7DD, 0x21F72E2A, 0x3FE4160A, 0x1C309278, 0xBC4EF369, - 0x04AC801C, 0x3FE3FA45, 0xF956F9F3, 0xBC87D023, 0x4C123422, 0x3FE3DEA6, - 0x11F09EBC, 0x3C7ADA09, 0xC313A8E5, 0x3FE3C32D, 0x375D29C3, 0xBC8EFFF8, - 0x34E59FF7, 0x3FE3A7DB, 0xD661F5E3, 0xBC65E436, 0x6D05D866, 0x3FE38CAE, - 0x3C9904BD, 0xBC8E958D, 0x373AA9CB, 0x3FE371A7, 0xBF42EAE2, 0xBC863AEA, - 0x5F929FF1, 0x3FE356C5, 0x5C4E4628, 0xBC7B5CEE, 0xB26416FF, 0x3FE33C08, - 0x843659A6, 0x3C832721, 0xFC4CD831, 0x3FE32170, 0x8E18047C, 0x3C7A9CE7, - 0x0A31B715, 0x3FE306FE, 0xD23182E4, 0x3C76F46A, 0xA93E2F56, 0x3FE2ECAF, - 0x45D52383, 0x3C61CA0F, 0xA6E4030B, 0x3FE2D285, 0x54DB41D5, 0x3C800247, - 0xD0DAD990, 0x3FE2B87F, 0xD6381AA4, 0xBC310ADC, 0xF51FDEE1, 0x3FE29E9D, - 0xAFAD1255, 0x3C7612E8, 0xE1F56381, 0x3FE284DF, 0x8C3F0D7E, 0xBC8A4C3A, - 0x65E27CDD, 0x3FE26B45, 0x9940E9D9, 0x3C72BD33, 0x4FB2A63F, 0x3FE251CE, - 0xBEF4F4A4, 0x3C7AC155, 0x6E756238, 0x3FE2387A, 0xB6C70573, 0x3C89B07E, - 0x917DDC96, 0x3FE21F49, 0x9494A5EE, 0x3C72A97E, 0x88628CD6, 0x3FE2063B, - 0x814A8495, 0x3C7DC775, 0x22FCD91D, 0x3FE1ED50, 0x027BB78C, 0xBC81DF98, - 0x3168B9AA, 0x3FE1D487, 0x00A2643C, 0x3C8E016E, 0x84045CD4, 0x3FE1BBE0, - 0x352EF607, 0xBC895386, 0xEB6FCB75, 0x3FE1A35B, 0x7B4968E4, 0x3C7E5B4C, - 0x388C8DEA, 0x3FE18AF9, 0xD1970F6C, 0xBC811023, 0x3C7D517B, 0x3FE172B8, - 0xB9D78A76, 0xBC719041, 0xC8A58E51, 0x3FE15A98, 0xB9EEAB0A, 0x3C72406A, - 0xAEA92DE0, 0x3FE1429A, 0x9AF1369E, 0xBC832FBF, 0xC06C31CC, 0x3FE12ABD, - 0xB36CA5C7, 0xBC41B514, 0xD0125B51, 0x3FE11301, 0x39449B3A, 0xBC86C510, - 0xAFFED31B, 0x3FE0FB66, 0xC44EBD7B, 0xBC5B9BED, 0x32D3D1A2, 0x3FE0E3EC, - 0x27C57B52, 0x3C303A17, 0x2B7247F7, 0x3FE0CC92, 0x16E24F71, 0x3C801EDC, - 0x6CF9890F, 0x3FE0B558, 0x4ADC610B, 0x3C88A62E, 0xCAC6F383, 0x3FE09E3E, - 0x18316136, 0x3C814878, 0x18759BC8, 0x3FE08745, 0x4BB284FF, 0x3C5186BE, - 0x29DDF6DE, 0x3FE0706B, 0xE2B13C27, 0xBC7C91DF, 0xD3158574, 0x3FE059B0, - 0xA475B465, 0x3C7D73E2, 0xE86E7F85, 0x3FE04315, 0x1977C96E, 0xBC80A31C, - 0x3E778061, 0x3FE02C9A, 0x535B085D, 0xBC619083, 0xA9FB3335, 0x3FE0163D, - 0x9AB8CDB7, 0x3C8B6129 - // @formatter:on - }); - - @Override - public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { - Label l2TAGPACKET002 = new Label(); - Label l2TAGPACKET102 = new Label(); - Label l2TAGPACKET302 = new Label(); - Label l2TAGPACKET402 = new Label(); - Label l2TAGPACKET502 = new Label(); - Label l2TAGPACKET602 = new Label(); - Label b12 = new Label(); - Label b15 = new Label(); - - masm.bind(b12); - masm.xorpd(xmm4, xmm4); - masm.movsd(xmm1, recordExternalAddress(crb, l2E)); - masm.movl(rax, 32768); - masm.pinsrw(xmm4, rax, 3); - masm.pextrw(rcx, xmm0, 3); - masm.andnpd(xmm4, xmm0); - masm.pshufd(xmm5, xmm4, 68); - masm.movl(rdx, 32768); - masm.andl(rdx, rcx); - masm.andl(rcx, 32767); - masm.subl(rcx, 16343); - // Branch only if |x| is not in [23/64, 3*2^8) - masm.cmplAndJcc(rcx, 177, ConditionFlag.AboveEqual, l2TAGPACKET002, false); - masm.movsd(xmm3, recordExternalAddress(crb, halfMask)); - masm.movsd(xmm2, recordExternalAddress(crb, l2E8)); - masm.movsd(xmm6, recordExternalAddress(crb, shifter)); - masm.andpd(xmm3, xmm0); - masm.subsd(xmm4, xmm3); - masm.mulsd(xmm3, xmm1); - masm.mulsd(xmm2, xmm5); - masm.cvtsd2siq(rax, xmm3); - masm.shll(rdx, 3); - masm.orl(rax, rdx); - masm.movq(xmm7, xmm3); - masm.addsd(xmm3, xmm6); - masm.mulsd(xmm1, xmm4); - masm.xorpd(xmm5, xmm5); - masm.subsd(xmm3, xmm6); - masm.movapd(xmm4, recordExternalAddress(crb, cv)); - masm.addsd(xmm2, xmm1); - masm.movapd(xmm6, recordExternalAddress(crb, cv16)); - masm.subsd(xmm7, xmm3); - masm.movl(rdx, 32704); - masm.pinsrw(xmm5, rdx, 3); - masm.movapd(xmm1, recordExternalAddress(crb, cv32)); - masm.addsd(xmm2, xmm7); - masm.movl(rdx, 127); - masm.andl(rdx, rax); - masm.addl(rdx, rdx); - masm.shrl(rax, 3); - masm.andl(rax, 65520); - masm.addl(rax, 16352); - masm.xorpd(xmm0, xmm0); - // Branch only if |x| is not in [23/64, 3*2^7) - masm.cmplAndJcc(rcx, 161, ConditionFlag.AboveEqual, l2TAGPACKET102, false); - masm.pshufd(xmm5, xmm5, 68); - masm.pinsrw(xmm0, rax, 3); - masm.pshufd(xmm0, xmm0, 68); - masm.psubw(xmm5, xmm0); - masm.leaq(r8, recordExternalAddress(crb, t2F)); - masm.mulpd(xmm0, new AMD64Address(r8, rdx, Stride.S8)); - masm.leaq(r8, recordExternalAddress(crb, t2NegF)); - masm.mulpd(xmm5, new AMD64Address(r8, rdx, Stride.S8)); - masm.pshufd(xmm3, xmm2, 68); - masm.movapd(xmm7, recordExternalAddress(crb, cv48)); - masm.pshufd(xmm2, xmm2, 68); - masm.mulpd(xmm3, xmm3); - masm.mulpd(xmm4, xmm2); - masm.mulpd(xmm6, xmm2); - masm.mulpd(xmm2, recordExternalAddress(crb, cv64)); - masm.mulpd(xmm1, xmm3); - masm.mulpd(xmm7, xmm3); - masm.mulpd(xmm4, xmm3); - masm.mulpd(xmm1, xmm3); - masm.addpd(xmm6, xmm7); - masm.movq(xmm7, xmm0); - masm.addpd(xmm4, xmm1); - masm.shufpd(xmm7, xmm5, 0); - masm.subpd(xmm0, xmm5); - masm.mulpd(xmm2, xmm7); - masm.addpd(xmm4, xmm6); - masm.subsd(xmm7, xmm0); - masm.mulpd(xmm4, xmm2); - masm.pshufd(xmm6, xmm0, 238); - masm.subsd(xmm7, xmm5); - masm.addpd(xmm4, xmm2); - masm.addsd(xmm7, xmm6); - masm.pshufd(xmm2, xmm4, 238); - masm.addsd(xmm2, xmm7); - masm.addsd(xmm2, xmm4); - masm.addsd(xmm0, xmm2); - masm.jmp(b15); - - masm.bind(l2TAGPACKET102); - masm.subl(rax, 16352); - masm.movl(rcx, rax); - masm.andl(rax, 32752); - masm.shrl(rax, 1); - masm.andl(rax, 65520); - masm.subl(rcx, rax); - masm.addl(rax, 16352); - masm.pinsrw(xmm0, rax, 3); - masm.pshufd(xmm0, xmm0, 68); - masm.leaq(r8, recordExternalAddress(crb, t2F)); - masm.mulpd(xmm0, new AMD64Address(r8, rdx, Stride.S8)); - masm.pshufd(xmm3, xmm2, 68); - masm.movsd(xmm7, recordExternalAddress(crb, cv48)); - masm.mulsd(xmm3, xmm3); - masm.mulsd(xmm4, xmm2); - masm.mulsd(xmm6, xmm2); - masm.mulsd(xmm2, recordExternalAddress(crb, cv64)); - masm.mulsd(xmm1, xmm3); - masm.mulsd(xmm7, xmm3); - masm.mulsd(xmm4, xmm3); - masm.addl(rcx, 16368); - masm.pinsrw(xmm5, rcx, 3); - masm.mulsd(xmm1, xmm3); - masm.addsd(xmm6, xmm7); - masm.addsd(xmm4, xmm1); - masm.mulsd(xmm2, xmm0); - masm.addsd(xmm4, xmm6); - masm.mulsd(xmm4, xmm2); - masm.pshufd(xmm6, xmm0, 238); - masm.addsd(xmm4, xmm6); - masm.addsd(xmm2, xmm4); - masm.addsd(xmm0, xmm2); - masm.mulsd(xmm0, xmm5); - masm.jmp(b15); - - masm.bind(l2TAGPACKET002); - masm.addl(rcx, 16343); - // Branch only if |x| > 23/64 - masm.cmplAndJcc(rcx, 16343, ConditionFlag.Above, l2TAGPACKET302, false); - // Branch only if |x| < 2^-32 - masm.cmplAndJcc(rcx, 15856, ConditionFlag.Below, l2TAGPACKET402, false); - masm.movapd(xmm1, recordExternalAddress(crb, pv)); - masm.pshufd(xmm6, xmm0, 68); - masm.mulpd(xmm5, xmm5); - masm.movapd(xmm2, recordExternalAddress(crb, pv16)); - masm.pshufd(xmm7, xmm0, 68); - masm.movapd(xmm3, recordExternalAddress(crb, pv32)); - masm.pshufd(xmm4, xmm0, 68); - masm.andpd(xmm6, recordExternalAddress(crb, mask3)); - masm.mulpd(xmm1, xmm5); - masm.mulsd(xmm2, xmm5); - masm.subpd(xmm4, xmm6); - masm.mulpd(xmm7, xmm5); - masm.addpd(xmm1, xmm3); - masm.pshufd(xmm3, xmm6, 68); - masm.mulpd(xmm5, xmm5); - masm.mulsd(xmm2, xmm7); - masm.mulpd(xmm1, xmm7); - masm.pshufd(xmm7, xmm0, 68); - masm.mulsd(xmm6, xmm6); - masm.addsd(xmm7, xmm7); - masm.mulsd(xmm4, xmm4); - masm.mulpd(xmm1, xmm5); - masm.addsd(xmm7, xmm0); - masm.mulsd(xmm6, xmm3); - masm.mulsd(xmm7, xmm3); - masm.pshufd(xmm3, xmm1, 238); - masm.mulsd(xmm1, xmm5); - masm.pshufd(xmm5, xmm4, 238); - masm.addsd(xmm3, xmm2); - masm.pshufd(xmm2, xmm2, 238); - masm.addsd(xmm7, xmm4); - masm.movq(xmm4, xmm0); - masm.mulsd(xmm6, xmm2); - masm.mulsd(xmm7, xmm5); - masm.addsd(xmm0, xmm6); - masm.mulsd(xmm7, xmm2); - masm.subsd(xmm4, xmm0); - masm.addsd(xmm1, xmm7); - masm.addsd(xmm6, xmm4); - masm.addsd(xmm1, xmm3); - masm.addsd(xmm1, xmm6); - masm.addsd(xmm0, xmm1); - masm.jmp(b15); - - masm.bind(l2TAGPACKET402); - // Branch only if |x| is not denormalized - masm.cmplAndJcc(rcx, 16, ConditionFlag.AboveEqual, l2TAGPACKET502, false); - masm.movq(xmm1, xmm0); - masm.mulsd(xmm1, xmm1); - masm.jmp(b15); - - masm.bind(l2TAGPACKET502); - masm.xorpd(xmm2, xmm2); - masm.movl(rcx, 17392); - masm.pinsrw(xmm2, rcx, 3); - masm.xorpd(xmm3, xmm3); - masm.movl(rdx, 15344); - masm.pinsrw(xmm3, rdx, 3); - masm.mulsd(xmm2, xmm0); - masm.addsd(xmm0, xmm2); - masm.mulsd(xmm0, xmm3); - masm.jmp(b15); - - masm.bind(l2TAGPACKET302); - // Branch only if |x| is INF or NaN - masm.cmplAndJcc(rcx, 32752, ConditionFlag.AboveEqual, l2TAGPACKET602, false); - masm.xorpd(xmm0, xmm0); - masm.movl(rax, 32736); - masm.pinsrw(xmm0, rax, 3); - masm.orl(rax, rdx); - masm.pinsrw(xmm1, rax, 3); - masm.mulsd(xmm0, xmm1); - masm.jmp(b15); - - masm.bind(l2TAGPACKET602); - masm.xorpd(xmm1, xmm1); - masm.movl(rax, 32768); - masm.pinsrw(xmm1, rax, 3); - masm.andnpd(xmm1, xmm0); - masm.mulsd(xmm0, xmm1); - - masm.bind(b15); - } -} 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 97966dd072e5..dd21e5d7d1af 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 @@ -159,11 +159,6 @@ default Value emitMathSin(Value input) { throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport } - @SuppressWarnings("unused") - default Value emitMathSinh(Value input) { - throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport - } - @SuppressWarnings("unused") default Value emitMathTan(Value input) { throw GraalError.unimplemented("No specialized implementation available"); // ExcludeFromJacocoGeneratedReport diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java index 5fd3948e44cf..f0f66c87ac94 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/amd64/AMD64GraphBuilderPlugins.java @@ -31,7 +31,6 @@ import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.LOG10; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SIN; -import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.SINH; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TAN; import static jdk.graal.compiler.replacements.nodes.UnaryMathIntrinsicNode.UnaryOperation.TANH; @@ -200,7 +199,6 @@ private static void registerMathPlugins(InvocationPlugins plugins) { registerUnaryMath(r, "exp", EXP); registerBinaryMath(r, "pow", BinaryMathIntrinsicNode.BinaryOperation.POW); registerUnaryMath(r, "sin", SIN); - registerUnaryMath(r, "sinh", SINH); registerUnaryMath(r, "cos", COS); registerUnaryMath(r, "tan", TAN); registerUnaryMath(r, "tanh", TANH); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java index 2d1a320e7522..385464b54ea6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/nodes/UnaryMathIntrinsicNode.java @@ -57,7 +57,6 @@ public enum UnaryOperation { LOG(new ForeignCallSignature("arithmeticLog", double.class, double.class)), LOG10(new ForeignCallSignature("arithmeticLog10", double.class, double.class)), SIN(new ForeignCallSignature("arithmeticSin", double.class, double.class)), - SINH(new ForeignCallSignature("arithmeticSinh", double.class, double.class)), COS(new ForeignCallSignature("arithmeticCos", double.class, double.class)), TAN(new ForeignCallSignature("arithmeticTan", double.class, double.class)), TANH(new ForeignCallSignature("arithmeticTanh", double.class, double.class)), @@ -76,7 +75,6 @@ public static double compute(UnaryOperation op, double value) { case LOG10 -> Math.log10(value); case EXP -> Math.exp(value); case SIN -> Math.sin(value); - case SINH -> Math.sinh(value); case COS -> Math.cos(value); case TAN -> Math.tan(value); case TANH -> Math.tanh(value); @@ -96,7 +94,6 @@ public static Stamp computeStamp(UnaryOperation op, Stamp valueStamp) { boolean nonNaN = floatStamp.lowerBound() != Double.NEGATIVE_INFINITY && floatStamp.upperBound() != Double.POSITIVE_INFINITY && floatStamp.isNonNaN(); return StampFactory.forFloat(JavaKind.Double, -1.0, 1.0, nonNaN); } - case SINH: case TAN: { boolean nonNaN = floatStamp.lowerBound() != Double.NEGATIVE_INFINITY && floatStamp.upperBound() != Double.POSITIVE_INFINITY && floatStamp.isNonNaN(); return StampFactory.forFloat(JavaKind.Double, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, nonNaN); @@ -166,7 +163,6 @@ public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool case LOG10 -> gen.emitMathLog(input, true); case EXP -> gen.emitMathExp(input); case SIN -> gen.emitMathSin(input); - case SINH -> gen.emitMathSinh(input); case COS -> gen.emitMathCos(input); case TAN -> gen.emitMathTan(input); case TANH -> gen.emitMathTanh(input); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java index 5d114a2ae32d..0eca9dab356f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/snippets/SnippetRuntime.java @@ -55,7 +55,6 @@ public class SnippetRuntime { * sequence. */ private static final SubstrateForeignCallDescriptor ARITHMETIC_SIN = findForeignJdkCall(UnaryOperation.SIN.foreignCallSignature.getName(), Math.class, "sin", NO_SIDE_EFFECT, true, true); - private static final SubstrateForeignCallDescriptor ARITHMETIC_SINH = findForeignJdkCall(UnaryOperation.SINH.foreignCallSignature.getName(), Math.class, "sinh", NO_SIDE_EFFECT, true, true); private static final SubstrateForeignCallDescriptor ARITHMETIC_COS = findForeignJdkCall(UnaryOperation.COS.foreignCallSignature.getName(), Math.class, "cos", NO_SIDE_EFFECT, true, true); private static final SubstrateForeignCallDescriptor ARITHMETIC_TAN = findForeignJdkCall(UnaryOperation.TAN.foreignCallSignature.getName(), Math.class, "tan", NO_SIDE_EFFECT, true, true); private static final SubstrateForeignCallDescriptor ARITHMETIC_TANH = findForeignJdkCall(UnaryOperation.TANH.foreignCallSignature.getName(), Math.class, "tanh", NO_SIDE_EFFECT, true, true); @@ -65,8 +64,8 @@ public class SnippetRuntime { private static final SubstrateForeignCallDescriptor ARITHMETIC_POW = findForeignJdkCall(BinaryOperation.POW.foreignCallSignature.getName(), Math.class, "pow", NO_SIDE_EFFECT, true, true); private static final SubstrateForeignCallDescriptor ARITHMETIC_CBRT = findForeignJdkCall(UnaryOperation.CBRT.foreignCallSignature.getName(), Math.class, "cbrt", NO_SIDE_EFFECT, true, true); - private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{UNSUPPORTED_FEATURE, REGISTER_FINALIZER, ARITHMETIC_SIN, ARITHMETIC_SINH, ARITHMETIC_COS, - ARITHMETIC_TAN, ARITHMETIC_TANH, ARITHMETIC_LOG, ARITHMETIC_LOG10, ARITHMETIC_EXP, ARITHMETIC_POW, ARITHMETIC_CBRT}; + private static final SubstrateForeignCallDescriptor[] FOREIGN_CALLS = new SubstrateForeignCallDescriptor[]{UNSUPPORTED_FEATURE, REGISTER_FINALIZER, ARITHMETIC_SIN, ARITHMETIC_COS, ARITHMETIC_TAN, + ARITHMETIC_TANH, ARITHMETIC_LOG, ARITHMETIC_LOG10, ARITHMETIC_EXP, ARITHMETIC_POW, ARITHMETIC_CBRT}; public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) { foreignCalls.register(FOREIGN_CALLS); diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java index b389c01885e8..befd0374e052 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/WasmImports.java @@ -60,7 +60,6 @@ public class WasmImports { public static final ImportDescriptor.Function F64Log = new ImportDescriptor.Function(MODULE_COMPAT, "f64log", TypeUse.forUnary(f64, f64), "Math.log"); public static final ImportDescriptor.Function F64Log10 = new ImportDescriptor.Function(MODULE_COMPAT, "f64log10", TypeUse.forUnary(f64, f64), "Math.log10"); public static final ImportDescriptor.Function F64Sin = new ImportDescriptor.Function(MODULE_COMPAT, "f64sin", TypeUse.forUnary(f64, f64), "Math.sin"); - public static final ImportDescriptor.Function F64Sinh = new ImportDescriptor.Function(MODULE_COMPAT, "f64sinh", TypeUse.forUnary(f64, f64), "Math.sinh"); public static final ImportDescriptor.Function F64Cos = new ImportDescriptor.Function(MODULE_COMPAT, "f64cos", TypeUse.forUnary(f64, f64), "Math.cos"); public static final ImportDescriptor.Function F64Tan = new ImportDescriptor.Function(MODULE_COMPAT, "f64tan", TypeUse.forUnary(f64, f64), "Math.tan"); public static final ImportDescriptor.Function F64Tanh = new ImportDescriptor.Function(MODULE_COMPAT, "f64tanh", TypeUse.forUnary(f64, f64), "Math.tanh"); diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java index de863d53c723..e79af8d3cf98 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/WebImageWasmNodeLowerer.java @@ -939,7 +939,6 @@ private Instruction lowerUnaryMathIntrinsic(UnaryMathIntrinsicNode node) { case LOG -> WasmImports.F64Log; case LOG10 -> WasmImports.F64Log10; case SIN -> WasmImports.F64Sin; - case SINH -> WasmImports.F64Sinh; case COS -> WasmImports.F64Cos; case TAN -> WasmImports.F64Tan; case TANH -> WasmImports.F64Tanh; diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js index 0da6cc686b12..51b697f45a24 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/wasm/codegen/runtime/wasm-bootstrap.js @@ -38,7 +38,6 @@ wasmImports.compat = { f64log: Math.log, f64log10: Math.log10, f64sin: Math.sin, - f64sinh: Math.sinh, f64cos: Math.cos, f64tan: Math.tan, f64tanh: Math.tanh, From 3547426eb80de643590adacbdbfe96932df2fb66 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Mon, 15 Sep 2025 11:42:25 +0200 Subject: [PATCH 05/49] Revert "[GR-68596] Update labsjdk to 26+10-jvmci-b01" This reverts commit 007426ec1f461facc1f2766db2edb106abb6bbf9, reversing changes made to e904e09c415a7ebc2ece6f3d8de81078fca075e7. --- common.json | 16 +++---- .../HotSpotCompressedKlassPointerTest.java | 4 +- .../hotspot/GraalHotSpotVMConfig.java | 3 -- .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- .../meta/HotSpotGraphBuilderPlugins.java | 18 ++++++- .../hotspot/nodes/HotSpotCompressionNode.java | 19 +++++--- .../graal/compiler/nodes/CompressionNode.java | 48 +++++++++++++------ .../espresso/classfile/JavaVersion.java | 9 ---- .../espresso/descriptors/EspressoSymbols.java | 1 - .../libjava/impl/Target_java_lang_Class.java | 1 - ...arget_jdk_internal_reflect_Reflection.java | 3 +- .../oracle/truffle/espresso/meta/Meta.java | 5 -- .../espresso/runtime/GuestAllocator.java | 4 -- .../espresso/substitutions/VersionFilter.java | 12 ----- .../com/oracle/truffle/espresso/vm/VM.java | 4 -- .../svm/core/container/ContainerLibrary.java | 8 ++-- .../com/oracle/svm/core/hub/DynamicHub.java | 24 +++++----- .../svm/core/hub/DynamicHubCompanion.java | 17 ++----- .../AbstractRuntimeClassRegistry.java | 5 +- ...arget_jdk_internal_reflect_Reflection.java | 5 ++ .../src/com/oracle/svm/hosted/SVMHost.java | 4 +- 21 files changed, 103 insertions(+), 111 deletions(-) diff --git a/common.json b/common.json index b82135fdd17f..2d4bc3971b56 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+10-1012", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+9-846", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+10", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+10-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+10-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+9", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotCompressedKlassPointerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotCompressedKlassPointerTest.java index e12281fb22a8..99984d3c4c8a 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotCompressedKlassPointerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/HotSpotCompressedKlassPointerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -40,7 +40,7 @@ public class HotSpotCompressedKlassPointerTest extends HotSpotGraalCompilerTest @Before public void setUp() { GraalHotSpotVMConfig config = runtime().getVMConfig(); - assumeTrue("compressed class pointers specific tests", config.useCompressedClassPointers && !config.useClassMetaspaceForAllClasses); + assumeTrue("compressed class pointers specific tests", config.useCompressedClassPointers); } // Non-abstract class diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 9575f0e566e9..cc4fac762a43 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -195,9 +195,6 @@ public long gcTotalCollectionsAddress() { // Compressed Oops related values. public final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); public final boolean useCompressedClassPointers = getFlag("UseCompressedClassPointers", Boolean.class); - - public final boolean useClassMetaspaceForAllClasses = getFlag("UseClassMetaspaceForAllClasses", Boolean.class); - // JDK-8305895 allows storing the compressed class pointer in the upper 22 bits of the mark // word. This runtime optimization is guarded by the flag UseCompactObjectHeaders. It depends // on compressed class pointers, meaning that if useCompactObjectHeaders is true, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index cc708e9b8f3b..7e5fe1c5ba42 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+10", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+10", 1))); + "Oracle Corporation", createLabsJDKVersion("26+9", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+9", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 49371c80f064..e4d7b54f3afc 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -289,7 +289,7 @@ public void run() { registerMathPlugins(invocationPlugins, target.arch); registerContinuationPlugins(invocationPlugins, config); registerCallSitePlugins(invocationPlugins); - registerReflectionPlugins(invocationPlugins); + registerReflectionPlugins(invocationPlugins, config); registerAESPlugins(invocationPlugins, config); registerAdler32Plugins(invocationPlugins, config); registerCRC32Plugins(invocationPlugins, config); @@ -508,7 +508,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec plugins.register(VolatileCallSite.class, plugin); } - private static void registerReflectionPlugins(InvocationPlugins plugins) { + private static void registerReflectionPlugins(InvocationPlugins plugins, GraalHotSpotVMConfig config) { Registration r = new Registration(plugins, "jdk.internal.reflect.Reflection"); r.register(new InlineOnlyInvocationPlugin("getCallerClass") { @Override @@ -517,6 +517,20 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec return true; } }); + r.register(new InvocationPlugin("getClassAccessFlags", Class.class) { + @Override + public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode arg) { + try (HotSpotInvocationPluginHelper helper = new HotSpotInvocationPluginHelper(b, targetMethod, config)) { + ValueNode klass = helper.readKlassFromClass(b.nullCheckedValue(arg)); + // Primitive Class case + ValueNode klassNonNull = helper.emitNullReturnGuard(klass, ConstantNode.forInt(Modifier.ABSTRACT | Modifier.FINAL | Modifier.PUBLIC), GraalDirectives.UNLIKELY_PROBABILITY); + // Return (Klass::_access_flags & jvmAccWrittenFlags) + ValueNode accessFlags = helper.readKlassAccessFlags(klassNonNull); + helper.emitFinalReturn(JavaKind.Int, accessFlags); + } + return true; + } + }); } private static final SpeculationReasonGroup JVMTI_NOTIFY_ALLOCATE_INSTANCE = new SpeculationReasonGroup("JvmtiNotifyAllocateInstance"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/nodes/HotSpotCompressionNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/nodes/HotSpotCompressionNode.java index 790cc1d7ec20..72ec01582775 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/nodes/HotSpotCompressionNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/nodes/HotSpotCompressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, 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. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.ResolvedJavaType; @NodeInfo(nameTemplate = "{p#op/s}", cycles = CYCLES_2, size = SIZE_2) public final class HotSpotCompressionNode extends CompressionNode { @@ -81,7 +82,9 @@ private static CompressionNode uncompress(ValueNode input, CompressEncoding enco @Override public boolean isCompressible(Constant constant) { if (constant instanceof HotSpotMetaspaceConstant mc) { - return mc.isCompressible(); + ResolvedJavaType type = mc.asResolvedJavaType(); + // As of JDK-8338526, interface and abstract types are not compressible. + return type.isArray() || (!type.isAbstract() && !type.isInterface()); } return true; } @@ -108,10 +111,14 @@ protected Constant uncompress(Constant c) { @Override public ValueNode reverse(ValueNode input) { - return switch (op) { - case Compress -> uncompress(input, encoding); - case Uncompress -> compress(input, encoding); - }; + switch (op) { + case Compress: + return uncompress(input, encoding); + case Uncompress: + return compress(input, encoding); + default: + throw GraalError.shouldNotReachHereUnexpectedValue(op); // ExcludeFromJacocoGeneratedReport + } } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/CompressionNode.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/CompressionNode.java index d08b3be2e22e..ed108c4c9686 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/CompressionNode.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/CompressionNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, 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 @@ -30,6 +30,7 @@ import jdk.graal.compiler.core.common.CompressEncoding; import jdk.graal.compiler.core.common.type.AbstractObjectStamp; 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.LIRGeneratorTool; import jdk.graal.compiler.nodeinfo.NodeInfo; @@ -82,18 +83,26 @@ public JavaConstant nullConstant() { @Override public Constant convert(Constant c, ConstantReflectionProvider constantReflection) { - return switch (op) { - case Compress -> compress(c); - case Uncompress -> uncompress(c); - }; + switch (op) { + case Compress: + return compress(c); + case Uncompress: + return uncompress(c); + default: + throw GraalError.shouldNotReachHereUnexpectedValue(op); // ExcludeFromJacocoGeneratedReport + } } @Override public Constant reverse(Constant c, ConstantReflectionProvider constantReflection) { - return switch (op) { - case Compress -> uncompress(c); - case Uncompress -> compress(c); - }; + switch (op) { + case Compress: + return uncompress(c); + case Uncompress: + return compress(c); + default: + throw GraalError.shouldNotReachHereUnexpectedValue(op); // ExcludeFromJacocoGeneratedReport + } } /** @@ -129,12 +138,14 @@ public boolean isCompressible(Constant constant) { @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue instanceof ConstantNode constant) { + if (forValue.isConstant()) { + ConstantNode constant = (ConstantNode) forValue; if (isCompressible(constant.getValue())) { return ConstantNode.forConstant(stamp(NodeView.DEFAULT), convert(constant.getValue(), tool.getConstantReflection()), constant.getStableDimension(), constant.isDefaultStable(), tool.getMetaAccess()); } - } else if (forValue instanceof CompressionNode other) { + } else if (forValue instanceof CompressionNode) { + CompressionNode other = (CompressionNode) forValue; if (op != other.op && encoding.equals(other.encoding)) { return other.getValue(); } @@ -153,10 +164,17 @@ public void generate(NodeLIRBuilderTool gen) { } LIRGeneratorTool tool = gen.getLIRGeneratorTool(); - Value result = switch (op) { - case Compress -> tool.emitCompress(gen.operand(value), encoding, nonNull); - case Uncompress -> tool.emitUncompress(gen.operand(value), encoding, nonNull); - }; + Value result; + switch (op) { + case Compress: + result = tool.emitCompress(gen.operand(value), encoding, nonNull); + break; + case Uncompress: + result = tool.emitUncompress(gen.operand(value), encoding, nonNull); + break; + default: + throw GraalError.shouldNotReachHereUnexpectedValue(op); // ExcludeFromJacocoGeneratedReport + } gen.setResult(this, result); } diff --git a/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java b/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java index 9dca107df3be..4adfd598b04f 100644 --- a/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java +++ b/espresso-shared/src/com.oracle.truffle.espresso.classfile/src/com/oracle/truffle/espresso/classfile/JavaVersion.java @@ -43,7 +43,6 @@ public static final class VersionRange { public static final VersionRange VERSION_22_OR_HIGHER = higher(22); public static final VersionRange VERSION_24_OR_LOWER = lower(24); public static final VersionRange VERSION_25_OR_HIGHER = higher(25); - public static final VersionRange VERSION_26_OR_HIGHER = higher(26); public static final VersionRange ALL = between(0, LATEST_SUPPORTED); public static final VersionRange VERSION_9_TO_21 = between(9, 21); @@ -220,14 +219,6 @@ public boolean java25OrLater() { return version >= 25; } - public boolean java25OrEarlier() { - return version <= 25; - } - - public boolean java26OrLater() { - return version >= 26; - } - public boolean inRange(int low, int high) { return version >= low && version <= high; } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java index 84db6a2943ff..4aa65c4ee79c 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java @@ -616,7 +616,6 @@ public static class Names { public static final Symbol componentType = SYMBOLS.putName("componentType"); public static final Symbol protectionDomain = SYMBOLS.putName("protectionDomain"); public static final Symbol modifiers = SYMBOLS.putName("modifiers"); - public static final Symbol classFileAccessFlags = SYMBOLS.putName("classFileAccessFlags"); public static final Symbol primitive = SYMBOLS.putName("primitive"); public static final Symbol signers = SYMBOLS.putName("signers"); // j.l.ClassLoader diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_java_lang_Class.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_java_lang_Class.java index 5e0fa170f882..377471485761 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_java_lang_Class.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_java_lang_Class.java @@ -186,7 +186,6 @@ public static boolean isRecord0(@JavaType(Class.class) StaticObject self, @Injec } @Substitution(hasReceiver = true) - // Method no longer exists in 26. public static int getClassAccessFlagsRaw0(@JavaType(Class.class) StaticObject self, @Inject EspressoContext ctx) { return ctx.getVM().JVM_GetClassAccessFlags(self); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_Reflection.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_Reflection.java index b734f1e9e574..0f531d78d591 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_Reflection.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/libs/libjava/impl/Target_jdk_internal_reflect_Reflection.java @@ -29,12 +29,11 @@ import com.oracle.truffle.espresso.substitutions.Inject; import com.oracle.truffle.espresso.substitutions.JavaType; import com.oracle.truffle.espresso.substitutions.Substitution; -import com.oracle.truffle.espresso.substitutions.VersionFilter; import com.oracle.truffle.espresso.vm.VM; @EspressoSubstitutions(type = "Ljdk/internal/reflect/Reflection;", group = LibJava.class) public final class Target_jdk_internal_reflect_Reflection { - @Substitution(languageFilter = VersionFilter.Java25OrEarlier.class) + @Substitution public static int getClassAccessFlags(@JavaType(Class.class) StaticObject cls, @Inject EspressoContext ctx) { return ctx.getVM().JVM_GetClassAccessFlags(cls); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java index ef03e6032a65..857107fc9384 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java @@ -33,7 +33,6 @@ import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_22_TO_23; import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_24_OR_LOWER; import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_25_OR_HIGHER; -import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_26_OR_HIGHER; import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_8_OR_LOWER; import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_9_OR_HIGHER; import static com.oracle.truffle.espresso.classfile.JavaVersion.VersionRange.VERSION_9_TO_21; @@ -118,9 +117,6 @@ public Meta(EspressoContext context) { java_lang_Class_modifiers = diff() // .field(VERSION_25_OR_HIGHER, Names.modifiers, Types._char) // .notRequiredField(java_lang_Class); - java_lang_Class_classFileAccessFlags = diff() // - .field(VERSION_26_OR_HIGHER, Names.classFileAccessFlags, Types._char) // - .notRequiredField(java_lang_Class); java_lang_Class_primitive = diff() // .field(VERSION_25_OR_HIGHER, Names.primitive, Types._boolean) // .notRequiredField(java_lang_Class); @@ -1365,7 +1361,6 @@ private DiffVersionLoadHelper diff() { public final Field java_lang_Class_module; public final Field java_lang_Class_classLoader; public final Field java_lang_Class_modifiers; - public final Field java_lang_Class_classFileAccessFlags; public final Field java_lang_Class_primitive; public final Field sun_reflect_ConstantPool_constantPoolOop; public final ArrayKlass java_lang_Class_array; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/GuestAllocator.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/GuestAllocator.java index 204e3d37a9f5..18cb1d3fbab7 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/GuestAllocator.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/GuestAllocator.java @@ -178,10 +178,6 @@ public StaticObject createClass(Klass klass) { meta.java_lang_Class_modifiers.setChar(newObj, (char) klass.getClassModifiers()); meta.java_lang_Class_primitive.setBoolean(newObj, klass.isPrimitive()); } - if (lang.getJavaVersion().java26OrLater()) { - assert meta.java_lang_Class_classFileAccessFlags != null; - meta.java_lang_Class_classFileAccessFlags.setChar(newObj, (char) VM.getClassAccessFlags(klass)); - } return trackAllocation(klass, newObj); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java index 607fda3739ef..c2e6588d6834 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/substitutions/VersionFilter.java @@ -225,16 +225,4 @@ public boolean isValidFor(JavaVersion version) { return version.java25OrLater(); } } - - final class Java25OrEarlier implements VersionFilter { - public static final Java25OrEarlier INSTANCE = new Java25OrEarlier(); - - private Java25OrEarlier() { - } - - @Override - public boolean isValidFor(JavaVersion version) { - return version.java25OrEarlier(); - } - } } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java index 322d124c151b..f5164240d521 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/vm/VM.java @@ -1378,10 +1378,6 @@ public boolean JVM_IsRecord(@JavaType(Class.class) StaticObject self) { @VmImpl(isJni = true) public int JVM_GetClassAccessFlags(@JavaType(Class.class) StaticObject clazz) { Klass klass = clazz.getMirrorKlass(getMeta()); - return getClassAccessFlags(klass); - } - - public static int getClassAccessFlags(Klass klass) { if (klass.isPrimitive()) { final int primitiveFlags = ACC_ABSTRACT | ACC_FINAL | ACC_PUBLIC; assert klass.getModifiers() == primitiveFlags; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 52517c20f395..ab2e3d30defb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -64,7 +64,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/os/posix/os_posix.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/os/posix/os_posix.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.hpp") @@ -72,13 +72,13 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allStatic.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/nmt/memTag.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/os.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/runtime/os.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/os.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/globalDefinitions.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.hpp") @@ -86,7 +86,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+10/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { 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 46dafe7b2417..a829e31355f6 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 @@ -93,7 +93,6 @@ import com.oracle.svm.configure.ClassNameSupport; import com.oracle.svm.configure.config.SignatureUtil; - import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.BuildPhaseProvider.AfterHeapLayout; import com.oracle.svm.core.BuildPhaseProvider.AfterHostedUniverse; @@ -439,8 +438,8 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ @Platforms(Platform.HOSTED_ONLY.class) public DynamicHub(Class hostedJavaClass, String name, byte hubType, ReferenceType referenceType, DynamicHub superType, - DynamicHub componentHub, String sourceFileName, int modifiers, int classFileAccessFlags, short flags, - ClassLoader classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature, int layerId) { + DynamicHub componentHub, String sourceFileName, int modifiers, short flags, ClassLoader classLoader, + Class nestHost, String simpleBinaryName, Object declaringClass, String signature, int layerId) { this.hostedJavaClass = hostedJavaClass; this.name = name; this.hubType = hubType; @@ -454,7 +453,7 @@ public DynamicHub(Class hostedJavaClass, String name, byte hubType, Reference Object loader = PredefinedClassesSupport.isPredefined(hostedJavaClass) ? NO_CLASS_LOADER : classLoader; this.companion = DynamicHubCompanion.createHosted(hostedJavaClass.getModule(), superType, sourceFileName, - modifiers, classFileAccessFlags, loader, nestHost, simpleBinaryName, declaringClass, signature); + modifiers, loader, nestHost, simpleBinaryName, declaringClass, signature); } /** @@ -474,7 +473,7 @@ public DynamicHub(Class hostedJavaClass, String name, byte hubType, Reference */ @NeverInline("Fields of DynamicHub are immutable. Immutable reads could float above ANY_LOCATION writes.") public static DynamicHub allocate(String name, DynamicHub superHub, Object interfacesEncoding, DynamicHub componentHub, String sourceFileName, - int modifiers, int classFileAccessFlags, short flags, ClassLoader classLoader, String simpleBinaryName, Module module, + int modifiers, short flags, ClassLoader classLoader, String simpleBinaryName, Module module, Object declaringClass, String signature, int typeID, int interfaceID, short numClassTypes, short typeIDDepth, @@ -502,7 +501,7 @@ public static DynamicHub allocate(String name, DynamicHub superHub, Object inter } } - DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classFileAccessFlags, classLoader, simpleBinaryName, declaringClass, + DynamicHubCompanion companion = DynamicHubCompanion.createAtRuntime(module, superHub, sourceFileName, modifiers, classLoader, simpleBinaryName, declaringClass, signature); /* Always allow unsafe allocation for classes that were loaded at run-time. */ @@ -1144,13 +1143,8 @@ public int getModifiers() { return companion.modifiers; } - @Substitute - int getClassFileAccessFlags() { + public int getClassAccessFlags() { if (ImageLayerBuildingSupport.buildingImageLayer()) { - /* - * Currently, layered images do not use the Class#classFileAccessFlags. This will be - * addressed by GR-68631. - */ int classAccessFlags = 0; for (var reflectionMetadataSingleton : LayeredReflectionMetadataSingleton.singletons()) { ImageReflectionMetadata reflectionMetadata = reflectionMetadataSingleton.getReflectionMetadata(this); @@ -1158,10 +1152,14 @@ int getClassFileAccessFlags() { } return classAccessFlags; } else { - return companion.classFileAccessFlags; + return getClassAccessFlags(reflectionMetadata()); } } + private int getClassAccessFlags(ReflectionMetadata reflectionMetadata) { + return reflectionMetadata != null ? (reflectionMetadata.getClassFlags() & CLASS_ACCESS_FLAGS_MASK) : companion.modifiers; + } + @Substitute private DynamicHub getComponentType() { return componentType; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java index 341349df75b8..256eeaf2e11e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHubCompanion.java @@ -67,12 +67,6 @@ public final class DynamicHubCompanion { /** The {@link Modifier modifiers} of this class. */ final int modifiers; - /** - * The access flags of this class as they were in the class's bytecode, including the original - * setting of ACC_SUPER. - */ - final int classFileAccessFlags; - /** * The class that serves as the host for the nest. All nestmates have the same host. Always * encoded with null for Dynamic hubs allocated at runtime. @@ -155,25 +149,24 @@ public final class DynamicHubCompanion { @Stable boolean canUnsafeAllocate; @Platforms(Platform.HOSTED_ONLY.class) - static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers, int classFileAccessFlags, + static DynamicHubCompanion createHosted(Module module, DynamicHub superHub, String sourceFileName, int modifiers, Object classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { - return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classFileAccessFlags, classLoader, nestHost, simpleBinaryName, declaringClass, signature); + return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, nestHost, simpleBinaryName, declaringClass, signature); } - static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers, int classFileAccessFlags, + static DynamicHubCompanion createAtRuntime(Module module, DynamicHub superHub, String sourceFileName, int modifiers, ClassLoader classLoader, String simpleBinaryName, Object declaringClass, String signature) { assert RuntimeClassLoading.isSupported(); - return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classFileAccessFlags, classLoader, null, simpleBinaryName, declaringClass, signature); + return new DynamicHubCompanion(module, superHub, sourceFileName, modifiers, classLoader, null, simpleBinaryName, declaringClass, signature); } - private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers, int classFileAccessFlags, + private DynamicHubCompanion(Module module, DynamicHub superHub, String sourceFileName, int modifiers, Object classLoader, Class nestHost, String simpleBinaryName, Object declaringClass, String signature) { this.module = module; this.superHub = superHub; this.sourceFileName = sourceFileName; this.modifiers = modifiers; - this.classFileAccessFlags = classFileAccessFlags; this.nestHost = nestHost; this.simpleBinaryName = simpleBinaryName; this.declaringClass = declaringClass; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractRuntimeClassRegistry.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractRuntimeClassRegistry.java index 3fa34a7ffd22..2a5753013ffd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractRuntimeClassRegistry.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/registry/AbstractRuntimeClassRegistry.java @@ -43,11 +43,11 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.graal.meta.KnownOffsets; -import com.oracle.svm.core.hub.crema.CremaSupport; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.DynamicHubTypeCheckUtil; import com.oracle.svm.core.hub.RuntimeClassLoading; import com.oracle.svm.core.hub.RuntimeClassLoading.ClassDefinitionInfo; +import com.oracle.svm.core.hub.crema.CremaSupport; import com.oracle.svm.core.hub.registry.SVMSymbols.SVMTypes; import com.oracle.svm.core.jdk.Target_java_lang_ClassLoader; import com.oracle.svm.core.util.VMError; @@ -289,7 +289,6 @@ private Class createClass(ParserKlass parsed, ClassDefinitionInfo info, Symbo String classSignature = getClassSignature(parsed); int modifiers = getClassModifiers(parsed); - int classFileAccessFlags = parsed.getFlags(); /* * The TypeCheckBuilder considers interface arrays as interfaces. Since we are dealing with @@ -413,7 +412,7 @@ private Class createClass(ParserKlass parsed, ClassDefinitionInfo info, Symbo checkNotHybrid(parsed); DynamicHub hub = DynamicHub.allocate(externalName, superHub, interfacesEncoding, null, - sourceFile, modifiers, classFileAccessFlags, flags, getClassLoader(), simpleBinaryName, module, enclosingClass, classSignature, + sourceFile, modifiers, flags, getClassLoader(), simpleBinaryName, module, enclosingClass, classSignature, typeID, interfaceID, numClassTypes, typeIDDepth, numIterableInterfaces, openTypeWorldTypeCheckSlots, openTypeWorldInterfaceHashTable, openTypeWorldInterfaceHashParam, dispatchTableLength, afterFieldsOffset, isValueBased); 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 3475bb62f960..76e39f35971d 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 @@ -44,6 +44,11 @@ private static Class getCallerClass() { return StackTraceUtils.getCallerClass(KnownIntrinsics.readCallerStackPointer(), true); } + @Substitute + private static int getClassAccessFlags(DynamicHub cls) { + return cls.getClassAccessFlags(); + } + @Substitute private static boolean areNestMates(Class currentClass, Class memberClass) { return DynamicHub.fromClass(currentClass).isNestmateOf(memberClass); 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 50edf6d8ff29..bdb44a1e5b68 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 @@ -164,7 +164,6 @@ import jdk.graal.compiler.phases.common.CanonicalizerPhase; import jdk.graal.compiler.virtual.phases.ea.PartialEscapePhase; import jdk.internal.loader.NativeLibraries; -import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.DontInline; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; @@ -558,7 +557,6 @@ private DynamicHub createHub(AnalysisType type) { componentHub = dynamicHub(hybrid.componentType()); } int modifiers = javaClass.getModifiers(); - int classFileAccessFlags = Reflection.getClassAccessFlags(javaClass); /* * If the class is an application class then it was loaded by NativeImageClassLoader. The @@ -604,7 +602,7 @@ private DynamicHub createHub(AnalysisType type) { isLambdaFormHidden, isLinked, isProxyClass); return new DynamicHub(javaClass, className, computeHubType(type), ReferenceType.computeReferenceType(javaClass), - superHub, componentHub, sourceFileName, modifiers, classFileAccessFlags, flags, hubClassLoader, nestHost, + superHub, componentHub, sourceFileName, modifiers, flags, hubClassLoader, nestHost, simpleBinaryName, getDeclaringClass(javaClass), getSignature(javaClass), layerId); } From 158b528a2221f177797b0ea084beaff6a393158e Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 11:19:51 +0200 Subject: [PATCH 06/49] Revert "[GR-68382] Update labsjdk to 26+9-jvmci-b01" This reverts commit 634bfcd223e84015e3373342f0e55b3f9a4ed97b, reversing changes made to f2a0e106c2908a46c16ae1313f85b27431adc9cd. --- common.json | 16 ++++++++-------- .../compiler/hotspot/GraalHotSpotVMConfig.java | 2 +- .../compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../genscavenge/AbstractCollectionPolicy.java | 3 +-- .../genscavenge/AdaptiveCollectionPolicy.java | 16 ++++++++-------- .../svm/core/container/ContainerLibrary.java | 12 ++++++------ .../svm/core/jvmti/headers/JvmtiDirectives.java | 2 +- 7 files changed, 27 insertions(+), 28 deletions(-) diff --git a/common.json b/common.json index 2d4bc3971b56..8d6bc8d371e9 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+9-846", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+7-655", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+9", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+9-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+9-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+8", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index cc4fac762a43..3fc50f8f3d6f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -461,7 +461,7 @@ public int threadTlabTopOffset() { public final long deoptBlobUncommonTrap = getFieldValue("CompilerToVM::Data::SharedRuntime_deopt_blob_uncommon_trap", Long.class, "address"); public final long updateBytesCRC32Stub = getFieldValue("StubRoutines::_updateBytesCRC32", Long.class, "address"); - public final long crcTableAddress = getFieldValue("CompilerToVM::Data::crc_table_addr", Long.class, "address"); + public final long crcTableAddress = getFieldValue("StubRoutines::_crc_table_adr", Long.class, "address"); public final long md5ImplCompressMultiBlock = getFieldValue("StubRoutines::_md5_implCompressMB", Long.class, "address"); public final long sha1ImplCompressMultiBlock = getFieldValue("StubRoutines::_sha1_implCompressMB", Long.class, "address"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 7e5fe1c5ba42..4264b7aed712 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+9", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+9", 1))); + "Oracle Corporation", createLabsJDKVersion("26+8", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+8", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index a4417d2c44c8..f9ed146f73f2 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -75,8 +75,7 @@ static int getMaxSurvivorSpaces(Integer userValue) { protected static final int INITIAL_SURVIVOR_RATIO = 8; @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/shared/gc_globals.hpp#L409-L411") // protected static final int MIN_SURVIVOR_RATIO = 3; - // GR-68417: adopt "JDK-8338977: Parallel: Improve heap resizing heuristics" - // @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/shared/gc_globals.hpp#L340-L342") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/shared/gc_globals.hpp#L340-L342") // protected static final int ADAPTIVE_TIME_WEIGHT = 25; /* Constants to compute defaults for values which can be set through existing options. */ diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index 7bd1411674a2..7a6db39f823e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -30,6 +30,7 @@ import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.heap.GCCause; +import com.oracle.svm.core.util.BasedOnJDKFile; import com.oracle.svm.core.util.TimeUtils; import com.oracle.svm.core.util.Timer; import com.oracle.svm.core.util.UnsignedUtils; @@ -44,14 +45,13 @@ * its base class {@code AdaptiveSizePolicy}. Method and variable names have been kept mostly the * same for comparability. */ -// GR-68417: adopt "JDK-8338977: Parallel: Improve heap resizing heuristics" -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+2/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+7/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+1/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/share/gc/parallel/psParallelCompact.cpp#L954-L1167") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/gc/parallel/psScavenge.cpp#L319-L634") -// @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/gc/shared/gc_globals.hpp#L303-L407") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+2/src/hotspot/share/gc/shared/adaptiveSizePolicy.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+7/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+1/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/share/gc/parallel/psParallelCompact.cpp#L954-L1167") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/gc/parallel/psScavenge.cpp#L319-L634") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/gc/shared/gc_globals.hpp#L303-L407") class AdaptiveCollectionPolicy extends AbstractCollectionPolicy { /* diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index ab2e3d30defb..810799dfd529 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -77,17 +77,17 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/share/utilities/globalDefinitions.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/ostream.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/permitForbiddenFunctions.hpp") // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/runtime/globals.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/utilities/debug.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { static final int VERSION = 240100; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java index 3ef48ecd7914..0a05da75a6b8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java @@ -35,7 +35,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.util.BasedOnJDKFile; -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+9/src/hotspot/share/prims/jvmti.xml") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+7/src/hotspot/share/prims/jvmti.xml") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+11/src/hotspot/share/prims/jvmtiH.xsl") class JvmtiDirectives implements CContext.Directives { private final Path jdkIncludeDir = Paths.get(System.getProperty("java.home")).resolve("include"); From 355b6b1b78822336850dc45a5ec2fc5c5cf034a2 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 11:23:58 +0200 Subject: [PATCH 07/49] Revert "[GR-68053] Update labsjdk to 26+8-jvmci-b01." This reverts commit 782b28c0a4978f1883d72d784967eaf262d06d34, reversing changes made to c18c686390ee4a15c3c3769a553d378f0c23ea1c. --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../core/genscavenge/AdaptiveCollectionPolicy.java | 2 +- .../svm/core/container/ContainerLibrary.java | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common.json b/common.json index 8d6bc8d371e9..7564ca657116 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+8", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+8-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+8-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+7", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 4264b7aed712..5667f980e925 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+8", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+8", 1))); + "Oracle Corporation", createLabsJDKVersion("26+7", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+7", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index 7a6db39f823e..ccef7cb2a6fa 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -49,7 +49,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+7/src/hotspot/share/gc/shared/adaptiveSizePolicy.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+1/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/share/gc/parallel/psParallelCompact.cpp#L954-L1167") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/parallel/psParallelCompact.cpp#L964-L1181") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/gc/parallel/psScavenge.cpp#L319-L634") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/gc/shared/gc_globals.hpp#L303-L407") class AdaptiveCollectionPolicy extends AbstractCollectionPolicy { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 810799dfd529..dc47be7c5b58 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -60,7 +60,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/os/linux/os_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/os/linux/os_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") @@ -78,7 +78,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+8/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/utilities/globalDefinitions.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.hpp") From e7d0b2ef2b7692da121f560e5201dd90f6a9f608 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 14:38:57 +0200 Subject: [PATCH 08/49] Revert "[GR-67719] Update labsjdk to 26+7-jvmci-b01." This reverts commit b6bc12be59f7fc7062e9e3bb01361eb61fb416aa, reversing changes made to 06223af9c9082088a15f77cd9a6b15647b6f66d1. --- ci/ci_common/galahad-common.libsonnet | 4 ++-- common.json | 16 ++++++++-------- compiler/mx.compiler/mx_compiler.py | 3 +++ .../compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../com/oracle/truffle/espresso/impl/Method.java | 4 ++-- .../oracle/svm/core/c/locale/LocaleCHelper.java | 2 +- .../core/jfr/Target_jdk_jfr_internal_JVM.java | 10 ++-------- .../svm/core/jvmti/headers/JvmtiDirectives.java | 2 +- .../src/locale.c | 2 -- .../tck/resources/jdk_privileged_methods.json | 11 +++++++++++ 10 files changed, 32 insertions(+), 26 deletions(-) diff --git a/ci/ci_common/galahad-common.libsonnet b/ci/ci_common/galahad-common.libsonnet index 3b89df1fcd77..200913fca05d 100644 --- a/ci/ci_common/galahad-common.libsonnet +++ b/ci/ci_common/galahad-common.libsonnet @@ -11,9 +11,9 @@ local utils = import "common-utils.libsonnet"; , # Return true if this is a gate job. local is_gate(b) = - std.setInter(["gate", "tier1", "tier2", "tier3"], b.targets) != [] + std.find("gate", b.targets) != [] , - local gate_or_postmerge_targets = ["gate", "tier1", "tier2", "tier3", "post-merge", "deploy"], + local gate_or_postmerge_targets = ["gate", "post-merge", "deploy"], # Return true if this is a gate or post-merge/deployment job. local is_gate_or_postmerge(b) = std.setInter(gate_or_postmerge_targets, b.targets) != [] diff --git a/common.json b/common.json index 7564ca657116..57c6d5d8f909 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+7-655", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+6-570", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+7", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+7-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+7-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+6", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+6-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+6-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+6-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+6-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 39d7fff61ebd..b7fab03c97ab 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1264,6 +1264,9 @@ def get_latest_jvmci_version(): mx.abort(msg) if version_check_setting == 'strict' and not success: + # [GR-67676] The `-llvm` artifacts are currently not up to date due to a JDK build system problem JDK-8361844. + if latest.endswith('-llvm'): + return if latest == 'not found': msg = f'No JVMCI JDK found in {common_path} that matches {_jdk_jvmci_version}.' msg += os.linesep + f'Check that {latest} matches the versions of the other JVMCI JDKs.' diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 5667f980e925..764f6195654c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+7", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+7", 1))); + "Oracle Corporation", createLabsJDKVersion("26+6", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+6", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java index f75cc86b23af..3091c81ac2a9 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java @@ -1961,10 +1961,10 @@ private EspressoException unsatisfiedLinkError() { private void checkPoisonPill(Meta meta) { if (poisonPill) { // Conflicting Maximally-specific non-abstract interface methods. - if (getJavaVersion().inRange(9, 25) && getSpecComplianceMode() == EspressoOptions.SpecComplianceMode.HOTSPOT) { + if (getJavaVersion().java9OrLater() && getSpecComplianceMode() == EspressoOptions.SpecComplianceMode.HOTSPOT) { /* * Supposed to be IncompatibleClassChangeError (see jvms-6.5.invokeinterface), - * but HotSpot throws AbstractMethodError. See JDK-8356942. + * but HotSpot throws AbstractMethodError. */ throw meta.throwExceptionWithMessage(meta.java_lang_AbstractMethodError, "Conflicting default methods: " + getName()); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleCHelper.java index 380121402099..5832b2e9bc73 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleCHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/locale/LocaleCHelper.java @@ -59,7 +59,7 @@ class LocaleCHelper { * {@link #SVM_LOCALE_INITIALIZATION_OUT_OF_MEMORY}. */ @CFunction(value = "svm_initialize_locale", transition = NO_TRANSITION) - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+7/src/java.base/unix/native/libjava/java_props_md.c#L71-L359") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/unix/native/libjava/java_props_md.c#L71-L357") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+17/src/java.base/unix/native/libjava/java_props_md.c#L436-L460") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/java.base/windows/native/libjava/java_props_md.c#L263-L721") static native int initializeLocale(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java index 2f66a5ed11f1..3b4d065267f9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java @@ -296,15 +296,9 @@ public static void setMethodSamplingPeriod(long type, long intervalMillis) { SubstrateJVM.get().setMethodSamplingInterval(type, intervalMillis); } - /** See {@code JVM#setCPURate}. */ + /** See {@code JVM#setCPUThrottle}. */ @Substitute - public static void setCPURate(double rate) { - // JFR CPUTimeSample is not supported. - } - - /** See {@code JVM#setCPUPeriod}. */ - @Substitute - public static void setCPUPeriod(long periodNanos) { + public static void setCPUThrottle(double rate, boolean autoAdapt) { // JFR CPUTimeSample is not supported. } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java index 0a05da75a6b8..f494545fc624 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java @@ -35,7 +35,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.util.BasedOnJDKFile; -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+7/src/hotspot/share/prims/jvmti.xml") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/share/prims/jvmti.xml") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+11/src/hotspot/share/prims/jvmtiH.xsl") class JvmtiDirectives implements CContext.Directives { private final Path jdkIncludeDir = Paths.get(System.getProperty("java.home")).resolve("include"); diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/locale.c b/substratevm/src/com.oracle.svm.native.libchelper/src/locale.c index bda9b7185476..25889390f680 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/locale.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/locale.c @@ -206,7 +206,6 @@ static int ParseLocale(int cat, char ** std_language, char ** std_script, if (language != NULL && mapLookup(language_names, language, std_language) == 0) { *std_language = malloc(strlen(language)+1); if (*std_language == NULL) { - free(temp); free(encoding_variant); return SVM_LOCALE_INITIALIZATION_OUT_OF_MEMORY; } @@ -219,7 +218,6 @@ static int ParseLocale(int cat, char ** std_language, char ** std_script, if (mapLookup(country_names, country, std_country) == 0) { *std_country = malloc(strlen(country)+1); if (*std_country == NULL) { - free(temp); free(encoding_variant); return SVM_LOCALE_INITIALIZATION_OUT_OF_MEMORY; } diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json index 38290834d06b..dd990fc9e451 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json @@ -2839,6 +2839,17 @@ } ] }, + { + "name": "java.applet.Applet", + "methods": [ + { + "name": "setStub", + "parameterTypes": [ + "java.applet.AppletStub" + ] + } + ] + }, { "name": "java.awt.Button", "methods": [ From 9479d28871728f0407f625e11219fdff79eb1aa4 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 15:17:34 +0200 Subject: [PATCH 09/49] Revert "[GR-67452] Update labsjdk to 26+6-jvmci-b01" This reverts commit 4c84b4e3c8e1da3f94c9fec6c33ad12773e2ee43, reversing changes made to d08dc0e15310e6534ad3df18edc368ddae46947f. --- common.json | 12 ++-- compiler/mx.compiler/mx_compiler.py | 3 - .../core/test/CountedLoopOverflowTest.java | 6 +- .../compiler/core/test/GraalCompilerTest.java | 38 +++++++--- .../core/test/tutorial/InvokeGraal.java | 2 +- .../test/DeoptimizeReasonAccountingTest.java | 4 +- .../hotspot/test/JVMCIInfopointErrorTest.java | 2 +- .../test/RangeCheckPredicatesTest.java | 2 +- .../test/ArrayCopyExceptionSeenTest.java | 2 +- .../test/DeoptimizeOnIntegerExactTest.java | 4 +- .../graal/compiler/core/target/Backend.java | 48 ++++++++++++- .../compiler/hotspot/CompilationTask.java | 3 - .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- .../aarch64/AArch64HotSpotBackend.java | 3 +- .../meta/UnimplementedGraalIntrinsics.java | 4 +- .../graal/compiler/hotspot/stubs/Stub.java | 2 +- .../compiler/truffle/TruffleCompilerImpl.java | 2 +- .../jvmci/DummyCodeCacheProvider.java | 2 +- .../espresso/descriptors/EspressoSymbols.java | 1 + .../oracle/truffle/espresso/meta/Meta.java | 7 +- .../runtime/EspressoReferenceDrainer.java | 12 ++-- sdk/mx.sdk/mx_sdk_benchmark.py | 7 -- substratevm/mx.substratevm/suite.py | 2 +- .../svm/core/container/ContainerLibrary.java | 8 +-- .../svm/core/heap/ReferenceInternals.java | 21 +++++- .../heap/Target_java_lang_ref_Reference.java | 3 - .../heap/Target_java_nio_BufferCleaner.java | 70 ------------------- ...a => Target_jdk_internal_ref_Cleaner.java} | 23 +++++- .../svm/core/heap/Target_sun_nio_Cleaner.java | 34 --------- .../image/DisallowedImageHeapObjects.java | 18 ++--- .../svm/core/jdk/Target_java_nio_Bits.java | 2 - .../jdk/Target_java_nio_DirectByteBuffer.java | 8 +-- .../IsolateAwareCodeCacheProvider.java | 6 +- .../meta/SubstrateCodeCacheProvider.java | 4 +- .../hosted/code/HostedCodeCacheProvider.java | 4 +- .../DisallowedImageHeapObjectFeature.java | 4 +- .../tck/resources/jdk_allowed_methods.json | 20 +++--- .../chromeinspector/test/EnginesGCedTest.java | 9 +-- 38 files changed, 191 insertions(+), 215 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/{Target_java_lang_ref_Cleaner.java => Target_jdk_internal_ref_Cleaner.java} (88%) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_sun_nio_Cleaner.java diff --git a/common.json b/common.json index 57c6d5d8f909..5d978eadf36b 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+6-570", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+5-361", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,12 +54,12 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+6", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+6-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+6-jvmci-b01-debug", "platformspecific": true }, + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+5", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01-debug", "platformspecific": true }, "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+6-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+6-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01-debug", "platformspecific": true }, "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01-sulong", "platformspecific": true } }, diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index b7fab03c97ab..39d7fff61ebd 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1264,9 +1264,6 @@ def get_latest_jvmci_version(): mx.abort(msg) if version_check_setting == 'strict' and not success: - # [GR-67676] The `-llvm` artifacts are currently not up to date due to a JDK build system problem JDK-8361844. - if latest.endswith('-llvm'): - return if latest == 'not found': msg = f'No JVMCI JDK found in {common_path} that matches {_jdk_jvmci_version}.' msg += os.linesep + f'Check that {latest} matches the versions of the other JVMCI JDKs.' diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java index d08937cf9995..2a386e4c4411 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java @@ -121,7 +121,7 @@ public void testDownOverflow() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { @@ -142,7 +142,7 @@ public void testDownOverflowUnsigned() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { @@ -163,7 +163,7 @@ public void testUpOverflow() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java index 5f8d751becf5..517427889029 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java @@ -903,17 +903,25 @@ protected Result executeActual(ResolvedJavaMethod method, Object receiver, Objec } protected Result executeActual(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { + return executeActual(options, method, false, receiver, args); + } + + protected Result executeActual(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Object receiver, Object... args) { before(method); Object[] executeArgs = argsWithReceiver(receiver, args); checkArgs(method, executeArgs); - InstalledCode compiledMethod = getCode(method, options); + InstalledCode compiledMethod = getCode(method, null, false, installAsDefault, options); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { return new Result(null, e); } finally { + // Prevent a subsequent `executeExpected' call from entering the compiled method + if (installAsDefault) { + compiledMethod.invalidate(); + } after(); } } @@ -1007,9 +1015,13 @@ protected Result test(ResolvedJavaMethod method, Object receiver, Object... args } protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { + return test(options, method, false, receiver, args); + } + + protected final Result test(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); if (getCodeCache() != null) { - testAgainstExpected(options, method, expect, CollectionsUtil.setOf(), receiver, args); + testAgainstExpected(options, method, installAsDefault, expect, CollectionsUtil.setOf(), receiver, args); } return expect; } @@ -1032,26 +1044,36 @@ protected Object[] applyArgSuppliers(Object... args) { } protected final void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(getInitialOptions(), method, expect, CollectionsUtil.setOf(), receiver, args); + testAgainstExpected(getInitialOptions(), method, false, expect, CollectionsUtil.setOf(), receiver, args); } protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(options, method, expect, CollectionsUtil.setOf(), receiver, args); + testAgainstExpected(options, method, false, expect, CollectionsUtil.setOf(), receiver, args); } protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - Result actual = executeActualCheckDeopt(options, method, shouldNotDeopt, receiver, args); + testAgainstExpected(options, method, true, expect, shouldNotDeopt, receiver, args); + } + + private void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Result expect, Set shouldNotDeopt, Object receiver, + Object... args) { + Result actual = executeActualCheckDeopt(options, method, installAsDefault, shouldNotDeopt, receiver, args); assertEquals(expect, actual); } protected final Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { + return executeActualCheckDeopt(options, method, !shouldNotDeopt.isEmpty(), shouldNotDeopt, receiver, args); + } + + protected final Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Set shouldNotDeopt, Object receiver, + Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); } - Result actual = executeActual(options, method, receiver, args); + Result actual = executeActual(options, method, installAsDefault, receiver, args); profile = method.getProfilingInfo(); // profile can change after execution for (DeoptimizationReason reason : shouldNotDeopt) { Assert.assertEquals("wrong number of deopt counts for " + reason, (int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); @@ -1184,7 +1206,7 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str } catch (Throwable e) { throw debug.handle(e); } - if (useCache) { + if (useCache && !installAsDefault) { cache.get().put(installedCodeOwner, Pair.create(options, installedCode)); } return installedCode; @@ -1365,7 +1387,7 @@ protected SpeculationLog createSpeculationLog() { } protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.createInstalledCode(debug, method, null, compilationResult, null, false, true, null); + return backend.addInstalledCode(debug, method, null, compilationResult); } protected InstalledCode addDefaultMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java index e744110062e4..a17fa2ad1acf 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java @@ -145,7 +145,7 @@ protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) { * Install the compilation result into the VM, i.e., copy the byte[] array that contains * the machine code into an actual executable memory location. */ - return backend.createInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult, null, false, true, null); + return backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult); } catch (Throwable ex) { throw debug.handle(ex); } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java index aa8ea90c7690..79ffca9ad5d6 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -124,7 +124,7 @@ public void testDeoptimize() { for (boolean osr : new boolean[]{false}) { this.reason = r; this.isOSR = osr; - test("deoptimizeSnippet"); + test(getInitialOptions(), getResolvedJavaMethod("deoptimizeSnippet"), true, null, new Object[0]); ProfilingInfo info = lastCompiledGraph.method().getProfilingInfo(!isOSR, isOSR); int count = info.getDeoptimizationCount(reason); Assert.assertEquals(String.format("reason:%s, osr:%s", r, osr), 1, count); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java index 9444c4b2d7fe..5976d66f24a2 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java @@ -159,7 +159,7 @@ private void test(DebugContext debug, TestSpec spec) { CompilationResult compResult = compile(method, graph); CodeCacheProvider codeCache = getCodeCache(); HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult, getInitialOptions()); - codeCache.addCode(method, compiledCode, null, null, true); + codeCache.addCode(method, compiledCode, null, null); } @Test(expected = Error.class) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java index 9d0466461be0..b913fe09e5ee 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java @@ -103,7 +103,7 @@ private void runOutOfBound(String methodName, int size, boolean loopLimitCheck, Object[] args = new Object[testParameters.length + 1]; args[0] = array; System.arraycopy(testParameters, 0, args, 1, testParameters.length); - Result result = executeActual(getOptionsMainPath(), method, null, args); + Result result = executeActual(getOptionsMainPath(), method, true, null, args); Assert.assertNotNull(result.exception); Assert.assertTrue(result.exception instanceof ArrayIndexOutOfBoundsException); profile = method.getProfilingInfo(); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java index e0424a60061d..bbdbd6f4681d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java @@ -88,7 +88,7 @@ public void testCopy() { public void testFailingCopy() throws InvalidInstalledCodeException { var method = getResolvedJavaMethod("copyWithHandler"); Assert.assertEquals("No recorded deopt expected before first invocation.", 0, method.getProfilingInfo().getDeoptimizationCount(DeoptimizationReason.BoundsCheckException)); - test(method, null, new Object[3], -1, new Object[3], 0, 1); + test(getInitialOptions(), method, true, null, new Object[]{new Object[3], -1, new Object[3], 0, 1}); Assert.assertEquals("Single deopt expected after first invocation.", 1, method.getProfilingInfo().getDeoptimizationCount(DeoptimizationReason.BoundsCheckException)); /* * Force a recompile which should create an explicit exception edge for the System.arraycopy diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java index d3d07743ef3b..1ea45a7b582d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,6 +135,6 @@ public void testNegateExact() throws InvalidInstalledCodeException { @Override protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { assert getSpeculationLog() == compilationResult.getSpeculationLog(); - return getBackend().createInstalledCode(debug, method, null, compilationResult, null, false, true, null); + return getBackend().createInstalledCode(debug, method, compilationResult, null, false); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java index 1e042a05f212..b7e6431b6b0e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java @@ -134,6 +134,32 @@ public > CodeEmissionOrder newBlockOrder(int original */ protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, boolean isDefault, OptionValues options); + /** + * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, + * CompilationResult, InstalledCode, boolean, Object[]) + */ + public InstalledCode createInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationResult compilationResult, + InstalledCode predefinedInstalledCode, + boolean isDefault) { + return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null); + } + + /** + * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, + * CompilationResult, InstalledCode, boolean, Object[]) + */ + @SuppressWarnings("try") + public InstalledCode createInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationRequest compilationRequest, + CompilationResult compilationResult, + InstalledCode predefinedInstalledCode, + boolean isDefault) { + return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null); + } + /** * Installs code based on a given compilation result. * @@ -162,7 +188,6 @@ public InstalledCode createInstalledCode(DebugContext debug, CompilationResult compilationResult, InstalledCode predefinedInstalledCode, boolean isDefault, - boolean profileDeopt, Object[] context) { Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult}; CodeInstallationTask[] tasks; @@ -179,7 +204,7 @@ public InstalledCode createInstalledCode(DebugContext debug, try { preCodeInstallationTasks(tasks, compilationResult); CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions()); - installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault, profileDeopt); + installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault); assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode : Assertions.errorMessage(predefinedInstalledCode, installedCode); } catch (Throwable t) { failCodeInstallationTasks(tasks, t); @@ -217,6 +242,23 @@ private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, Comp } } + /** + * Installs code based on a given compilation result. + * + * @param method the method compiled to produce {@code compiledCode} or {@code null} if the + * input to {@code compResult} was not a {@link ResolvedJavaMethod} + * @param compilationRequest the request or {@code null} + * @param compilationResult the compiled code + * @return a reference to the compiled and ready-to-run installed code + * @throws BailoutException if the code installation failed + */ + public InstalledCode addInstalledCode(DebugContext debug, + ResolvedJavaMethod method, + CompilationRequest compilationRequest, + CompilationResult compilationResult) { + return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false); + } + /** * Installs code based on a given compilation result and sets it as the default code to be used * when {@code method} is invoked. @@ -228,7 +270,7 @@ private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, Comp * @throws BailoutException if the code installation failed */ public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) { - return createInstalledCode(debug, method, null, compilationResult, (InstalledCode) null, true, true, null); + return createInstalledCode(debug, method, compilationResult, null, true); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index 42758b7c446e..ced10d5179f4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -697,15 +697,12 @@ protected void installMethod(HotSpotBackend backend, DebugContext debug, Structu Object[] context = {new DebugDumpScope(getIdString(), true), backend.getProviders().getCodeCache(), getMethod(), compResult}; try (DebugContext.Scope s = debug.scope("CodeInstall", context, graph)) { HotSpotCompilationRequest request = getRequest(); - // By default, we only profile deoptimizations for compiled methods installed as - // default. installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, request.getMethod(), request, compResult, null, installAsDefault, - installAsDefault, context); } catch (Throwable e) { throw debug.handle(e); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 764f6195654c..4c4bb11e4736 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+6", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+6", 1))); + "Oracle Corporation", createLabsJDKVersion("26+5", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+5", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index 3a9079dde0ed..f0ce7da5f738 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -159,7 +159,6 @@ public InstalledCode createInstalledCode(DebugContext debug, CompilationResult compilationResult, InstalledCode predefinedInstalledCode, boolean isDefault, - boolean profileDeopt, Object[] context) { boolean isStub = (method == null); if (!isStub) { @@ -171,7 +170,7 @@ public InstalledCode createInstalledCode(DebugContext debug, // in manually assembled code in CodeGenTest cases. assert hasInvalidatePlaceholder(compilationResult); } - return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, profileDeopt, context); + return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, context); } private boolean hasInvalidatePlaceholder(CompilationResult compilationResult) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index f4071eea460e..bf9e6698294e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -97,11 +97,11 @@ public UnimplementedGraalIntrinsics(Architecture arch) { // JDK-8353786: Migrate Vector API math library support to FFM API "jdk/internal/vm/vector/VectorSupport.libraryBinaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.libraryUnaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", + "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.maybeRebox(Ljdk/internal/vm/vector/VectorSupport$VectorPayload;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.selectFromOp(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorSelectFromOp;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.selectFromTwoVectorOp(Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$SelectFromTwoVector;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" + "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" // @formatter:on ); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java index 6e4f47b6f66a..12fee728f48e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java @@ -225,7 +225,7 @@ public synchronized InstalledCode getCode(final Backend backend) { DebugContext.Activation a = debug.activate()) { assert destroyedCallerRegisters != null; HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult, options); - code = codeCache.installCode(null, compiledCode, null, null, false, false); + code = codeCache.installCode(null, compiledCode, null, null, false); } catch (Throwable e) { throw debug.handle(e); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java index e9febd36db38..7855f91fcf67 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java @@ -679,7 +679,7 @@ public CompilationResult compilePEGraph(StructuredGraph graph, try (DebugCloseable a = CodeInstallationTime.start(debug); DebugCloseable c = CodeInstallationMemUse.start(debug)) { InstalledCode installedCode = createInstalledCode(compilable); assert graph.getSpeculationLog() == result.getSpeculationLog() : Assertions.errorMessage(graph, graph.getSpeculationLog(), result, result.getSpeculationLog()); - tier.backend().createInstalledCode(debug, graph.method(), compilationRequest, result, installedCode, false, false, null); + tier.backend().createInstalledCode(debug, graph.method(), compilationRequest, result, installedCode, false); if (outInstalledCode != null) { outInstalledCode[0] = installedCode; } diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java index e15e2cc3bfa4..ea93f35c2416 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java @@ -39,7 +39,7 @@ public DummyCodeCacheProvider(TargetDescription target) { } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { throw JVMCIError.unimplemented(); } diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java index 4aa65c4ee79c..a1688059a305 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/descriptors/EspressoSymbols.java @@ -327,6 +327,7 @@ public static void ensureInitialized() { public static final Symbol java_lang_ref_Reference$Lock = SYMBOLS.putType("Ljava/lang/ref/Reference$Lock;"); public static final Symbol sun_misc_Cleaner = SYMBOLS.putType("Lsun/misc/Cleaner;"); + public static final Symbol jdk_internal_ref_Cleaner = SYMBOLS.putType("Ljdk/internal/ref/Cleaner;"); public static final Symbol java_lang_StackTraceElement = SYMBOLS.putType("Ljava/lang/StackTraceElement;"); public static final Symbol java_lang_StackTraceElement_array = SYMBOLS.putType("[Ljava/lang/StackTraceElement;"); diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java index 857107fc9384..ea83ec0eb689 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/meta/Meta.java @@ -947,12 +947,15 @@ public Meta(EspressoContext context) { .klass(); sun_reflect_ConstantPool_constantPoolOop = sun_reflect_ConstantPool.requireDeclaredField(Names.constantPoolOop, Types.java_lang_Object); + sun_misc_Cleaner = diff() // + .klass(VERSION_8_OR_LOWER, Types.sun_misc_Cleaner) // + .klass(VERSION_9_OR_HIGHER, Types.jdk_internal_ref_Cleaner) // + .klass(); + if (getJavaVersion().java8OrEarlier()) { java_lang_ref_Reference_pending = java_lang_ref_Reference.requireDeclaredField(Names.pending, Types.java_lang_ref_Reference); - sun_misc_Cleaner = knownKlass(Types.sun_misc_Cleaner); } else { java_lang_ref_Reference_pending = null; - sun_misc_Cleaner = null; } java_lang_ref_Reference_lock = diff() // .field(VERSION_8_OR_LOWER, Names.lock, Types.java_lang_ref_Reference$Lock) // diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java index a0226bb4eb9a..c1c9f9c35c80 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/runtime/EspressoReferenceDrainer.java @@ -196,16 +196,12 @@ private void doWaitForReferencePendingList() { private void casNextIfNullAndMaybeClear(EspressoReference wrapper) { StaticObject ref = wrapper.getGuestReference(); - Meta meta = getMeta(); - assert meta.sun_misc_Cleaner != null || getJavaVersion().java9OrLater(); - if (meta.sun_misc_Cleaner != null && InterpreterToVM.instanceOf(ref, meta.sun_misc_Cleaner)) { - /* - * Cleaner references extends PhantomReference but are cleared. See HotSpot's - * ReferenceProcessor::process_discovered_references in referenceProcessor.cpp - */ + // Cleaner references extends PhantomReference but are cleared. + // See HotSpot's ReferenceProcessor::process_discovered_references in referenceProcessor.cpp + if (InterpreterToVM.instanceOf(ref, getMeta().sun_misc_Cleaner)) { wrapper.clear(); } - meta.java_lang_ref_Reference_next.compareAndSwapObject(ref, StaticObject.NULL, ref); + getMeta().java_lang_ref_Reference_next.compareAndSwapObject(ref, StaticObject.NULL, ref); } private static final class ExitTLA extends ThreadLocalAction { diff --git a/sdk/mx.sdk/mx_sdk_benchmark.py b/sdk/mx.sdk/mx_sdk_benchmark.py index 94791d69042e..0ffa9e3b4c6c 100644 --- a/sdk/mx.sdk/mx_sdk_benchmark.py +++ b/sdk/mx.sdk/mx_sdk_benchmark.py @@ -3430,13 +3430,6 @@ def renaissanceIterations(self): del benchmarks["gauss-mix"] del benchmarks["page-rank"] del benchmarks["movie-lens"] - if mx.get_jdk().javaCompliance >= '26': - # JDK-8361426 removes jdk.internal.ref.Cleaner and causes the following to fail - del benchmarks["als"] - del benchmarks["db-shootout"] - del benchmarks["dec-tree"] - del benchmarks["log-regression"] - del benchmarks["naive-bayes"] return benchmarks diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index 9bafaf3d14fd..9507701d2b8c 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -1240,7 +1240,7 @@ "requiresConcealed" : { "java.base" : [ "jdk.internal.misc", - "sun.nio", + "jdk.internal.ref", "sun.nio.ch", ], "jdk.internal.vm.ci" : [ diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index dc47be7c5b58..d7cd5b301ad5 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -64,15 +64,15 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/os/posix/os_posix.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/os/posix/os_posix.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allStatic.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/nmt/memTag.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/os.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/os.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/os.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/os.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @@ -86,7 +86,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceInternals.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceInternals.java index 5ac34fbd95a8..c576756a152c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceInternals.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/ReferenceInternals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -217,7 +217,24 @@ public static void processPendingReferences() { Target_java_lang_ref_Reference ref = pendingList; pendingList = ref.discovered; ref.discovered = null; - ref.enqueueFromPending(); + + if (Target_jdk_internal_ref_Cleaner.class.isInstance(ref)) { + Target_jdk_internal_ref_Cleaner cleaner = Target_jdk_internal_ref_Cleaner.class.cast(ref); + // Cleaner catches all exceptions, cannot be overridden due to private c'tor + cleaner.clean(); + synchronized (processPendingLock) { + // Notify any waiters that progress has been made. This improves latency + // for nio.Bits waiters, which are the only important ones. + processPendingLock.notifyAll(); + } + } else { + @SuppressWarnings("unchecked") + Target_java_lang_ref_ReferenceQueue queue = SubstrateUtil.cast(ref.queue, Target_java_lang_ref_ReferenceQueue.class); + if (queue != Target_java_lang_ref_ReferenceQueue.NULL_QUEUE) { + // Enqueues, avoiding the potentially overridden Reference.enqueue(). + queue.enqueue(ref); + } + } } synchronized (processPendingLock) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java index 2ed320704ecc..dd49aec700c3 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java @@ -154,9 +154,6 @@ boolean refersTo0(Object obj) { @KeepOriginal native boolean enqueue(); - @KeepOriginal - native void enqueueFromPending(); - @KeepOriginal native boolean isEnqueued(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java deleted file mode 100644 index e796e8d115d2..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_nio_BufferCleaner.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heap; - -import java.lang.ref.ReferenceQueue; - -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.RecomputeFieldValue; -import com.oracle.svm.core.annotate.Substitute; -import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.thread.VMThreads; - -@TargetClass(className = "java.nio.BufferCleaner") -public final class Target_java_nio_BufferCleaner { - - @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.NewInstance, declClassName = "java.nio.BufferCleaner$CleanerList")// - static Target_java_nio_BufferCleaner_CleanerList cleanerList; - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.None, isFinal = true) // - static ReferenceQueue queue; - @Alias // - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // - static Target_java_nio_BufferCleaner_CleaningThread cleaningThread; -} - -@TargetClass(className = "java.nio.BufferCleaner", innerClass = "CleaningThread") -final class Target_java_nio_BufferCleaner_CleaningThread { - @SuppressWarnings("static-method") - @Substitute - public void run() { - while (true) { - try { - Target_sun_nio_Cleaner c = SubstrateUtil.cast(Target_java_nio_BufferCleaner.queue.remove(), Target_sun_nio_Cleaner.class); - c.clean(); - } catch (InterruptedException e) { - if (VMThreads.isTearingDown()) { - return; - } - // Ignore InterruptedException in cleaner thread. - } - } - } -} - -@TargetClass(className = "java.nio.BufferCleaner", innerClass = "CleanerList") -final class Target_java_nio_BufferCleaner_CleanerList { -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Cleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_jdk_internal_ref_Cleaner.java similarity index 88% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Cleaner.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_jdk_internal_ref_Cleaner.java index 39ad8dcfebe4..9028f7bdcba8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Cleaner.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_jdk_internal_ref_Cleaner.java @@ -43,10 +43,29 @@ import jdk.internal.misc.InnocuousThread; +@TargetClass(className = "jdk.internal.ref.Cleaner") +public final class Target_jdk_internal_ref_Cleaner { + + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// + static Target_jdk_internal_ref_Cleaner first; + + @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.FromAlias)// + static ReferenceQueue dummyQueue = new ReferenceQueue<>(); + + @Alias + native void clean(); +} + +@TargetClass(className = "jdk.internal.ref.CleanerFactory") +final class Target_jdk_internal_ref_CleanerFactory { + @Alias + public static native Target_java_lang_ref_Cleaner cleaner(); +} + @TargetClass(className = "java.lang.ref.Cleaner") -public final class Target_java_lang_ref_Cleaner { +final class Target_java_lang_ref_Cleaner { @Alias// - Target_jdk_internal_ref_CleanerImpl impl; + public Target_jdk_internal_ref_CleanerImpl impl; } @TargetClass(className = "java.lang.ref.Cleaner$Cleanable") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_sun_nio_Cleaner.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_sun_nio_Cleaner.java deleted file mode 100644 index 1f883d4ac5c9..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_sun_nio_Cleaner.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.heap; - -import com.oracle.svm.core.annotate.Alias; -import com.oracle.svm.core.annotate.TargetClass; - -@TargetClass(className = "sun.nio.Cleaner") -public final class Target_sun_nio_Cleaner { - @Alias - native void clean(); -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java index cd82c8a718bc..6d741986bc5b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java @@ -59,7 +59,7 @@ public interface DisallowedObjectReporter { public static final Class CONTINUATION_CLASS = ReflectionUtil.lookupClass("jdk.internal.vm.Continuation"); private static final Method CONTINUATION_IS_STARTED_METHOD = ReflectionUtil.lookupMethod(CONTINUATION_CLASS, "isStarted"); private static final Class CLEANER_CLEANABLE_CLASS = ReflectionUtil.lookupClass("jdk.internal.ref.CleanerImpl$CleanerCleanable"); - public static final Class NIO_CLEANER_CLASS = ReflectionUtil.lookupClass("sun.nio.Cleaner"); + public static final Class LEGACY_CLEANER_CLASS = ReflectionUtil.lookupClass("jdk.internal.ref.Cleaner"); public static final Class MEMORY_SEGMENT_CLASS = ReflectionUtil.lookupClass("java.lang.foreign.MemorySegment"); public static final Class SCOPE_CLASS = ReflectionUtil.lookupClass("java.lang.foreign.MemorySegment$Scope"); @@ -86,7 +86,7 @@ public static void check(Object obj, DisallowedObjectReporter reporter) { onBufferReachable(buffer, reporter); } - if (obj instanceof Cleaner.Cleanable || NIO_CLEANER_CLASS.isInstance(obj)) { + if (obj instanceof Cleaner.Cleanable || LEGACY_CLEANER_CLASS.isInstance(obj)) { onCleanableReachable(obj, reporter); } @@ -182,10 +182,10 @@ public static void onBufferReachable(Buffer buffer, DisallowedObjectReporter rep } public static void onCleanableReachable(Object cleanable, DisallowedObjectReporter reporter) { - VMError.guarantee(cleanable instanceof Cleaner.Cleanable || NIO_CLEANER_CLASS.isInstance(cleanable)); + VMError.guarantee(cleanable instanceof Cleaner.Cleanable || LEGACY_CLEANER_CLASS.isInstance(cleanable)); /* - * Cleanable and sun.nio.Cleaner are used to release various resources such as native - * memory, file descriptors, or timers, which are not available at image runtime. By + * Cleanable and jdk.internal.ref.Cleaner are used to release various resources such as + * native memory, file descriptors, or timers, which are not available at image runtime. By * disallowing these objects, we detect when such resources are reachable. * * If a Cleanable is a nulled (Phantom)Reference, its problematic resource is already @@ -195,12 +195,12 @@ public static void onCleanableReachable(Object cleanable, DisallowedObjectReport * Thread) and does nothing, so we also tolerate it. We should encounter at least one such * object for jdk.internal.ref.CleanerFactory.commonCleaner. * - * Internal sun.nio.Cleaner objects (formerly in jdk.internal.ref, formerly in sun.misc) - * should be used only by DirectByteBuffer, which we already cover above, but other code - * could also use them. If they have been nulled, we tolerate them, too. + * Legacy jdk.internal.ref.Cleaner objects (formerly in sun.misc) should be used only by + * DirectByteBuffer, which we already cover above, but other code could also use them. If + * they have been nulled, we tolerate them, too. */ if (!(cleanable instanceof Reference && ((Reference) cleanable).refersTo(null)) && !CLEANER_CLEANABLE_CLASS.isInstance(cleanable)) { - throw reporter.raise("Detected an active instance of Cleanable or sun.io.Cleaner in the image heap. This usually means that a resource " + + throw reporter.raise("Detected an active instance of Cleanable or jdk.internal.ref.Cleaner in the image heap. This usually means that a resource " + "such as a Timer, native memory, a file descriptor or another resource is reachable which is not available at image runtime.", cleanable, "Prevent such objects being used during image generation, including by class initializers."); } 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 db66f1e0d7ba..9cfc3b9fbb85 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 @@ -52,8 +52,6 @@ final class Target_java_nio_Bits { @Alias @RecomputeFieldValue(kind = Kind.FromAlias) // private static AtomicLong COUNT = new AtomicLong(); - @Alias @RecomputeFieldValue(kind = Kind.Reset) // - private static int RESERVE_GC_EPOCH; // Checkstyle: resume } 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 9852c3591e95..d9be85aedfc8 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 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,12 @@ import com.oracle.svm.core.annotate.Alias; import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.heap.Target_sun_nio_Cleaner; +import com.oracle.svm.core.heap.Target_jdk_internal_ref_Cleaner; import com.oracle.svm.core.util.BasedOnJDKFile; import com.oracle.svm.core.util.VMError; @TargetClass(className = "java.nio.DirectByteBuffer") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+6/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template") public final class Target_java_nio_DirectByteBuffer { /** @@ -49,7 +49,7 @@ public final class Target_java_nio_DirectByteBuffer { * registered for the buffer by resetting the field {@link #cleaner}. */ @Alias @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset) // - Target_sun_nio_Cleaner cleaner; + Target_jdk_internal_ref_Cleaner cleaner; @Alias @SuppressWarnings("unused") diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java index 861b7ce79b8a..2c3322530f6d 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,9 @@ public IsolateAwareCodeCacheProvider(TargetDescription target, RegisterConfig re } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault) { if (!SubstrateOptions.shouldCompileInIsolates()) { - return super.installCode(method, compiledCode, predefinedInstalledCode, log, isDefault, profileDeopt); + return super.installCode(method, compiledCode, predefinedInstalledCode, log, isDefault); } VMError.guarantee(!isDefault); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java index 237f8367fb76..a29e8da48cd0 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ protected SubstrateCodeCacheProvider(TargetDescription target, RegisterConfig re @Override @SuppressFBWarnings(value = {"BC_UNCONFIRMED_CAST"}, justification = "We know what we are doing.") - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault) { VMError.guarantee(!isDefault); SubstrateInstalledCode substrateInstalledCode; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java index 58a9389c9d86..9b01a1aa2394 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -40,7 +40,7 @@ public class HostedCodeCacheProvider extends SharedCodeCacheProvider { } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport } } 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 4ad79573f67d..b68cf684b209 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 @@ -25,8 +25,8 @@ package com.oracle.svm.hosted.image; import static com.oracle.svm.core.image.DisallowedImageHeapObjects.CANCELLABLE_CLASS; +import static com.oracle.svm.core.image.DisallowedImageHeapObjects.LEGACY_CLEANER_CLASS; import static com.oracle.svm.core.image.DisallowedImageHeapObjects.MEMORY_SEGMENT_CLASS; -import static com.oracle.svm.core.image.DisallowedImageHeapObjects.NIO_CLEANER_CLASS; import static com.oracle.svm.core.image.DisallowedImageHeapObjects.SCOPE_CLASS; import java.io.File; @@ -85,7 +85,7 @@ public void duringSetup(DuringSetupAccess a) { access.registerObjectReachableCallback(FileDescriptor.class, (a1, obj, reason) -> DisallowedImageHeapObjects.onFileDescriptorReachable(obj, this::error)); access.registerObjectReachableCallback(Buffer.class, (a1, obj, reason) -> DisallowedImageHeapObjects.onBufferReachable(obj, this::error)); access.registerObjectReachableCallback(Cleaner.Cleanable.class, (a1, obj, reason) -> DisallowedImageHeapObjects.onCleanableReachable(obj, this::error)); - access.registerObjectReachableCallback(NIO_CLEANER_CLASS, (a1, obj, reason) -> DisallowedImageHeapObjects.onCleanableReachable(obj, this::error)); + access.registerObjectReachableCallback(LEGACY_CLEANER_CLASS, (a1, obj, reason) -> DisallowedImageHeapObjects.onCleanableReachable(obj, this::error)); access.registerObjectReachableCallback(Cleaner.class, (a1, obj, reason) -> DisallowedImageHeapObjects.onCleanerReachable(obj, this::error)); access.registerObjectReachableCallback(ZipFile.class, (a1, obj, reason) -> DisallowedImageHeapObjects.onZipFileReachable(obj, this::error)); access.registerObjectReachableCallback(CANCELLABLE_CLASS, (a1, obj, reason) -> DisallowedImageHeapObjects.onCancellableReachable(obj, this::error)); diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_allowed_methods.json b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_allowed_methods.json index 29f6e80d2189..abdd1534f245 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_allowed_methods.json +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_allowed_methods.json @@ -38,15 +38,6 @@ "justification" : "Bits are package private class used by direct buffers which uses Unsafe to access off heap memory.", "allDeclaredMethods" : true }, - { - "name" : "java.nio.BufferCleaner$PhantomCleaner", - "methods" : [ - { "name" : "clean" , - "justification" : "Calls System.exit if a failure occurs during VM boot.", - "parameterTypes" : [ - ]} - ] - }, { "name" : "java.nio.DirectByteBuffer", "justification" : "DirectByteBuffer uses Unsafe to allocate and initialize off heap memory.", @@ -348,5 +339,16 @@ "justification": "In native-image resource bundles are statically configured." } ] + }, + { + "name": "jdk.internal.ref.Cleaner", + "methods": [ + { + "name": "clean", + "parameterTypes" : [ + ], + "justification": "Internal JDK Cleaner which does System.exit if it fails during JVM boot." + } + ] } ] diff --git a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/EnginesGCedTest.java b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/EnginesGCedTest.java index 74f76cf4f696..2eff548caba0 100644 --- a/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/EnginesGCedTest.java +++ b/tools/src/com.oracle.truffle.tools.chromeinspector.test/src/com/oracle/truffle/tools/chromeinspector/test/EnginesGCedTest.java @@ -28,12 +28,13 @@ import java.util.HashSet; import java.util.Set; -import org.graalvm.polyglot.Context; -import org.graalvm.polyglot.Engine; import org.junit.After; import org.junit.Assert; import org.junit.Before; +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Engine; + import com.oracle.truffle.api.test.GCUtils; public abstract class EnginesGCedTest { @@ -88,10 +89,6 @@ void checkCollected() { // A libgraal thread continue; } - if (t.getClass().getName().equals("java.nio.BufferCleaner$CleaningThread")) { - // BufferCleaner::CleaningThread JDK-8344332 (JDK 26+6) [GR-67693] - continue; - } Assert.fail("An extra thread " + t + " is found after test finished."); } } From 2376d6772460ddd48e68073f8b9b6c84d253b55d Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 15:22:44 +0200 Subject: [PATCH 10/49] Revert "[GR-69070] Improve replayability with different compiler options" This reverts commit a0e665e0013fef599be6f58bd5b245963deb5b05, reversing changes made to f23bb724ae57bb7907f92c905a3023a385dadb5f. --- .../compiler/hotspot/HotSpotGraalRuntime.java | 2 +- .../hotspot/SymbolicSnippetEncoder.java | 3 - .../replaycomp/CompilationProxies.java | 7 - .../CompilerInterfaceDeclarations.java | 201 +++++++----------- .../HotSpotProxyBackendFactory.java | 15 +- .../RecordedOperationPersistence.java | 112 ++++------ .../RecordingCompilationProxies.java | 6 +- .../replaycomp/ReplayCompilationProxies.java | 41 +--- .../replaycomp/ReplayCompilationRunner.java | 2 - .../replaycomp/ReplayCompilationSupport.java | 31 ++- .../replaycomp/proxy/CompilationProxy.java | 25 +-- .../proxy/HotSpotConstantProxy.java | 88 -------- .../proxy/HotSpotMetaspaceConstantProxy.java | 51 ++++- .../proxy/HotSpotObjectConstantProxy.java | 48 ++++- .../proxy/HotSpotResolvedJavaMethodProxy.java | 2 +- .../proxy/HotSpotResolvedJavaTypeProxy.java | 2 +- .../proxy/HotSpotResolvedObjectTypeProxy.java | 6 +- .../replaycomp/proxy/SignatureProxy.java | 4 +- 18 files changed, 267 insertions(+), 379 deletions(-) delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java index 9585292993a5..103d8ad3249e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java @@ -172,7 +172,7 @@ public GlobalMetrics getMetricValues() { throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture); } if (replayCompilationSupport != null) { - factory = replayCompilationSupport.decorateBackendFactory(factory, jvmciRuntime); + factory = replayCompilationSupport.decorateBackendFactory(factory); } hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null)); } 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 9c97f59fe2c9..54676f8b4dd2 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 @@ -62,7 +62,6 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedObjectTypeProxy; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -533,8 +532,6 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic lookupSnippetType(SnippetTemplate.SnippetInfo.class); lookupSnippetType(ForeignCallStub.class); lookupSnippetType(HotSpotSpeculationLog.HotSpotSpeculation.class); - // Needed to pass constant type parameters to snippets when recording/replaying. - lookupSnippetType(HotSpotResolvedObjectTypeProxy.class); registerAbstractForeignCallStubInfo(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java index 8b73cec11272..e419bc98e993 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java @@ -73,11 +73,4 @@ public interface CompilationProxies { * @return a debug closeable object representing the debug context */ DebugCloseable withDebugContext(DebugContext debugContext); - - /** - * Enters the context of a method compilation. - * - * @return a scope for the context - */ - DebugCloseable enterCompilationContext(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index 8052190defd0..999c66f0f743 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -30,11 +30,10 @@ import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy.wrapInvocationExceptions; import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; +import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collections; import java.util.Formattable; @@ -56,7 +55,6 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.ConstantPoolProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotCodeCacheProviderProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantReflectionProviderProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotMetaspaceConstantProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotObjectConstantProxy; @@ -71,8 +69,6 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; -import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -85,14 +81,10 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.hotspot.HotSpotResolvedPrimitiveType; -import jdk.vm.ci.hotspot.HotSpotRuntimeStub; import jdk.vm.ci.hotspot.HotSpotSignature; -import jdk.vm.ci.hotspot.HotSpotSpeculationLog; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.MethodHandleAccessProvider; import jdk.vm.ci.meta.ProfilingInfo; @@ -229,10 +221,10 @@ public interface OperationResultSupplier { * @param proxy the proxy receiver * @param method the invoked method * @param args the arguments to the method - * @param metaAccess the host meta accces + * @param singletonObjects a map of provider classes to instances * @return the result of the operation */ - Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess); + Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects); } /** @@ -245,12 +237,10 @@ public interface LocalMirrorLocator { * found. * * @param proxy the proxy object - * @param metaAccess the unprofixied host meta access - * @param constantReflection the unproxified host constant reflection - * @param jvmciRuntime the JVMCI runtime + * @param singletonObjects a map of provider classes to instances * @return the local mirror or {@code null} */ - Object findLocalMirror(Object proxy, MetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotJVMCIRuntime jvmciRuntime); + Object findLocalMirror(Object proxy, EconomicMap, Object> singletonObjects); } /** @@ -345,15 +335,15 @@ public MethodStrategy findStrategy(CompilationProxy.SymbolicMethod method) { * @param proxy the proxy receiver object * @param method the invoked method * @param args the arguments passed to the invocation - * @param metaAccess the host meta access + * @param singletonObjects a map of provider classes to instances * @return the default value */ - public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { + public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { MethodRegistration found = methods.get(method); if (found == null) { return null; } else if (found.defaultValueSupplier != null) { - return found.defaultValueSupplier.apply(proxy, method, args, metaAccess); + return found.defaultValueSupplier.apply(proxy, method, args, singletonObjects); } else { return found.defaultValue; } @@ -518,7 +508,7 @@ public RegistrationBuilder setDefaultValueSupplier(CompilationProxy.SymbolicM public RegistrationBuilder ensureRecorded(CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object... arguments) { MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); builder.callsToRecordArguments.add(arguments); - builder.invokableMethod = wrapInvocationExceptions(invokableMethod); + builder.invokableMethod = invokableMethod; return this; } @@ -648,7 +638,7 @@ public static CompilerInterfaceDeclarations build() { .setStrategy(HotSpotConstantReflectionProviderProxy.asJavaClassMethod, MethodStrategy.Passthrough) .setStrategy(HotSpotConstantReflectionProviderProxy.asObjectHubMethod, MethodStrategy.Passthrough) .setDefaultValueSupplier(HotSpotConstantReflectionProviderProxy.asJavaTypeMethod, - (proxy, method, args, metaAccess) -> { + (proxy, method, args, singletonObjects) -> { if (args[0] instanceof HotSpotMetaspaceConstant constant) { return constant.asResolvedJavaType(); } @@ -656,16 +646,19 @@ public static CompilerInterfaceDeclarations build() { }) .register(declarations); new RegistrationBuilder<>(MethodHandleAccessProvider.class) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> - constantReflection.getMethodHandleAccess()) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); + return provider.getMethodHandleAccess(); + }) .register(declarations); new RegistrationBuilder<>(HotSpotMemoryAccessProvider.class) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> - constantReflection.getMemoryAccessProvider()) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); + return provider.getMemoryAccessProvider(); + }) .register(declarations); new RegistrationBuilder<>(HotSpotCodeCacheProvider.class).setSingleton(true) .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.installCodeMethod, null) - .setDefaultValueSupplier(HotSpotCodeCacheProviderProxy.installCodeMethod, CompilerInterfaceDeclarations::installCodeReplacement) // Interpreter frame size is not tracked since the arguments are not serializable. .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.interpreterFrameSizeMethod, 0) .register(declarations); @@ -677,7 +670,20 @@ public static CompilerInterfaceDeclarations build() { new RegistrationBuilder<>(HotSpotResolvedObjectType.class, HotSpotResolvedJavaType.class) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getNameMethod, HotSpotResolvedObjectTypeProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getModifiersMethod, HotSpotResolvedObjectTypeProxy.getModifiersInvokable) - .setLocalMirrorLocator(CompilerInterfaceDeclarations::findObjectTypeMirror) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; + Class clazz; + try { + clazz = Class.forName(type.toClassName()); + } catch (ClassNotFoundException e) { + return null; + } + if (Proxy.class.isAssignableFrom(clazz)) { + return null; + } + return metaAccess.lookupJavaType(clazz); + }) // getComponentType() is used by the default implementation of isArray(). .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) @@ -687,15 +693,12 @@ public static CompilerInterfaceDeclarations build() { HotSpotResolvedObjectTypeProxy.getInstanceFieldsInvokable, new Object[]{true}) // For snippet decoding .ensureRecorded(HotSpotResolvedObjectTypeProxy.getStaticFieldsMethod, HotSpotResolvedObjectTypeProxy.getStaticFieldsInvokable) // For snippet decoding .setDefaultValueStrategy(HotSpotResolvedObjectTypeProxy.getJavaKindMethod, JavaKind.Object) - .setDefaultValueStrategy(HotSpotResolvedJavaTypeProxy.isPrimitiveMethod, false) - .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, (proxy1, method1, args1, metaAccess) -> metaAccess.lookupJavaType(Object.class)) + .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, CompilerInterfaceDeclarations::javaLangObjectSupplier) .setDefaultValue(HotSpotResolvedObjectTypeProxy.isAssignableFromMethod, false) .ensureRecorded(HotSpotResolvedObjectTypeProxy.isInterfaceMethod, HotSpotResolvedObjectTypeProxy.isInterfaceInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.klassMethod, HotSpotResolvedObjectTypeProxy.klassInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getJavaMirrorMethod, HotSpotResolvedObjectTypeProxy.getJavaMirrorInvokable) .setDefaultValue(HotSpotResolvedObjectTypeProxy.isInitializedMethod, false) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.isPrimaryTypeMethod, HotSpotResolvedObjectTypeProxy.isPrimaryTypeInvokable) // For InstanceOfSnippets after divergence - .setDefaultValue(HotSpotResolvedObjectTypeProxy.superCheckOffsetMethod, 0) // For InstanceOfSnippets after divergence .provideMethodCallsToRecord((input) -> { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) input; if (!type.isArray() && !type.isInterface()) { @@ -710,8 +713,7 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaTypeProxy.getNameMethod, HotSpotResolvedJavaTypeProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaKindMethod, HotSpotResolvedJavaTypeProxy.getJavaKindInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) - .setDefaultValueStrategy(HotSpotResolvedJavaTypeProxy.isPrimitiveMethod, true) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { + .setLocalMirrorLocator((proxy, singletonObjects) -> { HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) proxy; return HotSpotResolvedPrimitiveType.forKind(type.getJavaKind()); }) @@ -725,9 +727,8 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaMethodProxy.isConstructorMethod, HotSpotResolvedJavaMethodProxy.isConstructorInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundMethod, HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getCodeMethod, HotSpotResolvedJavaMethodProxy.getCodeInvokable) - .setDefaultValue(HotSpotResolvedJavaMethodProxy.vtableEntryOffsetMethod, 0) // For LoadMethodNode lowering after divergence .setStrategy(HotSpotResolvedJavaMethodProxy.formatToMethod, MethodStrategy.DefaultValue) - .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, metaAccess) -> { + .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, singletonObjects) -> { ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; Formatter formatter = (Formatter) args[0]; int flags = (int) args[1]; @@ -737,11 +738,11 @@ public static CompilerInterfaceDeclarations build() { return null; }) .ensureRecorded(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, HotSpotResolvedJavaMethodProxy.asStackTraceElementInvokable, -1) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, metaAccess) -> { + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, singletonObjects) -> { ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; return receiver.asStackTraceElement(-1); }) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, metaAccess) -> { + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, singletonObjects) -> { byte[] code = ((ResolvedJavaMethod) proxy).getCode(); if (code == null) { return 0; @@ -751,14 +752,22 @@ public static CompilerInterfaceDeclarations build() { }) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getDeclaringClassMethod, HotSpotResolvedJavaMethodProxy.getDeclaringClassInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { + .setLocalMirrorLocator((proxy, singletonObjects) -> { ResolvedJavaMethod method = (ResolvedJavaMethod) proxy; - ResolvedJavaType holderMirror = findObjectTypeMirror(method.getDeclaringClass(), metaAccess, constantReflection, jvmciRuntime); - if (holderMirror == null) { - return null; - } String methodName = method.getName(); String methodDescriptor = method.getSignature().toMethodDescriptor(); + ResolvedJavaType holder = method.getDeclaringClass(); + Class clazz; + try { + clazz = Class.forName(holder.toClassName()); + } catch (ClassNotFoundException e) { + return null; + } + if (Proxy.class.isAssignableFrom(clazz)) { + return null; + } + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType holderMirror = metaAccess.lookupJavaType(clazz); if (method.isConstructor()) { for (ResolvedJavaMethod candidate : holderMirror.getDeclaredConstructors()) { if (candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { @@ -779,7 +788,7 @@ public static CompilerInterfaceDeclarations build() { .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) - .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, metaAccess) -> { + .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, singletonObjects) -> { // The HostInliningPhase can query Truffle-related annotations during replay on jargraal. It is safe to return null. return null; }) @@ -827,12 +836,14 @@ public static CompilerInterfaceDeclarations build() { Signature signature = (Signature) input; int count = signature.getParameterCount(false); List calls = new ArrayList<>(); + CompilationProxy.SymbolicMethod symbolicMethod = new CompilationProxy.SymbolicMethod(Signature.class, "getParameterType", int.class, ResolvedJavaType.class); + CompilationProxy.InvokableMethod invokableMethod = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); for (int i = 0; i < count; i++) { - calls.add(new MethodCallToRecord(input, SignatureProxy.getParameterTypeMethod, SignatureProxy.getParameterTypeInvokable, new Object[]{i, null})); + calls.add(new MethodCallToRecord(input, symbolicMethod, invokableMethod, new Object[]{i, null})); } return calls; }) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { + .setLocalMirrorLocator((proxy, singletonObjects) -> { Signature signature = (Signature) proxy; return new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature.toMethodDescriptor()); }) @@ -845,42 +856,47 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaFieldProxy.getNameMethod, HotSpotResolvedJavaFieldProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedJavaFieldProxy.getModifiersMethod, HotSpotResolvedJavaFieldProxy.getModifiersInvokable) // For graph dumps (BinaryGraphPrinter) .ensureRecorded(HotSpotResolvedJavaFieldProxy.getTypeMethod, HotSpotResolvedJavaFieldProxy.getTypeInvokable) // For graph dumps (BinaryGraphPrinter) - .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { + .setLocalMirrorLocator((proxy, singletonObjects) -> { ResolvedJavaField field = (ResolvedJavaField) proxy; - ResolvedJavaType holderMirror = findObjectTypeMirror(field.getDeclaringClass(), metaAccess, constantReflection, jvmciRuntime); - if (holderMirror == null) { + ResolvedJavaType holderProxy = field.getDeclaringClass(); + Class holderClazz; + try { + holderClazz = Class.forName(holderProxy.toClassName()); + } catch (ClassNotFoundException e) { return null; } + if (Proxy.class.isAssignableFrom(holderClazz)) { + return null; + } + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType holder = metaAccess.lookupJavaType(holderClazz); String name = field.getName(); boolean isStatic = field.isStatic(); - ResolvedJavaField[] fields = (isStatic) ? holderMirror.getStaticFields() : holderMirror.getInstanceFields(false); + ResolvedJavaField[] fields = (isStatic) ? holder.getStaticFields() : holder.getInstanceFields(false); for (ResolvedJavaField candidate : fields) { if (name.equals(candidate.getName())) { return candidate; } } - return null; + throw new IllegalStateException("Cannot find mirror for " + field + ": the local holder does not contain a matching field"); }) .register(declarations); new RegistrationBuilder<>(HotSpotObjectConstant.class) - .ensureRecorded(HotSpotConstantProxy.toValueStringMethod, HotSpotConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotConstantProxy.isCompressibleMethod, HotSpotConstantProxy.isCompressibleInvokable) - .ensureRecorded(HotSpotConstantProxy.isCompressedMethod, HotSpotConstantProxy.isCompressedInvokable) - .ensureRecorded(HotSpotConstantProxy.compressMethod, HotSpotConstantProxy.compressInvokable) - .ensureRecorded(HotSpotConstantProxy.uncompressMethod, HotSpotConstantProxy.uncompressInvokable) - .setDefaultValueStrategy(HotSpotConstantProxy.isDefaultForKindMethod, false) + .ensureRecorded(HotSpotObjectConstantProxy.toValueStringMethod, HotSpotObjectConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotObjectConstantProxy.isCompressedMethod, HotSpotObjectConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotObjectConstantProxy.getTypeMethod, HotSpotObjectConstantProxy.getTypeInvokable) .setDefaultValueStrategy(HotSpotObjectConstantProxy.isNullMethod, false) .setDefaultValueStrategy(HotSpotObjectConstantProxy.getJavaKindMethod, JavaKind.Object) + .setDefaultValueSupplier(HotSpotObjectConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) + .setDefaultValueSupplier(HotSpotObjectConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) .register(declarations); new RegistrationBuilder<>(HotSpotMetaspaceConstant.class) - .ensureRecorded(HotSpotConstantProxy.toValueStringMethod, HotSpotConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotConstantProxy.isCompressibleMethod, HotSpotConstantProxy.isCompressibleInvokable) - .ensureRecorded(HotSpotConstantProxy.isCompressedMethod, HotSpotConstantProxy.isCompressedInvokable) - .ensureRecorded(HotSpotConstantProxy.compressMethod, HotSpotConstantProxy.compressInvokable) - .ensureRecorded(HotSpotConstantProxy.uncompressMethod, HotSpotConstantProxy.uncompressInvokable) - .setDefaultValueStrategy(HotSpotConstantProxy.isDefaultForKindMethod, false) + .ensureRecorded(HotSpotMetaspaceConstantProxy.toValueStringMethod, HotSpotMetaspaceConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotMetaspaceConstantProxy.isCompressedMethod, HotSpotMetaspaceConstantProxy.isCompressedInvokable) .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaTypeMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaTypeInvokable) .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaMethodMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaMethodInvokable) + .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) + .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) .register(declarations); new RegistrationBuilder<>(HotSpotProfilingInfo.class) .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) @@ -896,12 +912,7 @@ public static CompilerInterfaceDeclarations build() { .register(declarations); new RegistrationBuilder<>(SpeculationLog.class) .setDefaultValue(SpeculationLogProxy.maySpeculateMethod, true) - .setDefaultValueSupplier(SpeculationLogProxy.speculateMethod, (Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) -> { - // Some callers expect to get an actual speculation rather than NO_SPECULATION. - SpeculationLog.SpeculationReason reason = (SpeculationLog.SpeculationReason) args[0]; - JavaConstant id = JavaConstant.forLong(-1); - return new HotSpotSpeculationLog.HotSpotSpeculation(reason, id, new byte[0]); - }) + .setDefaultValue(SpeculationLogProxy.speculateMethod, SpeculationLog.NO_SPECULATION) .register(declarations); new RegistrationBuilder<>(Predicate.class).setSingleton(true) .register(declarations); // Intrinsification trust predicate. @@ -909,41 +920,10 @@ public static CompilerInterfaceDeclarations build() { return declarations; } - /** - * Finds a local mirror for an object type proxy by resolving the class name on the host JVM. - * - * @param proxy the object type proxy - * @param metaAccess the host meta access - * @param constantReflection the host constant reflection - * @param jvmciRuntime the host JVMCI runtime - * @return the object type mirror or {@code null} if it cannot be resolved - */ @SuppressWarnings("unused") - private static HotSpotResolvedObjectType findObjectTypeMirror(Object proxy, MetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotJVMCIRuntime jvmciRuntime) { - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; - String typeName = type.getName(); - if (typeName.contains("$Proxy") || typeName.contains(".0x")) { - // Skip dynamic proxies and hidden classes, which have unstable names. - return null; - } - Class accessingClass = (inRuntimeCode()) ? Object.class : CompilerInterfaceDeclarations.class; - HotSpotResolvedObjectType accessingType = (HotSpotResolvedObjectType) metaAccess.lookupJavaType(accessingClass); - try { - JavaType result = jvmciRuntime.lookupType(typeName, accessingType, true); - if (result instanceof HotSpotResolvedObjectType mirror) { - /* - * Initialize the type to avoid reducing whole snippets to a deopt when replay - * diverges and depends on the mirrors (e.g., BoxingSnippets on libgraal). - */ - synchronized (CompilerInterfaceDeclarations.class) { - mirror.initialize(); - } - return mirror; - } - } catch (LinkageError | Exception ignored) { - // Ignore LinkageError or TranslatedException. - } - return null; + private static ResolvedJavaType javaLangObjectSupplier(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + return metaAccess.lookupJavaType(Object.class); } /** @@ -956,7 +936,7 @@ private static HotSpotResolvedObjectType findObjectTypeMirror(Object proxy, Meta */ @SuppressWarnings("unused") @ExcludeFromJacocoGeneratedReport("related to replay of libgraal compilations on jargraal") - private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { + private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { HotSpotResolvedObjectType receiverType = (HotSpotResolvedObjectType) proxy; if (!(args[0] instanceof HotSpotObjectConstant objectConstant)) { return false; @@ -968,21 +948,4 @@ private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationPro } return receiverType.isAssignableFrom(constantType); } - - /** - * Implements {@link HotSpotCodeCacheProvider#installCode} for replay compilation. - */ - @SuppressWarnings("unused") - private static InstalledCode installCodeReplacement(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { - ResolvedJavaMethod installedCodeOwner = (ResolvedJavaMethod) args[0]; - CompiledCode compiledCode = (CompiledCode) args[1]; - InstalledCode installedCode = (InstalledCode) args[2]; - if (installedCodeOwner == null) { - // This is an installation of a stub which was not compiled during recording. - return new HotSpotRuntimeStub(compiledCode.toString()); // ExcludeFromJacocoGeneratedReport - } else { - // For method installations, the return value is not important. - return installedCode; - } - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java index a97408fd5c0a..7e8ced5f0548 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java @@ -32,7 +32,6 @@ import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MemoryAccessProvider; @@ -49,12 +48,11 @@ class HotSpotProxyBackendFactory implements HotSpotBackendFactoryDecorators { private final ReplayCompilationSupport replayCompilationSupport; - private final HotSpotJVMCIRuntime jvmciRuntime; + private MetaAccessProvider metaAccessProviderProxy; - HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport, HotSpotJVMCIRuntime jvmciRuntime) { + HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport) { this.proxies = proxies; this.replayCompilationSupport = replayCompilationSupport; - this.jvmciRuntime = jvmciRuntime; } @Override @@ -64,13 +62,14 @@ public void afterJVMCIProvidersCreated() { * mirrors. We must identify the local mirrors before initialization continues to avoid * creating duplicate proxies for equivalent local mirrors. */ - replayCompilationSupport.findLocalMirrors(jvmciRuntime); + replayCompilationSupport.findLocalMirrors(); } @Override public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { // Do not record snippet types in libgraal - decorate the JVMCI meta access only. - return new HotSpotSnippetMetaAccessProvider((MetaAccessProvider) proxies.proxify(metaAccess)); + metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); + return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy); } @Override @@ -80,7 +79,7 @@ public HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotS return new DecoratedConstantReflectionProvider(delegate); } - private static final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { + private final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { private final HotSpotConstantReflectionProvider delegate; private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider delegate) { @@ -143,7 +142,7 @@ public ResolvedJavaType asJavaType(Constant constant) { * Avoid recording an operation with the snippet constant, which is not * serializable. */ - return objectConstant.asObject(ResolvedJavaType.class); + return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); } else { return delegate.asJavaType(constant); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java index 11e96f435754..1e31d9d44721 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java @@ -144,20 +144,6 @@ private interface RecursiveDeserializer { Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException; Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException; - - /** - * Sets the {@link Architecture} parsed by this deserializer. - * - * @param arch the architecture - */ - void setArchitecture(Architecture arch); - - /** - * Gets the {@link Architecture} parsed by this deserializer. - * - * @return the architecture - */ - Architecture getArchitecture(); } private sealed interface ObjectSerializer { @@ -819,6 +805,7 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize } private static final class RegisterSerializer implements ObjectSerializer { + @Override public Class clazz() { return Register.class; @@ -833,17 +820,20 @@ public String tag() { public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { Register register = (Register) instance; objectBuilder.append("number", register.number); + objectBuilder.append("name", register.name); + objectBuilder.append("encoding", register.encoding); + objectBuilder.append("catName", register.getRegisterCategory().toString()); + objectBuilder.append("containsRef", register.mayContainReference()); } @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { int number = (int) json.get("number"); - for (Register register : deserializer.getArchitecture().getRegisters()) { - if (register.number == number) { - return register; - } - } - throw new DeserializationException(this, json, "Register not found"); + String name = (String) json.get("name"); + int encoding = (int) json.get("encoding"); + String catName = (String) json.get("catName"); + boolean containsRef = (boolean) json.get("containsRef"); + return new Register(number, encoding, name, new Register.RegisterCategory(catName, containsRef)); } } @@ -1697,14 +1687,12 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { String name = (String) json.get("name"); EnumSet features = (EnumSet) deserializer.deserialize(json.get("features"), proxyFactory); - Architecture architecture = switch (name) { + return switch (name) { case "AMD64" -> new AMD64((EnumSet) features); case "riscv64" -> new RISCV64((EnumSet) features); case "aarch64" -> new AArch64((EnumSet) features); default -> throw new IllegalStateException("Unexpected value: " + name); }; - deserializer.setArchitecture(architecture); - return architecture; } } @@ -1944,55 +1932,41 @@ public void dump(RecordedCompilationUnit compilationUnit, JsonWriter writer) thr recursiveSerializer.serialize(compilationUnit, writer.valueBuilder(), RecordedCompilationUnitSerializer.TAG); } - private RecursiveDeserializer createRecursiveDeserializer() { - return new RecursiveDeserializer() { - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - String tag = (String) map.get("tag"); - if (tag == null) { - throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); - } - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); - } - return deserializer.deserialize(map, this, proxyFactory); - } else { - return json; + private final RecursiveDeserializer recursiveDeserializer = new RecursiveDeserializer() { + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + String tag = (String) map.get("tag"); + if (tag == null) { + throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); } - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); - } - return deserializer.deserialize(map, this, proxyFactory); - } else { - throw new IllegalArgumentException("Expected a map."); + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); } + return deserializer.deserialize(map, this, proxyFactory); + } else { + return json; } + } - private Architecture architecture; - - @Override - public void setArchitecture(Architecture arch) { - architecture = arch; - } - - @Override - public Architecture getArchitecture() { - return architecture; + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); + } + return deserializer.deserialize(map, this, proxyFactory); + } else { + throw new IllegalArgumentException("Expected a map."); } - }; - } + } + }; /** * Loads a recorded compilation unit from the given reader. @@ -2005,6 +1979,6 @@ public Architecture getArchitecture() { */ public RecordedCompilationUnit load(Reader source, ProxyFactory proxyFactory) throws IOException, DeserializationException { JsonParser parser = new JsonParser(source); - return (RecordedCompilationUnit) createRecursiveDeserializer().deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); + return (RecordedCompilationUnit) recursiveDeserializer.deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java index 2b1db7602c46..d264db2bd57b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java @@ -139,7 +139,11 @@ public List collectOperationsForSerializati return recorder.getCurrentRecordedOperations(); } - @Override + /** + * Enters the context of a method compilation for the current compilation thread. + * + * @return a scope for the context + */ public DebugCloseable enterCompilationContext() { return recorder.enterCompilationContext(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java index af7efd89df89..47b6fcc4d06b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java @@ -41,8 +41,6 @@ import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.debug.TimerKey; -import jdk.graal.compiler.hotspot.CompilationContext; -import jdk.graal.compiler.hotspot.HotSpotGraalServices; import jdk.graal.compiler.hotspot.Platform; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; @@ -51,10 +49,7 @@ import jdk.graal.compiler.options.OptionType; import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.MetaAccessProvider; //JaCoCo Exclude @@ -71,7 +66,7 @@ * memory usage low, which is important when replaying many compilations on libgraal and * benchmarking compile time. *

- * It is necessary to call {@link #findLocalMirrors} after the operations are loaded and JVMCI + * It is necessary to call {@link #findLocalMirrors()} after the operations are loaded and JVMCI * providers are created. The local mirrors may be required during a replayed compilation to query * information from the local VM, which is needed for snippet parsing. * @@ -148,11 +143,6 @@ public void setLocalMirror(Object newLocalMirror) { */ private final EconomicMap, Object> singletonObjects; - /** - * The host meta access provider. - */ - private MetaAccessProvider hostMetaAccess; - /** * Proxifies and unproxifies composite objects. */ @@ -224,17 +214,6 @@ public DebugCloseable withDebugContext(DebugContext debugContext) { }; } - @Override - public DebugCloseable enterCompilationContext() { - // The handles created during replay are cached across compilations. - CompilationContext context = HotSpotGraalServices.enterGlobalCompilationContext(); - if (context == null) { - return DebugCloseable.VOID_CLOSEABLE; - } else { - return context::close; - } - } - /** * Loads the recorded operations from a collection. * @@ -351,17 +330,14 @@ private static Object intern(Object object, EconomicMap internPo *

* During snippet parsing, the compiler may discover a JVMCI object which has no matching proxy. * For such objects, local-only proxies are created using {@link #proxify(Object)}. - * - * @param jvmciRuntime the JVMCI runtime */ - public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) { - HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); + public void findLocalMirrors() { var cursor = createdProxies.getEntries(); while (cursor.advance()) { CompilationProxy proxy = cursor.getKey(); CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(proxy); if (registration.mirrorLocator() != null) { - Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, hostMetaAccess, constantReflection, jvmciRuntime); + Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, singletonObjects); if (localMirror != null) { Object previousProxy = localMirrorToProxy.put(localMirror, proxy); GraalError.guarantee(previousProxy == null, "there must be at most one proxy instance for an object"); @@ -426,9 +402,6 @@ public CompilationProxy proxify(Object input) { localMirrorToProxy.put(input, proxy); if (registration.singleton()) { singletonObjects.put(registration.clazz(), input); - if (input instanceof MetaAccessProvider metaAccess) { - hostMetaAccess = metaAccess; - } } return proxy; } @@ -488,13 +461,13 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r if (proxyInfo.localMirror == null) { CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess)); + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); } } GraalError.guarantee(proxyInfo.localMirror != null, "a proxy with passthrough strategy must have a local mirror or fallback handler"); return callback.invoke(proxyInfo.localMirror, args); } else if (strategy == CompilerInterfaceDeclarations.MethodStrategy.DefaultValue) { - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess)); + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); } Object result = findResult(proxyInfo, method, args); if (result != SpecialResultMarker.NO_RESULT_MARKER) { @@ -522,7 +495,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r } CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess)); + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); } if (args != null) { for (Object arg : args) { @@ -534,7 +507,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r if (divergenceIsFailure) { failOnDivergence(proxy, proxyInfo, method, args); } - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess)); + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); } }); if (registration.singleton()) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java index 28c0ca445ef5..98e14350887a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java @@ -181,7 +181,6 @@ public static ExitStatus run(String[] args, PrintStream out) { codeHash = codeHash * 31 + Arrays.hashCode(replayResult.replayedArtifacts().result().getTargetCode()); } catch (Exception e) { out.println("Replay failed: " + e); - e.printStackTrace(out); return ExitStatus.Failure; } } @@ -207,7 +206,6 @@ public static ExitStatus run(String[] args, PrintStream out) { task.setFailureReason(failure.getMessage()); } catch (Exception e) { out.println("Replay failed: " + e); - e.printStackTrace(out); return ExitStatus.Failure; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java index 564687fbdbef..2ab23bbaecae 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java @@ -90,7 +90,7 @@ * *

* Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the - * proxies ({@link #findLocalMirrors}). This is useful when the compiler queries information that + * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that * was not recorded, including the information used to process snippets. There are also local-only * proxies that do not originate from the recorded JSON but are instead created from local JVMCI * objects (created using {@link CompilationProxies#proxify}). The exact rules when operations are @@ -263,16 +263,18 @@ public DebugCloseable withDebugContext(DebugContext debug) { * @return a debug closeable that should be closed after the compilation */ public DebugCloseable enterCompilationContext(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { - DebugCloseable context = proxies.enterCompilationContext(); - return () -> { - try { - if (proxies instanceof RecordingCompilationProxies) { + if (proxies instanceof RecordingCompilationProxies recordingCompilationProxies) { + DebugCloseable context = recordingCompilationProxies.enterCompilationContext(); + return () -> { + try { serializeRecordedCompilation(originalRequest, initialOptions); + } finally { + context.close(); } - } finally { - context.close(); - } - }; + }; + } else { + return DebugCloseable.VOID_CLOSEABLE; + } } private void serializeRecordedCompilation(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { @@ -320,12 +322,10 @@ public boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpo * Finds local mirrors for the parsed proxies during replay compilation. This should be invoked * just after the core JVMCI providers are created because they are needed to look up the * mirrors. - * - * @param jvmciRuntime the JVMCI runtime */ - public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) { + public void findLocalMirrors() { if (proxies instanceof ReplayCompilationProxies replayCompilationProxies) { - replayCompilationProxies.findLocalMirrors(jvmciRuntime); + replayCompilationProxies.findLocalMirrors(); } } @@ -333,11 +333,10 @@ public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) { * Decorates a backend factory. * * @param factory the backend factory to decorate - * @param jvmciRuntime the JVMCI runtime * @return the decorated backend factory */ - public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory, HotSpotJVMCIRuntime jvmciRuntime) { - return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this, jvmciRuntime)); + public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory) { + return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this)); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java index c1af98865630..35eb865bf83f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java @@ -229,7 +229,13 @@ interface InvocationHandler { */ static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod method, InvokableMethod invokable, Object... args) { try { - return handler.handle(proxy, method, wrapInvocationExceptions(invokable), (args.length == 0) ? null : args); + return handler.handle(proxy, method, (Object receiver, Object[] actualArgs) -> { + try { + return invokable.invoke(receiver, actualArgs); + } catch (Throwable e) { + throw new InvocationTargetException(e); + } + }, (args.length == 0) ? null : args); } catch (RuntimeException | Error e) { throw e; } catch (Throwable e) { @@ -237,23 +243,6 @@ static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod met } } - /** - * Returns a new invokable method that wraps the exceptions thrown by the provided invokable - * method. - * - * @param invokable an invokable method that can throw an unwrapped exception - * @return an invokable method that can throw an {@link InvocationTargetException} - */ - static InvokableMethod wrapInvocationExceptions(InvokableMethod invokable) { - return (Object receiver, Object[] actualArgs) -> { - try { - return invokable.invoke(receiver, actualArgs); - } catch (Throwable e) { - throw new InvocationTargetException(e); - } - }; - } - /** * Creates a new compilation proxy instance for the specified class and invocation handler. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java deleted file mode 100644 index 9f644e8fbe17..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotConstant; -import jdk.vm.ci.meta.Constant; - -//JaCoCo Exclude - -public sealed class HotSpotConstantProxy extends CompilationProxyBase implements HotSpotConstant permits HotSpotMetaspaceConstantProxy, HotSpotObjectConstantProxy { - HotSpotConstantProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotConstant.class, name, params); - } - - public static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); - private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isDefaultForKind(); - - @Override - public boolean isDefaultForKind() { - return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); - } - - public static final SymbolicMethod toValueStringMethod = method("toValueString"); - public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotConstant) receiver).toValueString(); - - @Override - public String toValueString() { - return (String) handle(toValueStringMethod, toValueStringInvokable); - } - - public static final SymbolicMethod isCompressedMethod = method("isCompressed"); - public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isCompressed(); - - @Override - public boolean isCompressed() { - return (boolean) handle(isCompressedMethod, isCompressedInvokable); - } - - public static final SymbolicMethod isCompressibleMethod = method("isCompressible"); - public static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isCompressible(); - - @Override - public boolean isCompressible() { - return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); - } - - public static final SymbolicMethod compressMethod = method("compress"); - public static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotConstant) receiver).compress(); - - @Override - public Constant compress() { - return (Constant) handle(compressMethod, compressInvokable); - } - - public static final SymbolicMethod uncompressMethod = method("uncompress"); - public static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotConstant) receiver).uncompress(); - - @Override - public Constant uncompress() { - return (Constant) handle(uncompressMethod, uncompressInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java index 7f31474d396a..52599c0f2c72 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java @@ -27,10 +27,11 @@ import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Constant; //JaCoCo Exclude -public final class HotSpotMetaspaceConstantProxy extends HotSpotConstantProxy implements HotSpotMetaspaceConstant { +public final class HotSpotMetaspaceConstantProxy extends CompilationProxyBase implements HotSpotMetaspaceConstant { HotSpotMetaspaceConstantProxy(InvocationHandler handler) { super(handler); } @@ -39,6 +40,54 @@ private static SymbolicMethod method(String name, Class... params) { return new SymbolicMethod(HotSpotMetaspaceConstant.class, name, params); } + private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); + private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isDefaultForKind(); + + @Override + public boolean isDefaultForKind() { + return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + } + + public static final SymbolicMethod toValueStringMethod = method("toValueString"); + public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).toValueString(); + + @Override + public String toValueString() { + return (String) handle(toValueStringMethod, toValueStringInvokable); + } + + public static final SymbolicMethod isCompressedMethod = method("isCompressed"); + public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressed(); + + @Override + public boolean isCompressed() { + return (boolean) handle(isCompressedMethod, isCompressedInvokable); + } + + private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); + private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressible(); + + @Override + public boolean isCompressible() { + return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); + } + + public static final SymbolicMethod compressMethod = method("compress"); + private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).compress(); + + @Override + public Constant compress() { + return (Constant) handle(compressMethod, compressInvokable); + } + + public static final SymbolicMethod uncompressMethod = method("uncompress"); + private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).uncompress(); + + @Override + public Constant uncompress() { + return (Constant) handle(uncompressMethod, uncompressInvokable); + } + public static final SymbolicMethod asResolvedJavaTypeMethod = method("asResolvedJavaType"); public static final InvokableMethod asResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaType(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java index 1b96b42a1b90..034db556df9d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java @@ -33,7 +33,7 @@ //JaCoCo Exclude -public final class HotSpotObjectConstantProxy extends HotSpotConstantProxy implements HotSpotObjectConstant { +public final class HotSpotObjectConstantProxy extends CompilationProxyBase implements HotSpotObjectConstant { HotSpotObjectConstantProxy(InvocationHandler handler) { super(handler); } @@ -42,6 +42,22 @@ private static SymbolicMethod method(String name, Class... params) { return new SymbolicMethod(HotSpotObjectConstant.class, name, params); } + public static final SymbolicMethod compressMethod = method("compress"); + private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).compress(); + + @Override + public JavaConstant compress() { + return (JavaConstant) handle(compressMethod, compressInvokable); + } + + public static final SymbolicMethod uncompressMethod = method("uncompress"); + private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).uncompress(); + + @Override + public JavaConstant uncompress() { + return (JavaConstant) handle(uncompressMethod, uncompressInvokable); + } + public static final SymbolicMethod getTypeMethod = method("getType"); public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getType(); @@ -156,13 +172,35 @@ public double asDouble() { return (double) handle(asDoubleMethod, asDoubleInvokable); } + public static final SymbolicMethod isCompressedMethod = method("isCompressed"); + public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressed(); + + @Override + public boolean isCompressed() { + return (boolean) handle(isCompressedMethod, isCompressedInvokable); + } + + private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); + private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressible(); + @Override - public JavaConstant compress() { - return (JavaConstant) super.compress(); + public boolean isCompressible() { + return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); } + private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); + private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isDefaultForKind(); + @Override - public JavaConstant uncompress() { - return (JavaConstant) super.uncompress(); + public boolean isDefaultForKind() { + return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + } + + public static final SymbolicMethod toValueStringMethod = method("toValueString"); + public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).toValueString(); + + @Override + public String toValueString() { + return (String) handle(toValueStringMethod, toValueStringInvokable); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java index e548431b9dd2..a81654130ee6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java @@ -372,7 +372,7 @@ public boolean hasCompiledCodeAtLevel(int level) { return (boolean) handle(hasCompiledCodeAtLevelMethod, hasCompiledCodeAtLevelInvokable, level); } - public static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); + private static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); private static final InvokableMethod vtableEntryOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).vtableEntryOffset((ResolvedJavaType) args[0]); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java index e18ae3bd4bb3..2dcd0363237a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -281,7 +281,7 @@ public final HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType return (HotSpotResolvedObjectType) handle(findLeastCommonAncestorMethod, findLeastCommonAncestorInvokable, otherType); } - public static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); + private static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); private static final InvokableMethod isPrimitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isPrimitive(); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java index 053daae2c5f1..7e1d52812e29 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java @@ -89,15 +89,15 @@ public Constant klass() { return (Constant) handle(klassMethod, klassInvokable); } - public static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); - public static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); + private static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); + private static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); @Override public boolean isPrimaryType() { return (boolean) handle(isPrimaryTypeMethod, isPrimaryTypeInvokable); } - public static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); + private static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); private static final InvokableMethod superCheckOffsetInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).superCheckOffset(); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java index 4e8c6b612de7..935e03bf1934 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java @@ -47,8 +47,8 @@ public int getParameterCount(boolean rec) { return (int) handle(getParameterCountMethod, getParameterCountInvokable, rec); } - public static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); - public static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); + private static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); + private static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); @Override public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { From 85ece500855d66c84251cec06ebcfcfe200f791b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 15:27:39 +0200 Subject: [PATCH 11/49] Revert "[GR-68990] [GR-69008] Fix graph equality when replaying libgraal compilation on jargraal and fix cache replacements" This reverts commit 3ff585bea7de9b5dc7027216c2de832eccde8780, reversing changes made to f4a4dcf4f18158314be4c92b5498cf0bac28bd27. --- .../test/ReplayCompilationTest.java | 24 ----------------- .../compiler/hotspot/EncodedSnippets.java | 11 +++----- .../replacements/AssertionSnippets.java | 2 +- .../CompilerInterfaceDeclarations.java | 27 ------------------- .../proxy/HotSpotResolvedJavaTypeProxy.java | 2 +- 5 files changed, 6 insertions(+), 60 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java index fcc5bd708c58..60eb1efb8085 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java @@ -38,8 +38,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; -import org.junit.AfterClass; -import org.junit.BeforeClass; import org.junit.Test; import com.oracle.truffle.api.Truffle; @@ -48,7 +46,6 @@ import jdk.graal.compiler.core.CompilationWrapper; import jdk.graal.compiler.core.GraalCompilerOptions; import jdk.graal.compiler.core.test.GraalCompilerTest; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.LogStream; @@ -57,11 +54,9 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; @@ -74,25 +69,6 @@ * Tests for compilation recording and replay. */ public class ReplayCompilationTest extends GraalCompilerTest { - /** - * A separate encoded snippet scope is necessary in case the global encoded snippets have cache - * replacements. - */ - private static DebugCloseable snippetScope; - - @BeforeClass - public static void setup() { - Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); - snippetScope = replacements.suppressEncodedSnippets(); - replacements.encode(getInitialOptions()); - } - - @AfterClass - public static void teardown() { - snippetScope.close(); - } - private static int[] lengthsSquared(List strings) { return strings.stream().mapToInt(String::length).map(i -> i * i).toArray(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index 73b2c868dd52..9acc8fffc452 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -47,7 +47,6 @@ import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.nodeinfo.Verbosity; import jdk.graal.compiler.nodes.ConstantNode; @@ -251,14 +250,12 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod declaringClass = replacements.getProviders().getMetaAccess().lookupJavaType(Object.class); } /* - * If there is a possibility of a recorded/replayed compilation, we must not mutate the - * snippet objects. During recording, this ensures that we record all relevant operations - * and the cached objects are resolved to proxies. During replay, this ensures that no - * proxies are stored in the snippet objects. + * If this is a recorded/replayed compilation, we must not mutate the snippet objects. This + * ensures we record all relevant operations during recording and no proxies are stored in + * the snippet objects during replay. */ boolean allowCacheReplacements = replacements.getProviders().getReplayCompilationSupport() == null && - GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose && - !DebugOptions.RecordForReplay.hasBeenSet(options); + GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, snippetNodeClasses, data.originalMethod, declaringClass); return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, true); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java index 884eef48837b..6d986a0e25cf 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java @@ -90,7 +90,7 @@ public void lower(AssertionNode assertionNode, LoweringTool tool) { Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph, tool.getLoweringStage()); args.add("condition", assertionNode.condition()); args.add("message", - graph.unique(new ConstantNode(new CStringConstant("failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method().format("%H.%n(%p)") + ")"), + graph.unique(new ConstantNode(new CStringConstant("failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"), StampFactory.pointer()))); args.add("l1", assertionNode.getL1()); args.add("l2", assertionNode.getL2()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index 999c66f0f743..abf8b60ff0bb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -30,7 +30,6 @@ import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; -import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; import java.lang.reflect.Proxy; @@ -49,7 +48,6 @@ import jdk.graal.compiler.core.common.CompilerProfiler; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; @@ -68,7 +66,6 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; -import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -706,7 +703,6 @@ public static CompilerInterfaceDeclarations build() { } return List.of(); }) - .setFallbackInvocationHandler(HotSpotResolvedObjectTypeProxy.isInstanceMethod, CompilerInterfaceDeclarations::objectTypeIsInstanceFallback) .register(declarations); // Must come after HotSpotResolvedObjectType. Needed for HotSpotResolvedPrimitiveType. new RegistrationBuilder<>(HotSpotResolvedJavaType.class) @@ -925,27 +921,4 @@ private static ResolvedJavaType javaLangObjectSupplier(Object proxy, Compilation MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); return metaAccess.lookupJavaType(Object.class); } - - /** - * Implements a fallback for {@link HotSpotResolvedObjectType#isInstance} calls performed by - * {@link HotSpotGraalConstantFieldProvider} when replaying a libgraal compilation on jargraal. - *

- * The provider performs checks like {@code getHotSpotVMConfigType().isInstance(receiver)}, - * which use snippet types on libgraal and HotSpot types on jargraal. Replay on jargraal needs - * to answer these queries when the receiver and argument are HotSpot proxies. - */ - @SuppressWarnings("unused") - @ExcludeFromJacocoGeneratedReport("related to replay of libgraal compilations on jargraal") - private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { - HotSpotResolvedObjectType receiverType = (HotSpotResolvedObjectType) proxy; - if (!(args[0] instanceof HotSpotObjectConstant objectConstant)) { - return false; - } - HotSpotResolvedObjectType constantType = objectConstant.getType(); - if (isGraalClass(receiverType) && !isGraalClass(constantType)) { - // Assumes that only a Graal class can subtype a Graal class. - return false; - } - return receiverType.isAssignableFrom(constantType); - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java index 2dcd0363237a..a9eaefc24157 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -241,7 +241,7 @@ public final boolean isAssignableFrom(ResolvedJavaType other) { return (boolean) handle(isAssignableFromMethod, isAssignableFromInvokable, other); } - public static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); + private static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); private static final InvokableMethod isInstanceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstance((JavaConstant) args[0]); @Override From a8c8c7401923367cbf29bb8c0886911bf198c829 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 15:29:20 +0200 Subject: [PATCH 12/49] Revert "[GR-68037] Use encoded snippets in jargraal." This reverts commit de29af876e539ec52e8e3ae6748deaeff059d90e, reversing changes made to e482f988939235ce94ee4a756c6bcc1d3df2bab2. --- compiler/docs/ReplayCompilation.md | 4 +- .../test/TransplantLowLevelGraphTest.java | 30 +-- .../hotspot/amd64/test/StubAVXTest.java | 11 +- .../test/ReplayCompilationTest.java | 31 +++- .../test/TestNewInstanceWithException.java | 19 +- ...estNewInstanceWithExceptionRegression.java | 4 +- .../test/SnippetCountersTest.java | 87 --------- .../compiler/core/common/GraalOptions.java | 3 + .../compiler/hotspot/CompilerConfig.java | 9 +- .../compiler/hotspot/EncodedSnippets.java | 171 ++++-------------- .../hotspot/HotSpotBackendFactory.java | 6 +- .../compiler/hotspot/HotSpotHostBackend.java | 50 ----- .../hotspot/HotSpotReplacementsImpl.java | 98 +++++----- .../HotSpotSnippetMetaAccessProvider.java | 28 ++- .../hotspot/SymbolicSnippetEncoder.java | 38 ++-- .../meta/HotSpotHostForeignCallsProvider.java | 4 +- .../HotSpotSnippetReflectionProvider.java | 4 +- .../CompilerInterfaceDeclarations.java | 25 +++ .../HotSpotProxyBackendFactory.java | 17 +- .../RecordedOperationPersistence.java | 8 +- .../replaycomp/ReplayCompilationRunner.java | 43 ++++- .../replaycomp/ReplayCompilationSupport.java | 96 ++++++++-- .../hotspot/stubs/HotSpotGraphKit.java | 19 +- .../replacements/SnippetTemplate.java | 105 ++++++++--- .../compiler/replacements/TestSnippets.java | 30 --- .../hotspot/HotSpotTruffleCompilerImpl.java | 22 --- .../IntentionallyUnsupportedOptions.java | 2 + .../svm/hosted/NativeImageGenerator.java | 6 + .../AnalysisToHostedGraphTransplanter.java | 4 +- .../NativeImageWasmGeneratorRunner.java | 5 + 30 files changed, 471 insertions(+), 508 deletions(-) delete mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java diff --git a/compiler/docs/ReplayCompilation.md b/compiler/docs/ReplayCompilation.md index 66ad033ad9d7..cafbf5a9e5bc 100644 --- a/compiler/docs/ReplayCompilation.md +++ b/compiler/docs/ReplayCompilation.md @@ -63,7 +63,9 @@ Any `-ea`, `-esa`, and `-X` arguments from the command line are passed to the JV ## Jargraal vs. Libgraal -Jargraal can replay both jargraal and libgraal compilations. Libgraal can replay only libgraal compilations. +Both jargraal and libgraal compilations can be replayed on jargraal. When jargraal replays a libgraal compilation, +it uses encoded snippets to match the behavior and compilations results of libgraal. It is also possible to replay +libgraal compilations on libgraal. Replaying jargraal compilations on libgraal is not supported. It is necessary to explicitly enable the replay launcher entry point when building libgraal using the VM argument `-Ddebug.jdk.graal.enableReplayLauncher=true`. diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java index 6564eff47c6b..22301acd9cbd 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java @@ -31,12 +31,9 @@ import org.junit.Test; import jdk.graal.compiler.api.directives.GraalDirectives; -import jdk.graal.compiler.api.test.Graal; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.phases.HighTier; -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.nodes.GraphState.GuardsStage; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -51,30 +48,35 @@ import jdk.graal.compiler.replacements.TestSnippets; import jdk.graal.compiler.replacements.TestSnippets.TransplantTestSnippets; import jdk.graal.compiler.replacements.nodes.LateLoweredNode; -import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; public class TransplantLowLevelGraphTest extends GraalCompilerTest { - private static DebugCloseable snippetScope; - - private static TestSnippets.TransplantTestSnippets.Templates transplantTestSnippets; @BeforeClass public static void setup() { - Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); - OptionValues options = getInitialOptions(); - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); - snippetScope = replacements.suppressEncodedSnippets(); - transplantTestSnippets = new TestSnippets.TransplantTestSnippets.Templates(options, providers); - replacements.encode(options); + /** + * Ensure snippets can be registered in a test setup running jargraal only. + */ + System.setProperty("GraalUnitTest", "true"); } @AfterClass public static void teardown() { - snippetScope.close(); + System.clearProperty("GraalUnitTest"); + } + + TestSnippets.TransplantTestSnippets.Templates transplantTestSnippets; + + @SuppressWarnings("this-escape") + public TransplantLowLevelGraphTest() { + Providers p = getProviders(); + OptionValues opt = getInitialOptions(); + + // ensure that the snippets are registered + transplantTestSnippets = new TestSnippets.TransplantTestSnippets.Templates(opt, p); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java index 8abab2966bd6..5662e05d71f9 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java @@ -44,11 +44,9 @@ import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.type.DataPointerConstant; import jdk.graal.compiler.core.test.GraalCompilerTest; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.hotspot.HotSpotBackend; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; @@ -242,11 +240,8 @@ public static int testStub() { public void test() { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = providers.getForeignCalls(); - OptionValues options = GraalCompilerTest.getInitialOptions(); - try (DebugCloseable _ = ((HotSpotReplacementsImpl) providers.getReplacements()).suppressEncodedSnippets()) { - HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED); - linkage.setCompiledStub(new TestStub(options, providers, linkage)); - runTest("testStub"); - } + HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED); + linkage.setCompiledStub(new TestStub(GraalCompilerTest.getInitialOptions(), providers, linkage)); + runTest("testStub"); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java index 60eb1efb8085..95beb5cbf83b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java @@ -25,6 +25,7 @@ package jdk.graal.compiler.hotspot.replaycomp.test; import java.io.ByteArrayOutputStream; +import java.io.FileReader; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; @@ -54,10 +55,15 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; +import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.runtime.RuntimeProvider; +import jdk.graal.compiler.util.json.JsonParser; +import jdk.graal.compiler.util.json.JsonWriter; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -118,17 +124,36 @@ public void recordAndExecuteReplayRunner() throws Throwable { HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, recordOptions); assertTrue(regularResult.getFailure() == null); Path replayFile = findReplayCompFile(temp.path); + Path replayFileLibgraal = Path.of(temp.path.toString(), "libgraal.json"); + copyReplayFileAsLibgraalCompilation(replayFile, replayFileLibgraal); String[][] argumentLists = new String[][]{ new String[]{"--compare-graphs=true", replayFile.toString()}, - new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", temp.path.toString()} + new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", replayFileLibgraal.toString()} }; for (String[] arguments : argumentLists) { ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(arguments, TTY.out().out()); assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); } + assertTrue(HotSpotReplacementsImpl.snippetsAreEncoded()); }); } + /** + * Creates a copy of the source replay file that acts as if it was compiled with libgraal. This + * way, we test replaying libgraal compilations on jargraal (without access to libgraal). + * + * @param replayFile the source replay file + * @param destFile the created replay file that acts as a libgraal compilation + * ({@link jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence.RecordedCompilationUnit#isLibgraal()}) + */ + private static void copyReplayFileAsLibgraalCompilation(Path replayFile, Path destFile) throws Throwable { + try (FileReader reader = new FileReader(replayFile.toFile()); JsonWriter writer = new JsonWriter(destFile)) { + EconomicMap json = JsonParser.parseDict(reader); + json.put(RecordedOperationPersistence.RecordedCompilationUnitSerializer.IS_LIBGRAAL_PROPERTY, true); + writer.print(json); + } + } + @Test public void unparsableReplayFileSucceeds() throws Throwable { runTest((temp) -> { @@ -165,6 +190,10 @@ private static void runTest(TestRunner test) throws Throwable { System.err.println(outputStream.toString(Charset.defaultCharset())); throw throwable; } + } finally { + HotSpotReplacementsImpl.setEncodedSnippets(null); + HotSpotReplacementsImpl.clearSnippetEncoder(); + ReplayCompilationSupport.setReplayingLibgraalInJargraal(false); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java index ec22c1155ab4..ed89537bd54f 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java @@ -569,11 +569,6 @@ public void runSubprocessTest(Runnable r, String... args) throws IOException, In } } - /** - * The argument setting the maximum heap space of the subprocess. - */ - public static final String MAX_HEAP_SPACE_ARG = "-Xmx64m"; - public static class TestNewInstanceWithException1 extends TestNewInstanceWithException { @Test @@ -584,7 +579,7 @@ public void testNewArrayWithException() throws IOException, InterruptedException } catch (InvalidInstalledCodeException e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -597,7 +592,7 @@ public void testNewInstanceWithException() throws IOException, InterruptedExcept } catch (InvalidInstalledCodeException e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -610,7 +605,7 @@ public void testDynamicNewInstanceWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -623,7 +618,7 @@ public void testDynamicNewInstanceWithExceptionCanonToInstanceWithException() th } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -636,7 +631,7 @@ public void testDynamicNewArrayWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -649,7 +644,7 @@ public void testDynamicNewArrayWithExceptionCanonToArrayWithException() throws T } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } @@ -662,7 +657,7 @@ public void testNewMultiArrayWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java index 52c94dce692d..fbac45013caa 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.hotspot.test; -import static jdk.graal.compiler.hotspot.test.TestNewInstanceWithException.MAX_HEAP_SPACE_ARG; - import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -72,7 +70,7 @@ public void test01() throws IOException, InterruptedException { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, MAX_HEAP_SPACE_ARG); + }, "-Xmx32m"); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java deleted file mode 100644 index a38cc64deb94..000000000000 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.replacements.test; - -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.DebugCloseable; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.replacements.SnippetCounter; -import jdk.graal.compiler.replacements.SnippetSubstitutionInvocationPlugin; -import jdk.graal.compiler.replacements.SnippetTemplate; -import jdk.graal.compiler.replacements.TestSnippets; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * Tests snippet counters with encoded snippets on jargraal. - */ -public class SnippetCountersTest extends GraalCompilerTest { - public static void testedMethod() { - substitutedInvoke(); - } - - public static void substitutedInvoke() { - } - - private TestSnippets.CounterTestSnippets.TestSnippetCounters counters; - - @Test - public void test() { - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) getReplacements(); - try (DebugCloseable _ = replacements.suppressEncodedSnippets()) { - OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.SnippetCounters, true); - replacements.registerSnippetTemplateCache(new TestSnippets.CounterTestSnippets.Templates(options, getProviders())); - replacements.encode(options); - counters = new TestSnippets.CounterTestSnippets.TestSnippetCounters(SnippetCounter.Group::new); - executeActual(getResolvedJavaMethod("testedMethod"), null); - Assert.assertEquals(1L, counters.increments.value()); - Assert.assertEquals(2L, counters.doubleIncrements.value()); - } - } - - @Override - protected GraphBuilderConfiguration.Plugins getDefaultGraphBuilderPlugins() { - GraphBuilderConfiguration.Plugins p = super.getDefaultGraphBuilderPlugins(); - InvocationPlugins.Registration r = new InvocationPlugins.Registration(p.getInvocationPlugins(), SnippetCountersTest.class); - r.register(new SnippetSubstitutionInvocationPlugin<>(TestSnippets.CounterTestSnippets.Templates.class, "substitutedInvoke") { - @Override - public SnippetTemplate.SnippetInfo getSnippet(TestSnippets.CounterTestSnippets.Templates templates) { - return templates.increase; - } - - @Override - protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { - return new Object[]{counters}; - } - }); - return p; - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java index 07a59d640c71..3731b473d95d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java @@ -291,6 +291,9 @@ public final class GraalOptions { @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug) public static final OptionKey SnippetCounters = new OptionKey<>(false); + @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug) + public static final OptionKey EagerSnippets = new OptionKey<>(false); + @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug) public static final OptionKey UseSnippetGraphCache = new OptionKey<>(true); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java index 2fdeceb8a130..ffef728cb93f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java @@ -38,8 +38,8 @@ import org.graalvm.collections.MapCursor; import jdk.graal.compiler.core.common.Fields; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass; @@ -104,7 +104,6 @@ protected ClassInfo makeClassInfo(Class declaringClass) { } private static EncodedSnippets getEncodedSnippets(HotSpotReplacementsImpl replacements, OptionValues options) { - GraalError.guarantee(!HotSpotReplacementsImpl.snippetsAreEncoded(), "snippets should not be encoded"); SymbolicSnippetEncoder snippetEncoder = replacements.maybeInitializeEncoder(); return snippetEncoder.encodeSnippets(options); } @@ -131,11 +130,7 @@ private static EconomicMap coll HotSpotProviders providers = replacements.getProviders(); collectForeignCalls(providers.getForeignCalls(), allForeignCalls); - /* - * Instantiate the Truffle compiler to collect its foreign calls as well. Ensure the - * snippets are registered using this encoder. - */ - replacements.shareSnippetEncoder(); + // Instantiate the Truffle compiler to collect its foreign calls as well for (Backend truffleBackend : HotSpotTruffleCompilerImpl.ensureBackendsInitialized(options)) { HotSpotProviders truffleProviders = (HotSpotProviders) truffleBackend.getProviders(); collectForeignCalls(truffleProviders.getForeignCalls(), allForeignCalls); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index 9acc8fffc452..c09b8a98ad6a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -27,6 +27,7 @@ import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.snippetsAreEncoded; +import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Executable; @@ -40,9 +41,7 @@ import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.CompilationWrapper; import jdk.graal.compiler.core.GraalCompilerOptions; -import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; @@ -55,10 +54,8 @@ import jdk.graal.compiler.nodes.NodeClassMap; 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; import jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext; -import jdk.graal.compiler.nodes.graphbuilderconf.NodePlugin; import jdk.graal.compiler.nodes.graphbuilderconf.ParameterPlugin; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; import jdk.graal.compiler.nodes.spi.SnippetParameterInfo; @@ -67,7 +64,6 @@ import jdk.graal.compiler.replacements.ConstantBindingParameterPlugin; import jdk.graal.compiler.replacements.PEGraphDecoder; import jdk.graal.compiler.replacements.PartialIntrinsicCallTargetNode; -import jdk.graal.compiler.replacements.SnippetCounter; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -79,6 +75,17 @@ import jdk.vm.ci.meta.UnresolvedJavaType; public class EncodedSnippets { + /** + * Returns true if the current runtime or current compilation thread uses encoded snippets + * rather than parsing them directly. This is always true when executing in libgraal, and it is + * also true when the current thread is replaying a libgraal compilation in jargraal. + * + * @return true if encoded snippets are currently in use + */ + public static boolean isUsingEncodedSnippets() { + return inRuntimeCode() || isReplayingLibgraalInJargraal(); + } + /** * Returns true if the current runtime or current compilation thread uses encoded snippets and * the snippets are already encoded. This is always true when executing in libgraal. If the @@ -88,7 +95,7 @@ public class EncodedSnippets { * @return true if encoded snippets are in use and already encoded */ public static boolean isAfterSnippetEncoding() { - return inRuntimeCode() || snippetsAreEncoded(); + return inRuntimeCode() || (isReplayingLibgraalInJargraal() && snippetsAreEncoded()); } /** @@ -211,11 +218,8 @@ public NodeClassMap getSnippetNodeClasses() { public ResolvedJavaType lookupSnippetType(Class clazz) { SnippetResolvedJavaType type = snippetTypes.get(clazz); if (type == null && isGraalClass(clazz)) { - /* - * During snippet encoding, references to Graal classes from snippets are tracked. If a - * class isn't found in this path at runtime it means something was missed. However, - * Truffle on jargraal can look up Graal classes that are not snippet types. - */ + // During image building, references to Graal classes from snippets are tracked. + // If a class isn't found in this path at runtime it means something was missed. throw new GraalError("Missing Graal class " + clazz.getName()); } return type; @@ -236,7 +240,11 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod data = graphDatas.get(methodKey(method)); } if (data == null) { - throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport + if (isUsingEncodedSnippets()) { + throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport + } else { + return null; + } } Class receiverClass = null; @@ -254,11 +262,11 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod * ensures we record all relevant operations during recording and no proxies are stored in * the snippet objects during replay. */ - boolean allowCacheReplacements = replacements.getProviders().getReplayCompilationSupport() == null && + boolean allowCacheReplacements = LibGraalSupport.inLibGraalRuntime() && replacements.getProviders().getReplayCompilationSupport() == null && GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, snippetNodeClasses, data.originalMethod, declaringClass); - return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, true); + return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, isUsingEncodedSnippets()); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @@ -334,17 +342,11 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.getProviders().getSnippetReflection(); - snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); + if (isUsingEncodedSnippets()) { + snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); + } parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); } - NodePlugin[] nodePlugins = null; - if (!inRuntimeCode() && GraalOptions.SnippetCounters.getValue(options)) { - /* - * SnippetCounters are supported on jargraal, but they require a plugin to fold the - * loads of SnippetCounter objects during decoding. - */ - nodePlugins = new NodePlugin[]{new SnippetCounterFoldingPlugin()}; - } try (DebugContext debug = replacements.openDebugContext("LibGraal", method, options)) { // @formatter:off @@ -356,10 +358,10 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res .build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("LibGraal.DecodeSnippet", result)) { - PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, nodePlugins, mustSucceed); + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, mustSucceed); assert result.isSubstitution(); graphDecoder.decode(method); - postDecode(debug, result, original, providers.getSnippetReflection(), providers.getMetaAccess()); + postDecode(debug, result, original); assert result.verify(); return result; } catch (Throwable t) { @@ -368,7 +370,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res } } - private static void postDecode(DebugContext debug, StructuredGraph result, ResolvedJavaMethod original, SnippetReflectionProvider snippetReflection, MetaAccessProvider metaAccess) { + private static void postDecode(DebugContext debug, StructuredGraph result, ResolvedJavaMethod original) { debug.dump(DebugContext.VERBOSE_LEVEL, result, "Before PartialIntrinsicCallTargetNode replacement"); for (PartialIntrinsicCallTargetNode partial : result.getNodes(PartialIntrinsicCallTargetNode.TYPE)) { // Ensure the original method matches @@ -379,18 +381,11 @@ private static void postDecode(DebugContext debug, StructuredGraph result, Resol partial.replaceAndDelete(target); } debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding"); - for (ConstantNode constant : result.getNodes().filter(ConstantNode.class).snapshot()) { - if (constant.asConstant() instanceof SnippetObjectConstant snippetConstant) { - if (!inRuntimeCode() && snippetConstant.asObject(SnippetCounter.class) != null) { - /* - * Convert SnippetCounter objects wrapped in SnippetObjectConstants to HotSpot - * constants (when snippet counters are enabled on jargraal). - */ - ConstantNode replacement = ConstantNode.forConstant(SnippetCounterFoldingPlugin.asHotSpotConstant(snippetConstant, snippetReflection), metaAccess); - replacement = result.unique(replacement); - constant.replace(result, replacement); - } else { - throw new InternalError(constant.toString(Verbosity.Debugger)); + for (ValueNode n : result.getNodes().filter(ValueNode.class)) { + if (n instanceof ConstantNode) { + ConstantNode constant = (ConstantNode) n; + if (constant.asConstant() instanceof SnippetObjectConstant) { + throw new InternalError(n.toString(Verbosity.Debugger)); } } } @@ -403,10 +398,10 @@ static class SubstitutionGraphDecoder extends PEGraphDecoder { private final boolean mustSucceed; SubstitutionGraphDecoder(Providers providers, StructuredGraph result, HotSpotReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, - IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, NodePlugin[] nodePlugins, boolean mustSucceed) { + IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, boolean mustSucceed) { super(providers.getCodeCache().getTarget().arch, result, providers, null, replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin, - nodePlugins, null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), false, false); + null, null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), false, false); this.method = method; this.encodedGraph = encodedGraph; this.mustSucceed = mustSucceed; @@ -434,109 +429,17 @@ protected boolean pluginReplacementMustSucceed() { } } - /** - * Performs constant folding of snippet counter code during snippet decoding on jargraal. - * Folding the loads allows the SnippetCounterNode_add plugin to succeed. - */ - @LibGraalSupport.HostedOnly - private static final class SnippetCounterFoldingPlugin implements NodePlugin { - @Override - public boolean handleLoadField(GraphBuilderContext b, ValueNode receiver, ResolvedJavaField field) { - if (receiver.isConstant()) { - JavaConstant asJavaConstant = receiver.asJavaConstant(); - return tryConstantFold(b, field, asJavaConstant); - } - return false; - } - - @Override - public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { - return tryConstantFold(b, field, null); - } - - /** - * Converts a snippet object constant to a HotSpot constant. - * - * @param snippetConstant the snippet constant - * @param snippetReflection snippet reflection - * @return the HotSpot constant - */ - private static JavaConstant asHotSpotConstant(SnippetObjectConstant snippetConstant, SnippetReflectionProvider snippetReflection) { - return snippetReflection.forObject(snippetConstant.asObject(Object.class)); - } - - private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant receiver) { - if (!field.isStatic() && (receiver == null || receiver.isNull())) { - return false; - } - ConstantNode result = b.getConstantFieldProvider().readConstantField(field, new ConstantFieldProvider.ConstantFieldTool<>() { - @Override - public JavaConstant readValue() { - JavaConstant hotSpotReceiver = receiver; - if (receiver instanceof SnippetObjectConstant objectConstant) { - hotSpotReceiver = asHotSpotConstant(objectConstant, b.getSnippetReflection()); - } - /* - * The result may be a HotSpotObjectConstant, which may also have field loads we - * need to fold. - */ - return b.getConstantReflection().readFieldValue(field, hotSpotReceiver); - } - - @Override - public JavaConstant getReceiver() { - return receiver; - } - - @Override - public Object getReason() { - return b.getGraph().currentNodeSourcePosition(); - } - - @Override - public ConstantNode foldConstant(JavaConstant ret) { - if (ret != null) { - return ConstantNode.forConstant(ret, b.getMetaAccess()); - } else { - return null; - } - } - - @Override - public ConstantNode foldStableArray(JavaConstant ret, int stableDimensions, boolean isDefaultStable) { - if (ret != null) { - return ConstantNode.forConstant(ret, stableDimensions, isDefaultStable, b.getMetaAccess()); - } else { - return null; - } - } - - @Override - public OptionValues getOptions() { - return b.getOptions(); - } - }); - if (result != null) { - result = b.getGraph().unique(result); - b.push(field.getJavaKind(), result); - return true; - } - return false; - } - } - static class SymbolicEncodedGraph extends EncodedGraph { private final ResolvedJavaType[] accessingClasses; private final String originalMethod; private final boolean allowCacheReplacements; - SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowCacheReplacements, NodeClassMap nodeClasses, String originalMethod, - ResolvedJavaType... accessingClasses) { + SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowObjectsMutations, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { super(encoding, startOffset, objects, nodeClasses, null, null, false, false); this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; - this.allowCacheReplacements = allowCacheReplacements; + this.allowCacheReplacements = allowObjectsMutations; } SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod, boolean allowCacheReplacements) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index 6ea000c69ab1..5895c1acfdd1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -24,7 +24,9 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.vm.ci.common.InitTimer.timer; import jdk.graal.compiler.bytecode.BytecodeProvider; @@ -176,7 +178,9 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti HotSpotConstantReflectionProvider constantReflection = createConstantReflectionProvider(jvmci); afterJVMCIProvidersCreated(); TargetDescription target = codeCache.getTarget(); - SnippetSignature.initPrimitiveKindCache(metaAccess); + if (inBuildtimeCode() || isUsingEncodedSnippets()) { + SnippetSignature.initPrimitiveKindCache(metaAccess); + } ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess); HotSpotProviders providers; HotSpotReplacementsImpl replacements; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java index 1974ac9ef08a..0fc684bd8b75 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO; import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.NO_LOCATIONS; @@ -36,13 +34,11 @@ import java.util.Collections; import jdk.graal.compiler.core.common.CompilationIdentifier; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.graal.compiler.core.gen.LIRGenerationProvider; import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugDumpHandlersFactory; -import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; @@ -57,7 +53,6 @@ import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.printer.GraalDebugHandlersFactory; -import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.RegisterConfig; @@ -125,51 +120,6 @@ public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValue } providers.getReplacements().closeSnippetRegistration(); providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().maybePrintIntrinsics(options); - maybeEncodeSnippets(options, jvmciRuntime); - } - - /** - * {@code true} when snippet encoding is in progress on jargraal. - *

- * The purpose of tracking whether snippets are being encoded is to allow the backend - * initialization code to trigger the initialization of Truffle backends and break from the - * recursion. - */ - @LibGraalSupport.HostedOnly// - private static boolean snippetEncodingInProgress; - - /** - * Encodes snippets on jargraal if they are not already encoded (or being encoded by a caller). - * - * @param options option values - * @param jvmciRuntime the JVMCI runtime - */ - @SuppressWarnings("try") - private void maybeEncodeSnippets(OptionValues options, HotSpotJVMCIRuntime jvmciRuntime) { - if (!inRuntimeCode() && !inBuildtimeCode() && !HotSpotReplacementsImpl.snippetsAreEncoded() && !snippetEncodingInProgress) { - try (InitTimer st = timer("encodeSnippets")) { - GraalError.guarantee(getProviders().getReplayCompilationSupport() == null, "encode snippets without replay support"); - snippetEncodingInProgress = true; - /* - * Initialize Truffle backends to register their snippets. We must perform this - * initialization since those backends could be initialized at any time in the - * future. The backends must register the snippets to our encoder so we share it - * with them. - */ - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) getProviders().getReplacements(); - replacements.shareSnippetEncoder(); - HotSpotGraalRuntimeProvider truffleGraalRuntime = getRuntime(); - if (HotSpotTruffleCompilerImpl.Options.TruffleCompilerConfiguration.hasBeenSet(options)) { - CompilerConfigurationFactory compilerConfigurationFactory = CompilerConfigurationFactory.selectFactory( - HotSpotTruffleCompilerImpl.Options.TruffleCompilerConfiguration.getValue(options), options, jvmciRuntime); - truffleGraalRuntime = new HotSpotGraalRuntime("Truffle", jvmciRuntime, compilerConfigurationFactory, options, null); - } - HotSpotTruffleCompilerImpl.ensureBackendsInitialized(options, truffleGraalRuntime); - replacements.encode(options); - } finally { - snippetEncodingInProgress = false; - } - } } protected CallingConvention makeCallingConvention(StructuredGraph graph, Stub stub) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 502f4d23f93e..80c59b7b0e43 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -27,6 +27,8 @@ import static jdk.graal.compiler.core.common.LibGraalSupport.inLibGraalRuntime; import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; +import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import java.util.BitSet; @@ -63,6 +65,7 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.replacements.IntrinsicGraphBuilder; import jdk.graal.compiler.replacements.ReplacementsImpl; +import jdk.graal.compiler.replacements.SnippetTemplate; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -93,12 +96,19 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } + @LibGraalSupport.HostedOnly + public static void clearSnippetEncoder() { + synchronized (HotSpotReplacementsImpl.class) { + snippetEncoder = null; + } + } + @LibGraalSupport.HostedOnly public SymbolicSnippetEncoder maybeInitializeEncoder() { - if (sharedSnippetEncoder != null) { - snippetEncoder = sharedSnippetEncoder; - } else { - snippetEncoder = new SymbolicSnippetEncoder(this); + synchronized (HotSpotReplacementsImpl.class) { + if (snippetEncoder == null) { + snippetEncoder = new SymbolicSnippetEncoder(this); + } } return snippetEncoder; } @@ -190,9 +200,10 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (!isAfterSnippetEncoding()) { - assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); + if (isRegisteringSnippetMethods()) { + assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); } @@ -200,6 +211,17 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin } } + /** + * Returns true if the current runtime or current compilation thread registers snippet methods + * to be encoded. This is true when building libgraal or when replaying a libgraal compilation + * in jargraal. + * + * @return true if snippets methods should be registered + */ + private static boolean isRegisteringSnippetMethods() { + return !inLibGraalRuntime() && (inBuildtimeCode() || isReplayingLibgraalInJargraal()); + } + @Override public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { if (isAfterSnippetEncoding()) { @@ -238,69 +260,39 @@ public static boolean snippetsAreEncoded() { @LibGraalSupport.HostedOnly// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; + SnippetTemplate.setHostedEncodedSnippets(snippetsAreEncoded()); } @LibGraalSupport.HostedOnly// - public void encode(OptionValues options) { - GraalError.guarantee(!snippetsAreEncoded(), "snippets should not be encoded yet"); - GraalError.guarantee(snippetEncoder != null && snippetEncoder == sharedSnippetEncoder, "only the shared encoder can encode snippets"); - setEncodedSnippets(snippetEncoder.encodeSnippets(options)); - } - - /** - * Opens a scope without encoded snippets, in which additional snippets can be registered and - * encoded. The previous encoded snippets are restored when the scope is closed. Useful for - * testing. - * - * @return a scope without encoded snippets - */ - @LibGraalSupport.HostedOnly - public DebugCloseable suppressEncodedSnippets() { - EncodedSnippets previous = encodedSnippets; - setEncodedSnippets(null); - return () -> setEncodedSnippets(previous); + @SuppressWarnings("try") + public boolean encode(OptionValues options) { + SymbolicSnippetEncoder encoder = snippetEncoder; + if (encoder != null) { + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { + return encoder.encode(options); + } + } + return false; } - /** - * The global shared instance of encoded snippets. - */ private static volatile EncodedSnippets encodedSnippets; - /** - * The shared snippet encoder. The purpose of the shared encoder is to initialize other (i.e., - * Truffle) backends, which should register their snippets to the shared encoder. - */ @LibGraalSupport.HostedOnly// - private static volatile SymbolicSnippetEncoder sharedSnippetEncoder; - - /** - * The snippet encoder used by this instance. Before the encoder is used to encode snippets, it - * must be {@link #sharedSnippetEncoder shared} with Truffle backends to allow them to register - * their snippets. - */ - @LibGraalSupport.HostedOnly// - private SymbolicSnippetEncoder snippetEncoder; - - /** - * Shares this encoder with all subsequently initialized backends. Consequently, these backends - * will register their snippets to the encoder used by this instance. Only one encoder can be - * shared, and only the shared encoder can encode snippets. - */ - @LibGraalSupport.HostedOnly - public void shareSnippetEncoder() { - GraalError.guarantee(sharedSnippetEncoder == null, "only a single encoder can be shared"); - sharedSnippetEncoder = snippetEncoder; - } + private static SymbolicSnippetEncoder snippetEncoder; @SuppressWarnings("try") @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (isAfterSnippetEncoding()) { + if (isUsingEncodedSnippets()) { // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { - return getEncodedSnippets().getEncodedSnippet(method, original, this, args, AllowAssumptions.NO, options); + StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, original, this, args, AllowAssumptions.NO, options); + if (graph == null) { + throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport + } + return graph; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index 07d06f36fa85..2c714cada6ac 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -24,12 +24,11 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; - import java.lang.reflect.Executable; import java.lang.reflect.Field; import jdk.graal.compiler.debug.GraalError; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; @@ -41,16 +40,28 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; + public class HotSpotSnippetMetaAccessProvider implements MetaAccessProvider { private final MetaAccessProvider delegate; - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { + /** + * {@code true} if the compiler is recording/replaying a compilation. + */ + private final boolean replayCompilationEnabled; + + public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate, boolean replayCompilationEnabled) { this.delegate = delegate; + this.replayCompilationEnabled = replayCompilationEnabled; + } + + public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { + this(delegate, false); } @Override public ResolvedJavaType lookupJavaType(Class clazz) { - if (inRuntimeCode()) { + if (isAfterSnippetEncoding()) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); if (type != null) { return type; @@ -73,13 +84,20 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - if (HotSpotReplacementsImpl.isGraalClass(clazz)) { + if (isAfterSnippetEncoding() && HotSpotReplacementsImpl.isGraalClass(clazz)) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); return type; } return delegate.lookupJavaType(clazz); } + if (constant instanceof HotSpotObjectConstant hsConstant && !replayCompilationEnabled) { + Object object = hsConstant.asObject(Object.class); + if (object != null) { + Class clazz = object.getClass(); + return lookupJavaType(clazz); + } + } return delegate.lookupJavaType(constant); } 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 54676f8b4dd2..15658006810c 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 @@ -24,7 +24,6 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; @@ -47,7 +46,6 @@ import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; -import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.type.AbstractObjectStamp; @@ -62,6 +60,7 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -404,9 +403,7 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { snippetReplacements.setGraphBuilderPlugins(copy); copy.clearInlineInvokePlugins(); copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); - if (inBuildtimeCode() || !GraalOptions.SnippetCounters.getValue(options)) { - copy.appendNodePlugin(new SnippetCounterPlugin()); - } + copy.appendNodePlugin(new SnippetCounterPlugin()); EconomicMap preparedSnippetGraphs = EconomicMap.create(); MapCursor> cursor = pendingSnippetGraphs.getEntries(); @@ -427,6 +424,13 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { } synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { + if (HotSpotReplacementsImpl.snippetsAreEncoded()) { + if (ReplayCompilationSupport.isReplayingLibgraalInJargraal()) { + return; + } + throw new GraalError("Snippet encoding has already been done"); + } + assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); SnippetKey key = new SnippetKey(method, original, receiver); findSnippetMethod(method); @@ -529,7 +533,7 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic // Ensure a few well known types are available lookupSnippetType(GraalHotSpotVMConfig.class); lookupSnippetType(NamedLocationIdentity.class); - lookupSnippetType(SnippetTemplate.SnippetInfo.class); + lookupSnippetType(SnippetTemplate.EagerSnippetInfo.class); lookupSnippetType(ForeignCallStub.class); lookupSnippetType(HotSpotSpeculationLog.HotSpotSpeculation.class); @@ -556,6 +560,19 @@ private void registerAbstractForeignCallStubInfo() { findSnippetMethod(AbstractForeignCallStub.getGraphMethod(metaAccess)); } + /** + * Encode any outstanding graphs and return true if any work was done. + */ + @SuppressWarnings("try") + public synchronized boolean encode(OptionValues options) { + EncodedSnippets encodedSnippets = encodeSnippets(options); + if (encodedSnippets != null) { + HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); + return true; + } + return false; + } + static class HotSpotSubstrateConstantReflectionProvider implements ConstantReflectionProvider { private final ConstantReflectionProvider constantReflection; @@ -717,8 +734,7 @@ private EncodedSnippets.SymbolicResolvedJavaMethod filterMethod(DebugContext deb if (symbolic != null) { return symbolic; } - if (inBuildtimeCode() && HotSpotReplacementsImpl.isGraalClass(method.getDeclaringClass())) { - // Snippet counter methods in jargraal are allowed. + if (HotSpotReplacementsImpl.isGraalClass(method.getDeclaringClass())) { throw new GraalError("Graal methods shouldn't leak into image: " + method); } UnresolvedJavaType type = (UnresolvedJavaType) filterType(debug, method.getDeclaringClass()); @@ -746,8 +762,7 @@ private JavaType filterType(DebugContext debug, ResolvedJavaType type) { if (unresolvedJavaType != null) { return unresolvedJavaType; } - if (inBuildtimeCode() && HotSpotReplacementsImpl.isGraalClass(type)) { - // Snippet counter types in jargraal are allowed. + if (HotSpotReplacementsImpl.isGraalClass(type)) { throw new GraalError("Graal types shouldn't leak into image: " + type); } unresolvedJavaType = UnresolvedJavaType.create(type.getName()); @@ -761,8 +776,7 @@ private Object filterFieldLocationIdentity(DebugContext debug, HotSpotResolvedJa } private Object filterField(DebugContext debug, HotSpotResolvedJavaField field) { - if (inBuildtimeCode() && !field.getDeclaringClass().getName().startsWith("Ljava/lang/")) { - // Snippet counter fields in jargraal are allowed. + if (!field.getDeclaringClass().getName().startsWith("Ljava/lang/")) { // Might require adjustments in HotSpotSubstrateConstantReflectionProvider throw new InternalError("All other fields must have been resolved: " + field); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 483a94a160ad..65ea199b8596 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -28,7 +28,7 @@ import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_DREM; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_FREM; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_PARTITION; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_SORT; import static jdk.graal.compiler.hotspot.HotSpotBackend.BASE64_DECODE_BLOCK; @@ -379,7 +379,7 @@ private void registerStubCallFunctions(OptionValues options, HotSpotProviders pr } registerForeignCall(INVOKE_STATIC_METHOD_ONE_ARG, invokeJavaMethodAddress, NativeCall); - if (!isAfterSnippetEncoding()) { + if (!isUsingEncodedSnippets()) { /* * These functions are only used for testing purposes but their registration also * ensures that libgraal has support for InvokeJavaMethodStub built into the image, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index c3e723c6ee82..975975f3087a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -24,7 +24,7 @@ */ package jdk.graal.compiler.hotspot.meta; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import java.lang.reflect.Executable; @@ -62,7 +62,7 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { - if (inRuntimeCode()) { + if (isAfterSnippetEncoding()) { HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); // This can only be a compiler object when in libgraal. return new SnippetObjectConstant(object); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index abf8b60ff0bb..1da729880499 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -46,8 +46,11 @@ import jdk.graal.compiler.bytecode.BytecodeStream; import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.NodeClass; +import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; @@ -66,6 +69,7 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; +import jdk.graal.compiler.replacements.SnippetCounter; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -629,6 +633,27 @@ public static CompilerInterfaceDeclarations build() { .setDefaultValue(MetaAccessProviderProxy.decodeSpeculationMethod, SpeculationLog.NO_SPECULATION) .setStrategy(MetaAccessProviderProxy.getArrayBaseOffsetMethod, MethodStrategy.Passthrough) .setStrategy(MetaAccessProviderProxy.getArrayIndexScaleMethod, MethodStrategy.Passthrough) + .provideMethodCallsToRecord((input) -> { + List result = new ArrayList<>(); + if (!LibGraalSupport.inLibGraalRuntime()) { + // Record the calls needed for HotSpotGraalConstantFieldProvider in jargraal. + // Not needed in libgraal because the lookups are handled by HotSpotSnippetMetaAccessProvider. + for (Class clazz : List.of(GraalHotSpotVMConfig.class, SnippetCounter.class, NodeClass.class)) { + result.add(new MethodCallToRecord(input, MetaAccessProviderProxy.lookupJavaTypeClassMethod, MetaAccessProviderProxy.lookupJavaTypeClassInvokable, new Object[]{clazz})); + } + } + return result; + }) + .setFallbackInvocationHandler(MetaAccessProviderProxy.lookupJavaTypeClassMethod, (proxy, method, args, singletonObjects) -> { + // Needed for Word types when replaying libgraal compilations on jargraal. + Class clazz = (Class) args[0]; + MetaAccessProvider localMetaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType localMirror = localMetaAccess.lookupJavaType(clazz); + if (localMirror == null) { + throw new IllegalArgumentException(); + } + return localMirror; + }) .register(declarations); new RegistrationBuilder<>(HotSpotConstantReflectionProvider.class).setSingleton(true) .ensureRecorded(HotSpotConstantReflectionProviderProxy.forObjectMethod, HotSpotConstantReflectionProviderProxy.forObjectInvokable,(Object) null) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java index 7e8ced5f0548..4b48176c6bfd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java @@ -24,8 +24,12 @@ */ package jdk.graal.compiler.hotspot.replaycomp; +import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; + +import java.util.List; import java.util.Objects; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.hotspot.HotSpotBackendFactoryDecorators; import jdk.graal.compiler.hotspot.HotSpotSnippetMetaAccessProvider; import jdk.graal.compiler.hotspot.SnippetObjectConstant; @@ -69,7 +73,7 @@ public void afterJVMCIProvidersCreated() { public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { // Do not record snippet types in libgraal - decorate the JVMCI meta access only. metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); - return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy); + return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy, true); } @Override @@ -87,8 +91,17 @@ private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider de this.delegate = delegate; } + private static final List allowedFields = List.of("TYPE", "COMPACT_STRINGS"); + @Override public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { + /* + * Prevents jargraal from encoding runtime constants in snippets (such as in boxing + * snippets). Follows the logic of HotSpotSubstrateConstantReflectionProvider. + */ + if (!LibGraalSupport.inLibGraalRuntime() && replayCompilationSupport.isInSnippetContext() && !isGraalClass(field.getDeclaringClass()) && !allowedFields.contains(field.getName())) { + return null; + } return delegate.readFieldValue(field, receiver); } @@ -139,7 +152,7 @@ public JavaConstant forString(String value) { public ResolvedJavaType asJavaType(Constant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { /* - * Avoid recording an operation with the snippet constant, which is not + * Avoids recording an operation with the snippet constant, which is not * serializable. */ return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java index 1e31d9d44721..504c0a705500 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java @@ -1379,7 +1379,9 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize } } - private static final class RecordedCompilationUnitSerializer implements ObjectSerializer { + public static final class RecordedCompilationUnitSerializer implements ObjectSerializer { + public static final String IS_LIBGRAAL_PROPERTY = "isLibgraal"; + private static final String TAG = "recordedCompilationUnit"; @Override @@ -1399,7 +1401,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, objectBuilder.append("osName", unit.platform.osName()); objectBuilder.append("archName", unit.platform.archName()); objectBuilder.append("compilerConfiguration", unit.compilerConfiguration); - objectBuilder.append("isLibgraal", unit.isLibgraal); + objectBuilder.append(IS_LIBGRAAL_PROPERTY, unit.isLibgraal); objectBuilder.append("entryBCI", unit.request.getEntryBCI()); objectBuilder.append("compileId", unit.request.getId()); try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("operations").array()) { @@ -1419,7 +1421,7 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize String archName = (String) json.get("archName"); Platform platform = new Platform(osName, archName); String compilerConfiguration = (String) json.get("compilerConfiguration"); - boolean isLibgraal = (boolean) json.get("isLibgraal"); + boolean isLibgraal = (boolean) json.get(IS_LIBGRAAL_PROPERTY); int entryBCI = (int) json.get("entryBCI"); int compileId = (int) json.get("compileId"); List list = (List) json.get("operations"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java index 98e14350887a..025e14ab43d3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.hotspot.replaycomp; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; - import java.io.Closeable; import java.io.FileReader; import java.io.IOException; @@ -44,6 +42,7 @@ import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.core.GraalCompilerOptions; +import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; @@ -321,11 +320,18 @@ public static final class Reproducer implements Closeable { */ private final OptionValues options; - private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options) { + /** + * Whether the recorded compilation was performed on libgraal. + */ + private final boolean isLibgraal; + + private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options, + boolean isLibgraal) { this.replayCompiler = replayCompiler; this.request = request; this.finalGraph = finalGraph; this.options = options; + this.isLibgraal = isLibgraal; } /** @@ -346,10 +352,6 @@ private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationReques @SuppressWarnings("try") public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDeclarations declarations, HotSpotJVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory factory, GlobalMetrics globalMetrics, PrintStream out, EconomicMap internPool) throws ReplayLauncherFailure { - if (!inRuntimeCode() && !HotSpotReplacementsImpl.snippetsAreEncoded()) { - out.println("Encode snippets"); - HotSpotJVMCIRuntime.runtime().getCompiler(); - } ReplayCompilationProxies proxies = new ReplayCompilationProxies(declarations, globalMetrics, options); out.println("Loading " + fileName); RecordedOperationPersistence.RecordedCompilationUnit compilationUnit; @@ -366,18 +368,38 @@ public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDe throw new ReplayParserFailure("Parsing failed due to " + exception.getMessage()); } HotSpotCompilationRequest request = compilationUnit.request(); + boolean replayingLibgraalInJargraal = !LibGraalSupport.inLibGraalRuntime() && compilationUnit.isLibgraal(); + ReplayCompilationSupport.setReplayingLibgraalInJargraal(replayingLibgraalInJargraal); if (LibGraalSupport.inLibGraalRuntime() && !compilationUnit.isLibgraal()) { throw new ReplayLauncherFailure("Cannot replay jargraal compilation " + request + " in libgraal"); } + boolean encodeSnippets = replayingLibgraalInJargraal && !HotSpotReplacementsImpl.snippetsAreEncoded(); + if (encodeSnippets) { + /* + * Ensure the snippet encoder will be created and linked to the decorated providers + * created below. + */ + HotSpotReplacementsImpl.clearSnippetEncoder(); + } + OptionValues selectedOptions = options; + if (replayingLibgraalInJargraal) { + selectedOptions = new OptionValues(options, GraalOptions.EagerSnippets, true); + } out.println("Initializing the replay compiler for " + request); - HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, options, factory, new ReplayCompilationSupport(proxies, factory.getName())); + HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, selectedOptions, factory, new ReplayCompilationSupport(proxies, factory.getName())); HotSpotGraalRuntimeProvider graalRuntime = replayCompiler.getGraalRuntime(); if (!graalRuntime.getCompilerConfigurationName().equals(compilationUnit.compilerConfiguration())) { throw new ReplayLauncherFailure(("Compiler configuration mismatch: the task was compiled using " + compilationUnit.compilerConfiguration() + " but the initialized compiler is " + graalRuntime.getCompilerConfigurationName())); } - graalRuntime.getReplayCompilationSupport().setRecordedForeignCallLinkages(compilationUnit.linkages()); - return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), options); + ReplayCompilationSupport support = graalRuntime.getReplayCompilationSupport(); + support.setRecordedForeignCallLinkages(compilationUnit.linkages()); + if (encodeSnippets) { + out.println("Encoding snippets"); + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) graalRuntime.getHostProviders().getReplacements(); + replacements.encode(graalRuntime.getOptions()); + } + return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), selectedOptions, compilationUnit.isLibgraal()); } /** @@ -387,6 +409,7 @@ public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDe */ @SuppressWarnings("try") public ReplayResult compile() { + ReplayCompilationSupport.setReplayingLibgraalInJargraal(!LibGraalSupport.inLibGraalRuntime() && isLibgraal); ReplayCompilationSupport support = replayCompiler.getGraalRuntime().getReplayCompilationSupport(); CompilationRequestResult result = replayCompiler.compileMethod(request, true, options); ReplayCompilationSupport.CompilationArtifacts replayedArtifacts = support.clearCompilationArtifacts(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java index 2ab23bbaecae..19b390fea953 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.hotspot.replaycomp; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; + import java.nio.file.Path; import java.util.function.Predicate; @@ -34,6 +36,7 @@ import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugOptions; +import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.PathUtilities; import jdk.graal.compiler.debug.TTY; @@ -80,22 +83,33 @@ * {@link #decorateIntrinsificationTrustPredicate} return proxies for additional objects. * *

- * Compiler Instances and Snippets. Since we hijack the compiler's backend factory, a - * dedicated compiler instance must be created for recording and replay. During recording, separate - * compiler instances should be used for the recorded methods - * ({@link #matchesRecordCompilationFilter}) and the methods that are not recorded. This ensures - * that the recording overhead is paid for the recorded methods only. Snippets and stubs are - * considered part of the compiler rather than the application, and they should never be recorded. - * It is possible to record a libgraal compilation and replay it on jargraal. + * Compiler Instances. Since we hijack the compiler's backend factory, a dedicated compiler + * instance must be created for recording and replay. To modify the compiler's behavior even from + * places where an instance of this class cannot be reasonably obtained, this class tracks whether + * the current compiler thread is performing a replay of a libgraal compilation in jargraal + * ({@link #isReplayingLibgraalInJargraal()}) and whether it is in a snippet context + * ({@link #isInSnippetContext()}). During recording, separate compiler instances should be used for + * the recorded methods ({@link #matchesRecordCompilationFilter}) and the methods that are not + * recorded. This ensures that the recording overhead is paid for the recorded methods only. + * + *

+ * Snippets. It is possible to record a libgraal compilation and replay it on jargraal. To + * ensure the replayed compilation matches the recorded one, we replay such compilations using + * encoded snippets ({@link #isReplayingLibgraalInJargraal()}). We must never mix raw JVMCI object + * and JVMCI proxies in a single graph, so we create proxies even during snippet parsing. Due to the + * need to replay libgraal compilations on jargraal and since snippets are compiler code rather than + * application code, the proxies do not record the operations during snippet parsing (i.e., inside + * snippet context {@link #enterSnippetContext}). When snippets are parsed during replay, the + * proxies may use local mirrors to query the information required for the snippets from the host VM + * instance. * *

* Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that - * was not recorded, including the information used to process snippets. There are also local-only - * proxies that do not originate from the recorded JSON but are instead created from local JVMCI - * objects (created using {@link CompilationProxies#proxify}). The exact rules when operations are - * delegated to local mirrors are dictated by the strategies defined in - * {@link CompilerInterfaceDeclarations}. + * was not recorded, including the information to parse snippets. There are also local-only proxies + * that do not originate from the recorded JSON but are instead created from local JVMCI objects + * (created using {@link CompilationProxies#proxify}). The exact rules when operations are delegated + * to local mirrors are dictated by the strategies defined in {@link CompilerInterfaceDeclarations}. * *

* Foreign Call Linkages. During recording, we capture the addresses and killed registers of @@ -114,6 +128,26 @@ public final class ReplayCompilationSupport { */ public static final boolean ENABLE_REPLAY_LAUNCHER = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_REPLAY_LAUNCHER_PROP)); + /** + * Returns whether this compiler thread is replaying a libgraal compilation in jargraal. + */ + public static boolean isReplayingLibgraalInJargraal() { + return !inRuntimeCode() && isReplayingLibgraalInJargraal.get(); + } + + /** + * Sets whether the current compiler thread is replaying a libgraal compilation in jargraal. + * + * @param replayingLibgraalInJargraal true if the current compiler thread is replaying a + * libgraal compilation in jargraal, false otherwise + */ + public static void setReplayingLibgraalInJargraal(boolean replayingLibgraalInJargraal) { + if (replayingLibgraalInJargraal) { + GraalError.guarantee(!inRuntimeCode(), "this option is only valid in jargraal"); + } + ReplayCompilationSupport.isReplayingLibgraalInJargraal.set(replayingLibgraalInJargraal); + } + /** * Checks whether the given method's compilation should be recorded according to the given * options. @@ -131,6 +165,11 @@ public static boolean matchesRecordCompilationFilter(OptionValues options, Resol } } + /** + * Whether the current compiler thread is replaying a libgraal compilation in jargraal. + */ + private static final ThreadLocal isReplayingLibgraalInJargraal = ThreadLocal.withInitial(() -> false); + /** * The proxies used for recording/replaying the compilations. */ @@ -146,6 +185,11 @@ public static boolean matchesRecordCompilationFilter(OptionValues options, Resol */ private RecordedForeignCallLinkages recordedForeignCallLinkages; + /** + * Whether the compiler thread is in a snippet context. + */ + private final ThreadLocal inSnippetContext = ThreadLocal.withInitial(() -> false); + /** * The compilation artifacts of the current compiler thread. */ @@ -205,21 +249,28 @@ public OptionValues filterOptions(OptionValues options) { } /** - * Enters a snippet context. In a recorded compilation, the proxies should not record JVMCI - * calls and results related to snippet processing. In a replayed compilation, the proxies can - * delegate to the local mirrors to handle JVMCI calls. + * Enters a snippet context for the current compiler thread. In a recorded compilation, the + * proxies should not record JVMCI calls and results related to snippet parsing and + * optimization. In a replayed compilation, the proxies can delegate to the local mirrors to + * handle JVMCI calls. * * @return a debug closeable that should be closed when exiting the context */ private DebugCloseable enterSnippetContext() { - return proxies.enterSnippetContext(); + boolean previous = inSnippetContext.get(); + inSnippetContext.set(true); + DebugCloseable closeable = proxies.enterSnippetContext(); + return () -> { + inSnippetContext.set(previous); + closeable.close(); + }; } /** * Enters a snippet context for the given providers. *

* If the providers have a non-null {@link ReplayCompilationSupport} instance, this method - * enters a snippet context. Otherwise, it returns {@code null}. + * enters a snippet context for the current compiler thread. Otherwise, it returns {@code null}. * * @param providers the providers to check for {@link ReplayCompilationSupport} * @return a scope representing the snippet context, or {@code null} if not supported @@ -231,8 +282,8 @@ public static DebugCloseable enterSnippetContext(HotSpotProviders providers) { /** * Enters a snippet context for the given {@link ReplayCompilationSupport} instance. *

- * If the provided {@code support} is not {@code null}, this method enters a snippet context. - * Otherwise, it returns {@code null}. + * If the provided {@code support} is not {@code null}, this method enters a snippet context for + * the current compiler thread. Otherwise, it returns {@code null}. * * @param support the instance to check * @return a scope representing the snippet context, or {@code null} if not supported @@ -245,6 +296,13 @@ public static DebugCloseable enterSnippetContext(ReplayCompilationSupport suppor } } + /** + * Returns whether this compiler thread is in a snippet context. + */ + public boolean isInSnippetContext() { + return inSnippetContext.get(); + } + /** * Enters a scope with a given debug context. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java index 449bf4912831..da960aab56f1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java @@ -24,7 +24,10 @@ */ package jdk.graal.compiler.hotspot.stubs; +import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; + import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.graph.Node; @@ -81,8 +84,22 @@ public void inlineAsIntrinsic(Invoke invoke, String reason, String phase) { assert invoke instanceof Node : Assertions.errorMessage(invoke, reason, phase); Node invokeNode = (Node) invoke; ResolvedJavaMethod method = invoke.callTarget().targetMethod(); - StructuredGraph calleeGraph = getReplacements().getSnippet(method, null, null, null, false, null, invokeNode.getOptions()); + + Plugins plugins = new Plugins(graphBuilderPlugins); + GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); + + StructuredGraph calleeGraph; + if (LibGraalSupport.inLibGraalRuntime()) { + calleeGraph = getReplacements().getSnippet(method, null, null, null, false, null, invokeNode.getOptions()); + } else { + calleeGraph = new StructuredGraph.Builder(invokeNode.getOptions(), invokeNode.getDebug()).method(method).trackNodeSourcePosition( + invokeNode.graph().trackNodeSourcePosition()).setIsSubstitution(true).build(); + IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING); + GraphBuilderPhase.Instance instance = createGraphBuilderInstance(config, OptimisticOptimizations.NONE, initialReplacementContext); + instance.apply(calleeGraph); + } new DeadCodeEliminationPhase().apply(calleeGraph); + InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java index 638869f728d6..240d54a188b9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java @@ -46,6 +46,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import org.graalvm.collections.EconomicMap; @@ -479,12 +480,12 @@ public class SnippetTemplate { * method that needs to be computed only once. The {@link SnippetInfo} should be created once * per snippet and then cached. */ - public static final class SnippetInfo { + public abstract static class SnippetInfo { - private final ResolvedJavaMethod method; - private final ResolvedJavaMethod original; - private final LocationIdentity[] privateLocations; - private final Object receiver; + protected final ResolvedJavaMethod method; + protected final ResolvedJavaMethod original; + protected final LocationIdentity[] privateLocations; + protected final Object receiver; public Object getReceiver() { return receiver; @@ -513,22 +514,20 @@ static boolean hasReceiver(ResolvedJavaMethod method) { private final TimerKey creationTimer; - private final Snippet.SnippetType type; + protected final Snippet.SnippetType type; - private final SnippetParameterInfo snippetParameterInfo; + protected abstract SnippetParameterInfo info(); - private SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, SnippetParameterInfo snippetParameterInfo, - Snippet.SnippetType type) { + protected SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, Snippet.SnippetType type) { this.method = method; this.original = original; this.privateLocations = privateLocations; - this.instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName()); - this.instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName()); - this.creationCounter = DebugContext.counter("SnippetCreationCount[%s]", method.getName()); - this.creationTimer = DebugContext.timer("SnippetCreationTime[%s]", method.getName()); + instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName()); + instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName()); + creationCounter = DebugContext.counter("SnippetCreationCount[%s]", method.getName()); + creationTimer = DebugContext.timer("SnippetCreationTime[%s]", method.getName()); this.receiver = receiver; this.type = type; - this.snippetParameterInfo = snippetParameterInfo; } public boolean isPrivateLocation(LocationIdentity identity) { @@ -545,27 +544,23 @@ public ResolvedJavaMethod getMethod() { } public int getParameterCount() { - return snippetParameterInfo.getParameterCount(); + return info().getParameterCount(); } public boolean isConstantParameter(int paramIdx) { - return snippetParameterInfo.isConstantParameter(paramIdx); + return info().isConstantParameter(paramIdx); } public boolean isVarargsParameter(int paramIdx) { - return snippetParameterInfo.isVarargsParameter(paramIdx); + return info().isVarargsParameter(paramIdx); } public boolean isNonNullParameter(int paramIdx) { - return snippetParameterInfo.isNonNullParameter(paramIdx); + return info().isNonNullParameter(paramIdx); } public String getParameterName(int paramIdx) { - return snippetParameterInfo.getParameterName(paramIdx); - } - - public SnippetInfo copyWith(ResolvedJavaMethod newMethod) { - return new SnippetInfo(newMethod, original, privateLocations, receiver, snippetParameterInfo, type); + return info().getParameterName(paramIdx); } @Override @@ -574,6 +569,41 @@ public String toString() { } } + protected static class LazySnippetInfo extends SnippetInfo { + protected final AtomicReference lazy = new AtomicReference<>(null); + + protected LazySnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, Snippet.SnippetType type) { + super(method, original, privateLocations, receiver, type); + } + + @Override + protected SnippetParameterInfo info() { + if (lazy.get() == null) { + lazy.compareAndSet(null, new SnippetParameterInfo(method)); + } + return lazy.get(); + } + } + + public static class EagerSnippetInfo extends SnippetInfo { + protected final SnippetParameterInfo snippetParameterInfo; + + protected EagerSnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, SnippetParameterInfo snippetParameterInfo, + Snippet.SnippetType type) { + super(method, original, privateLocations, receiver, type); + this.snippetParameterInfo = snippetParameterInfo; + } + + @Override + protected SnippetParameterInfo info() { + return snippetParameterInfo; + } + + public EagerSnippetInfo copyWith(ResolvedJavaMethod newMethod) { + return new EagerSnippetInfo(newMethod, original, privateLocations, receiver, snippetParameterInfo, type); + } + } + /** * Values that are bound to the snippet method parameters. The methods {@link #add} and * {@link #addVarargs} must be called in the same order as in the signature of the snippet @@ -932,8 +962,12 @@ protected SnippetInfo snippet(Providers providers, } providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options), options); LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations; - SnippetParameterInfo snippetParameterInfo = providers.getReplacements().getSnippetParameterInfo(javaMethod); - return new SnippetInfo(javaMethod, original, privateLocations, receiver, snippetParameterInfo, type); + if (inRuntimeCode() || GraalOptions.EagerSnippets.getValue(options)) { + SnippetParameterInfo snippetParameterInfo = providers.getReplacements().getSnippetParameterInfo(javaMethod); + return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver, snippetParameterInfo, type); + } else { + return new LazySnippetInfo(javaMethod, original, privateLocations, receiver, type); + } } /** @@ -2895,17 +2929,34 @@ public String toString() { return buf.append(')').toString(); } + /** + * {@code true} if encoded snippets are in use in a hosted context. This is needed to disable + * assertions that are not supported with encoded snippets. {@code EncodedSnippets} is not + * referencable from this context, so this is the only way to check this fact. + */ + private static volatile boolean hostedEncodedSnippets = false; + + /** + * Notifies snippet templates whether snippets are encoded in a hosted context. If {@code true}, + * this call disables assertions that are not supported with encoded snippets. + * + * @param value whether snippets are encoded in a hosted context + */ + public static void setHostedEncodedSnippets(boolean value) { + hostedEncodedSnippets = value; + } + private static boolean checkTemplate(MetaAccessProvider metaAccess, Arguments args, ResolvedJavaMethod method) { Signature signature = method.getSignature(); int offset = args.info.hasReceiver() ? 1 : 0; for (int i = offset; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { JavaKind kind = signature.getParameterKind(i - offset); - assert inRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); + assert inRuntimeCode() || hostedEncodedSnippets || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); } else if (args.info.isVarargsParameter(i)) { assert args.values[i] instanceof Varargs : Assertions.errorMessage(args.values[i], args, method); Varargs varargs = (Varargs) args.values[i]; - assert inRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); + assert inRuntimeCode() || hostedEncodedSnippets || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); } else if (args.info.isNonNullParameter(i)) { assert checkNonNull(method, args.info.getParameterName(i), args.values[i]); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java index 2761f74e80fa..5b3828ca4b08 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java @@ -90,34 +90,4 @@ public Templates(OptionValues options, Providers providers) { } } } - - public static class CounterTestSnippets implements Snippets { - @Snippet - public static void increase(@Snippet.ConstantParameter TestSnippetCounters counters) { - counters.increments.inc(); - counters.doubleIncrements.add(2); - } - - public static class Templates extends AbstractTemplates { - public final SnippetInfo increase; - - @SuppressWarnings("this-escape") - public Templates(OptionValues options, Providers providers) { - super(options, providers); - increase = snippet(providers, CounterTestSnippets.class, "increase"); - } - } - - public static class TestSnippetCounters { - public TestSnippetCounters(SnippetCounter.Group.Factory factory) { - SnippetCounter.Group allocations = factory.createSnippetCounterGroup("Increments"); - increments = new SnippetCounter(allocations, "increments", "number of increments"); - doubleIncrements = new SnippetCounter(allocations, "doubleIncrements", "number of increments times two"); - } - - public final SnippetCounter increments; - - public final SnippetCounter doubleIncrements; - } - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java index 4c7b9b02218a..38cb88f0eeb2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java @@ -124,30 +124,8 @@ public static class Options { */ private final HotSpotGraalRuntimeProvider hotspotGraalRuntime; - /** - * Initialize and return Truffle backends. - * - * @param options option values - * @return a list of Truffle backends - */ public static List ensureBackendsInitialized(OptionValues options) { HotSpotGraalRuntimeProvider graalRuntime = (HotSpotGraalRuntimeProvider) getCompiler(options).getGraalRuntime(); - return ensureBackendsInitialized(options, graalRuntime); - } - - /** - * Initialize and return Truffle backends using the provided Graal runtime, which must match the - * {@link Options#TruffleCompilerConfiguration} or the host configuration if not set. - * - * @param options option values - * @param graalRuntime the Graal runtime - * @return a list of Truffle backends - */ - public static List ensureBackendsInitialized(OptionValues options, HotSpotGraalRuntimeProvider graalRuntime) { - if (Options.TruffleCompilerConfiguration.hasBeenSet(options)) { - GraalError.guarantee(graalRuntime.getCompilerConfigurationName().equals(Options.TruffleCompilerConfiguration.getValue(options)), - "the provided runtime must match the Truffle compiler configuration"); - } List backends = new ArrayList<>(); backends.add(createTruffleBackend(graalRuntime, options, null, null)); backends.add(createTruffleBackend(graalRuntime, options, null, EconomyCompilerConfigurationFactory.NAME)); diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java index deb8df3c7a15..aece96b5b7ea 100644 --- a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java @@ -27,6 +27,7 @@ import java.util.HashSet; import java.util.Set; +import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.util.CompilationAlarm; import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.options.OptionKey; @@ -43,6 +44,7 @@ public final class IntentionallyUnsupportedOptions { static { unsupportedOptions.add(CompilerConfigurationFactory.Options.CompilerConfiguration); + unsupportedOptions.add(GraalOptions.EagerSnippets); unsupportedOptions.add(CompilationAlarm.Options.CompilationNoProgressPeriod); } 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 1336fc434a0e..d7b07ee65504 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 @@ -350,7 +350,13 @@ public NativeImageGenerator(ImageClassLoader loader, HostedOptionProvider option this.featureHandler = new FeatureHandler(); this.optionProvider = optionProvider; this.reporter = reporter; + /* + * Substrate VM parses all graphs, including snippets, early. We do not support bytecode + * parsing at run time. + */ + optionProvider.getHostedValues().put(GraalOptions.EagerSnippets, true); optionProvider.getHostedValues().put(CompilationAlarm.Options.CompilationNoProgressPeriod, 0D); + optionProvider.getRuntimeValues().put(GraalOptions.EagerSnippets, true); if (!optionProvider.getHostedValues().containsKey(BciBlockMapping.Options.MaxDuplicationFactor)) { /* diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java index 634c79351c32..22837011f519 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java @@ -344,8 +344,8 @@ static Object replaceAnalysisObjects(Object obj, Node node, IdentityHashMap Date: Tue, 16 Sep 2025 15:44:14 +0200 Subject: [PATCH 13/49] Revert "[GR-58163] Replay compilation." This reverts commit e7bc0ca1b749a34f38ffcd5a6338cc540eeb26ae, reversing changes made to b887c36841e9616b56272395b2b105b8877e4292. --- compiler/CHANGELOG.md | 4 - compiler/docs/ReplayCompilation.md | 100 - compiler/mx.compiler/mx_compiler.py | 36 - .../libgraal/LibGraalEntryPoints.java | 44 - .../compiler/libgraal/LibGraalFeature.java | 7 +- .../RecordedOperationPersistenceTest.java | 181 -- .../test/ReplayCompilationLauncher.java | 81 - .../test/ReplayCompilationTest.java | 231 -- .../test/LibGraalCompilationDriver.java | 24 - .../util/json/test/JsonParserTest.java | 25 - .../bytecode/BytecodeDisassembler.java | 12 +- .../compiler/core/CompilationWrapper.java | 2 - .../compiler/core/common/LibGraalSupport.java | 6 - .../graal/compiler/debug/DebugOptions.java | 3 - .../compiler/hotspot/CompilationTask.java | 141 +- .../compiler/hotspot/EncodedSnippets.java | 61 +- .../hotspot/GraalHotSpotVMConfig.java | 6 +- .../hotspot/GraalHotSpotVMConfigAccess.java | 45 +- .../hotspot/HotSpotBackendFactory.java | 54 +- .../HotSpotBackendFactoryDecorators.java | 81 - .../HotSpotDecoratedBackendFactory.java | 212 -- .../hotspot/HotSpotForeignCallLinkage.java | 5 - .../HotSpotForeignCallLinkageImpl.java | 19 - .../hotspot/HotSpotGraalCompilerFactory.java | 12 +- .../compiler/hotspot/HotSpotGraalRuntime.java | 46 +- .../hotspot/HotSpotGraalRuntimeProvider.java | 6 - .../compiler/hotspot/HotSpotHostBackend.java | 6 +- .../hotspot/HotSpotReplacementsImpl.java | 67 +- .../HotSpotSnippetMetaAccessProvider.java | 21 +- .../jdk/graal/compiler/hotspot/Platform.java | 94 - .../hotspot/SymbolicSnippetEncoder.java | 8 +- .../meta/HotSpotForeignCallsProviderImpl.java | 14 +- .../meta/HotSpotGraphBuilderPlugins.java | 9 +- .../meta/HotSpotHostForeignCallsProvider.java | 4 +- .../meta/HotSpotInvocationPlugins.java | 8 +- .../hotspot/meta/HotSpotProviders.java | 25 +- .../HotSpotSnippetReflectionProvider.java | 5 +- .../replaycomp/CompilationProxies.java | 76 - .../replaycomp/CompilationProxyMapper.java | 298 --- .../CompilerInterfaceDeclarations.java | 949 -------- .../DelayedDeserializationObject.java | 120 - .../HotSpotProxyBackendFactory.java | 195 -- .../hotspot/replaycomp/OperationRecorder.java | 290 --- .../RecordedForeignCallLinkages.java | 88 - .../RecordedOperationPersistence.java | 1986 ----------------- .../RecordingCompilationProxies.java | 241 -- .../replaycomp/ReplayCompilationProxies.java | 618 ----- .../replaycomp/ReplayCompilationRunner.java | 495 ---- .../replaycomp/ReplayCompilationSupport.java | 502 ----- .../replaycomp/SpecialResultMarker.java | 120 - .../replaycomp/proxy/CompilationProxy.java | 297 --- .../proxy/CompilationProxyBase.java | 112 - .../proxy/CompilerProfilerProxy.java | 71 - .../replaycomp/proxy/ConstantPoolProxy.java | 155 -- .../proxy/HotSpotCodeCacheProviderProxy.java | 178 -- ...otSpotConstantReflectionProviderProxy.java | 186 -- .../HotSpotMemoryAccessProviderProxy.java | 93 - .../proxy/HotSpotMetaspaceConstantProxy.java | 106 - .../proxy/HotSpotObjectConstantProxy.java | 206 -- .../proxy/HotSpotProfilingInfoProxy.java | 63 - .../proxy/HotSpotResolvedJavaFieldProxy.java | 122 - .../proxy/HotSpotResolvedJavaMethodProxy.java | 449 ---- .../proxy/HotSpotResolvedJavaTypeProxy.java | 482 ---- .../proxy/HotSpotResolvedObjectTypeProxy.java | 123 - .../proxy/HotSpotVMConfigAccessProxy.java | 120 - .../proxy/MetaAccessProviderProxy.java | 164 -- .../MethodHandleAccessProviderProxy.java | 66 - .../replaycomp/proxy/PredicateProxy.java | 48 - .../replaycomp/proxy/ProfilingInfoProxy.java | 150 -- .../replaycomp/proxy/SignatureProxy.java | 65 - .../replaycomp/proxy/SpeculationLogProxy.java | 83 - .../nodes/spi/StableProfileProvider.java | 29 +- .../replacements/SnippetTemplate.java | 23 +- .../SpeculationReasonGroup.java | 29 +- .../hotspot/HotSpotTruffleCompilerImpl.java | 2 +- .../graal/compiler/util/json/JsonParser.java | 7 +- .../util/json/JsonParserException.java | 35 - 77 files changed, 156 insertions(+), 10991 deletions(-) delete mode 100644 compiler/docs/ReplayCompilation.md delete mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java delete mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java delete mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java delete mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index 9b995317b436..6a96191f05fa 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -4,10 +4,6 @@ This changelog summarizes newly introduced optimizations and other compiler rela ## GraalVM for JDK 26 (Internal Version 26.0.0) * (GR-69280): Allow use of the `graal.` prefix for Graal compiler options without issuing a warning. -* (GR-58163): Added support for recording and replaying JIT compilations. The `-Djdk.graal.RecordForReplay=*` option - serializes all compilations matching the pattern to JSON files, which contain the results of JVMCI calls. The - recorded compilations can be replayed with the `mx replaycomp` command. Truffle compilations are currently not - supported. See `docs/ReplayCompilation.md` for details. ## GraalVM 25 (Internal Version 25.0.0) * (GR-60088): This PR adds the `org.graalvm.nativeimage.libgraal` SDK module. With this module, all logic for building diff --git a/compiler/docs/ReplayCompilation.md b/compiler/docs/ReplayCompilation.md deleted file mode 100644 index cafbf5a9e5bc..000000000000 --- a/compiler/docs/ReplayCompilation.md +++ /dev/null @@ -1,100 +0,0 @@ -# Replay Compilation - -The GraalVM compiler can record the inputs to a compilation task, serialize these inputs into a JSON file, and reproduce -the compilation using the same inputs. Replay compilation is based on instrumenting the JVM Compiler Interface (JVMCI). -Truffle compilations are currently not supported. It is not a goal to execute the replayed code. - -This file is a manual from the user's perspective. To learn how replay compilation is implemented, start by reading -`ReplayCompilationSupport.java` and `CompilerInterfaceDeclarations.java`. - -## Example - -Recording is enabled with the option `-Djdk.graal.RecordForReplay=*`. The value is a method filter selecting the methods -to be recorded. The syntax of method filters is explained `MethodFilter.java`. - -The below command records and serializes every compilation into `./replay-files/replaycomp/.json`. -The directories are created if they do not exist. - -```shell -mx benchmark renaissance:scrabble -- -Djdk.graal.RecordForReplay='*' -Djdk.graal.DumpPath=$PWD/replay-files -- -r 1 -``` - -It is recommended to select specific methods rather than `*` to avoid slowing the compiler down and producing gigabytes -of data. The compile speed overhead for recorded methods can be on the order of 10x. The size of a typical compilation -unit is between 1 and 10 MB but compression saves 95% of space. Note that if the VM exits during an ongoing compilation, -some of the JSON files may be incomplete. - -The `mx replaycomp` command finds all JSON replay files found in a given directory (and subdirectories) and invokes -the replay compiler on each. The command also accepts a path to a single file. - -```shell -mx replaycomp ./replay-files -``` - -## Debugging - -A replayed compilation can be debugged using a standard Java debugger (see `Debugging.md`). - -```shell -mx -d replaycomp ./replay-files -``` - -## Record Crashed Compilations - -Using the `-Djdk.graal.CompilationFailureAction=Diagnose` option, the compiler retries and records crashed compilations. -The command below exercises this behavior by forcing a crash. The JSON replay file can then be found in the `replaycomp` -directory inside the diagnostic zip archive. - -```shell -mx benchmark renaissance:scrabble -- -Djdk.graal.CompilationFailureAction=Diagnose -Djdk.graal.CrashAt=hashCode -- -r 1 -``` - -It is possible to **not** record retried compilations with the option `-Djdk.graal.DiagnoseOptions=RecordForReplay=`. - -## Replay with JVM Arguments - -JVM arguments, including compiler options, can be passed directly to the `replaycomp` command. - -```shell -mx replaycomp -Djdk.graal.Dump=:1 ./replay-files -``` - -Any `-ea`, `-esa`, and `-X` arguments from the command line are passed to the JVM as well. - -## Jargraal vs. Libgraal - -Both jargraal and libgraal compilations can be replayed on jargraal. When jargraal replays a libgraal compilation, -it uses encoded snippets to match the behavior and compilations results of libgraal. It is also possible to replay -libgraal compilations on libgraal. Replaying jargraal compilations on libgraal is not supported. - -It is necessary to explicitly enable the replay launcher entry point when building libgraal using the VM argument -`-Ddebug.jdk.graal.enableReplayLauncher=true`. - -```shell -EXTRA_IMAGE_BUILDER_ARGUMENTS=-Ddebug.jdk.graal.enableReplayLauncher=true mx --env libgraal build -``` - -When the `--libgraal` argument is passed to `mx replaycomp`, the previously built libgraal native library is loaded, and -the native launcher is invoked instead of the Java launcher. With the below command, all replay related processing -(including JSON parsing) is performed by libgraal code. - -```shell -mx replaycomp --libgraal ./replay-files -``` - -## Replay Options - -`--compare-graphs=true` compares the final canonical graph of the replayed compilation to the recorded one, which is -included in the JSON replay file. If there is a mismatch, the command exits with a non-zero status. - -```shell -mx replaycomp --compare-graphs=true ./replay-files -``` - -If the replayed compilation diverges from the recorded one, the compiler may query JVMCI information that is not -recorded in the JSON file. The default behavior is to return default values, which may not cause a compiler crash. -The `-Djdk.graal.ReplayDivergenceIsFailure=true` argument prevents using default values and instead causes a crash. - -```shell -mx replaycomp -Djdk.graal.ReplayDivergenceIsFailure=true ./replay-files -``` diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 39d7fff61ebd..6047b0e56565 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1571,41 +1571,6 @@ def profdiff(args): vm_args = ['-cp', cp, 'org.graalvm.profdiff.Profdiff'] + args return jdk.run_java(args=vm_args) -def replaycomp_vm_args(): - """Returns the VM arguments required to run the replay compilation launcher.""" - vm_args = [ - '-XX:-UseJVMCICompiler', - '--enable-native-access=org.graalvm.truffle', - '--add-exports=java.base/jdk.internal.module=ALL-UNNAMED', - '-Djdk.graal.CompilationFailureAction=Print' - ] - _, dists = mx.defaultDependencies(opt_limit_to_suite=True) - dists = [d for d in dists if d.isJARDistribution() and os.path.exists(d.classpath_repr(resolve=False))] - return mx.get_runtime_jvm_args(dists) + vm_args - -def replaycomp_main_class(): - """Returns the main class name for the replay compilation launcher.""" - return 'jdk.graal.compiler.hotspot.replaycomp.test.ReplayCompilationLauncher' - -def replaycomp(args): - """Runs the replay compilation launcher with the provided launcher and VM arguments.""" - extra_vm_args = [] - launcher_args = [] - for arg in args: - vm_arg_prefixes = ['-X', '-D', '-ea', '-enableassertions', '-esa', '-enablesystemassertions'] - if any(map(arg.startswith, vm_arg_prefixes)): - extra_vm_args.append(arg) - elif arg == '--libgraal': - jvmci_lib_path = os.path.join(mx.suite('sdk').get_output_root(platformDependent=True, jdkDependent=False), - mx.add_lib_suffix(mx.add_lib_prefix('jvmcicompiler')) + '.image') - extra_vm_args.extend([ - '-XX:+UseJVMCINativeLibrary', - f'-XX:JVMCILibPath={jvmci_lib_path}' - ]) - else: - launcher_args.append(arg) - return run_vm([*replaycomp_vm_args(), *extra_vm_args, replaycomp_main_class(), *launcher_args], nonZeroIsFatal=False) - def igvutil(args): """various utilities to inspect and modify IGV graphs""" cp = mx.classpath('GRAAL_IGVUTIL', jdk=jdk) @@ -1624,7 +1589,6 @@ def igvutil(args): 'graaljdk-show': [print_graaljdk_config, '[options]'], 'phaseplan-fuzz-jtt-tests': [phaseplan_fuzz_jtt_tests, "Runs JTT's unit tests with fuzzed phase plans."], 'profdiff': [profdiff, '[options] proftool_output1 optimization_log1 proftool_output2 optimization_log2'], - 'replaycomp': [replaycomp, ''], 'igvutil': [igvutil, '[subcommand] [options]'], }) diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java index 30680f01da9f..eee479e027c6 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java @@ -31,7 +31,6 @@ import java.io.PrintStream; import java.util.Arrays; import java.util.Map; -import java.util.function.BooleanSupplier; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.JNI.JNIEnv; @@ -46,15 +45,12 @@ import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.hotspot.CompilationContext; import jdk.graal.compiler.hotspot.CompilationTask; 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.replaycomp.ReplayCompilationRunner; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionDescriptors; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionValues; @@ -292,44 +288,4 @@ private static long hashConstantOopFields(JNIEnv jniEnv, return 0; } } - - /** - * Runs the replay compilation launcher in libgraal with the provided command-line arguments. - * - * @param argBuffer a native buffer containing a zero-terminated UTF-8 string of - * {@code '\n'}-separated arguments for the replay compilation launcher - * @return the exit status of the replay compilation launcher - */ - @SuppressWarnings({"unused", "try"}) - @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_replaycomp_test_ReplayCompilationLauncher_runInLibgraal", include = LibGraalReplayLauncherEnabled.class) - private static int replayCompilation(JNIEnv jniEnv, - PointerBase jclass, - @IsolateThreadContext long isolateThread, - long argBuffer) { - try (JNIMethodScope scope = new JNIMethodScope("replayCompilation", jniEnv)) { - String argString = CTypeConversion.utf8ToJavaString(Word.pointer(argBuffer)); - String[] args; - if (argString.isEmpty()) { - args = new String[0]; - } else { - args = argString.split("\n"); - } - return ReplayCompilationRunner.run(args, TTY.out().out()).getStatus(); - } catch (Throwable t) { - JNIExceptionWrapper.throwInHotSpot(jniEnv, t); - return ReplayCompilationRunner.ExitStatus.Failure.getStatus(); - } finally { - LibGraalSupportImpl.doReferenceHandling(); - } - } - - /** - * Controls whether the replay launcher entry point should be included in libgraal. - */ - private static final class LibGraalReplayLauncherEnabled implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return new LibGraalFeature.IsEnabled().getAsBoolean() && ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER; - } - } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java index d8c1300f8d37..3a078f678880 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java @@ -44,7 +44,6 @@ import java.util.function.Consumer; import java.util.stream.Collectors; -import jdk.graal.compiler.serviceprovider.GraalServices; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.NativeBridgeSupport; import org.graalvm.nativeimage.ImageInfo; @@ -316,11 +315,7 @@ public void accept(DuringAnalysisAccess duringAnalysisAccess) { private void registerHostedOnlyElements(BeforeAnalysisAccess access, AnnotatedElement... elements) { for (AnnotatedElement element : elements) { - HostedOnly annotation = element.getAnnotation(HostedOnly.class); - if (annotation == null) { - continue; - } - if (annotation.unlessTrue().isEmpty() || !Boolean.parseBoolean(GraalServices.getSavedProperty(annotation.unlessTrue()))) { + if (element.getAnnotation(HostedOnly.class) != null) { access.registerReachabilityHandler(new HostedOnlyElementCallback(element, reachedHostedOnlyElements), element); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java deleted file mode 100644 index 2c4ae5c65394..000000000000 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.test; - -import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; - -import java.io.IOException; -import java.io.StringReader; -import java.io.StringWriter; -import java.util.BitSet; -import java.util.List; -import java.util.Objects; - -import org.graalvm.collections.EconomicMap; -import org.junit.Assert; -import org.junit.Test; - -import jdk.graal.compiler.core.test.GraalCompilerTest; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.replaycomp.CompilationProxyMapper; -import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; -import jdk.graal.compiler.hotspot.replaycomp.OperationRecorder; -import jdk.graal.compiler.hotspot.replaycomp.RecordedForeignCallLinkages; -import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; -import jdk.graal.compiler.hotspot.replaycomp.SpecialResultMarker; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; -import jdk.graal.compiler.util.CollectionsUtil; -import jdk.graal.compiler.util.json.JsonWriter; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaConstant; - -/** - * Tests the JSON serialization and deserialization performed by - * {@link RecordedOperationPersistence}. - */ -public class RecordedOperationPersistenceTest extends GraalCompilerTest { - @Test - public void dumpsAndLoads() throws IOException, RecordedOperationPersistence.DeserializationException { - CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); - RecordedOperationPersistence persistence = new RecordedOperationPersistence(declarations, Platform.ofCurrentHost(), - HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); - var compilationUnit = createRecordedCompilationUnit(); - ProxyFactory proxyFactory = new ProxyFactory(declarations); - CompilationProxyMapper proxyMapper = new CompilationProxyMapper(declarations, proxyFactory::proxify); - List proxifiedOperations = compilationUnit.operations().stream().map( - (operation) -> new OperationRecorder.RecordedOperation(proxyMapper.proxifyRecursive(operation.receiver()), operation.method(), - (Object[]) proxyMapper.proxifyRecursive(operation.args()), proxyMapper.proxifyRecursive(operation.resultOrMarker()))).toList(); - String json; - try (StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter)) { - persistence.dump(compilationUnit, jsonWriter); - json = stringWriter.toString(); - } - RecordedOperationPersistence.RecordedCompilationUnit parsedCompilationUnit; - try (StringReader reader = new StringReader(json)) { - parsedCompilationUnit = persistence.load(reader, proxyFactory); - } - for (var pair : CollectionsUtil.zipLongest(proxifiedOperations, parsedCompilationUnit.operations())) { - Assert.assertEquals(pair.getLeft().receiver(), pair.getRight().receiver()); - Assert.assertTrue(Objects.deepEquals(pair.getLeft().args(), pair.getRight().args())); - Object expectedResult = pair.getLeft().resultOrMarker(); - Object actualResult = pair.getRight().resultOrMarker(); - if (expectedResult instanceof SpecialResultMarker.ExceptionThrownMarker) { - Assert.assertTrue(actualResult instanceof SpecialResultMarker.ExceptionThrownMarker); - } else if (expectedResult instanceof Assumptions.AssumptionResult expectedAssumptionResult) { - if (actualResult instanceof Assumptions.AssumptionResult actualAssumptionResult) { - Assert.assertEquals(expectedAssumptionResult.getResult(), actualAssumptionResult.getResult()); - Assumptions expectedAssumptions = new Assumptions(); - expectedAssumptionResult.recordTo(expectedAssumptions); - Assumptions actualAssumptions = new Assumptions(); - actualAssumptionResult.recordTo(actualAssumptions); - Assert.assertEquals(expectedAssumptions, actualAssumptions); - } else { - Assert.fail(); - } - } else { - Assert.assertTrue(Objects.deepEquals(expectedResult, actualResult)); - } - } - } - - public static Object dummyMethod() { - try { - throw new Exception(); - } catch (Exception e) { - return null; - } - } - - private RecordedOperationPersistence.RecordedCompilationUnit createRecordedCompilationUnit() { - HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) getResolvedJavaMethod("dummyMethod"); - - CompilationProxy.SymbolicMethod constantGetCallSiteTarget = new CompilationProxy.SymbolicMethod(HotSpotObjectConstant.class, "getCallSiteTarget"); - CompilationProxy.SymbolicMethod symbolicReadArrayLength = new CompilationProxy.SymbolicMethod(ConstantReflectionProvider.class, "readArrayLength", JavaConstant.class); - CompilationProxy.SymbolicMethod symbolicGetHandlers = new CompilationProxy.SymbolicMethod(HotSpotResolvedJavaMethod.class, "getExceptionHandlers"); - CompilationProxy.SymbolicMethod symbolicGetOopMap = new CompilationProxy.SymbolicMethod(HotSpotResolvedJavaMethod.class, "getOopMapAt", int.class); - - JavaConstant constant = getSnippetReflection().forObject(new Object()); - JavaConstant otherConstant = getSnippetReflection().forObject(new Object()); - SpecialResultMarker exceptionMarker = new SpecialResultMarker.ExceptionThrownMarker(new IllegalArgumentException("test exception")); - BitSet bitSet = new BitSet(8); - bitSet.set(4); - bitSet.set(6); - - List operations = List.of( - new OperationRecorder.RecordedOperation(constant, constantGetCallSiteTarget, null, - new Assumptions.AssumptionResult<>(otherConstant, new Assumptions.CallSiteTargetValue(constant, otherConstant))), - new OperationRecorder.RecordedOperation(getConstantReflection(), symbolicReadArrayLength, new Object[]{constant}, exceptionMarker), - new OperationRecorder.RecordedOperation(dummyMethod, symbolicGetHandlers, null, dummyMethod.getExceptionHandlers()), - new OperationRecorder.RecordedOperation(dummyMethod, symbolicGetOopMap, new Object[]{0}, bitSet)); - - return new RecordedOperationPersistence.RecordedCompilationUnit( - new HotSpotCompilationRequest(dummyMethod, INVOCATION_ENTRY_BCI, 0L, 1), - "test configuration", - false, - Platform.ofCurrentHost(), - new RecordedForeignCallLinkages(EconomicMap.create()), - "test graph", - operations); - } - - private static final class ProxyFactory implements RecordedOperationPersistence.ProxyFactory { - private final CompilerInterfaceDeclarations declarations; - - private ProxyFactory(CompilerInterfaceDeclarations declarations) { - this.declarations = declarations; - } - - public CompilationProxy proxify(Object input) { - return createProxy(declarations.findRegistrationForInstance(input)); - } - - @Override - public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration) { - return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, invokableMethod, args) -> { - if (method.equals(CompilationProxyBase.unproxifyMethod)) { - return registration; - } else if (method.equals(CompilationProxyBase.equalsMethod)) { - if (args[0] instanceof CompilationProxy other) { - return registration == other.unproxify(); - } else { - return false; - } - } else if (method.equals(CompilationProxyBase.hashCodeMethod)) { - return registration.hashCode(); - } else if (method.equals(CompilationProxyBase.toStringMethod)) { - return registration.clazz().getSimpleName(); - } else { - return null; - } - }); - } - } -} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java deleted file mode 100644 index 42680566b949..000000000000 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.test; - -import java.io.PrintStream; - -import com.oracle.truffle.runtime.hotspot.libgraal.LibGraal; -import com.oracle.truffle.runtime.hotspot.libgraal.LibGraalScope; - -import jdk.graal.compiler.api.test.ModuleSupport; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; -import jdk.graal.compiler.hotspot.test.LibGraalCompilationDriver; - -/** - * The first entry point for the replay compilation launcher. This class determines whether libgraal - * is available and tries to invoke the launcher in libgraal. Otherwise, it invokes the launcher in - * jargraal. - */ -public class ReplayCompilationLauncher { - static { - ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.graal.compiler"); - ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.internal.vm.ci"); - ModuleSupport.exportAndOpenAllPackagesToUnnamed("org.graalvm.truffle.runtime"); - } - - /** - * Calls libgraal C entry point - * {@code jdk.graal.compiler.libgraal.LibGraalEntryPoints#replayCompilation}, which in turn - * calls {@link ReplayCompilationRunner#run(String[], PrintStream)}. - */ - public static native int runInLibgraal(long isolateThread, long argBuffer); - - public static void main(String[] args) { - if (LibGraal.isAvailable()) { - try { - LibGraal.registerNativeMethods(ReplayCompilationLauncher.class); - } catch (Error error) { - System.err.printf("The replay launcher entry point could not be linked. Build libgraal with -D%s=true as an extra image builder option to enable the launcher.%n", - ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP); - throw error; - } - StringBuilder argString = new StringBuilder(); - for (String arg : args) { - if (!argString.isEmpty()) { - argString.append('\n'); - } - argString.append(arg); - } - try (var stringBuffer = new LibGraalCompilationDriver.LibGraalParams.UTF8CStringBuffer(argString.toString()); - LibGraalScope scope = new LibGraalScope()) { - int status = runInLibgraal(scope.getIsolateThreadAddress(), stringBuffer.getAddress()); - System.exit(status); - } - } else { - ReplayCompilationRunner.run(args, System.out).exitVM(); - } - } -} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java deleted file mode 100644 index 95beb5cbf83b..000000000000 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp.test; - -import java.io.ByteArrayOutputStream; -import java.io.FileReader; -import java.io.IOException; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.EconomicSet; -import org.junit.Test; - -import com.oracle.truffle.api.Truffle; - -import jdk.graal.compiler.api.test.Graal; -import jdk.graal.compiler.core.CompilationWrapper; -import jdk.graal.compiler.core.GraalCompilerOptions; -import jdk.graal.compiler.core.test.GraalCompilerTest; -import jdk.graal.compiler.debug.DebugOptions; -import jdk.graal.compiler.debug.GlobalMetrics; -import jdk.graal.compiler.debug.LogStream; -import jdk.graal.compiler.debug.TTY; -import jdk.graal.compiler.hotspot.CompilationTask; -import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; -import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; -import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; -import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.runtime.RuntimeProvider; -import jdk.graal.compiler.util.json.JsonParser; -import jdk.graal.compiler.util.json.JsonWriter; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.runtime.JVMCICompiler; - -/** - * Tests for compilation recording and replay. - */ -public class ReplayCompilationTest extends GraalCompilerTest { - private static int[] lengthsSquared(List strings) { - return strings.stream().mapToInt(String::length).map(i -> i * i).toArray(); - } - - private static Map wordCount(List sentences) { - return sentences.stream().flatMap(sentence -> Arrays.stream(sentence.split("\\s+"))).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); - } - - @Test - public void recordsOnRetryAndReplays() throws Throwable { - lengthsSquared(List.of("foo", "bar", "baz")); - runTest((temp) -> { - String methodName = "lengthsSquared"; - ResolvedJavaMethod method = getResolvedJavaMethod(methodName); - OptionValues initialOptions = getInitialOptions(); - String diagnoseOptionValue = DebugOptions.RecordForReplay.getName() + "=" + methodName; - OptionValues crashAndDiagnoseOptions = new OptionValues(initialOptions, DebugOptions.DumpPath, temp.toString(), - GraalCompilerOptions.CompilationFailureAction, CompilationWrapper.ExceptionAction.Diagnose, - DebugOptions.DiagnoseOptions, diagnoseOptionValue, GraalCompilerOptions.CrashAt, methodName); - /* - * Run a regular compilation with a forced crash, then retry and record the compilation. - * We need to run in a new compiler instance to override the dump path for diagnostics, - * where the recorded compilation unit is saved. - */ - HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, crashAndDiagnoseOptions); - assertTrue(regularResult.getFailure() != null); - - // Replay the compilation without forcing a crash and enable diagnostic options. - EconomicSet logTargets = EconomicSet.create(); - logTargets.add(DebugOptions.OptimizationLogTarget.Stdout); - OptionValues replayOptions = new OptionValues(initialOptions, DebugOptions.DumpPath, temp.toString(), - DebugOptions.PrintGraph, DebugOptions.PrintGraphTarget.File, DebugOptions.Dump, ":1", - DebugOptions.OptimizationLog, logTargets, DebugOptions.Log, "", DebugOptions.PrintBackendCFG, true); - replayCompilation(findReplayCompFile(temp.path), replayOptions); - }); - } - - @Test - public void recordAndExecuteReplayRunner() throws Throwable { - wordCount(List.of("first test sentence", "second test sentence")); - runTest((temp) -> { - String methodName = "wordCount"; - ResolvedJavaMethod method = getResolvedJavaMethod(methodName); - OptionValues initialOptions = getInitialOptions(); - OptionValues recordOptions = new OptionValues(initialOptions, DebugOptions.RecordForReplay, "*", - DebugOptions.DumpPath, temp.toString()); - HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, recordOptions); - assertTrue(regularResult.getFailure() == null); - Path replayFile = findReplayCompFile(temp.path); - Path replayFileLibgraal = Path.of(temp.path.toString(), "libgraal.json"); - copyReplayFileAsLibgraalCompilation(replayFile, replayFileLibgraal); - String[][] argumentLists = new String[][]{ - new String[]{"--compare-graphs=true", replayFile.toString()}, - new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", replayFileLibgraal.toString()} - }; - for (String[] arguments : argumentLists) { - ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(arguments, TTY.out().out()); - assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); - } - assertTrue(HotSpotReplacementsImpl.snippetsAreEncoded()); - }); - } - - /** - * Creates a copy of the source replay file that acts as if it was compiled with libgraal. This - * way, we test replaying libgraal compilations on jargraal (without access to libgraal). - * - * @param replayFile the source replay file - * @param destFile the created replay file that acts as a libgraal compilation - * ({@link jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence.RecordedCompilationUnit#isLibgraal()}) - */ - private static void copyReplayFileAsLibgraalCompilation(Path replayFile, Path destFile) throws Throwable { - try (FileReader reader = new FileReader(replayFile.toFile()); JsonWriter writer = new JsonWriter(destFile)) { - EconomicMap json = JsonParser.parseDict(reader); - json.put(RecordedOperationPersistence.RecordedCompilationUnitSerializer.IS_LIBGRAAL_PROPERTY, true); - writer.print(json); - } - } - - @Test - public void unparsableReplayFileSucceeds() throws Throwable { - runTest((temp) -> { - /* - * A replay file may not be parsable when the compiler thread exits during writing - - * this is not an error. - */ - assertTrue(Path.of(temp.path.toString(), "empty.json").toFile().createNewFile()); - ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(new String[]{temp.path.toString()}, TTY.out().out()); - assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); - }); - } - - @Test - public void emptyLauncherInputFails() throws Throwable { - runTest((temp) -> { - ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(new String[]{temp.path.toString()}, TTY.out().out()); - assertTrue(status == ReplayCompilationRunner.ExitStatus.Failure); - }); - } - - @FunctionalInterface - interface TestRunner { - void run(TemporaryDirectory temp) throws Throwable; - } - - @SuppressWarnings("try") - private static void runTest(TestRunner test) throws Throwable { - Truffle.getRuntime(); // Initialize the Truffle runtime and enable the HostInliningPhase. - try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); TTY.Filter filter = new TTY.Filter(new LogStream(outputStream))) { - try (TemporaryDirectory temp = new TemporaryDirectory("ReplayCompilationTest")) { - test.run(temp); - } catch (Throwable throwable) { - System.err.println(outputStream.toString(Charset.defaultCharset())); - throw throwable; - } - } finally { - HotSpotReplacementsImpl.setEncodedSnippets(null); - HotSpotReplacementsImpl.clearSnippetEncoder(); - ReplayCompilationSupport.setReplayingLibgraalInJargraal(false); - } - } - - private static HotSpotCompilationRequestResult runRegularCompilation(ResolvedJavaMethod method, OptionValues options) { - HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); - RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); - CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(runtimeProvider.getCompilerConfigurationName(), options, jvmciRuntime); - HotSpotGraalCompiler compiler = HotSpotGraalCompilerFactory.createCompiler("VM-test", jvmciRuntime, options, configFactory, null); - HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, JVMCICompiler.INVOCATION_ENTRY_BCI, 0L); - CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, true, false, false, false); - return task.runCompilation(options); - } - - private static void replayCompilation(Path replayCompFile, OptionValues options) throws ReplayCompilationRunner.ReplayLauncherFailure { - CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); - HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); - RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); - CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(runtimeProvider.getCompilerConfigurationName(), options, jvmciRuntime); - try (ReplayCompilationRunner.Reproducer reproducer = ReplayCompilationRunner.Reproducer.initializeFromFile(replayCompFile.toString(), - declarations, jvmciRuntime, options, configFactory, new GlobalMetrics(), TTY.out().out(), EconomicMap.create())) { - reproducer.compile().verify(false); - } - } - - private static Path findReplayCompFile(Path dumpPath) throws IOException { - Path replayCompDirectory; - try (Stream replayCompDirectoryStream = Files.find(dumpPath, 8, - (path, attributes) -> attributes.isDirectory() && path.toFile().getName().equals("replaycomp"))) { - replayCompDirectory = replayCompDirectoryStream.findAny().orElseThrow(); - } - try (Stream replayCompFileStream = Files.list(replayCompDirectory)) { - return replayCompFileStream.findAny().orElseThrow(); - } - } -} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java index 145d5d180004..21ef8073fc7c 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java @@ -28,7 +28,6 @@ import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; import java.io.ByteArrayOutputStream; -import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -236,29 +235,6 @@ public void close() { } } - /** - * A buffer holding a zero-terminated UTF-8 string. - */ - public static class UTF8CStringBuffer extends NativeBuffer { - private final byte[] encoded; - - public UTF8CStringBuffer(String string) { - byte[] utf8Bytes = string.getBytes(StandardCharsets.UTF_8); - encoded = new byte[utf8Bytes.length + 1]; - System.arraycopy(utf8Bytes, 0, encoded, 0, utf8Bytes.length); - } - - @Override - public void initialize(long address) { - UNSAFE.copyMemory(encoded, ARRAY_BYTE_BASE_OFFSET, null, address, encoded.length); - } - - @Override - public int length() { - return encoded.length; - } - } - /** * Native memory containing {@linkplain OptionsEncoder encoded} {@link OptionValues}. */ diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java index 35587d41f14f..3b54f81d76ed 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java @@ -35,7 +35,6 @@ import jdk.graal.compiler.util.json.JsonFormatter; import jdk.graal.compiler.util.json.JsonParser; import jdk.graal.compiler.util.json.JsonParserException; -import jdk.vm.ci.meta.TriState; public class JsonParserTest { @@ -190,30 +189,6 @@ public void parseAllowedKeysErrors() throws IOException { } } - @Test - public void parserExceptionsAtEOF() throws IOException { - for (String input : List.of("", "[", "{", "{\"", "{\"a", "{\"a\"", "{\"a\":", "[\"a\",", "tru", "nul", "fals")) { - try { - new JsonParser(input).parse(); - Assert.fail("The input string is not a valid JSON."); - } catch (JsonParserException exception) { - Assert.assertEquals(TriState.TRUE, exception.isAtEOF()); - } - } - } - - @Test - public void parserExceptionsBeforeEOF() throws IOException { - for (String input : List.of("true??", "[?,", "{\"a\",\"b\"}")) { - try { - new JsonParser(input).parse(); - Assert.fail("The input string is not a valid JSON."); - } catch (JsonParserException exception) { - Assert.assertEquals(TriState.FALSE, exception.isAtEOF()); - } - } - } - private static void testErrorIntl(String json, String expectedMessage) throws IOException { JsonParser parser = new JsonParser(json); try { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java index 102d3951f6f0..e5adffecec85 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java @@ -298,7 +298,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo case INVOKESPECIAL : case INVOKESTATIC : { int cpi = stream.readCPI(); - JavaMethod callee = cp.lookupMethod(cpi, opcode, method); + JavaMethod callee = cp.lookupMethod(cpi, opcode); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -315,7 +315,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo } case INVOKEINTERFACE: { int cpi = stream.readCPI(); - JavaMethod callee = cp.lookupMethod(cpi, opcode, method); + JavaMethod callee = cp.lookupMethod(cpi, opcode); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -334,7 +334,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo } case INVOKEDYNAMIC: { int cpi = stream.readCPI4(); - JavaMethod callee = cp.lookupMethod(cpi, opcode, method); + JavaMethod callee = cp.lookupMethod(cpi, opcode); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -497,11 +497,13 @@ public static JavaMethod getInvokedMethodAt(ResolvedJavaMethod method, int invok case INVOKESTATIC: case INVOKEINTERFACE: { int cpi = stream.readCPI(); - return cp.lookupMethod(cpi, opcode, method); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + return callee; } case INVOKEDYNAMIC: { int cpi = stream.readCPI4(); - return cp.lookupMethod(cpi, opcode, method); + JavaMethod callee = cp.lookupMethod(cpi, opcode); + return callee; } default: throw new InternalError(BytecodeDisassembler.disassembleOne(method, invokeBci)); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java index e2641c7057e6..8dfa836187d0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java @@ -33,7 +33,6 @@ import static jdk.graal.compiler.debug.DebugOptions.Counters; import static jdk.graal.compiler.debug.DebugOptions.Timers; import static jdk.graal.compiler.debug.PathUtilities.getPath; -import static jdk.graal.compiler.debug.DebugOptions.RecordForReplay; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -398,7 +397,6 @@ private OptionValues getRetryOptions(OptionValues initialOptions, String dumpPat values.put(DumpPath, dumpPath); values.put(PrintBackendCFG, true); values.put(TrackNodeSourcePosition, true); - values.put(RecordForReplay, "*"); String diagnoseOptions = DebugOptions.DiagnoseOptions.getValue(initialOptions); parseRetryOptions(OptionsParser.splitOptions(diagnoseOptions), values); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java index 00826e59b1d6..fa36e8acba76 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java @@ -55,12 +55,6 @@ public interface LibGraalSupport { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) @interface HostedOnly { - /** - * The name of a libgraal build-time system property that allows the annotated element to be - * used at libgraal run time. The value of the property is parsed using - * {@link Boolean#parseBoolean}. - */ - String unlessTrue() default ""; } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java index 8e7372082ebd..63784ab3300f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java @@ -286,9 +286,6 @@ public enum OptimizationLogTarget { @Option(help = "Path to the directory where the optimization log is saved if OptimizationLog is set to Directory. " + "Directories are created if they do no exist.", type = OptionType.Debug) public static final OptionKey OptimizationLogPath = new OptionKey<>(null); - - @Option(help = "Record the compilations matching the method filter for replay compilation.", type = OptionType.Debug) - public static final OptionKey RecordForReplay = new OptionKey<>(null); // @formatter:on /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index ced10d5179f4..9d9554d49b28 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -34,7 +34,6 @@ import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.io.PrintStream; -import java.util.List; import java.util.ListIterator; import org.graalvm.collections.EconomicMap; @@ -58,9 +57,7 @@ import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.debug.TimerKey; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.nodes.spi.ProfileProvider; import jdk.graal.compiler.nodes.spi.StableProfileProvider; import jdk.graal.compiler.nodes.spi.StableProfileProvider.TypeFilter; import jdk.graal.compiler.options.Option; @@ -78,6 +75,7 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.BailoutException; +import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -292,10 +290,6 @@ private static boolean isNotCausedByOOME(Throwable throwable) { @Override protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) { HotSpotResolvedJavaMethod method = getMethod(); - if (ReplayCompilationSupport.matchesRecordCompilationFilter(debug.getOptions(), method) || compiler.getGraalRuntime().getReplayCompilationSupport() != null) { - return performCompilationWithReplaySupport(debug); - } - int entryBCI = getEntryBCI(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR); @@ -305,15 +299,32 @@ protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { graph = compiler.createGraph(method, entryBCI, profileProvider, compilationId, debug.getOptions(), debug); Suites suites = compiler.getSuites(compiler.getGraalRuntime().getHostProviders(), debug.getOptions()); - adjustSuitesForRecompilation(debug.getOptions(), suites); + if (checkRecompileCycle && (MethodRecompilationLimit.getValue(debug.getOptions()) < 0 || decompileCount < MethodRecompilationLimit.getValue(debug.getOptions()))) { + /* + * Disable DeoptimizationGroupingPhase to simplify the creation of the + * speculations for each deopt. + */ + ListIterator> phase = suites.getMidTier().findPhase(DeoptimizationGroupingPhase.class); + if (phase != null) { + phase.remove(); + } + ListIterator> lowTierPhasesIterator = suites.getLowTier().findPhase(SchedulePhase.FinalSchedulePhase.class); + if (lowTierPhasesIterator != null) { + lowTierPhasesIterator.previous(); + lowTierPhasesIterator.add(new ForceDeoptSpeculationPhase(decompileCount)); + } + } result = compiler.compile(graph, shouldRetainLocalVariables, shouldUsePreciseUnresolvedDeopts, eagerResolving, compilationId, debug, suites); - performRecompilationCheck(debug.getOptions(), method); + if (checkRecompileCycle && (MethodRecompilationLimit.getValue(debug.getOptions()) >= 0 && decompileCount >= MethodRecompilationLimit.getValue(debug.getOptions()))) { + ProfilingInfo info = profileProvider.getProfilingInfo(method); + throw new ForceDeoptSpeculationPhase.TooManyDeoptimizationsError("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase.getDeoptSummary(info)); + } } catch (Throwable e) { throw debug.handle(e); } try (DebugCloseable b = CodeInstallationTime.start(debug)) { - installMethod(compiler.getGraalRuntime().getHostBackend(), debug, graph, result); + installMethod(debug, graph, result); } // Installation is included in compilation time and memory usage reported by printer printer.finish(result, installedCode); @@ -323,110 +334,6 @@ protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) return buildCompilationRequestResult(method); } - /** - * Modifies the provided suites to prevent excessive recompilation if necessary. - * - * @param options the option values - * @param suites the suites to modify - */ - private void adjustSuitesForRecompilation(OptionValues options, Suites suites) { - if (checkRecompileCycle && (MethodRecompilationLimit.getValue(options) < 0 || decompileCount < MethodRecompilationLimit.getValue(options))) { - /* - * Disable DeoptimizationGroupingPhase to simplify the creation of the speculations - * for each deopt. - */ - ListIterator> phase = suites.getMidTier().findPhase(DeoptimizationGroupingPhase.class); - if (phase != null) { - phase.remove(); - } - ListIterator> lowTierPhasesIterator = suites.getLowTier().findPhase(SchedulePhase.FinalSchedulePhase.class); - if (lowTierPhasesIterator != null) { - lowTierPhasesIterator.previous(); - lowTierPhasesIterator.add(new ForceDeoptSpeculationPhase(decompileCount)); - } - } - } - - /** - * Checks whether the recompilation limit is exceeded, and if so, throws an exception. - * - * @param options the option values - * @param method the compiled method - */ - private void performRecompilationCheck(OptionValues options, HotSpotResolvedJavaMethod method) { - if (checkRecompileCycle && (MethodRecompilationLimit.getValue(options) >= 0 && decompileCount >= MethodRecompilationLimit.getValue(options))) { - ProfilingInfo info = profileProvider.getProfilingInfo(method); - throw new ForceDeoptSpeculationPhase.TooManyDeoptimizationsError("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase.getDeoptSummary(info)); - } - } - - private static final TimerKey CompilationReplayTime = DebugContext.timer("CompilationReplayTime").doc("The time spent in recorded/replayed compilations."); - - private static final CounterKey CompilationReplayBytecodes = DebugContext.counter("CompilationReplayBytecodes").doc("The size of bytecodes compiled in recorded/replayed compilations."); - - /** - * Performs a recorded or replayed compilation. - * - * @param initialDebug the initial debug context - * @return the compilation result - */ - @SuppressWarnings("try") - private HotSpotCompilationRequestResult performCompilationWithReplaySupport(DebugContext initialDebug) { - OptionValues options = initialDebug.getOptions(); - HotSpotGraalCompiler selectedCompiler; - if (compiler.getGraalRuntime().getReplayCompilationSupport() != null) { - selectedCompiler = compiler; - } else { - CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(compiler.getGraalRuntime().getCompilerConfigurationName(), options, jvmciRuntime); - selectedCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-record", jvmciRuntime, options, configFactory, ReplayCompilationSupport.createRecording(configFactory.getName())); - } - ReplayCompilationSupport replaySupport = selectedCompiler.getGraalRuntime().getReplayCompilationSupport(); - HotSpotCompilationRequest request = getRequest(); - try (DebugCloseable closeable = replaySupport.enterCompilationContext(request, options)) { - request = replaySupport.decorateCompilationRequest(request); - HotSpotResolvedJavaMethod method = request.getMethod(); - /* - * Passing a snippet reflection instance to the debug handlers would cause replay - * failures. - */ - List debugHandlersFactories = List.of(new GraalDebugHandlersFactory(null)); - PrintStream selectedPrintStream = initialDebug.getConfig() == null ? DebugContext.getDefaultLogStream() : initialDebug.getConfig().output(); - try (DebugContext debug = selectedCompiler.getGraalRuntime().openDebugContext(options, compilationId, method, debugHandlersFactories, selectedPrintStream); - DebugContext.Activation a = debug.activate(); - DebugCloseable d = replaySupport.withDebugContext(debug); - DebugCloseable c = initialDebug.inRetryCompilation() ? debug.openRetryCompilation() : null; - DebugCloseable t = CompilationReplayTime.start(debug)) { - int entryBCI = getEntryBCI(); - boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; - CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); - CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI); - if (initialDebug.inRetryCompilation()) { - profileProvider.forQueriedProfiles((profileKey, profilingInfo) -> { - replaySupport.injectProfiles(profileKey.method(), profileKey.includeNormal(), profileKey.includeOSR(), profilingInfo); - }); - } - ProfileProvider selectedProfileProvider = new StableProfileProvider(); - try (DebugContext.Scope s = debug.scope("Compiling with replay support", new DebugDumpScope(getIdString(), true))) { - graph = selectedCompiler.createGraph(method, entryBCI, selectedProfileProvider, compilationId, options, debug); - Suites suites = compiler.getSuites(compiler.getGraalRuntime().getHostProviders(), debug.getOptions()); - adjustSuitesForRecompilation(options, suites); - result = selectedCompiler.compile(graph, shouldRetainLocalVariables, shouldUsePreciseUnresolvedDeopts, eagerResolving, compilationId, debug, suites); - performRecompilationCheck(options, method); - CompilationReplayBytecodes.add(debug, result.getBytecodeSize()); - } catch (Throwable e) { - throw debug.handle(e); - } - try (DebugCloseable b = CodeInstallationTime.start(debug)) { - installMethod(selectedCompiler.getGraalRuntime().getHostBackend(), debug, graph, result); - } - printer.finish(result, installedCode); - stats.finish(method, installedCode); - replaySupport.recordCompilationArtifacts(graph, result); - return buildCompilationRequestResult(method); - } - } - } - protected HotSpotCompilationRequestResult buildCompilationRequestResult(HotSpotResolvedJavaMethod method) { // For compilation of substitutions the method in the compilation request might be // different than the actual method parsed. The root of the compilation will always @@ -692,9 +599,11 @@ protected HotSpotCompilationRequestResult runCompilation(DebugContext debug, Hot } @SuppressWarnings("try") - protected void installMethod(HotSpotBackend backend, DebugContext debug, StructuredGraph graph, final CompilationResult compResult) { + protected void installMethod(DebugContext debug, StructuredGraph graph, final CompilationResult compResult) { + final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); + HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); installedCode = null; - Object[] context = {new DebugDumpScope(getIdString(), true), backend.getProviders().getCodeCache(), getMethod(), compResult}; + Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; try (DebugContext.Scope s = debug.scope("CodeInstall", context, graph)) { HotSpotCompilationRequest request = getRequest(); installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index c09b8a98ad6a..f6f1862f75b2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -24,24 +24,20 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; -import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.snippetsAreEncoded; -import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.util.concurrent.ConcurrentHashMap; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.nodes.NodeClassMap; import org.graalvm.collections.UnmodifiableEconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; -import jdk.graal.compiler.core.CompilationWrapper; -import jdk.graal.compiler.core.GraalCompilerOptions; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; @@ -51,7 +47,6 @@ import jdk.graal.compiler.nodes.ConstantNode; import jdk.graal.compiler.nodes.EncodedGraph; import jdk.graal.compiler.nodes.FieldLocationIdentity; -import jdk.graal.compiler.nodes.NodeClassMap; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin; @@ -75,29 +70,6 @@ import jdk.vm.ci.meta.UnresolvedJavaType; public class EncodedSnippets { - /** - * Returns true if the current runtime or current compilation thread uses encoded snippets - * rather than parsing them directly. This is always true when executing in libgraal, and it is - * also true when the current thread is replaying a libgraal compilation in jargraal. - * - * @return true if encoded snippets are currently in use - */ - public static boolean isUsingEncodedSnippets() { - return inRuntimeCode() || isReplayingLibgraalInJargraal(); - } - - /** - * Returns true if the current runtime or current compilation thread uses encoded snippets and - * the snippets are already encoded. This is always true when executing in libgraal. If the - * current thread is replaying a libgraal compilation in jargraal, the method returns true after - * the snippets are encoded. - * - * @return true if encoded snippets are in use and already encoded - */ - public static boolean isAfterSnippetEncoding() { - return inRuntimeCode() || (isReplayingLibgraalInJargraal() && snippetsAreEncoded()); - } - /** * Metadata about a graph encoded in {@link EncodedSnippets#snippetEncoding}. */ @@ -240,7 +212,7 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod data = graphDatas.get(methodKey(method)); } if (data == null) { - if (isUsingEncodedSnippets()) { + if (LibGraalSupport.inLibGraalRuntime()) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport } else { return null; @@ -257,16 +229,8 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod if (declaringClass instanceof SnippetResolvedJavaType) { declaringClass = replacements.getProviders().getMetaAccess().lookupJavaType(Object.class); } - /* - * If this is a recorded/replayed compilation, we must not mutate the snippet objects. This - * ensures we record all relevant operations during recording and no proxies are stored in - * the snippet objects during replay. - */ - boolean allowCacheReplacements = LibGraalSupport.inLibGraalRuntime() && replacements.getProviders().getReplayCompilationSupport() == null && - GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; - SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, - snippetNodeClasses, data.originalMethod, declaringClass); - return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, isUsingEncodedSnippets()); + SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, data.originalMethod, declaringClass); + return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, LibGraalSupport.inLibGraalRuntime()); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @@ -342,7 +306,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.getProviders().getSnippetReflection(); - if (isUsingEncodedSnippets()) { + if (LibGraalSupport.inLibGraalRuntime()) { snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); } parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); @@ -433,17 +397,15 @@ static class SymbolicEncodedGraph extends EncodedGraph { private final ResolvedJavaType[] accessingClasses; private final String originalMethod; - private final boolean allowCacheReplacements; - SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowObjectsMutations, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { + SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { super(encoding, startOffset, objects, nodeClasses, null, null, false, false); this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; - this.allowCacheReplacements = allowObjectsMutations; } - SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod, boolean allowCacheReplacements) { - this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), allowCacheReplacements, encodedGraph.getNodeClasses(), + SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod) { + this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(), originalMethod, declaringClass); } @@ -491,10 +453,7 @@ public Object getObject(int i) { return o; } if (replacement != null) { - o = replacement; - if (allowCacheReplacements) { - objects[i] = replacement; - } + objects[i] = o = replacement; } else { throw new GraalError(error, "Can't resolve %s", o); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 3fc50f8f3d6f..47465b8db293 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -36,7 +36,7 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -63,8 +63,8 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess { */ public static final OptionValues INJECTED_OPTIONVALUES = null; - GraalHotSpotVMConfig(HotSpotVMConfigAccess access, Platform platform) { - super(access, platform); + GraalHotSpotVMConfig(HotSpotVMConfigStore store) { + super(store); int logMinObjAlignment = logMinObjAlignment(); assert narrowOopShift <= logMinObjAlignment : Assertions.errorMessageContext("narrowOopShift", narrowOopShift, "logMinObjAlignment", logMinObjAlignment); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java index cfef20e412f8..0664afc3c9bd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java @@ -30,9 +30,11 @@ import java.util.Formatter; import java.util.List; import java.util.Map; +import java.util.Set; import java.util.stream.Collectors; import jdk.graal.compiler.debug.Assertions; +import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -49,27 +51,56 @@ public class GraalHotSpotVMConfigAccess { private final Map vmConstants; private final Map vmFields; - GraalHotSpotVMConfigAccess(HotSpotVMConfigAccess access, Platform platform) { - this.access = access; - HotSpotVMConfigStore store = access.getStore(); + GraalHotSpotVMConfigAccess(HotSpotVMConfigStore store) { + this.access = new HotSpotVMConfigAccess(store); this.vmAddresses = store.getAddresses(); this.vmConstants = store.getConstants(); this.vmFields = store.getFields(); - this.osName = platform.osName(); - this.osArch = platform.archName(); + + String value = getSavedProperty("os.name"); + switch (value) { + case "Linux": + value = "linux"; + break; + case "SunOS": + value = "solaris"; + break; + case "Mac OS X": + value = "darwin"; + break; + default: + // Of course Windows is different... + if (value.startsWith("Windows")) { + value = "windows"; + } else { + throw new JVMCIError("Unexpected OS name: " + value); + } + } + assert KNOWN_OS_NAMES.contains(value); + this.osName = value; + + String arch = getSavedProperty("os.arch"); + if (arch.equals("x86_64")) { + arch = "amd64"; + } + osArch = arch; + assert KNOWN_ARCHITECTURES.contains(arch) : arch; } public HotSpotVMConfigStore getStore() { return access.getStore(); } + public static final Set KNOWN_ARCHITECTURES = CollectionsUtil.setOf("amd64", "aarch64", "riscv64"); + public static final Set KNOWN_OS_NAMES = CollectionsUtil.setOf("windows", "linux", "darwin"); + /** - * Name for current OS. Will be a value in {@link Platform#KNOWN_OS_NAMES}. + * Name for current OS. Will be a value in {@link #KNOWN_OS_NAMES}. */ public final String osName; /** - * Name for current CPU architecture. Will be a value in {@link Platform#KNOWN_ARCHITECTURES}. + * Name for current CPU architecture. Will be a value in {@link #KNOWN_ARCHITECTURES}. */ public final String osArch; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index 5895c1acfdd1..933532b4feae 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -26,7 +26,6 @@ import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.vm.ci.common.InitTimer.timer; import jdk.graal.compiler.bytecode.BytecodeProvider; @@ -86,35 +85,6 @@ @LibGraalService public abstract class HotSpotBackendFactory implements ArchitectureSpecific { - /** - * Creates a meta access provider based on a JVMCI backend. - * - * @param jvmci the JVMCI backend - * @return a meta access provider - */ - protected MetaAccessProvider createMetaAccessProvider(JVMCIBackend jvmci) { - return new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); - } - - /** - * Creates a constant reflection provider based on a JVMCI backend. - * - * @param jvmci the JVMCI backend - * @return a constant reflection provider - */ - protected HotSpotConstantReflectionProvider createConstantReflectionProvider(JVMCIBackend jvmci) { - return (HotSpotConstantReflectionProvider) jvmci.getConstantReflection(); - } - - /** - * Creates a code cache provider based on a JVMCI backend. - * - * @param jvmci the JVMCI backend - * @return a code cache provider. - */ - protected HotSpotCodeCacheProvider createCodeCacheProvider(JVMCIBackend jvmci) { - return (HotSpotCodeCacheProvider) jvmci.getCodeCache(); - } protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { return new HotSpotGraalConstantFieldProvider(config, metaAccess); @@ -159,13 +129,6 @@ protected LoopsDataProvider createLoopsDataProvider() { return new LoopsDataProviderImpl(); } - /** - * Hook method called after all JVMCI providers have been created (meta access, code cache, - * constant reflection). - */ - protected void afterJVMCIProvidersCreated() { - } - @SuppressWarnings("try") public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) { assert host == null; @@ -173,14 +136,14 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - MetaAccessProvider metaAccess = createMetaAccessProvider(jvmci); - HotSpotCodeCacheProvider codeCache = createCodeCacheProvider(jvmci); - HotSpotConstantReflectionProvider constantReflection = createConstantReflectionProvider(jvmci); - afterJVMCIProvidersCreated(); - TargetDescription target = codeCache.getTarget(); - if (inBuildtimeCode() || isUsingEncodedSnippets()) { - SnippetSignature.initPrimitiveKindCache(metaAccess); + if (inBuildtimeCode() || inRuntimeCode()) { + SnippetSignature.initPrimitiveKindCache(jvmci.getMetaAccess()); } + + HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache(); + TargetDescription target = codeCache.getTarget(); + MetaAccessProvider metaAccess = new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); + HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection(); ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess); HotSpotProviders providers; HotSpotReplacementsImpl replacements; @@ -236,8 +199,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti identityHashCodeProvider = createIdentityHashCodeProvider(); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, null, registers, - snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config, identityHashCodeProvider, - graalRuntime.getReplayCompilationSupport()); + snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config, identityHashCodeProvider); try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, bytecodeProvider); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java deleted file mode 100644 index b4a4c9361c2b..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 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.hotspot; - -import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.meta.MetaAccessProvider; - -/** - * Decorators for the providers created by a backend factory. - */ -public interface HotSpotBackendFactoryDecorators { - /** - * Decorates the given MetaAccessProvider. - * - * @param metaAccess the MetaAccessProvider to decorate - * @return the decorated MetaAccessProvider - */ - default MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { - return metaAccess; - } - - /** - * Decorates the given constant reflection provider. - * - * @param constantReflection the constant reflection provider to decorate - * @return the decorated constant reflection provider - */ - default HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotSpotConstantReflectionProvider constantReflection) { - return constantReflection; - } - - /** - * Decorates the given code cache provider. - * - * @param codeCacheProvider the code cache provider to decorate - * @return the decorated code cache provider - */ - default HotSpotCodeCacheProvider decorateCodeCacheProvider(HotSpotCodeCacheProvider codeCacheProvider) { - return codeCacheProvider; - } - - /** - * Decorates the given foreign calls provider. - * - * @param foreignCalls the foreign calls provider to decorate - * @return the decorated foreign calls provider - */ - default HotSpotHostForeignCallsProvider decorateForeignCallsProvider(HotSpotHostForeignCallsProvider foreignCalls) { - return foreignCalls; - } - - /** - * Called after JVMCI providers have been created. - */ - default void afterJVMCIProvidersCreated() { - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java deleted file mode 100644 index ff6db885e18a..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Copyright (c) 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.hotspot; - -import jdk.graal.compiler.bytecode.BytecodeProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.meta.HotSpotRegistersProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotStampProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotSuitesProvider; -import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; -import jdk.graal.compiler.nodes.FixedWithNextNode; -import jdk.graal.compiler.nodes.ValueNode; -import jdk.graal.compiler.nodes.gc.BarrierSet; -import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; -import jdk.graal.compiler.nodes.memory.FixedAccessNode; -import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; -import jdk.graal.compiler.nodes.spi.LoopsDataProvider; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.phases.tiers.CompilerConfiguration; -import jdk.graal.compiler.replacements.classfile.ClassfileBytecodeProvider; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.Value; -import jdk.vm.ci.runtime.JVMCIBackend; - -/** - * A backend factory that creates providers via a delegate factory and decorates them. - */ -public class HotSpotDecoratedBackendFactory extends HotSpotBackendFactory { - /** - * The delegate backend factory. - */ - private final HotSpotBackendFactory delegate; - - /** - * The decorators to apply to the providers created by the delegate factory. - */ - private final HotSpotBackendFactoryDecorators decorators; - - /** - * Constructs a new instance of a decorated backend factory. - * - * @param delegate the delegate backend factory - * @param decorators the decorators to apply to the providers created by the delegate factory - */ - public HotSpotDecoratedBackendFactory(HotSpotBackendFactory delegate, HotSpotBackendFactoryDecorators decorators) { - this.delegate = delegate; - this.decorators = decorators; - } - - @Override - protected void afterJVMCIProvidersCreated() { - decorators.afterJVMCIProvidersCreated(); - delegate.afterJVMCIProvidersCreated(); - } - - @Override - protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { - return delegate.createConstantFieldProvider(config, metaAccess); - } - - @Override - protected HotSpotWordTypes createWordTypes(MetaAccessProvider metaAccess, TargetDescription target) { - return delegate.createWordTypes(metaAccess, target); - } - - @Override - protected HotSpotStampProvider createStampProvider() { - return delegate.createStampProvider(); - } - - @Override - protected HotSpotPlatformConfigurationProvider createConfigInfoProvider(GraalHotSpotVMConfig config, BarrierSet barrierSet) { - return delegate.createConfigInfoProvider(config, barrierSet); - } - - @Override - protected HotSpotReplacementsImpl createReplacements(TargetDescription target, HotSpotProviders p, BytecodeProvider bytecodeProvider) { - return delegate.createReplacements(target, p, bytecodeProvider); - } - - @Override - protected ClassfileBytecodeProvider createBytecodeProvider(MetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection) { - return delegate.createBytecodeProvider(metaAccess, snippetReflection); - } - - @Override - protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, HotSpotWordTypes wordTypes) { - return delegate.createSnippetReflection(runtime, constantReflection, wordTypes); - } - - @Override - protected IdentityHashCodeProvider createIdentityHashCodeProvider() { - return delegate.createIdentityHashCodeProvider(); - } - - @Override - protected boolean isWriteToNewObject(FixedAccessNode node) { - return delegate.isWriteToNewObject(node); - } - - @Override - protected boolean isWriteToNewObject(FixedWithNextNode node, ValueNode base) { - return delegate.isWriteToNewObject(node, base); - } - - @Override - protected LoopsDataProvider createLoopsDataProvider() { - return delegate.createLoopsDataProvider(); - } - - @Override - protected MetaAccessProvider createMetaAccessProvider(JVMCIBackend jvmci) { - return decorators.decorateMetaAccessProvider(jvmci.getMetaAccess()); - } - - @Override - protected HotSpotConstantReflectionProvider createConstantReflectionProvider(JVMCIBackend jvmci) { - return decorators.decorateConstantReflectionProvider(delegate.createConstantReflectionProvider(jvmci)); - } - - @Override - protected HotSpotCodeCacheProvider createCodeCacheProvider(JVMCIBackend jvmci) { - return decorators.decorateCodeCacheProvider(delegate.createCodeCacheProvider(jvmci)); - } - - @Override - public String getName() { - return delegate.getName(); - } - - @Override - protected HotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider graalRuntime, HotSpotProviders providers) { - return delegate.createBackend(config, graalRuntime, providers); - } - - @Override - protected Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig registerConfig) { - return delegate.createNativeABICallerSaveRegisters(config, registerConfig); - } - - @Override - protected GraphBuilderConfiguration.Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, - CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, - HotSpotHostForeignCallsProvider foreignCalls, MetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, - HotSpotWordTypes wordTypes, OptionValues options, BarrierSet barrierSet) { - return delegate.createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, target, constantReflection, - foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options, barrierSet); - } - - @Override - protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, - GraphBuilderConfiguration.Plugins plugins, HotSpotRegistersProvider registers, OptionValues options) { - return delegate.createSuites(config, runtime, compilerConfiguration, plugins, registers, options); - } - - @Override - protected HotSpotRegistersProvider createRegisters() { - return delegate.createRegisters(); - } - - @Override - protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider graalRuntime, MetaAccessProvider metaAccess, HotSpotHostForeignCallsProvider foreignCalls, - HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, HotSpotPlatformConfigurationProvider platformConfig, - HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider, TargetDescription target) { - return delegate.createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfig, - metaAccessExtensionProvider, target); - } - - @Override - protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, MetaAccessProvider metaAccess, - HotSpotCodeCacheProvider codeCache, HotSpotWordTypes wordTypes, Value[] nativeABICallerSaveRegisters) { - return decorators.decorateForeignCallsProvider(delegate.createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters)); - } - - @Override - public String getArchitecture() { - return delegate.getArchitecture(); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java index 5114de56f07c..7ab569bf3561 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -266,11 +266,6 @@ enum RegisterEffect { long getAddress(); - /** - * Returns {@code true} if this linkage has a finalized address. - */ - boolean hasAddress(); - /** * Determines if the runtime function or stub might use floating point registers. If the answer * is no, then no FPU state management prologue or epilogue needs to be emitted around the call. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index df1aef148d26..dbeeb30c7f89 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -319,31 +319,12 @@ public void finalizeAddress(Backend backend) { } } - /** - * Sets the address and killed slots/registers of this foreign call linkage. This linkage should - * not have an address yet, and the new address must not be {@code 0L}. - * - * @param newAddress the new address of the linkage - * @param newTemporaries the new killed slots and registers - */ - public void finalizeExternally(long newAddress, Value[] newTemporaries) { - GraalError.guarantee(!hasAddress(), "the linkage should not be finalized yet"); - GraalError.guarantee(newAddress != 0L, "the updated linkage must have an address"); - address = newAddress; - temporaries = newTemporaries.clone(); - } - @Override public long getAddress() { assert address != 0L : "address not yet finalized: " + this; return address; } - @Override - public boolean hasAddress() { - return address != 0L; - } - @Override public boolean destroysRegisters() { return effect == RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java index bf7baa99a0e1..6bb24817b00c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -28,11 +28,11 @@ import java.io.PrintStream; -import jdk.graal.compiler.api.runtime.GraalRuntime; import jdk.graal.compiler.core.common.LibGraalSupport; + +import jdk.graal.compiler.api.runtime.GraalRuntime; import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.TTY; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionType; @@ -183,7 +183,7 @@ public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { if (isGraalPredicate != null) { isGraalPredicate.onCompilerConfigurationFactorySelection(hsRuntime, factory); } - HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory, null); + HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory); // Only the HotSpotGraalRuntime associated with the compiler created via // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving // VM events. @@ -222,14 +222,12 @@ private void checkUnsafeAccess(HotSpotJVMCIRuntime hsRuntime) { * by this method * @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} - * @param replaySupport replay compilation support if this is a recording or replaying compiler */ @SuppressWarnings("try") - public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory, - ReplayCompilationSupport replaySupport) { + public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; try (InitTimer t = timer("HotSpotGraalRuntime.")) { - HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options, replaySupport); + HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options); return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions()); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java index 103d8ad3249e..54bc15d5e8a3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java @@ -59,7 +59,6 @@ import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.hotspot.debug.BenchmarkCounters; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.nodes.spi.StampProvider; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.tiers.CompilerConfiguration; @@ -71,7 +70,6 @@ import jdk.vm.ci.code.stack.StackIntrospection; import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -120,40 +118,24 @@ public GlobalMetrics getMetricValues() { private final CompilerProfiler compilerProfiler; - /** - * The interface for recording/replaying compilations or {@code null} if disabled. - */ - private final ReplayCompilationSupport replayCompilationSupport; - /** * @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name} * @param compilerConfigurationFactory factory for the compiler configuration * {@link CompilerConfigurationFactory#selectFactory} - * @param replaySupport replay compilation support if this is a runtime for a recording or - * replaying compiler */ @SuppressWarnings("try") - HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions, - ReplayCompilationSupport replaySupport) { + HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier; HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(store); - GraalHotSpotVMConfig selectedConfig = new GraalHotSpotVMConfig(access, Platform.ofCurrentHost()); + config = new GraalHotSpotVMConfig(store); // Only set HotSpotPrintInlining if it still has its default value (false). - OptionValues selectedOptions = initialOptions; - if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && selectedConfig.printInlining) { - selectedOptions = new OptionValues(selectedOptions, HotSpotPrintInlining, true); + if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { + options = new OptionValues(initialOptions, HotSpotPrintInlining, true); + } else { + options = initialOptions; } - replayCompilationSupport = replaySupport; - if (replayCompilationSupport != null) { - access = replayCompilationSupport.decorateVMConfigAccess(access); - selectedConfig = new GraalHotSpotVMConfig(access, replayCompilationSupport.targetPlatform()); - selectedOptions = replayCompilationSupport.filterOptions(selectedOptions); - } - options = selectedOptions; - config = selectedConfig; outputDirectory = new DiagnosticsOutputDirectory(options); compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; @@ -171,9 +153,6 @@ public GlobalMetrics getMetricValues() { if (factory == null) { throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture); } - if (replayCompilationSupport != null) { - factory = replayCompilationSupport.decorateBackendFactory(factory); - } hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null)); } @@ -211,11 +190,7 @@ public GlobalMetrics getMetricValues() { runtimeStartTime = System.nanoTime(); bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class); - CompilerProfiler selectedCompilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); - if (replayCompilationSupport != null) { - selectedCompilerProfiler = replayCompilationSupport.decorateCompilerProfiler(selectedCompilerProfiler); - } - this.compilerProfiler = selectedCompilerProfiler; + this.compilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); LibGraalSupport libgraal = LibGraalSupport.INSTANCE; if (libgraal != null) { @@ -435,7 +410,7 @@ public synchronized void addShutdownHook(Runnable hook) { } } - public synchronized void shutdown() { + synchronized void shutdown() { shutdown = true; for (Runnable r : shutdownHooks) { @@ -506,9 +481,4 @@ public DiagnosticsOutputDirectory getOutputDirectory() { public Map getCompilationProblemsPerAction() { return compilationProblemsPerAction; } - - @Override - public ReplayCompilationSupport getReplayCompilationSupport() { - return replayCompilationSupport; - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java index 9bf9fcde651f..323b7bfdc56c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -35,7 +35,6 @@ import jdk.graal.compiler.debug.DebugDumpHandlersFactory; import jdk.graal.compiler.debug.DiagnosticsOutputDirectory; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.replacements.SnippetCounter.Group; import jdk.graal.compiler.runtime.RuntimeProvider; @@ -108,9 +107,4 @@ default String getName() { * Returns the instance holding the instrumentation data structures. */ Instrumentation getInstrumentation(); - - /** - * Returns the interface for recording/replaying compilations or {@code null} if disabled. - */ - ReplayCompilationSupport getReplayCompilationSupport(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java index 0fc684bd8b75..9a6f5803423c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java @@ -37,13 +37,11 @@ import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.graal.compiler.core.gen.LIRGenerationProvider; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugDumpHandlersFactory; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.Stub; import jdk.graal.compiler.lir.LIR; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; @@ -111,10 +109,10 @@ public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValue HotSpotHostForeignCallsProvider foreignCalls = providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - try (InitTimer st = timer("foreignCalls.initialize"); DebugCloseable c = ReplayCompilationSupport.enterSnippetContext(providers)) { + try (InitTimer st = timer("foreignCalls.initialize")) { foreignCalls.initialize(providers, options); } - try (InitTimer st = timer("lowerer.initialize"); DebugCloseable c = ReplayCompilationSupport.enterSnippetContext(providers)) { + try (InitTimer st = timer("lowerer.initialize")) { Iterable factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())); lowerer.initialize(options, factories, providers, config); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 80c59b7b0e43..81a73c8343f7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -24,11 +24,8 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.LibGraalSupport.inLibGraalRuntime; import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; -import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import java.util.BitSet; @@ -38,13 +35,11 @@ import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.meta.HotSpotWordOperationPlugin; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotOperation; import jdk.graal.compiler.java.GraphBuilderPhase.Instance; import jdk.graal.compiler.nodes.Invoke; @@ -65,7 +60,6 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.replacements.IntrinsicGraphBuilder; import jdk.graal.compiler.replacements.ReplacementsImpl; -import jdk.graal.compiler.replacements.SnippetTemplate; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -78,7 +72,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl { public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider bytecodeProvider, TargetDescription target) { super(new GraalDebugHandlersFactory(providers.getSnippetReflection()), providers, bytecodeProvider, target); - if (!inLibGraalRuntime()) { + if (!LibGraalSupport.inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -86,7 +80,7 @@ public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider byte HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(new GraalDebugHandlersFactory(replacements.getProviders().getSnippetReflection()), providers, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); - if (!inLibGraalRuntime()) { + if (!LibGraalSupport.inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -96,13 +90,6 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } - @LibGraalSupport.HostedOnly - public static void clearSnippetEncoder() { - synchronized (HotSpotReplacementsImpl.class) { - snippetEncoder = null; - } - } - @LibGraalSupport.HostedOnly public SymbolicSnippetEncoder maybeInitializeEncoder() { synchronized (HotSpotReplacementsImpl.class) { @@ -115,7 +102,7 @@ public SymbolicSnippetEncoder maybeInitializeEncoder() { @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { - if (!inLibGraalRuntime()) { + if (!LibGraalSupport.inLibGraalRuntime()) { if (method.getAnnotation(HotSpotOperation.class) != null) { return HotSpotWordOperationPlugin.class; } @@ -125,7 +112,7 @@ public Class getIntrinsifyingPlugin(ResolvedJavaMe @Override public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { - if (!inLibGraalRuntime()) { + if (!LibGraalSupport.inLibGraalRuntime()) { if (b.parsingIntrinsic() && snippetEncoder != null) { if (getIntrinsifyingPlugin(method) != null) { snippetEncoder.addDelayedInvocationPluginMethod(method); @@ -196,35 +183,20 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo @LibGraalSupport.HostedOnly// private boolean snippetRegistrationClosed; - @SuppressWarnings("try") @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (isRegisteringSnippetMethods()) { + if (inBuildtimeCode()) { assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { - snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); - } } } } - /** - * Returns true if the current runtime or current compilation thread registers snippet methods - * to be encoded. This is true when building libgraal or when replaying a libgraal compilation - * in jargraal. - * - * @return true if snippets methods should be registered - */ - private static boolean isRegisteringSnippetMethods() { - return !inLibGraalRuntime() && (inBuildtimeCode() || isReplayingLibgraalInJargraal()); - } - @Override public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { - if (isAfterSnippetEncoding()) { + if (inRuntimeCode()) { return getEncodedSnippets().getSnippetParameterInfo(method); } return super.getSnippetParameterInfo(method); @@ -232,7 +204,7 @@ public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @Override public boolean isSnippet(ResolvedJavaMethod method) { - if (isAfterSnippetEncoding()) { + if (inRuntimeCode()) { return getEncodedSnippets().isSnippet(method); } return super.isSnippet(method); @@ -260,19 +232,6 @@ public static boolean snippetsAreEncoded() { @LibGraalSupport.HostedOnly// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; - SnippetTemplate.setHostedEncodedSnippets(snippetsAreEncoded()); - } - - @LibGraalSupport.HostedOnly// - @SuppressWarnings("try") - public boolean encode(OptionValues options) { - SymbolicSnippetEncoder encoder = snippetEncoder; - if (encoder != null) { - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { - return encoder.encode(options); - } - } - return false; } private static volatile EncodedSnippets encodedSnippets; @@ -284,7 +243,7 @@ public boolean encode(OptionValues options) { @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (isUsingEncodedSnippets()) { + if (LibGraalSupport.inLibGraalRuntime()) { // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { @@ -297,9 +256,7 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } assert !inBuildtimeCode() || registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { - return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); - } + return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); } @SuppressWarnings("unchecked") @@ -312,13 +269,13 @@ public T getInjectedArgument(Class capability) { } public static MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { - if (!inLibGraalRuntime()) { + if (!LibGraalSupport.inLibGraalRuntime()) { return SymbolicSnippetEncoder.noticeTypes(metaAccess); } return metaAccess; } - public static boolean isGraalClass(ResolvedJavaType type) { + static boolean isGraalClass(ResolvedJavaType type) { return isGraalClass(type.toClassName()); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index 2c714cada6ac..4373fd196925 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -27,6 +27,7 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; @@ -40,28 +41,16 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; - public class HotSpotSnippetMetaAccessProvider implements MetaAccessProvider { private final MetaAccessProvider delegate; - /** - * {@code true} if the compiler is recording/replaying a compilation. - */ - private final boolean replayCompilationEnabled; - - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate, boolean replayCompilationEnabled) { - this.delegate = delegate; - this.replayCompilationEnabled = replayCompilationEnabled; - } - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { - this(delegate, false); + this.delegate = delegate; } @Override public ResolvedJavaType lookupJavaType(Class clazz) { - if (isAfterSnippetEncoding()) { + if (LibGraalSupport.inLibGraalRuntime()) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); if (type != null) { return type; @@ -84,14 +73,14 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - if (isAfterSnippetEncoding() && HotSpotReplacementsImpl.isGraalClass(clazz)) { + if (LibGraalSupport.inLibGraalRuntime() && HotSpotReplacementsImpl.isGraalClass(clazz)) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); return type; } return delegate.lookupJavaType(clazz); } - if (constant instanceof HotSpotObjectConstant hsConstant && !replayCompilationEnabled) { + if (constant instanceof HotSpotObjectConstant hsConstant) { Object object = hsConstant.asObject(Object.class); if (object != null) { Class clazz = object.getClass(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java deleted file mode 100644 index 7020c628a468..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot; - -import static jdk.graal.compiler.serviceprovider.GraalServices.getSavedProperty; - -import java.util.Set; - -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.util.CollectionsUtil; -import jdk.vm.ci.common.JVMCIError; - -/** - * The name of a known OS and architecture. - * - * @param osName the name of a known OS (one of {@link #KNOWN_OS_NAMES}) - * @param archName the name of a known architecture (one of {@link #KNOWN_ARCHITECTURES}) - */ -public record Platform(String osName, String archName) { - public Platform { - GraalError.guarantee(KNOWN_OS_NAMES.contains(osName), "unknown OS name"); - GraalError.guarantee(KNOWN_ARCHITECTURES.contains(archName), "unknown architecture"); - } - - /** - * Returns the platform of the current host based on system properties. - */ - public static Platform ofCurrentHost() { - return new Platform(getCurrentOSName(), getCurrentArchName()); - } - - public static final Set KNOWN_ARCHITECTURES = CollectionsUtil.setOf("amd64", "aarch64", "riscv64"); - - public static final Set KNOWN_OS_NAMES = CollectionsUtil.setOf("windows", "linux", "darwin"); - - /** - * Returns the name of the host OS. - */ - private static String getCurrentOSName() { - String value = getSavedProperty("os.name"); - switch (value) { - case "Linux": - value = "linux"; - break; - case "SunOS": - value = "solaris"; - break; - case "Mac OS X": - value = "darwin"; - break; - default: - // Windows names contain the OS version. - if (value.startsWith("Windows")) { - value = "windows"; - } else { - throw new JVMCIError("Unexpected OS name: " + value); - } - } - return value; - } - - /** - * Returns the name of the host architecture. - */ - private static String getCurrentArchName() { - String arch = getSavedProperty("os.arch"); - if (arch.equals("x86_64")) { - arch = "amd64"; - } - return arch; - } -} 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 15658006810c..36c94930b3ed 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 @@ -60,7 +60,6 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -357,7 +356,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), originalProvider.getRegisters(), originalProvider.getSnippetReflection(), originalProvider.getWordTypes(), originalProvider.getStampProvider(), originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getLoopsDataProvider(), originalProvider.getConfig(), - originalProvider.getIdentityHashCodeProvider(), originalProvider.getReplayCompilationSupport()); + originalProvider.getIdentityHashCodeProvider()); HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); @@ -368,7 +367,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod } StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, args, null, original, trackNodeSourcePosition, null); - EncodedSnippets.SymbolicEncodedGraph symbolicGraph = new EncodedSnippets.SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), null, false); + EncodedSnippets.SymbolicEncodedGraph symbolicGraph = new EncodedSnippets.SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), null); StructuredGraph decodedSnippet = EncodedSnippets.decodeSnippetGraph(symbolicGraph, original != null ? original : method, original, originalReplacements, null, StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions(), false); String snippetString = getCanonicalGraphString(snippet, true, false); @@ -425,9 +424,6 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { if (HotSpotReplacementsImpl.snippetsAreEncoded()) { - if (ReplayCompilationSupport.isReplayingLibgraalInJargraal()) { - return; - } throw new GraalError("Snippet encoding has already been done"); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index 64479a1f99b0..9d469c91bae5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -46,14 +46,12 @@ import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkageImpl; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.stubs.InvokeJavaMethodStub; import jdk.graal.compiler.hotspot.stubs.Stub; @@ -266,23 +264,13 @@ public void invokeJavaMethodStub(OptionValues options, public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; @Override - @SuppressWarnings("try") public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallSignature signature) { GraalError.guarantee(foreignCalls != null, "%s", signature); HotSpotForeignCallLinkage callTarget = foreignCalls.get(signature); if (callTarget == null) { throw GraalError.shouldNotReachHere("Missing implementation for runtime call: " + signature); // ExcludeFromJacocoGeneratedReport } - if (callTarget.hasAddress()) { - return callTarget; - } - ReplayCompilationSupport support = getRuntime().getReplayCompilationSupport(); - if (support != null && support.finalizeForeignCallLinkage(signature, callTarget)) { - return callTarget; - } - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(support)) { - callTarget.finalizeAddress(runtime.getHostBackend()); - } + callTarget.finalizeAddress(runtime.getHostBackend()); return callTarget; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index e4d7b54f3afc..d684caf4233e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -96,7 +96,6 @@ import jdk.graal.compiler.core.common.type.ObjectStamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.common.type.TypeReference; -import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotBackend; @@ -117,7 +116,6 @@ import jdk.graal.compiler.hotspot.replacements.ObjectCloneNode; import jdk.graal.compiler.hotspot.replacements.UnsafeCopyMemoryNode; import jdk.graal.compiler.hotspot.replacements.UnsafeSetMemoryNode; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; import jdk.graal.compiler.java.BytecodeParser; import jdk.graal.compiler.lir.SyncPort; @@ -238,7 +236,6 @@ public static class Options { /** * Creates a {@link Plugins} object that should be used when running on HotSpot. */ - @SuppressWarnings("try") public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, @@ -323,10 +320,8 @@ public void run() { // In libgraal, all NodeIntrinsics have already been converted into nodes. NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); invocationPlugins.defer(() -> { - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(graalRuntime.getReplayCompilationSupport())) { - for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) { - factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); - } + for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) { + factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); } }); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 65ea199b8596..74e721af3e9f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -28,7 +28,6 @@ import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_DREM; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_FREM; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_PARTITION; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_SORT; import static jdk.graal.compiler.hotspot.HotSpotBackend.BASE64_DECODE_BLOCK; @@ -121,6 +120,7 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.word.LocationIdentity; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; @@ -379,7 +379,7 @@ private void registerStubCallFunctions(OptionValues options, HotSpotProviders pr } registerForeignCall(INVOKE_STATIC_METHOD_ONE_ARG, invokeJavaMethodAddress, NativeCall); - if (!isUsingEncodedSnippets()) { + if (!LibGraalSupport.inLibGraalRuntime()) { /* * These functions are only used for testing purposes but their registration also * ensures that libgraal has support for InvokeJavaMethodStub built into the image, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 1e6f1dd314b7..7e1f42cb720a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -32,7 +32,6 @@ import java.util.List; import java.util.function.Predicate; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; @@ -95,12 +94,7 @@ record MethodKey(String name, String descriptor) { } } - Predicate predicate = runtime().getIntrinsificationTrustPredicate(compilerConfiguration.getClass()); - ReplayCompilationSupport replayCompilationSupport = graalRuntime.getReplayCompilationSupport(); - if (replayCompilationSupport != null) { - predicate = replayCompilationSupport.decorateIntrinsificationTrustPredicate(predicate); - } - registerIntrinsificationPredicate(predicate); + registerIntrinsificationPredicate(runtime().getIntrinsificationTrustPredicate(compilerConfiguration.getClass())); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java index 874f9c0dbcbb..dff5d5f9c340 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java @@ -28,7 +28,6 @@ import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; @@ -53,11 +52,6 @@ public class HotSpotProviders extends Providers { private final HotSpotRegistersProvider registers; private final GraalHotSpotVMConfig config; - /** - * The interface for recording and replaying compilations or {@code null} if disabled. - */ - private final ReplayCompilationSupport replayCompilationSupport; - public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, @@ -74,14 +68,12 @@ public HotSpotProviders(MetaAccessProvider metaAccess, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider, GraalHotSpotVMConfig config, - IdentityHashCodeProvider identityHashCodeProvider, - ReplayCompilationSupport replayCompilationSupport) { + IdentityHashCodeProvider identityHashCodeProvider) { super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); this.suites = suites; this.registers = registers; this.config = config; - this.replayCompilationSupport = replayCompilationSupport; } @Override @@ -125,7 +117,7 @@ public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); + config, getIdentityHashCodeProvider()); } @Override @@ -134,7 +126,7 @@ public HotSpotProviders copyWith(ConstantFieldProvider substitution) { getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); + config, getIdentityHashCodeProvider()); } @Override @@ -142,24 +134,17 @@ public HotSpotProviders copyWith(Replacements substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), - getLoopsDataProvider(), config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); + getLoopsDataProvider(), config, getIdentityHashCodeProvider()); } public HotSpotProviders copyWith() { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); + config, getIdentityHashCodeProvider()); } public void setSuites(HotSpotSuitesProvider suites) { this.suites = suites; } - - /** - * Returns the interface for recording and replaying compilations or {@code null} if disabled. - */ - public ReplayCompilationSupport getReplayCompilationSupport() { - return replayCompilationSupport; - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index 975975f3087a..14649c1fa292 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -24,7 +24,6 @@ */ package jdk.graal.compiler.hotspot.meta; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import java.lang.reflect.Executable; @@ -32,12 +31,14 @@ import java.util.Objects; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.SnippetObjectConstant; import jdk.graal.compiler.word.WordTypes; + import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; @@ -62,7 +63,7 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { - if (isAfterSnippetEncoding()) { + if (LibGraalSupport.inLibGraalRuntime()) { HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); // This can only be a compiler object when in libgraal. return new SnippetObjectConstant(object); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java deleted file mode 100644 index e419bc98e993..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; - -/** - * A holder and factory for compiler-interface proxies during a recorded/replayed compilation. - */ -public interface CompilationProxies { - /** - * Proxifies an instance of a registered compiler-interface class. In general, the returned - * proxy either records or replays the results of method invocations based on the argument - * values. The registered classes are declared by {@link CompilerInterfaceDeclarations} - * ({@link #getDeclarations()}). The behavior of the proxy is also defined by - * {@link CompilerInterfaceDeclarations}. - * - * @param input the instance for which a proxy should be created - * @return the proxy object - */ - CompilationProxy proxify(Object input); - - /** - * Gets the compiler interface declarations. This class defines for which classes proxies should - * be created and the method invocation behavior of these proxies. - * - * @return compiler interface declarations - */ - CompilerInterfaceDeclarations getDeclarations(); - - /** - * Enters the context of a snippet compilation. - * - * @return a debug closeable object representing the snippet context - */ - DebugCloseable enterSnippetContext(); - - /** - * Gets the target platform (the host platform during recording and the compilation target - * during replay). - */ - Platform targetPlatform(); - - /** - * Temporarily sets a debug context. - * - * @param debugContext the debug context to enter - * @return a debug closeable object representing the debug context - */ - DebugCloseable withDebugContext(DebugContext debugContext); -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java deleted file mode 100644 index 2a1f69d04b86..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java +++ /dev/null @@ -1,298 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.lang.reflect.Array; -import java.util.Map; -import java.util.WeakHashMap; -import java.util.function.Function; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Equivalence; - -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.code.BytecodePosition; -import jdk.vm.ci.code.DebugInfo; -import jdk.vm.ci.code.StackLockValue; -import jdk.vm.ci.code.VirtualObject; -import jdk.vm.ci.code.site.Call; -import jdk.vm.ci.code.site.ConstantReference; -import jdk.vm.ci.code.site.DataPatch; -import jdk.vm.ci.code.site.ImplicitExceptionDispatch; -import jdk.vm.ci.code.site.Infopoint; -import jdk.vm.ci.code.site.Reference; -import jdk.vm.ci.code.site.Site; -import jdk.vm.ci.hotspot.HotSpotCompiledNmethod; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotSpeculationLog; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.EncodedSpeculationReason; -import jdk.vm.ci.meta.InvokeTarget; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaMethodProfile; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.JavaValue; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; -import jdk.vm.ci.meta.UnresolvedJavaField; -import jdk.vm.ci.meta.UnresolvedJavaMethod; -import jdk.vm.ci.meta.VMConstant; - -/** - * Recursively proxifies or unproxifies instances of registered classes in composite objects. - *

- * {@link CompilerInterfaceDeclarations} declares for which JVMCI objects proxies should be created. - * When these objects are stored inside composite objects (e.g., inside arrays or - * {@link DebugInfo}), this class can create deep copies of such composite objects, replacing the - * registered instances with proxies. This mapping is performed by the {@link #proxifyRecursive} - * method. - *

- * This class can also perform the reverse mapping, i.e., create a deep copy of an object and - * replace the proxy with a local JVMCI object (by calling {@link CompilationProxy#unproxify()} on - * the proxies). This is performed by the {@link #unproxifyRecursive}. - */ -public class CompilationProxyMapper { - /** - * Declares the registered classes, indicating which objects should be proxified. - */ - private final CompilerInterfaceDeclarations declarations; - - /** - * Function that proxifies instances of registered classes. - */ - private final Function proxify; - - /** - * Maps instances of proxified arrays to the component types of the original arrays. - */ - private final Map> originalComponentType; - - /** - * Constructs a new proxy mapper. - * - * @param declarations the compiler interface declarations - * @param proxify the function used to proxify a single registered instance - */ - public CompilationProxyMapper(CompilerInterfaceDeclarations declarations, Function proxify) { - this.declarations = declarations; - this.proxify = proxify; - this.originalComponentType = new WeakHashMap<>(); - } - - /** - * Proxifies the given object, i.e., creates proxies for the instances of registered types and - * replaces them with proxies. - * - * @param input the input object - * @return an object where the registered instances are replaced with proxies - */ - public Object proxifyRecursive(Object input) { - return proxifyInternal(input, null); - } - - /** - * Unproxifies the given object, i.e., removes proxies from the instances of registered types. - * - * @param input the input object - * @return an object where the proxies are replaced with the original objects/local mirrors - */ - public Object unproxifyRecursive(Object input) { - return unproxifyInternal(input, null); - } - - @FunctionalInterface - private interface Mapper { - Object apply(Object input, EconomicMap cache); - } - - private Object proxifyInternal(Object input, EconomicMap cache) { - if (input instanceof Object[] array) { - Class originalClazz = input.getClass().componentType(); - Class adjustedClazz = declarations.findRegisteredSupertype(originalClazz); - if (adjustedClazz == null) { - adjustedClazz = originalClazz; - } - Object[] result = (Object[]) Array.newInstance(adjustedClazz, array.length); - for (int i = 0; i < array.length; i++) { - result[i] = proxifyInternal(array[i], null); - } - if (!adjustedClazz.equals(originalClazz)) { - originalComponentType.put(result, originalClazz); - } - return result; - } else if (declarations.isRegisteredClassInstance(input)) { - return proxify.apply(input); - } else { - return map(input, this::proxifyInternal, cache); - } - } - - private Object unproxifyInternal(Object input, EconomicMap cache) { - if (input instanceof Object[] array) { - Class clazz = originalComponentType.get(input); - if (clazz == null) { - clazz = input.getClass().componentType(); - } - Object[] result = (Object[]) Array.newInstance(clazz, array.length); - for (int i = 0; i < array.length; i++) { - result[i] = unproxifyInternal(array[i], cache); - } - return result; - } else if (input instanceof CompilationProxy compilationProxy) { - return compilationProxy.unproxify(); - } else { - return map(input, this::unproxifyInternal, cache); - } - } - - private static Object map(Object input, Mapper mapper, EconomicMap cache) { - switch (input) { - case SpecialResultMarker.ExceptionThrownMarker marker -> { - return new SpecialResultMarker.ExceptionThrownMarker((Throwable) mapper.apply(marker.getThrown(), cache)); - } - case HotSpotCompiledNmethod nmethod -> { - return new HotSpotCompiledNmethod(nmethod.getName(), nmethod.getTargetCode(), nmethod.getTargetCodeSize(), - (Site[]) mapper.apply(nmethod.getSites(), cache), (Assumptions.Assumption[]) mapper.apply(nmethod.getAssumptions(), cache), - (ResolvedJavaMethod[]) mapper.apply(nmethod.getMethods(), cache), nmethod.getComments(), - nmethod.getDataSection(), nmethod.getDataSectionAlignment(), (DataPatch[]) mapper.apply(nmethod.getDataSectionPatches(), cache), nmethod.isImmutablePIC(), - nmethod.getTotalFrameSize(), nmethod.getDeoptRescueSlot(), (HotSpotResolvedJavaMethod) mapper.apply(nmethod.getMethod(), cache), nmethod.getEntryBCI(), - nmethod.getId(), nmethod.getCompileState(), nmethod.hasUnsafeAccess()); - } - case Call call -> { - return new Call((InvokeTarget) mapper.apply(call.target, cache), call.pcOffset, call.size, call.direct, (DebugInfo) mapper.apply(call.debugInfo, cache)); - } - case ImplicitExceptionDispatch dispatch -> { - return new ImplicitExceptionDispatch(dispatch.pcOffset, dispatch.dispatchOffset, (DebugInfo) mapper.apply(dispatch.debugInfo, cache)); - } - case Infopoint infopoint -> { - return new Infopoint(infopoint.pcOffset, (DebugInfo) mapper.apply(infopoint.debugInfo, cache), infopoint.reason); - } - case DataPatch dataPatch -> { - return new DataPatch(dataPatch.pcOffset, (Reference) mapper.apply(dataPatch.reference, cache), mapper.apply(dataPatch.note, cache)); - } - case ConstantReference constantReference -> { - return new ConstantReference((VMConstant) mapper.apply(constantReference.getConstant(), cache)); - } - case HotSpotSpeculationLog.HotSpotSpeculation speculation -> { - return new HotSpotSpeculationLog.HotSpotSpeculation((SpeculationLog.SpeculationReason) mapper.apply(speculation.getReason(), cache), - (JavaConstant) mapper.apply(speculation.getEncoding(), cache), speculation.getReasonEncoding()); - } - case SpeculationLog.Speculation speculation -> { - return new SpeculationLog.Speculation((SpeculationLog.SpeculationReason) mapper.apply(speculation.getReason(), cache)); - } - case EncodedSpeculationReason speculationReason -> { - return new EncodedSpeculationReason(speculationReason.getGroupId(), speculationReason.getGroupName(), (Object[]) mapper.apply(speculationReason.getContext(), cache)); - } - case BytecodeFrame bytecodeFrame -> { - return new BytecodeFrame((BytecodeFrame) mapper.apply(bytecodeFrame.caller(), cache), (ResolvedJavaMethod) mapper.apply(bytecodeFrame.getMethod(), cache), - bytecodeFrame.getBCI(), bytecodeFrame.rethrowException, bytecodeFrame.duringCall, (JavaValue[]) mapper.apply(bytecodeFrame.values, cache), - bytecodeFrame.getSlotKinds(), bytecodeFrame.numLocals, bytecodeFrame.numStack, bytecodeFrame.numLocks); - } - case BytecodePosition bytecodePosition -> { - return new BytecodePosition((BytecodePosition) mapper.apply(bytecodePosition.getCaller(), cache), (ResolvedJavaMethod) mapper.apply(bytecodePosition.getMethod(), cache), - bytecodePosition.getBCI()); - } - case StackLockValue value -> { - return new StackLockValue((JavaValue) mapper.apply(value.getOwner(), cache), value.getSlot(), value.isEliminated()); - } - case JavaTypeProfile typeProfile -> { - return new JavaTypeProfile(typeProfile.getNullSeen(), typeProfile.getNotRecordedProbability(), (JavaTypeProfile.ProfiledType[]) mapper.apply(typeProfile.getTypes(), cache)); - } - case JavaTypeProfile.ProfiledType profiledType -> { - return new JavaTypeProfile.ProfiledType((ResolvedJavaType) mapper.apply(profiledType.getType(), cache), profiledType.getProbability()); - } - case JavaMethodProfile methodProfile -> { - return new JavaMethodProfile(methodProfile.getNotRecordedProbability(), (JavaMethodProfile.ProfiledMethod[]) mapper.apply(methodProfile.getMethods(), cache)); - } - case JavaMethodProfile.ProfiledMethod profiledMethod -> { - return new JavaMethodProfile.ProfiledMethod((ResolvedJavaMethod) mapper.apply(profiledMethod.getMethod(), cache), profiledMethod.getProbability()); - } - case DebugInfo debugInfo -> { - DebugInfo newDebugInfo = new DebugInfo((BytecodePosition) mapper.apply(debugInfo.frame(), cache), (VirtualObject[]) mapper.apply(debugInfo.getVirtualObjectMapping(), cache)); - newDebugInfo.setCalleeSaveInfo(debugInfo.getCalleeSaveInfo()); - newDebugInfo.setReferenceMap(debugInfo.getReferenceMap()); - return newDebugInfo; - } - case VirtualObject virtualObject -> { - VirtualObject newVirtualObject = VirtualObject.get((ResolvedJavaType) mapper.apply(virtualObject.getType(), cache), virtualObject.getId(), virtualObject.isAutoBox()); - EconomicMap selectedCache = cache; - if (selectedCache == null) { - selectedCache = EconomicMap.create(Equivalence.IDENTITY); - } else { - Object found = selectedCache.get(virtualObject); - if (found != null) { - return found; - } - } - selectedCache.put(virtualObject, newVirtualObject); - if (virtualObject.getValues() != null) { - newVirtualObject.setValues((JavaValue[]) mapper.apply(virtualObject.getValues(), selectedCache), virtualObject.getSlotKinds()); - } - return newVirtualObject; - } - case Assumptions.AssumptionResult result -> { - Assumptions assumptions = new Assumptions(); - result.recordTo(assumptions); - return new Assumptions.AssumptionResult<>(mapper.apply(result.getResult(), cache), (Assumptions.Assumption[]) mapper.apply(assumptions.toArray(), cache)); - } - case Assumptions.NoFinalizableSubclass assumption -> { - return new Assumptions.NoFinalizableSubclass((ResolvedJavaType) mapper.apply(assumption.receiverType, cache)); - } - case Assumptions.ConcreteSubtype assumption -> { - return new Assumptions.ConcreteSubtype((ResolvedJavaType) mapper.apply(assumption.context, cache), (ResolvedJavaType) mapper.apply(assumption.subtype, cache)); - } - case Assumptions.LeafType assumption -> { - return new Assumptions.LeafType((ResolvedJavaType) mapper.apply(assumption.context, cache)); - } - case Assumptions.ConcreteMethod assumption -> { - return new Assumptions.ConcreteMethod((ResolvedJavaMethod) mapper.apply(assumption.method, cache), (ResolvedJavaType) mapper.apply(assumption.context, cache), - (ResolvedJavaMethod) mapper.apply(assumption.impl, cache)); - } - case Assumptions.CallSiteTargetValue assumption -> { - return new Assumptions.CallSiteTargetValue((JavaConstant) mapper.apply(assumption.callSite, cache), (JavaConstant) mapper.apply(assumption.methodHandle, cache)); - } - case jdk.vm.ci.meta.ExceptionHandler exceptionHandler -> { - return new jdk.vm.ci.meta.ExceptionHandler(exceptionHandler.getStartBCI(), exceptionHandler.getEndBCI(), - exceptionHandler.getHandlerBCI(), exceptionHandler.catchTypeCPI(), (JavaType) mapper.apply(exceptionHandler.getCatchType(), cache)); - } - case UnresolvedJavaMethod method -> { - return new UnresolvedJavaMethod(method.getName(), (Signature) mapper.apply(method.getSignature(), cache), (JavaType) mapper.apply(method.getDeclaringClass(), cache)); - } - case UnresolvedJavaField field -> { - return new UnresolvedJavaField((JavaType) mapper.apply(field.getDeclaringClass(), cache), field.getName(), (JavaType) mapper.apply(field.getType(), cache)); - } - case DelayedDeserializationObject delayedDeserialization -> { - return mapper.apply(delayedDeserialization.deserialize(), cache); - } - case null, default -> { - return input; - } - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java deleted file mode 100644 index 1da729880499..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ /dev/null @@ -1,949 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import static java.util.FormattableFlags.ALTERNATE; -import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEDYNAMIC; -import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEINTERFACE; -import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; -import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; -import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; -import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; - -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Formattable; -import java.util.Formatter; -import java.util.List; -import java.util.function.Predicate; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Equivalence; -import org.graalvm.collections.UnmodifiableEconomicMap; - -import jdk.graal.compiler.bytecode.BytecodeStream; -import jdk.graal.compiler.core.common.CompilerProfiler; -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.graph.NodeClass; -import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.ConstantPoolProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotCodeCacheProviderProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantReflectionProviderProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotMetaspaceConstantProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotObjectConstantProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotProfilingInfoProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaFieldProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaMethodProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaTypeProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedObjectTypeProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.MetaAccessProviderProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.ProfilingInfoProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; -import jdk.graal.compiler.java.LambdaUtils; -import jdk.graal.compiler.replacements.SnippetCounter; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotProfilingInfo; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.hotspot.HotSpotResolvedPrimitiveType; -import jdk.vm.ci.hotspot.HotSpotSignature; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.MethodHandleAccessProvider; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; - -/** - * Defines how the VM's interface to the compiler should be recorded and replayed. - * - *

- * Recording and replaying is implemented by instrumenting JVMCI. For relevant JVMCI objects and - * service providers ({@link HotSpotResolvedJavaMethod}, {@link MetaAccessProvider}...), we create - * proxy implementations ({@link HotSpotResolvedJavaMethodProxy}, {@link MetaAccessProvider}...). - * These proxies do not implement any specific behavior; {@link CompilerInterfaceDeclarations} - * declares this behavior. {@link RecordingCompilationProxies} and {@link ReplayCompilationProxies} - * then provide proxy instance with the declared behavior during recording and replay, respectively. - * - *

- * Registered Classes. This class defines for which JVMCI object we must create proxies - * during recording and replay. Whether an object is an instance of such a class can be queried - * using {@link #isRegisteredClassInstance} and the registration can be obtained with - * {@link #findRegistrationForInstance}. The {@link Registration} describes the behavior of the - * individual methods during replay and recording, how local mirrors are located, and other - * information. - * - *

- * Method Registrations. A {@link MethodRegistration} describes the behavior of a proxy - * method invocation during recording and replay and also provides the arguments of method calls - * whose results should always be recorded even if the compiler does not invoke the method during - * the recorded compilation. The results of these operations may be needed during replay, e.g., to - * produce some diagnostic output. A default registration - * ({@link MethodRegistrationBuilder#createDefault}) is used if this class does not explicitly - * override it. {@link MethodStrategy} defines the behavior of a method during recording and replay. - * - *

- * Recording. During recording, the proxies ({@link RecordingCompilationProxies}) either save - * the result of a method invocation or not. The result of a method invocation (an operation) is - * either a return value or an exception. The result is saved iff the strategy is - * {@link MethodStrategy#RecordReplay}. The recording proxies also ensure the result of an operation - * is stable during a single compilation by caching the result when the operation is performed for - * the first time. Subsequent proxy method invocations reuse the recorded result. - *

- * At the end of a compilation, we also perform and record additional calls whose results could be - * needed during replay. These calls are declared in this class using {@link MethodCallToRecord} - * instances or a {@link MethodCallsToRecordProvider}. - * - *

- * Replay. During a replayed compilation, there are multiple ways how to obtain a result for - * an operation invoked on a proxy object. The options are the following: - *

    - *
  • Look up a result in the recorded JSON file using the values of the argument and the - * receiver.
  • - *
  • Invoke the same method on a local mirror (may also replace the arguments with local - * mirrors).
  • - *
  • Return a predefined default value (e.g., {@code null}, {@code 0}, {@code false}) or a default - * value computed by an instance of {@link OperationResultSupplier}.
  • - *
  • Delegate to a fallback handler, which is also an instance of - * {@link OperationResultSupplier}.
  • - *
  • Ad-hoc special handling (for {@link Object#equals}, {@link Object#hashCode}).
  • - *
- * In many conditions, only some of these options are available (there may be no recorded result, no - * local mirror, no fallback handler...). A {@link MethodStrategy} defines which of these options - * should be tried in what order and also which conditions are considered errors. - */ -public final class CompilerInterfaceDeclarations { - /** - * The strategy for replaying/recording a method. These strategies are implemented in - * {@link RecordingCompilationProxies} and {@link ReplayCompilationProxies} for recording and - * replay, respectively. - */ - public enum MethodStrategy { - /** - * A strategy that records the method's results and replays them. This is the default - * strategy for most methods. - *

- * During recording, the strategy records the result of a method the first time it is - * invoked. If the compiler invokes the method with the same arguments again, the recorded - * result is returned instead of re-executing the method. This ensures a set of arguments - * can be unambiguously mapped to a result. - *

- * During replay, the strategy looks up and returns the result from the recorded JSON file. - *

    - *
  • If no appropriate recorded result is found, falls back to invoking the same method on - * local mirrors (replacing both the receiver and arguments with local mirrors).
  • - *
  • If a local mirror cannot be identified, invokes the fallback handler.
  • - *
  • If there is no fallback handler, returns the default value. This is considered an - * error if {@link ReplayCompilationProxies.Options#ReplayDivergenceIsFailure} is set.
  • - *
- */ - RecordReplay, - - /** - * A strategy that does not record the method's results and invokes the local mirror instead - * (without unproxifying the arguments). - *

- * During recording, the results of method calls are not recorded since they will not be - * needed during replay. - *

- * During replay, the strategy invokes the same method on the local mirror without - * unproxifying the arguments. Invokes the fallback handler if there is no local mirror. - */ - Passthrough, - - /** - * A strategy that does not record the method's results and returns a pre-defined or - * computed value during replay. - *

- * During recording, the results of method calls are not recorded since they will not be - * needed during replay. - *

- * During replay, the strategy returns the value computed by - * {@link Registration#findDefaultValue}. - */ - DefaultValue, - - /** - * A strategy that does not record the method's results and is handled specially during - * replay. - */ - Special - } - - /** - * Supplies the result of an operation during replay. - */ - @FunctionalInterface - public interface OperationResultSupplier { - /** - * Computes the result of the invoked method. - * - * @param proxy the proxy receiver - * @param method the invoked method - * @param args the arguments to the method - * @param singletonObjects a map of provider classes to instances - * @return the result of the operation - */ - Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects); - } - - /** - * Finds the local mirror of a proxy object during replay. - */ - @FunctionalInterface - public interface LocalMirrorLocator { - /** - * Finds and returns the local mirror of the given proxy object or {@code null} if not - * found. - * - * @param proxy the proxy object - * @param singletonObjects a map of provider classes to instances - * @return the local mirror or {@code null} - */ - Object findLocalMirror(Object proxy, EconomicMap, Object> singletonObjects); - } - - /** - * Provides a list of method calls that should be recorded for a given receiver object. - */ - @FunctionalInterface - public interface MethodCallsToRecordProvider { - /** - * Returns a list of method calls that should be recorded in the serialized compilation unit - * for the given receiver object. Every such call should be performed and recorded at the - * end of the compilation unless it was already recorded during the compilation. - * - * @param receiver the receiver object - * @return a list of method calls that should be recorded - */ - List getMethodCallsToRecord(Object receiver); - } - - /** - * Describes the recording and replay behavior for a method of one of the registered classes. - * - * @param methodStrategy the strategy to record/replay the method's results - * @param defaultValueSupplier a supplier for a default result value or {@code null} - * @param defaultValue the default result value - * @param callsToRecordArguments a list of argument arrays for which the method results should - * be recorded in the serialized compilation unit - * @param fallbackInvocationHandler a handler to use as a fallback when there is no recorded - * result or {@code null} - * @param invokableMethod a lambda to invoke the method (needed if there are calls to record) or - * {@code null} - */ - public record MethodRegistration(MethodStrategy methodStrategy, OperationResultSupplier defaultValueSupplier, Object defaultValue, - List callsToRecordArguments, OperationResultSupplier fallbackInvocationHandler, CompilationProxy.InvokableMethod invokableMethod) { - public MethodRegistration { - if (!callsToRecordArguments.isEmpty()) { - GraalError.guarantee(invokableMethod != null, "invokable method needed because there are calls that must be recorded"); - } - } - } - - /** - * Describes a method call that should be recorded in the serialized compilation unit. - * - * @param receiver the receiver object of the call - * @param symbolicMethod the method to invoke - * @param invokableMethod a lambda to invoke the method - * @param args the arguments to use for the method call (can be {@code null} for methods without - * parameters) - */ - public record MethodCallToRecord(Object receiver, CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object[] args) { - public MethodCallToRecord { - int argsLength = (args == null) ? 0 : args.length; - GraalError.guarantee(argsLength == symbolicMethod.paramCount(), "the provided number of arguments does not match the method signature"); - } - } - - /** - * Describes the recording and replay behavior of a compiler-interface class. - * - * @param clazz the class - * @param singleton {@code true} iff the class should be treated as a singleton (e.g., a - * provider) - * @param mirrorLocator a method that can find the local mirror of a proxy during replay or - * {@code null} - * @param methods the recording/replay behavior the methods - only needed for non-default - * behavior - * @param extraInterfaces additional interfaces the proxy should implement - * @param methodCallsToRecordProvider provides the methods calls that should be recorded in the - * serialized compilation unit - */ - public record Registration(Class clazz, boolean singleton, LocalMirrorLocator mirrorLocator, - UnmodifiableEconomicMap methods, Class[] extraInterfaces, - MethodCallsToRecordProvider methodCallsToRecordProvider) { - /** - * Finds the recording/replay strategy for a method of this class. - * - * @param method the method - * @return the strategy - */ - public MethodStrategy findStrategy(CompilationProxy.SymbolicMethod method) { - MethodRegistration found = methods.get(method); - if (found == null) { - return MethodRegistrationBuilder.defaultStrategy(method); - } else { - return found.methodStrategy; - } - } - - /** - * Finds the default value to return for a given call. - * - * @param proxy the proxy receiver object - * @param method the invoked method - * @param args the arguments passed to the invocation - * @param singletonObjects a map of provider classes to instances - * @return the default value - */ - public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { - MethodRegistration found = methods.get(method); - if (found == null) { - return null; - } else if (found.defaultValueSupplier != null) { - return found.defaultValueSupplier.apply(proxy, method, args, singletonObjects); - } else { - return found.defaultValue; - } - } - - /** - * Finds a fallbacks handler for an invoked method. - * - * @param method the invoked method - * @return a handler or {@code null} - */ - public OperationResultSupplier findFallbackHandler(CompilationProxy.SymbolicMethod method) { - MethodRegistration found = methods.get(method); - if (found == null) { - return null; - } else { - return found.fallbackInvocationHandler; - } - } - - /** - * Gets a list of method calls that should be recorded in the serialized compilation unit. - * - * @param receiver the receiver object - * @return a list of method calls that should be recorded - */ - public List getMethodCallsToRecord(Object receiver) { - List calls = new ArrayList<>(); - var cursor = methods.getEntries(); - while (cursor.advance()) { - for (Object[] arguments : cursor.getValue().callsToRecordArguments()) { - calls.add(new MethodCallToRecord(receiver, cursor.getKey(), cursor.getValue().invokableMethod(), arguments)); - } - } - if (methodCallsToRecordProvider != null) { - calls.addAll(methodCallsToRecordProvider.getMethodCallsToRecord(receiver)); - } - return calls; - } - - /** - * Finds an invokable method for the given symbolic method. - * - * @param method the symbolic method - * @return the invokable method or {@code null} if not found - */ - public CompilationProxy.InvokableMethod findInvokableMethod(CompilationProxy.SymbolicMethod method) { - MethodRegistration found = methods.get(method); - if (found == null) { - return null; - } - return found.invokableMethod; - } - } - - private static final class MethodRegistrationBuilder { - private MethodStrategy methodStrategy; - private OperationResultSupplier defaultValueSupplier; - private Object defaultValue; - private final List callsToRecordArguments; - private OperationResultSupplier fallbackInvocationHandler; - private CompilationProxy.InvokableMethod invokableMethod; - - private MethodRegistrationBuilder(MethodStrategy methodStrategy, CompilationProxy.InvokableMethod invokableMethod, List callsToRecordArguments) { - this.methodStrategy = methodStrategy; - this.invokableMethod = invokableMethod; - this.callsToRecordArguments = callsToRecordArguments; - } - - public static MethodRegistrationBuilder createDefault(CompilationProxy.SymbolicMethod method) { - CompilationProxy.InvokableMethod invokableMethod = null; - List callsToRecordArguments = new ArrayList<>(); - if (CompilationProxyBase.toStringMethod.equals(method)) { - invokableMethod = (receiver, args) -> receiver.toString(); - callsToRecordArguments.add(null); - } - return new MethodRegistrationBuilder(defaultStrategy(method), invokableMethod, callsToRecordArguments); - } - - public static MethodStrategy defaultStrategy(CompilationProxy.SymbolicMethod method) { - if (CompilationProxyBase.hashCodeMethod.equals(method) || CompilationProxyBase.equalsMethod.equals(method) || CompilationProxyBase.toStringMethod.equals(method)) { - return MethodStrategy.Special; - } else { - return MethodStrategy.RecordReplay; - } - } - - private MethodRegistration build() { - return new MethodRegistration(methodStrategy, defaultValueSupplier, defaultValue, Collections.unmodifiableList(callsToRecordArguments), - fallbackInvocationHandler, invokableMethod); - } - } - - private static class RegistrationBuilder { - private final Class clazz; - - private boolean singleton; - - private LocalMirrorLocator mirrorLocator; - - private final EconomicMap methods; - - private final Class[] extraInterfaces; - - private MethodCallsToRecordProvider methodCallsToRecordProvider; - - RegistrationBuilder(Class clazz, Class... extraInterfaces) { - this.clazz = clazz; - this.methods = EconomicMap.create(); - this.extraInterfaces = extraInterfaces; - this.methods.put(CompilationProxyBase.toStringMethod, MethodRegistrationBuilder.createDefault(CompilationProxyBase.toStringMethod)); - } - - public RegistrationBuilder setLocalMirrorLocator(LocalMirrorLocator newLocator) { - mirrorLocator = newLocator; - return this; - } - - public RegistrationBuilder setSingleton(boolean newSingleton) { - singleton = newSingleton; - return this; - } - - private MethodRegistrationBuilder findRegistrationBuilder(CompilationProxy.SymbolicMethod symbolicMethod) { - MethodRegistrationBuilder builder = methods.get(symbolicMethod); - if (builder == null) { - builder = MethodRegistrationBuilder.createDefault(symbolicMethod); - methods.put(symbolicMethod, builder); - } - return builder; - } - - public RegistrationBuilder setStrategy(CompilationProxy.SymbolicMethod method, MethodStrategy strategy) { - findRegistrationBuilder(method).methodStrategy = strategy; - return this; - } - - public RegistrationBuilder setFallbackInvocationHandler(CompilationProxy.SymbolicMethod method, OperationResultSupplier handler) { - findRegistrationBuilder(method).fallbackInvocationHandler = handler; - return this; - } - - public RegistrationBuilder setDefaultValueStrategy(CompilationProxy.SymbolicMethod symbolicMethod, Object defaultValue) { - MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); - builder.methodStrategy = MethodStrategy.DefaultValue; - builder.defaultValue = defaultValue; - return this; - } - - public RegistrationBuilder setDefaultValue(CompilationProxy.SymbolicMethod method, Object defaultValue) { - findRegistrationBuilder(method).defaultValue = defaultValue; - return this; - } - - public RegistrationBuilder setDefaultValueSupplier(CompilationProxy.SymbolicMethod symbolicMethod, OperationResultSupplier supplier) { - MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); - builder.defaultValue = null; - builder.defaultValueSupplier = supplier; - return this; - } - - public RegistrationBuilder ensureRecorded(CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object... arguments) { - MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); - builder.callsToRecordArguments.add(arguments); - builder.invokableMethod = invokableMethod; - return this; - } - - public RegistrationBuilder provideMethodCallsToRecord(MethodCallsToRecordProvider newProvider) { - methodCallsToRecordProvider = newProvider; - return this; - } - - private void register(CompilerInterfaceDeclarations declarations) { - EconomicMap registrations = EconomicMap.create(); - var cursor = methods.getEntries(); - while (cursor.advance()) { - registrations.put(cursor.getKey(), cursor.getValue().build()); - } - declarations.addRegistration(new Registration(clazz, singleton, mirrorLocator, registrations, extraInterfaces, methodCallsToRecordProvider)); - } - } - - /** - * The list of the registered compiler-interface classes whose methods are recorded/replayed. - */ - private final List> classes; - - /** - * Maps the registered classes to the appropriate registrations. - */ - private final EconomicMap, Registration> registrations; - - private final EconomicMap, Class> supertypeCache; - - private static final Class NOT_REGISTERED = Class.class; - - private CompilerInterfaceDeclarations() { - classes = new ArrayList<>(); - registrations = EconomicMap.create(); - supertypeCache = EconomicMap.create(Equivalence.IDENTITY); - } - - /** - * Gets an iterable of the registered compiler-interface classes. - */ - public Iterable getRegistrations() { - return registrations.getValues(); - } - - private void addRegistration(Registration registration) { - classes.add(registration.clazz); - registrations.put(registration.clazz, registration); - } - - /** - * Finds and returns the registered supertype of the given type if it has a registered - * supertype. - * - * @param type the given type - * @return a registered (super)type or {@code null} - */ - public Class findRegisteredSupertype(Class type) { - Class cached = supertypeCache.get(type); - if (cached != null) { - if (cached == NOT_REGISTERED) { - return null; - } - return cached; - } - for (Class declared : classes) { - if (declared.isAssignableFrom(type)) { - supertypeCache.put(type, declared); - return declared; - } - } - supertypeCache.put(type, NOT_REGISTERED); - return null; - } - - /** - * Returns {@code true} if the given object is an instance of a registered class. - * - * @param object the object - * @return {@code true} if the given object is an instance of a registered class - */ - public boolean isRegisteredClassInstance(Object object) { - if (object == null) { - return false; - } - return findRegisteredSupertype(object.getClass()) != null; - } - - /** - * Finds the registration for the type of the given object if it is an instance of a registered - * type. - * - * @param object the object - * @return the registration or {@code null} - */ - public Registration findRegistrationForInstance(Object object) { - if (object == null) { - return null; - } - return registrations.get(findRegisteredSupertype(object.getClass())); - } - - /** - * Creates and returns a description of how the compiler interface should be recorded and - * replayed. - * - * @implNote The {@link MethodRegistrationBuilder#defaultStrategy default strategy} is - * sufficient for most methods, and it does not require an explicit registration. - */ - public static CompilerInterfaceDeclarations build() { - // @formatter:off - CompilerInterfaceDeclarations declarations = new CompilerInterfaceDeclarations(); - new RegistrationBuilder<>(HotSpotVMConfigAccess.class).setSingleton(true) - .register(declarations); - new RegistrationBuilder<>(MetaAccessProvider.class).setSingleton(true) - .setStrategy(MetaAccessProviderProxy.encodeDeoptActionAndReasonMethod, MethodStrategy.Passthrough) - .setStrategy(MetaAccessProviderProxy.decodeDeoptReasonMethod, MethodStrategy.Passthrough) - .setStrategy(MetaAccessProviderProxy.decodeDeoptActionMethod, MethodStrategy.Passthrough) - .setStrategy(MetaAccessProviderProxy.decodeDebugIdMethod, MethodStrategy.Passthrough) - .setStrategy(MetaAccessProviderProxy.encodeSpeculationMethod, MethodStrategy.Passthrough) - .setDefaultValue(MetaAccessProviderProxy.decodeSpeculationMethod, SpeculationLog.NO_SPECULATION) - .setStrategy(MetaAccessProviderProxy.getArrayBaseOffsetMethod, MethodStrategy.Passthrough) - .setStrategy(MetaAccessProviderProxy.getArrayIndexScaleMethod, MethodStrategy.Passthrough) - .provideMethodCallsToRecord((input) -> { - List result = new ArrayList<>(); - if (!LibGraalSupport.inLibGraalRuntime()) { - // Record the calls needed for HotSpotGraalConstantFieldProvider in jargraal. - // Not needed in libgraal because the lookups are handled by HotSpotSnippetMetaAccessProvider. - for (Class clazz : List.of(GraalHotSpotVMConfig.class, SnippetCounter.class, NodeClass.class)) { - result.add(new MethodCallToRecord(input, MetaAccessProviderProxy.lookupJavaTypeClassMethod, MetaAccessProviderProxy.lookupJavaTypeClassInvokable, new Object[]{clazz})); - } - } - return result; - }) - .setFallbackInvocationHandler(MetaAccessProviderProxy.lookupJavaTypeClassMethod, (proxy, method, args, singletonObjects) -> { - // Needed for Word types when replaying libgraal compilations on jargraal. - Class clazz = (Class) args[0]; - MetaAccessProvider localMetaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType localMirror = localMetaAccess.lookupJavaType(clazz); - if (localMirror == null) { - throw new IllegalArgumentException(); - } - return localMirror; - }) - .register(declarations); - new RegistrationBuilder<>(HotSpotConstantReflectionProvider.class).setSingleton(true) - .ensureRecorded(HotSpotConstantReflectionProviderProxy.forObjectMethod, HotSpotConstantReflectionProviderProxy.forObjectInvokable,(Object) null) - .setStrategy(HotSpotConstantReflectionProviderProxy.asJavaClassMethod, MethodStrategy.Passthrough) - .setStrategy(HotSpotConstantReflectionProviderProxy.asObjectHubMethod, MethodStrategy.Passthrough) - .setDefaultValueSupplier(HotSpotConstantReflectionProviderProxy.asJavaTypeMethod, - (proxy, method, args, singletonObjects) -> { - if (args[0] instanceof HotSpotMetaspaceConstant constant) { - return constant.asResolvedJavaType(); - } - return null; - }) - .register(declarations); - new RegistrationBuilder<>(MethodHandleAccessProvider.class) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); - return provider.getMethodHandleAccess(); - }) - .register(declarations); - new RegistrationBuilder<>(HotSpotMemoryAccessProvider.class) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); - return provider.getMemoryAccessProvider(); - }) - .register(declarations); - new RegistrationBuilder<>(HotSpotCodeCacheProvider.class).setSingleton(true) - .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.installCodeMethod, null) - // Interpreter frame size is not tracked since the arguments are not serializable. - .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.interpreterFrameSizeMethod, 0) - .register(declarations); - new RegistrationBuilder<>(CompilerProfiler.class).setSingleton(true) - .setStrategy(CompilerProfilerProxy.getTicksMethod, MethodStrategy.Passthrough) - .setStrategy(CompilerProfilerProxy.notifyCompilerPhaseEventMethod, MethodStrategy.Passthrough) - .setDefaultValueStrategy(CompilerProfilerProxy.notifyCompilerInliningEventMethod, null) - .register(declarations); - new RegistrationBuilder<>(HotSpotResolvedObjectType.class, HotSpotResolvedJavaType.class) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getNameMethod, HotSpotResolvedObjectTypeProxy.getNameInvokable) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getModifiersMethod, HotSpotResolvedObjectTypeProxy.getModifiersInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; - Class clazz; - try { - clazz = Class.forName(type.toClassName()); - } catch (ClassNotFoundException e) { - return null; - } - if (Proxy.class.isAssignableFrom(clazz)) { - return null; - } - return metaAccess.lookupJavaType(clazz); - }) - // getComponentType() is used by the default implementation of isArray(). - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getInstanceFieldsMethod, - HotSpotResolvedObjectTypeProxy.getInstanceFieldsInvokable, new Object[]{true}) // For snippet decoding - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getStaticFieldsMethod, HotSpotResolvedObjectTypeProxy.getStaticFieldsInvokable) // For snippet decoding - .setDefaultValueStrategy(HotSpotResolvedObjectTypeProxy.getJavaKindMethod, JavaKind.Object) - .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, CompilerInterfaceDeclarations::javaLangObjectSupplier) - .setDefaultValue(HotSpotResolvedObjectTypeProxy.isAssignableFromMethod, false) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.isInterfaceMethod, HotSpotResolvedObjectTypeProxy.isInterfaceInvokable) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.klassMethod, HotSpotResolvedObjectTypeProxy.klassInvokable) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getJavaMirrorMethod, HotSpotResolvedObjectTypeProxy.getJavaMirrorInvokable) - .setDefaultValue(HotSpotResolvedObjectTypeProxy.isInitializedMethod, false) - .provideMethodCallsToRecord((input) -> { - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) input; - if (!type.isArray() && !type.isInterface()) { - return List.of(new MethodCallToRecord(input, HotSpotResolvedObjectTypeProxy.instanceSizeMethod, HotSpotResolvedObjectTypeProxy.instanceSizeInvokable, null)); - } - return List.of(); - }) - .register(declarations); - // Must come after HotSpotResolvedObjectType. Needed for HotSpotResolvedPrimitiveType. - new RegistrationBuilder<>(HotSpotResolvedJavaType.class) - .ensureRecorded(HotSpotResolvedJavaTypeProxy.getNameMethod, HotSpotResolvedJavaTypeProxy.getNameInvokable) - .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaKindMethod, HotSpotResolvedJavaTypeProxy.getJavaKindInvokable) - .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) proxy; - return HotSpotResolvedPrimitiveType.forKind(type.getJavaKind()); - }) - .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaMirrorMethod, HotSpotResolvedJavaTypeProxy.getJavaMirrorInvokable) - .register(declarations); - new RegistrationBuilder<>(ConstantPool.class).register(declarations); - new RegistrationBuilder<>(HotSpotResolvedJavaMethod.class, Formattable.class) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getNameMethod, HotSpotResolvedJavaMethodProxy.getNameInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getModifiersMethod, HotSpotResolvedJavaMethodProxy.getModifiersInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.isConstructorMethod, HotSpotResolvedJavaMethodProxy.isConstructorInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundMethod, HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getCodeMethod, HotSpotResolvedJavaMethodProxy.getCodeInvokable) - .setStrategy(HotSpotResolvedJavaMethodProxy.formatToMethod, MethodStrategy.DefaultValue) - .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, singletonObjects) -> { - ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; - Formatter formatter = (Formatter) args[0]; - int flags = (int) args[1]; - int width = (int) args[2]; - String base = (flags & ALTERNATE) == ALTERNATE ? receiver.getName() : receiver.toString(); - formatter.format(DebugContext.applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width)); - return null; - }) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, HotSpotResolvedJavaMethodProxy.asStackTraceElementInvokable, -1) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, singletonObjects) -> { - ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; - return receiver.asStackTraceElement(-1); - }) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, singletonObjects) -> { - byte[] code = ((ResolvedJavaMethod) proxy).getCode(); - if (code == null) { - return 0; - } else { - return code.length; - } - }) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getDeclaringClassMethod, HotSpotResolvedJavaMethodProxy.getDeclaringClassInvokable) - .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - ResolvedJavaMethod method = (ResolvedJavaMethod) proxy; - String methodName = method.getName(); - String methodDescriptor = method.getSignature().toMethodDescriptor(); - ResolvedJavaType holder = method.getDeclaringClass(); - Class clazz; - try { - clazz = Class.forName(holder.toClassName()); - } catch (ClassNotFoundException e) { - return null; - } - if (Proxy.class.isAssignableFrom(clazz)) { - return null; - } - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType holderMirror = metaAccess.lookupJavaType(clazz); - if (method.isConstructor()) { - for (ResolvedJavaMethod candidate : holderMirror.getDeclaredConstructors()) { - if (candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { - return candidate; - } - } - } else { - for (ResolvedJavaMethod candidate : holderMirror.getDeclaredMethods()) { - if (candidate.getName().equals(methodName) && candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { - return candidate; - } - } - } - return null; - }) - .setStrategy(HotSpotResolvedJavaMethodProxy.getParametersMethod, MethodStrategy.Passthrough) - .setStrategy(HotSpotResolvedJavaMethodProxy.getParameterAnnotationsMethod, MethodStrategy.Passthrough) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) - .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) - .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, singletonObjects) -> { - // The HostInliningPhase can query Truffle-related annotations during replay on jargraal. It is safe to return null. - return null; - }) - .setStrategy(HotSpotResolvedJavaMethodProxy.getGenericParameterTypesMethod, MethodStrategy.Passthrough) - .setDefaultValueStrategy(HotSpotResolvedJavaMethodProxy.hasCodeAtLevelMethod, false) - .setDefaultValue(HotSpotResolvedJavaMethodProxy.isInVirtualMethodTableMethod, false) - .setDefaultValue(HotSpotResolvedJavaMethodProxy.intrinsicIdMethod, 0) - .setDefaultValue(HotSpotResolvedJavaMethodProxy.canBeInlinedMethod, false) - .provideMethodCallsToRecord((receiver) -> { - // Record calls to be able to format stable lambda names during replay (using StableMethodNameFormatter). - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) receiver; - List calls = new ArrayList<>(); - if (LambdaUtils.isLambdaType(method.getDeclaringClass()) || isMethodHandle(method.getDeclaringClass())) { - ConstantPool constantPool = method.getConstantPool(); - calls.add(new MethodCallToRecord(method, HotSpotResolvedJavaMethodProxy.getConstantPoolMethod, HotSpotResolvedJavaMethodProxy.getConstantPoolInvokable, null)); - for (BytecodeStream stream = new BytecodeStream(method.getCode()); stream.currentBCI() < stream.endBCI(); stream.next()) { - int opcode = stream.currentBC(); - int cpi; - switch (opcode) { - case INVOKEVIRTUAL: // fall through - case INVOKESPECIAL: // fall through - case INVOKESTATIC: // fall through - case INVOKEINTERFACE: - cpi = stream.readCPI(); - calls.add(new MethodCallToRecord(constantPool, ConstantPoolProxy.lookupMethodMethod, ConstantPoolProxy.lookupMethodInvokable, new Object[]{cpi, opcode, method})); - break; - case INVOKEDYNAMIC: - cpi = stream.readCPI4(); - calls.add(new MethodCallToRecord(constantPool, ConstantPoolProxy.lookupMethodMethod, ConstantPoolProxy.lookupMethodInvokable, new Object[]{cpi, opcode, method})); - break; - default: - break; - } - } - } - return calls; - }) - .register(declarations); - - new RegistrationBuilder<>(Signature.class) - .ensureRecorded(SignatureProxy.getParameterCountMethod, SignatureProxy.getParameterCountInvokable, false) - .ensureRecorded(SignatureProxy.getParameterCountMethod, SignatureProxy.getParameterCountInvokable, true) - .ensureRecorded(SignatureProxy.getReturnTypeMethod, SignatureProxy.getReturnTypeInvokable, (Object) null) - .provideMethodCallsToRecord((input) -> { - Signature signature = (Signature) input; - int count = signature.getParameterCount(false); - List calls = new ArrayList<>(); - CompilationProxy.SymbolicMethod symbolicMethod = new CompilationProxy.SymbolicMethod(Signature.class, "getParameterType", int.class, ResolvedJavaType.class); - CompilationProxy.InvokableMethod invokableMethod = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); - for (int i = 0; i < count; i++) { - calls.add(new MethodCallToRecord(input, symbolicMethod, invokableMethod, new Object[]{i, null})); - } - return calls; - }) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - Signature signature = (Signature) proxy; - return new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature.toMethodDescriptor()); - }) - .register(declarations); - new RegistrationBuilder<>(HotSpotResolvedJavaField.class) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.isStableMethod, HotSpotResolvedJavaFieldProxy.isStableInvokable) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.isSyntheticMethod, HotSpotResolvedJavaFieldProxy.isSyntheticInvokable) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.getOffsetMethod, HotSpotResolvedJavaFieldProxy.getOffsetInvokable) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.getDeclaringClassMethod, HotSpotResolvedJavaFieldProxy.getDeclaringClassInvokable) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.getNameMethod, HotSpotResolvedJavaFieldProxy.getNameInvokable) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.getModifiersMethod, HotSpotResolvedJavaFieldProxy.getModifiersInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotResolvedJavaFieldProxy.getTypeMethod, HotSpotResolvedJavaFieldProxy.getTypeInvokable) // For graph dumps (BinaryGraphPrinter) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - ResolvedJavaField field = (ResolvedJavaField) proxy; - ResolvedJavaType holderProxy = field.getDeclaringClass(); - Class holderClazz; - try { - holderClazz = Class.forName(holderProxy.toClassName()); - } catch (ClassNotFoundException e) { - return null; - } - if (Proxy.class.isAssignableFrom(holderClazz)) { - return null; - } - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType holder = metaAccess.lookupJavaType(holderClazz); - String name = field.getName(); - boolean isStatic = field.isStatic(); - ResolvedJavaField[] fields = (isStatic) ? holder.getStaticFields() : holder.getInstanceFields(false); - for (ResolvedJavaField candidate : fields) { - if (name.equals(candidate.getName())) { - return candidate; - } - } - throw new IllegalStateException("Cannot find mirror for " + field + ": the local holder does not contain a matching field"); - }) - .register(declarations); - new RegistrationBuilder<>(HotSpotObjectConstant.class) - .ensureRecorded(HotSpotObjectConstantProxy.toValueStringMethod, HotSpotObjectConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotObjectConstantProxy.isCompressedMethod, HotSpotObjectConstantProxy.isCompressedInvokable) - .ensureRecorded(HotSpotObjectConstantProxy.getTypeMethod, HotSpotObjectConstantProxy.getTypeInvokable) - .setDefaultValueStrategy(HotSpotObjectConstantProxy.isNullMethod, false) - .setDefaultValueStrategy(HotSpotObjectConstantProxy.getJavaKindMethod, JavaKind.Object) - .setDefaultValueSupplier(HotSpotObjectConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) - .setDefaultValueSupplier(HotSpotObjectConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) - .register(declarations); - new RegistrationBuilder<>(HotSpotMetaspaceConstant.class) - .ensureRecorded(HotSpotMetaspaceConstantProxy.toValueStringMethod, HotSpotMetaspaceConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotMetaspaceConstantProxy.isCompressedMethod, HotSpotMetaspaceConstantProxy.isCompressedInvokable) - .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaTypeMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaTypeInvokable) - .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaMethodMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaMethodInvokable) - .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) - .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) - .register(declarations); - new RegistrationBuilder<>(HotSpotProfilingInfo.class) - .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) - .setDefaultValue(ProfilingInfoProxy.isMatureMethod, false) - // For CompilationTask constructor. - .ensureRecorded(HotSpotProfilingInfoProxy.getDecompileCountMethod, HotSpotProfilingInfoProxy.getDecompileCountInvokable) - .setDefaultValue(HotSpotProfilingInfoProxy.getDeoptimizationCountMethod, -1) - .register(declarations); - new RegistrationBuilder<>(ProfilingInfo.class) // Needed for DefaultProfilingInfo, CachingProfilingInfo. - .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) - .setDefaultValue(ProfilingInfoProxy.isMatureMethod, false) - .setDefaultValue(HotSpotProfilingInfoProxy.getDeoptimizationCountMethod, -1) - .register(declarations); - new RegistrationBuilder<>(SpeculationLog.class) - .setDefaultValue(SpeculationLogProxy.maySpeculateMethod, true) - .setDefaultValue(SpeculationLogProxy.speculateMethod, SpeculationLog.NO_SPECULATION) - .register(declarations); - new RegistrationBuilder<>(Predicate.class).setSingleton(true) - .register(declarations); // Intrinsification trust predicate. - // @formatter:on - return declarations; - } - - @SuppressWarnings("unused") - private static ResolvedJavaType javaLangObjectSupplier(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - return metaAccess.lookupJavaType(Object.class); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java deleted file mode 100644 index 279bc5b543e3..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp; - -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.TriState; - -/** - * Object that cannot be directly deserialized because it invokes methods on the supplied arguments. - * These methods cannot be replayed at the time of deserialization. - */ -sealed interface DelayedDeserializationObject { - /** - * Deserializes the object, returning the deserialized instance. - * - * @return the deserialized object - */ - Object deserialize(); - - /** - * A {@link jdk.vm.ci.meta.Assumptions.LeafType} assumption that will be deserialized later. - */ - final class LeafTypeWithDelayedDeserialization extends Assumptions.Assumption implements DelayedDeserializationObject { - private final ResolvedJavaType context; - - LeafTypeWithDelayedDeserialization(ResolvedJavaType context) { - this.context = context; - } - - @Override - public Object deserialize() { - return new Assumptions.LeafType(context); - } - } - - /** - * A {@link jdk.vm.ci.meta.Assumptions.ConcreteSubtype} assumption that will be deserialized - * later. - */ - final class ConcreteSubtypeWithDelayedDeserialization extends Assumptions.Assumption implements DelayedDeserializationObject { - private final ResolvedJavaType context; - private final ResolvedJavaType subtype; - - ConcreteSubtypeWithDelayedDeserialization(ResolvedJavaType context, ResolvedJavaType subtype) { - this.context = context; - this.subtype = subtype; - } - - @Override - public Object deserialize() { - return new Assumptions.ConcreteSubtype(context, subtype); - } - } - - /** - * A {@link JavaTypeProfile} that will be deserialized later. - */ - final class JavaTypeProfileWithDelayedDeserialization implements DelayedDeserializationObject { - private final TriState nullSeen; - private final double notRecordedProbability; - private final ProfiledTypeWithDelayedDeserialization[] items; - - JavaTypeProfileWithDelayedDeserialization(TriState nullSeen, double notRecordedProbability, ProfiledTypeWithDelayedDeserialization[] items) { - this.nullSeen = nullSeen; - this.notRecordedProbability = notRecordedProbability; - this.items = items; - } - - @Override - public Object deserialize() { - JavaTypeProfile.ProfiledType[] profiledTypes = new JavaTypeProfile.ProfiledType[items.length]; - for (int i = 0; i < items.length; i++) { - profiledTypes[i] = items[i].deserialize(); - } - return new JavaTypeProfile(nullSeen, notRecordedProbability, profiledTypes); - } - } - - /** - * A {@link ProfiledTypeWithDelayedDeserialization} that will be deserialized later. - */ - final class ProfiledTypeWithDelayedDeserialization implements DelayedDeserializationObject { - private final ResolvedJavaType type; - private final double probability; - - ProfiledTypeWithDelayedDeserialization(ResolvedJavaType type, double probability) { - this.type = type; - this.probability = probability; - } - - @Override - public JavaTypeProfile.ProfiledType deserialize() { - return new JavaTypeProfile.ProfiledType(type, probability); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java deleted file mode 100644 index 4b48176c6bfd..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; - -import java.util.List; -import java.util.Objects; - -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.hotspot.HotSpotBackendFactoryDecorators; -import jdk.graal.compiler.hotspot.HotSpotSnippetMetaAccessProvider; -import jdk.graal.compiler.hotspot.SnippetObjectConstant; -import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.MemoryAccessProvider; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.MethodHandleAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * A backend factory that decorates the providers during recording and replay. - */ -class HotSpotProxyBackendFactory implements HotSpotBackendFactoryDecorators { - private final CompilationProxies proxies; - - private final ReplayCompilationSupport replayCompilationSupport; - - private MetaAccessProvider metaAccessProviderProxy; - - HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport) { - this.proxies = proxies; - this.replayCompilationSupport = replayCompilationSupport; - } - - @Override - public void afterJVMCIProvidersCreated() { - /* - * We need the key JVMCI providers (such as meta access) available to be able to find local - * mirrors. We must identify the local mirrors before initialization continues to avoid - * creating duplicate proxies for equivalent local mirrors. - */ - replayCompilationSupport.findLocalMirrors(); - } - - @Override - public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { - // Do not record snippet types in libgraal - decorate the JVMCI meta access only. - metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); - return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy, true); - } - - @Override - public HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotSpotConstantReflectionProvider constantReflection) { - // Only the operations invoked on the delegate are recorded and replayed. - HotSpotConstantReflectionProvider delegate = (HotSpotConstantReflectionProvider) proxies.proxify(constantReflection); - return new DecoratedConstantReflectionProvider(delegate); - } - - private final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { - private final HotSpotConstantReflectionProvider delegate; - - private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider delegate) { - super(null); - this.delegate = delegate; - } - - private static final List allowedFields = List.of("TYPE", "COMPACT_STRINGS"); - - @Override - public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { - /* - * Prevents jargraal from encoding runtime constants in snippets (such as in boxing - * snippets). Follows the logic of HotSpotSubstrateConstantReflectionProvider. - */ - if (!LibGraalSupport.inLibGraalRuntime() && replayCompilationSupport.isInSnippetContext() && !isGraalClass(field.getDeclaringClass()) && !allowedFields.contains(field.getName())) { - return null; - } - return delegate.readFieldValue(field, receiver); - } - - @Override - public JavaConstant forObject(Object value) { - return delegate.forObject(value); - } - - @Override - public Boolean constantEquals(Constant x, Constant y) { - if (x instanceof SnippetObjectConstant || y instanceof SnippetObjectConstant) { - /* - * Equality checks for snippet constants are not recorded because snippet constants - * are not serializable. - */ - return Objects.equals(x, y); - } else { - return delegate.constantEquals(x, y); - } - } - - @Override - public Integer readArrayLength(JavaConstant array) { - return delegate.readArrayLength(array); - } - - @Override - public JavaConstant readArrayElement(JavaConstant array, int index) { - return delegate.readArrayElement(array, index); - } - - @Override - public JavaConstant boxPrimitive(JavaConstant source) { - return delegate.boxPrimitive(source); - } - - @Override - public JavaConstant unboxPrimitive(JavaConstant source) { - return delegate.unboxPrimitive(source); - } - - @Override - public JavaConstant forString(String value) { - return delegate.forString(value); - } - - @Override - public ResolvedJavaType asJavaType(Constant constant) { - if (constant instanceof SnippetObjectConstant objectConstant) { - /* - * Avoids recording an operation with the snippet constant, which is not - * serializable. - */ - return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); - } else { - return delegate.asJavaType(constant); - } - } - - @Override - public MethodHandleAccessProvider getMethodHandleAccess() { - return delegate.getMethodHandleAccess(); - } - - @Override - public MemoryAccessProvider getMemoryAccessProvider() { - return delegate.getMemoryAccessProvider(); - } - - @Override - public JavaConstant asJavaClass(ResolvedJavaType type) { - return delegate.asJavaClass(type); - } - - @Override - public Constant asObjectHub(ResolvedJavaType type) { - return delegate.asObjectHub(type); - } - } - - @Override - public HotSpotCodeCacheProvider decorateCodeCacheProvider(HotSpotCodeCacheProvider codeCacheProvider) { - return (HotSpotCodeCacheProvider) proxies.proxify(codeCacheProvider); - } - - @Override - public HotSpotHostForeignCallsProvider decorateForeignCallsProvider(HotSpotHostForeignCallsProvider foreignCalls) { - replayCompilationSupport.setForeignCallsProvider(foreignCalls); - return foreignCalls; - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java deleted file mode 100644 index 38a4b2d077ab..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; -import java.util.concurrent.ConcurrentHashMap; - -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import org.graalvm.collections.EconomicMap; - -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.debug.GraalError; - -/** - * Records the results of operations during a recorded compilation. - *

- * An operation is a method call with a JVMCI object proxy as a receiver. The JVMCI objects for - * which proxies are created are registered in {@link CompilerInterfaceDeclarations}. - * {@link CompilerInterfaceDeclarations} also declares the behavior of the proxies during recording, - * i.e., which operations should be recorded or prefetched. - *

- * This class is also used to ensure that the results of operations return stable values during a - * recorded compilation. The first invocation of a method should record the result and all - * subsequent invocations with the same arguments should reuse the result obtained from - * {@link #getRecordedResultOrMarker}. - *

- * The recorder tracks the context of the current compiler thread. There are the following contexts: - *

    - *
  • global context - the initial context in which all results are recorded (e.g., compiler - * initialization),
  • - *
  • compilation context ({@link #enterCompilationContext()}) - a recorded compilation of a - * method,
  • - *
  • ignored context ({@link #enterIgnoredContext()}) - in this context, the results of operations - * are not recorded and the results of previous operations are not returned (useful for snippet - * parsing).
  • - *
- * A context is open until the respective is scope is closed. A compilation context also considers - * the operations recorded in the global context (i.e., {@link #getRecordedResultOrMarker} and - * {@link #getCurrentRecordedOperations()} also returns the operations from the global context). - * - * @see ReplayCompilationSupport - * @see RecordingCompilationProxies - */ -public class OperationRecorder { - /** - * A recorded operation. - *

- * Represents the receiver object, arguments, and the result of a method call from a recorded - * compilation. The result of an operation is either a return value or a thrown exception. - * Results other that non-null return values are represented with {@link SpecialResultMarker}. - *

- * During a recorded compilation, the instances of this class reference raw JVMCI objects - * (without proxies). During a replayed compilation, the instances reference proxy objects. - * - * @param receiver the receiver object of the operation - * @param method the invoked method - * @param args the arguments passed to the method - * @param resultOrMarker the return value or a marker for the result (e.g., a thrown exception) - */ - public record RecordedOperation(Object receiver, CompilationProxy.SymbolicMethod method, Object[] args, Object resultOrMarker) { - public RecordedOperation { - Objects.requireNonNull(receiver); - Objects.requireNonNull(method); - Objects.requireNonNull(resultOrMarker); - } - } - - /** - * The key of a recorded operation. - * - * @param receiver the receiver object of the operation - * @param method the invoked methods - * @param args the arguments passed to the method - */ - public record RecordedOperationKey(Object receiver, CompilationProxy.SymbolicMethod method, Object[] args) { - @Override - public boolean equals(Object object) { - if (this == object) { - return true; - } - if (object == null || getClass() != object.getClass()) { - return false; - } - RecordedOperationKey that = (RecordedOperationKey) object; - return receiver.equals(that.receiver) && method.equals(that.method) && Arrays.equals(args, that.args); - } - - @Override - public int hashCode() { - return Objects.hash(receiver, method, Arrays.hashCode(args)); - } - } - - private sealed interface RecordingContext { - Object getRecordedResultOrMarker(RecordedOperationKey key); - - void recordReturnValue(RecordedOperationKey key, Object result); - - void recordExceptionThrown(RecordedOperationKey key, Throwable throwable); - - List getRecordedOperations(); - } - - private static final class IgnoredRecordingContext implements RecordingContext { - @Override - public Object getRecordedResultOrMarker(RecordedOperationKey key) { - return SpecialResultMarker.NO_RESULT_MARKER; - } - - @Override - public void recordReturnValue(RecordedOperationKey key, Object result) { - } - - @Override - public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { - - } - - @Override - public List getRecordedOperations() { - return List.of(); - } - } - - private static final class GlobalRecordingContext implements RecordingContext { - private final ConcurrentHashMap operationResults; - - private GlobalRecordingContext() { - operationResults = new ConcurrentHashMap<>(); - } - - @Override - public Object getRecordedResultOrMarker(RecordedOperationKey key) { - return operationResults.getOrDefault(key, SpecialResultMarker.NO_RESULT_MARKER); - } - - @Override - public void recordReturnValue(RecordedOperationKey key, Object result) { - operationResults.put(key, (result == null) ? SpecialResultMarker.NULL_RESULT_MARKER : result); - } - - @Override - public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { - Objects.requireNonNull(throwable); - operationResults.put(key, new SpecialResultMarker.ExceptionThrownMarker(throwable)); - } - - @Override - public List getRecordedOperations() { - List results = new ArrayList<>(); - for (var entry : operationResults.entrySet()) { - RecordedOperationKey key = entry.getKey(); - results.add(new RecordedOperation(key.receiver, key.method, key.args, entry.getValue())); - } - return results; - } - } - - private static final class CompilationRecordingContext implements RecordingContext { - private final EconomicMap operationResults; - - private CompilationRecordingContext() { - this.operationResults = EconomicMap.create(); - } - - @Override - public Object getRecordedResultOrMarker(RecordedOperationKey key) { - return operationResults.get(key, SpecialResultMarker.NO_RESULT_MARKER); - } - - @Override - public void recordReturnValue(RecordedOperationKey key, Object result) { - operationResults.put(key, (result == null) ? SpecialResultMarker.NULL_RESULT_MARKER : result); - } - - @Override - public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { - Objects.requireNonNull(throwable); - operationResults.put(key, new SpecialResultMarker.ExceptionThrownMarker(throwable)); - } - - @Override - public List getRecordedOperations() { - List results = new ArrayList<>(); - var cursor = operationResults.getEntries(); - while (cursor.advance()) { - RecordedOperationKey key = cursor.getKey(); - results.add(new RecordedOperation(key.receiver, key.method, key.args, cursor.getValue())); - } - return results; - } - } - - private final GlobalRecordingContext globalContext; - - private final ThreadLocal currentContext; - - OperationRecorder() { - this.globalContext = new GlobalRecordingContext(); - this.currentContext = ThreadLocal.withInitial(() -> globalContext); - } - - /** - * Gets the result for a given operation. - * - * @param key the keu of the operation - * @return the return value or a marker for the result of the operation - */ - public Object getRecordedResultOrMarker(RecordedOperationKey key) { - return currentContext.get().getRecordedResultOrMarker(key); - } - - /** - * Records the return value for a recorded operation. - * - * @param key the key of the operation - * @param result the return value of the operation - */ - public void recordReturnValue(RecordedOperationKey key, Object result) { - currentContext.get().recordReturnValue(key, result); - } - - /** - * Records the exception thrown for a given operation. - * - * @param key the key of the operation - * @param throwable the exception thrown by the operation - */ - public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { - currentContext.get().recordExceptionThrown(key, throwable); - } - - /** - * Gets the recorded operations in the global and current compilation context. - */ - public List getCurrentRecordedOperations() { - RecordingContext context = currentContext.get(); - GraalError.guarantee(context instanceof CompilationRecordingContext, "recorded operations can be retrieved in compilation context only"); - List results = globalContext.getRecordedOperations(); - results.addAll(context.getRecordedOperations()); - return results; - } - - /** - * Enters the context of a method compilation for the current compilation thread. - * - * @return a scope for the context - */ - public DebugCloseable enterCompilationContext() { - RecordingContext previousContext = currentContext.get(); - currentContext.set(new CompilationRecordingContext()); - return () -> currentContext.set(previousContext); - } - - /** - * Enters a context where recording should be disabled for the current compilation thread. - * - * @return a scope for the context - */ - public DebugCloseable enterIgnoredContext() { - RecordingContext previousContext = currentContext.get(); - currentContext.set(new IgnoredRecordingContext()); - return () -> currentContext.set(previousContext); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java deleted file mode 100644 index 510206482d5e..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import org.graalvm.collections.EconomicMap; - -import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; -import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkageImpl; -import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.vm.ci.meta.Value; - -/** - * Represents the finalized foreign call linkages from a recorded compilation. - * - * @param linkages a list of individual linkages mapped by {@link ForeignCallSignature#toString()} - */ -public record RecordedForeignCallLinkages(EconomicMap linkages) { - /** - * A finalized foreign call linkage from a recorded compilation. - * - * @param address the address of the callee - * @param temporaries the slots and registers killed by the callee - */ - record RecordedForeignCallLinkage(long address, Value[] temporaries) { - RecordedForeignCallLinkage { - GraalError.guarantee(address != 0L, "only finalized linkages should be recorded"); - } - } - - /** - * Creates an instance of {@link RecordedForeignCallLinkages} using the finalized linkages from - * the given foreign calls provider. - * - * @param provider foreign calls provider - * @return the recorded linkages - */ - public static RecordedForeignCallLinkages createFrom(HotSpotHostForeignCallsProvider provider) { - EconomicMap linkages = EconomicMap.create(); - provider.forEachForeignCall((signature, linkage) -> { - if (linkage == null || !linkage.hasAddress()) { - return; - } - linkages.put(signature.toString(), new RecordedForeignCallLinkage(linkage.getAddress(), linkage.getTemporaries())); - }); - return new RecordedForeignCallLinkages(linkages); - } - - /** - * Sets the address and temporaries of a foreign call linkage to the recorded address and - * temporaries. This is a no-op if there is no recorded linkage with a matching signature. - * - * @param signature the signature of the foreign call - * @param linkage the linkage to be updated - * @return true if the linkage was finalized - */ - boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpotForeignCallLinkage linkage) { - RecordedForeignCallLinkage recordedLinkage = linkages.get(signature.toString()); - if (recordedLinkage == null) { - return false; - } - ((HotSpotForeignCallLinkageImpl) linkage).finalizeExternally(recordedLinkage.address, recordedLinkage.temporaries); - return true; - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java deleted file mode 100644 index 504c0a705500..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java +++ /dev/null @@ -1,1986 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.io.IOException; -import java.io.Reader; -import java.io.Serial; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.BitSet; -import java.util.Collection; -import java.util.EnumSet; -import java.util.List; -import java.util.Optional; - -import org.graalvm.collections.EconomicMap; - -import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.graal.compiler.hotspot.stubs.IllegalArgumentExceptionArgumentIsNotAnArrayStub; -import jdk.graal.compiler.util.json.JsonBuilder; -import jdk.graal.compiler.util.json.JsonParser; -import jdk.graal.compiler.util.json.JsonWriter; -import jdk.vm.ci.aarch64.AArch64; -import jdk.vm.ci.amd64.AMD64; -import jdk.vm.ci.code.Architecture; -import jdk.vm.ci.code.Register; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.RegisterValue; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotSpeculationLog; -import jdk.vm.ci.hotspot.VMField; -import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; -import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; -import jdk.vm.ci.hotspot.riscv64.RISCV64HotSpotRegisterConfig; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.EncodedSpeculationReason; -import jdk.vm.ci.meta.ExceptionHandler; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.PrimitiveConstant; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; -import jdk.vm.ci.meta.TriState; -import jdk.vm.ci.meta.UnresolvedJavaField; -import jdk.vm.ci.meta.UnresolvedJavaMethod; -import jdk.vm.ci.meta.UnresolvedJavaType; -import jdk.vm.ci.meta.Value; -import jdk.vm.ci.meta.ValueKind; -import jdk.vm.ci.riscv64.RISCV64; - -/** - * Provides functionality for persisting and loading recorded compilation units. - *

- * A {@link RecordedCompilationUnit} contains all data required to run a replay compilation. This - * class can serialize these records to and from JSON files. A recorded compilation unit contains a - * list of the recorded operations (method calls and their results during a recorded compilation), - * foreign call linkages, and other metadata. - *

- * The operations are collected during a recorded compilation via an {@link OperationRecorder}. An - * operation comprises a symbolic name of a method, the receiver object, argument values, and the - * result of that operation (a return value or an exception). After a recorded compilation, this - * class expects the raw JVMCI objects (without any proxies). It deduplicates these JVMCI objects by - * assigning a single ID to all JVMCI objects that are {@link Object#equals equal}. - *

- * When {@link #load loading} the recorded compilation unit from JSON, the class creates proxies in - * place of the JVMCI objects using the provided {@link ProxyFactory}. - * - * @see ReplayCompilationSupport - * @see CompilerInterfaceDeclarations - */ -public class RecordedOperationPersistence { - /** - * A recorded compilation unit. - * - * @param request the compilation request - * @param compilerConfiguration the name of the compiler configuration - * @param isLibgraal {@code true} if the recorded compilation executed on libgraal - * @param platform the platform of the system - * @param linkages the recorded foreign call linkages - * @param finalGraph the final canonical graph or {@code null} if not available - * @param operations the recorded operations and their results - */ - public record RecordedCompilationUnit(HotSpotCompilationRequest request, String compilerConfiguration, - boolean isLibgraal, Platform platform, RecordedForeignCallLinkages linkages, String finalGraph, - List operations) { - } - - /** - * Factory for creating generic proxy objects for register compiler-interface classes. - */ - @FunctionalInterface - public interface ProxyFactory { - /** - * Creates a proxy for the given registration. - * - * @param registration the registration - * @return the proxy - */ - CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration); - } - - private interface RecursiveSerializer { - void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder) throws IOException; - - void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder, String tag) throws IOException; - } - - private interface RecursiveDeserializer { - Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException; - - Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException; - } - - private sealed interface ObjectSerializer { - default boolean serializesSubclasses() { - return false; - } - - Class clazz(); - - String tag(); - - void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException; - - Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException; - } - - public static final class DeserializationException extends Exception { - @Serial private static final long serialVersionUID = -6470496032190913296L; - - private DeserializationException(ObjectSerializer serializer, EconomicMap json, Throwable cause) { - super("Serializer " + serializer + " failed to deserialize " + json, cause); - } - - private DeserializationException(ObjectSerializer serializer, EconomicMap json, String message) { - super("Serializer " + serializer + " failed to deserialize " + json + ": " + message); - } - } - - private static final class ClassSerializer implements ObjectSerializer { - private static final Class[] knownClasses = new Class[]{String.class, System.class, Object[].class, - ExceptionHandler.class, IllegalArgumentExceptionArgumentIsNotAnArrayStub.class}; - - @Override - public Class clazz() { - return Class.class; - } - - @Override - public String tag() { - return "class"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - objectBuilder.append("name", ((Class) instance).getName()); - } - - @Override - public Class deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - Class primitiveClass = Class.forPrimitiveName(name); - if (primitiveClass != null) { - return primitiveClass; - } - for (Class knownClass : knownClasses) { - if (knownClass.getName().equals(name)) { - return knownClass; - } - } - try { - return Class.forName(name); - } catch (ClassNotFoundException e) { - throw new DeserializationException(this, json, e); - } - } - } - - private static final class OperationSerializer implements ObjectSerializer { - private static final String TAG = "operation"; - - @Override - public Class clazz() { - return OperationRecorder.RecordedOperation.class; - } - - @Override - public String tag() { - return TAG; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - OperationRecorder.RecordedOperation op = (OperationRecorder.RecordedOperation) instance; - try { - serializer.serialize(op.receiver(), objectBuilder.append("recv")); - objectBuilder.append("method", Arrays.asList(op.method().methodAndParamNames())); - if (op.args() != null) { - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("args").array()) { - for (Object arg : op.args()) { - serializer.serialize(arg, arrayBuilder.nextEntry()); - } - } - } - serializer.serialize(op.resultOrMarker(), objectBuilder.append("res")); - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException("Failed to serialize " + op + " due to: " + e.getMessage(), e); - } - } - - @SuppressWarnings("unchecked") - @Override - public OperationRecorder.RecordedOperation deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) - throws DeserializationException { - Object recv = deserializer.deserialize(json.get("recv"), proxyFactory); - List methodProp = (List) json.get("method"); - String[] methodArray = new String[methodProp.size()]; - for (int i = 0; i < methodArray.length; i++) { - methodArray[i] = (String) methodProp.get(i); - } - CompilationProxy.SymbolicMethod method = new CompilationProxy.SymbolicMethod(methodArray); - List list = (List) json.get("args"); - Object[] args; - if (list == null) { - args = null; - } else { - args = new Object[list.size()]; - for (int i = 0; i < args.length; i++) { - args[i] = deserializer.deserialize(list.get(i), proxyFactory); - } - } - Object res = deserializer.deserialize(json.get("res"), proxyFactory); - return new OperationRecorder.RecordedOperation(recv, method, args, res); - } - } - - private static final class RegisteredSingletonSerializer implements ObjectSerializer { - private final CompilerInterfaceDeclarations.Registration registration; - - private Object singletonProxy; - - private RegisteredSingletonSerializer(CompilerInterfaceDeclarations.Registration registration) { - this.registration = registration; - if (!registration.singleton()) { - throw new IllegalArgumentException(); - } - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return registration.clazz(); - } - - @Override - public String tag() { - return clazz().getName(); - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) { - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - if (singletonProxy == null) { - singletonProxy = proxyFactory.createProxy(registration); - } - if (singletonProxy == null) { - throw new IllegalStateException("No singleton found for " + registration); - } - return singletonProxy; - } - } - - private static final class RegisteredInstanceSerializer implements ObjectSerializer { - private final CompilerInterfaceDeclarations.Registration registration; - - private final EconomicMap instanceId; - - private final EconomicMap proxyById; - - private RegisteredInstanceSerializer(CompilerInterfaceDeclarations.Registration registration) { - this.registration = registration; - this.instanceId = EconomicMap.create(); - this.proxyById = EconomicMap.create(); - if (registration.singleton()) { - throw new IllegalArgumentException(); - } - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return registration.clazz(); - } - - @Override - public String tag() { - return clazz().getSimpleName(); - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Integer id = instanceId.get(instance); - if (id == null) { - id = instanceId.size(); - instanceId.put(instance, id); - } - objectBuilder.append("id", id); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - int id = ((Number) json.get("id")).intValue(); - Object proxyInstance = proxyById.get(id); - if (proxyInstance == null) { - proxyInstance = proxyFactory.createProxy(registration); - proxyById.put(id, proxyInstance); - } - return proxyInstance; - } - } - - private static final class StackTraceElementSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return StackTraceElement.class; - } - - @Override - public String tag() { - return "ste"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - StackTraceElement ste = (StackTraceElement) instance; - objectBuilder.append("loader", ste.getClassLoaderName()); - objectBuilder.append("module", ste.getModuleName()); - objectBuilder.append("moduleVer", ste.getModuleVersion()); - objectBuilder.append("holder", ste.getClassName()); - objectBuilder.append("method", ste.getMethodName()); - objectBuilder.append("file", ste.getFileName()); - objectBuilder.append("line", ste.getLineNumber()); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String loader = (String) json.get("loader"); - String module = (String) json.get("module"); - String moduleVer = (String) json.get("moduleVer"); - String holder = (String) json.get("holder"); - String method = (String) json.get("method"); - String file = (String) json.get("file"); - int line = (int) json.get("line"); - return new StackTraceElement(loader, module, moduleVer, holder, method, file, line); - } - } - - private static final class StringSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return String.class; - } - - @Override - public String tag() { - return "string"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - objectBuilder.append("content", instance); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - return json.get("content"); - } - } - - private static final class BooleanSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Boolean.class; - } - - @Override - public String tag() { - return "boolean"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - objectBuilder.append("value", instance); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - return json.get("value"); - } - } - - private static final int HEX_RADIX = 16; - - private static String floatToHex(float value) { - return Integer.toHexString(Float.floatToRawIntBits(value)); - } - - private static float hexToFloat(String value) { - return Float.intBitsToFloat(Integer.parseUnsignedInt(value, HEX_RADIX)); - } - - private static String doubleToHex(double value) { - return Long.toHexString(Double.doubleToRawLongBits(value)); - } - - private static double hexToDouble(String value) { - return Double.longBitsToDouble(Long.parseUnsignedLong(value, HEX_RADIX)); - } - - private static final class NumberSerializer implements ObjectSerializer { - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return Number.class; - } - - @Override - public String tag() { - return "number"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - objectBuilder.append("class", instance.getClass().getSimpleName()); - String value = switch (instance) { - case Integer n -> Integer.toHexString(n); - case Byte n -> Integer.toHexString(n); - case Short n -> Integer.toHexString(n); - case Long n -> Long.toHexString(n); - case Float n -> floatToHex(n); - case Double n -> doubleToHex(n); - default -> throw new IllegalArgumentException("Unexpected value: " + instance); - }; - objectBuilder.append("value", value); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String className = (String) json.get("class"); - String value = (String) json.get("value"); - switch (className) { - case "Integer" -> { - return Integer.parseUnsignedInt(value, HEX_RADIX); - } - case "Byte" -> { - return (byte) Integer.parseUnsignedInt(value, HEX_RADIX); - } - case "Short" -> { - return (short) Integer.parseUnsignedInt(value, HEX_RADIX); - } - case "Long" -> { - return Long.parseUnsignedLong(value, HEX_RADIX); - } - case "Float" -> { - return hexToFloat(value); - } - case "Double" -> { - return hexToDouble(value); - } - default -> throw new IllegalArgumentException("Unknown class " + className + " for constant" + value); - } - } - } - - private static final class ResultMarkerSerializer implements ObjectSerializer { - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return SpecialResultMarker.class; - } - - @Override - public String tag() { - return "marker"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - String type; - if (instance == SpecialResultMarker.NO_RESULT_MARKER) { - type = "noResult"; - } else if (instance == SpecialResultMarker.NULL_RESULT_MARKER) { - type = "null"; - } else if (instance instanceof SpecialResultMarker.ExceptionThrownMarker thrownMarker) { - type = "exception"; - serializer.serialize(thrownMarker.getThrown(), objectBuilder.append("throwable")); - } else { - throw new IllegalArgumentException("Cannot serialize result marker " + instance); - } - objectBuilder.append("type", type); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - switch ((String) json.get("type")) { - case "noResult" -> { - return SpecialResultMarker.NO_RESULT_MARKER; - } - case "null" -> { - return SpecialResultMarker.NULL_RESULT_MARKER; - } - case "exception" -> { - return new SpecialResultMarker.ExceptionThrownMarker((Throwable) deserializer.deserialize(json.get("throwable"), proxyFactory)); - } - case null, default -> throw new DeserializationException(this, json, "Invalid marker type."); - } - } - } - - private static final class EnumSerializer implements ObjectSerializer { - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return Enum.class; - } - - @Override - public String tag() { - return "enum"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Enum en = (Enum) instance; - objectBuilder.append("holder", en.getClass().getName()); - objectBuilder.append("constant", en.name()); - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String holderName = (String) json.get("holder"); - String constantName = (String) json.get("constant"); - Class> enumClass; - try { - enumClass = (Class>) Class.forName(holderName); - } catch (ClassNotFoundException e) { - throw new DeserializationException(this, json, e); - } - // TODO This could be more efficient. - for (Enum constant : enumClass.getEnumConstants()) { - if (constant.name().equals(constantName)) { - return constant; - } - } - throw new DeserializationException(this, json, "Invalid constant."); - } - } - - private static final class ArraySerializer implements ObjectSerializer { - - private final CompilerInterfaceDeclarations declarations; - - private ArraySerializer(CompilerInterfaceDeclarations declarations) { - this.declarations = declarations; - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return Object[].class; - } - - @Override - public String tag() { - return "array"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Object[] array = (Object[]) instance; - Class componentType = array.getClass().getComponentType(); - Class supertype = declarations.findRegisteredSupertype(componentType); - if (supertype != null) { - componentType = supertype; - } - serializer.serialize(componentType, objectBuilder.append("component")); - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("elements").array()) { - for (Object object : array) { - serializer.serialize(object, arrayBuilder.nextEntry()); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Class component = (Class) deserializer.deserialize(json.get("component"), proxyFactory); - List elements = (List) json.get("elements"); - Object[] array = (Object[]) Array.newInstance(component, elements.size()); - for (int i = 0; i < elements.size(); i++) { - array[i] = deserializer.deserialize(elements.get(i), proxyFactory); - } - return array; - } - } - - private static final class ListSerializer implements ObjectSerializer { - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return List.class; - } - - @Override - public String tag() { - return "list"; - } - - @Override - @SuppressWarnings("unchecked") - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - List list = (List) instance; - try (var array = objectBuilder.append("elements").array()) { - for (Object element : list) { - serializer.serialize(element, array.nextEntry()); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - List list = new ArrayList<>(); - for (Object element : (List) json.get("elements")) { - list.add(deserializer.deserialize(element, proxyFactory)); - } - return list; - } - } - - private static final class ByteArraySerializer implements ObjectSerializer { - @Override - public Class clazz() { - return byte[].class; - } - - @Override - public String tag() { - return "byteArray"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - byte[] bytes = (byte[]) instance; - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("bytes").array()) { - for (byte b : bytes) { - arrayBuilder.append(b); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - List byteList = (List) json.get("bytes"); - byte[] bytes = new byte[byteList.size()]; - for (int i = 0; i < bytes.length; i++) { - bytes[i] = ((Number) byteList.get(i)).byteValue(); - } - return bytes; - } - } - - private static final class DoubleArraySerializer implements ObjectSerializer { - @Override - public Class clazz() { - return double[].class; - } - - @Override - public String tag() { - return "doubleArray"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - double[] doubles = (double[]) instance; - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("doubles").array()) { - for (double i : doubles) { - arrayBuilder.append(doubleToHex(i)); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - List doubleList = (List) json.get("doubles"); - double[] doubles = new double[doubleList.size()]; - for (int i = 0; i < doubles.length; i++) { - doubles[i] = hexToDouble((String) doubleList.get(i)); - } - return doubles; - } - } - - private static final class SingletonSerializer implements ObjectSerializer { - private final Object singleton; - - private SingletonSerializer(Object singleton) { - this.singleton = singleton; - } - - @Override - public Class clazz() { - return singleton.getClass(); - } - - @Override - public String tag() { - return singleton.getClass().getName(); - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) { - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - return singleton; - } - } - - private static final class RegisterSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Register.class; - } - - @Override - public String tag() { - return "register"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Register register = (Register) instance; - objectBuilder.append("number", register.number); - objectBuilder.append("name", register.name); - objectBuilder.append("encoding", register.encoding); - objectBuilder.append("catName", register.getRegisterCategory().toString()); - objectBuilder.append("containsRef", register.mayContainReference()); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - int number = (int) json.get("number"); - String name = (String) json.get("name"); - int encoding = (int) json.get("encoding"); - String catName = (String) json.get("catName"); - boolean containsRef = (boolean) json.get("containsRef"); - return new Register(number, encoding, name, new Register.RegisterCategory(catName, containsRef)); - } - } - - private static final class FieldSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Field.class; - } - - @Override - public String tag() { - return "field"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Field field = (Field) instance; - serializer.serialize(field.getDeclaringClass(), objectBuilder.append("holder")); - objectBuilder.append("name", field.getName()); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Class holder = (Class) deserializer.deserialize(json.get("holder"), proxyFactory); - String name = (String) json.get("name"); - try { - if (holder == String.class) { - // Ensure the reflection metadata is included in the libgraal image. - if ("coder".equals(name)) { - return String.class.getDeclaredField("coder"); - } else if ("value".equals(name)) { - return String.class.getDeclaredField("value"); - } - } - return holder.getDeclaredField(name); - } catch (NoSuchFieldException e) { - throw new DeserializationException(this, json, e); - } - } - } - - private static final class AssumptionResultSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.AssumptionResult.class; - } - - @Override - public String tag() { - return "assumpRes"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.AssumptionResult result = (Assumptions.AssumptionResult) instance; - serializer.serialize(result.getResult(), objectBuilder.append("result")); - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("assumptions").array()) { - Assumptions assumptions = new Assumptions(); - result.recordTo(assumptions); - for (Assumptions.Assumption assumption : assumptions) { - serializer.serialize(assumption, arrayBuilder.nextEntry()); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Object result = deserializer.deserialize(json.get("result"), proxyFactory); - List assumptions = new ArrayList<>(); - for (Object assumption : (List) json.get("assumptions")) { - assumptions.add((Assumptions.Assumption) deserializer.deserialize(assumption, proxyFactory)); - } - return new Assumptions.AssumptionResult<>(result, assumptions.toArray(Assumptions.Assumption[]::new)); - } - } - - private static final class NoFinalizableSubclassAssumptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.NoFinalizableSubclass.class; - } - - @Override - public String tag() { - return "noFinSubclass"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.NoFinalizableSubclass assumption = (Assumptions.NoFinalizableSubclass) instance; - serializer.serialize(assumption.receiverType, objectBuilder.append("receiverType")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - ResolvedJavaType receiverType = (ResolvedJavaType) deserializer.deserialize(json.get("receiverType"), proxyFactory); - return new Assumptions.NoFinalizableSubclass(receiverType); - } - } - - private static final class ConcreteSubtypeAssumptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.ConcreteSubtype.class; - } - - @Override - public String tag() { - return "concreteSubtype"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.ConcreteSubtype assumption = (Assumptions.ConcreteSubtype) instance; - serializer.serialize(assumption.subtype, objectBuilder.append("subtype")); - serializer.serialize(assumption.context, objectBuilder.append("context")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - ResolvedJavaType subtype = (ResolvedJavaType) deserializer.deserialize(json.get("subtype"), proxyFactory); - ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); - return new DelayedDeserializationObject.ConcreteSubtypeWithDelayedDeserialization(context, subtype); - } - } - - private static final class LeafTypeAssumptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.LeafType.class; - } - - @Override - public String tag() { - return "leafType"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.LeafType assumption = (Assumptions.LeafType) instance; - serializer.serialize(assumption.context, objectBuilder.append("context")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); - return new DelayedDeserializationObject.LeafTypeWithDelayedDeserialization(context); - } - } - - private static final class ConcreteMethodAssumptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.ConcreteMethod.class; - } - - @Override - public String tag() { - return "concreteMethod"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.ConcreteMethod assumption = (Assumptions.ConcreteMethod) instance; - serializer.serialize(assumption.context, objectBuilder.append("context")); - serializer.serialize(assumption.method, objectBuilder.append("method")); - serializer.serialize(assumption.impl, objectBuilder.append("impl")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); - ResolvedJavaMethod method = (ResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); - ResolvedJavaMethod impl = (ResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); - return new Assumptions.ConcreteMethod(method, context, impl); - } - } - - private static final class CallSiteTargetValueAssumptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return Assumptions.CallSiteTargetValue.class; - } - - @Override - public String tag() { - return "callSiteTarget"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Assumptions.CallSiteTargetValue assumption = (Assumptions.CallSiteTargetValue) instance; - serializer.serialize(assumption.callSite, objectBuilder.append("callSite")); - serializer.serialize(assumption.methodHandle, objectBuilder.append("methodHandle")); - - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - JavaConstant callSite = (JavaConstant) deserializer.deserialize(json.get("callSite"), proxyFactory); - JavaConstant methodHandle = (JavaConstant) deserializer.deserialize(json.get("methodHandle"), proxyFactory); - return new Assumptions.CallSiteTargetValue(callSite, methodHandle); - } - } - - private static final class UnresolvedJavaTypeSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return UnresolvedJavaType.class; - } - - @Override - public String tag() { - return "unresType"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - UnresolvedJavaType type = (UnresolvedJavaType) instance; - objectBuilder.append("name", type.getName()); - - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - return UnresolvedJavaType.create(name); - } - } - - private static final class UnresolvedJavaMethodSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return UnresolvedJavaMethod.class; - } - - @Override - public String tag() { - return "unresMethod"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - UnresolvedJavaMethod method = (UnresolvedJavaMethod) instance; - objectBuilder.append("name", method.getName()); - serializer.serialize(method.getSignature(), objectBuilder.append("signature")); - serializer.serialize(method.getDeclaringClass(), objectBuilder.append("holder")); - - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - Signature signature = (Signature) deserializer.deserialize(json.get("signature"), proxyFactory); - JavaType holder = (JavaType) deserializer.deserialize(json.get("holder"), proxyFactory); - return new UnresolvedJavaMethod(name, signature, holder); - } - } - - private static final class UnresolvedJavaFieldSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return UnresolvedJavaField.class; - } - - @Override - public String tag() { - return "unresField"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - UnresolvedJavaField method = (UnresolvedJavaField) instance; - objectBuilder.append("name", method.getName()); - serializer.serialize(method.getType(), objectBuilder.append("type")); - serializer.serialize(method.getDeclaringClass(), objectBuilder.append("holder")); - - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - JavaType type = (JavaType) deserializer.deserialize(json.get("type"), proxyFactory); - JavaType holder = (JavaType) deserializer.deserialize(json.get("holder"), proxyFactory); - return new UnresolvedJavaField(holder, name, type); - } - } - - private static final class PrimitiveConstantSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return PrimitiveConstant.class; - } - - @Override - public String tag() { - return "primConst"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - PrimitiveConstant constant = (PrimitiveConstant) instance; - objectBuilder.append("raw", constant.getRawValue()); - serializer.serialize(constant.getJavaKind(), objectBuilder.append("kind")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Number raw = (Number) json.get("raw"); - JavaKind kind = (JavaKind) deserializer.deserialize(json.get("kind"), proxyFactory); - return JavaConstant.forPrimitive(kind, raw.longValue()); - } - } - - private static final class ForeignCallDescriptorSerializer implements ObjectSerializer { - private static final class ForeignCallDescriptorSurrogate { - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return ForeignCallDescriptor.class; - } - - @Override - public String tag() { - return "foreignCallDesc"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - return new ForeignCallDescriptorSurrogate(); - } - } - - private static final class EncodedSpeculationReasonSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return EncodedSpeculationReason.class; - } - - @Override - public String tag() { - return "encSpecReason"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - EncodedSpeculationReason reason = (EncodedSpeculationReason) instance; - objectBuilder.append("groupName", reason.getGroupName()); - objectBuilder.append("groupId", reason.getGroupId()); - serializer.serialize(reason.getContext(), objectBuilder.append("context")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("groupName"); - int groupId = (int) json.get("groupId"); - Object[] context = (Object[]) deserializer.deserialize(json.get("context"), proxyFactory); - return new EncodedSpeculationReason(groupId, name, context); - } - } - - private static final class HotSpotSpeculationSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return HotSpotSpeculationLog.HotSpotSpeculation.class; - } - - @Override - public String tag() { - return "hsSpec"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - HotSpotSpeculationLog.HotSpotSpeculation speculation = (HotSpotSpeculationLog.HotSpotSpeculation) instance; - serializer.serialize(speculation.getReason(), objectBuilder.append("reason")); - serializer.serialize(speculation.getReasonEncoding(), objectBuilder.append("bytes")); - serializer.serialize(speculation.getEncoding(), objectBuilder.append("encoding")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - JavaConstant encoding = (JavaConstant) deserializer.deserialize(json.get("encoding"), proxyFactory); - byte[] bytes = (byte[]) deserializer.deserialize(json.get("bytes"), proxyFactory); - SpeculationLog.SpeculationReason reason = (SpeculationLog.SpeculationReason) deserializer.deserialize(json.get("reason"), proxyFactory); - return new HotSpotSpeculationLog.HotSpotSpeculation(reason, encoding, bytes); - } - } - - private static final class JavaTypeProfileSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return JavaTypeProfile.class; - } - - @Override - public String tag() { - return "typeProf"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - JavaTypeProfile typeProfile = (JavaTypeProfile) instance; - serializer.serialize(typeProfile.getNullSeen(), objectBuilder.append("nullSeen")); - objectBuilder.append("notRecorded", doubleToHex(typeProfile.getNotRecordedProbability())); - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("types").array()) { - for (JavaTypeProfile.ProfiledType item : typeProfile.getTypes()) { - serializer.serialize(item, arrayBuilder.nextEntry()); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - TriState nullSeen = (TriState) deserializer.deserialize(json.get("nullSeen"), proxyFactory); - double notRecorded = hexToDouble((String) json.get("notRecorded")); - List types = new ArrayList<>(); - for (var type : (List) json.get("types")) { - types.add((DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization) deserializer.deserialize(type, proxyFactory)); - } - return new DelayedDeserializationObject.JavaTypeProfileWithDelayedDeserialization(nullSeen, notRecorded, - types.toArray(DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization[]::new)); - } - } - - private static final class ProfiledTypeSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return JavaTypeProfile.ProfiledType.class; - } - - @Override - public String tag() { - return "ptype"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - JavaTypeProfile.ProfiledType profiledType = (JavaTypeProfile.ProfiledType) instance; - serializer.serialize(profiledType.getType(), objectBuilder.append("type")); - objectBuilder.append("prob", doubleToHex(profiledType.getProbability())); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - double prob = hexToDouble((String) json.get("prob")); - ResolvedJavaType type = (ResolvedJavaType) deserializer.deserialize(json.get("type"), proxyFactory); - return new DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization(type, prob); - } - } - - private static final class BitSetSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return BitSet.class; - } - - @Override - public String tag() { - return "bitset"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - BitSet bitSet = (BitSet) instance; - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("words").array()) { - for (long word : bitSet.toLongArray()) { - arrayBuilder.append(word); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { - List list = (List) json.get("words"); - long[] longArray = new long[list.size()]; - for (int i = 0; i < list.size(); i++) { - longArray[i] = ((Number) list.get(i)).longValue(); - } - return BitSet.valueOf(longArray); - } - } - - private static final class VMFieldSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return VMField.class; - } - - @Override - public String tag() { - return "vmField"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - VMField vmField = (VMField) instance; - objectBuilder.append("name", vmField.name); - objectBuilder.append("type", vmField.type); - objectBuilder.append("offset", vmField.offset); - objectBuilder.append("address", Long.toHexString(vmField.address)); - serializer.serialize(vmField.value, objectBuilder.append("value")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - String type = (String) json.get("type"); - long offset = ((Number) json.get("offset")).longValue(); - long address = Long.parseUnsignedLong((String) json.get("address"), HEX_RADIX); - Object value = deserializer.deserialize(json.get("value"), proxyFactory); - return new VMField(name, type, offset, address, value); - } - } - - public static final class RecordedCompilationUnitSerializer implements ObjectSerializer { - public static final String IS_LIBGRAAL_PROPERTY = "isLibgraal"; - - private static final String TAG = "recordedCompilationUnit"; - - @Override - public Class clazz() { - return RecordedCompilationUnit.class; - } - - @Override - public String tag() { - return TAG; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - RecordedCompilationUnit unit = (RecordedCompilationUnit) instance; - serializer.serialize(unit.request.getMethod(), objectBuilder.append("method")); - objectBuilder.append("osName", unit.platform.osName()); - objectBuilder.append("archName", unit.platform.archName()); - objectBuilder.append("compilerConfiguration", unit.compilerConfiguration); - objectBuilder.append(IS_LIBGRAAL_PROPERTY, unit.isLibgraal); - objectBuilder.append("entryBCI", unit.request.getEntryBCI()); - objectBuilder.append("compileId", unit.request.getId()); - try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("operations").array()) { - for (OperationRecorder.RecordedOperation operation : unit.operations) { - serializer.serialize(operation, arrayBuilder.nextEntry(), OperationSerializer.TAG); - } - } - serializer.serialize(unit.linkages, objectBuilder.append("linkages"), RecordedForeignCallLinkagesSerializer.TAG); - objectBuilder.append("finalGraph", unit.finalGraph); - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); - String osName = (String) json.get("osName"); - String archName = (String) json.get("archName"); - Platform platform = new Platform(osName, archName); - String compilerConfiguration = (String) json.get("compilerConfiguration"); - boolean isLibgraal = (boolean) json.get(IS_LIBGRAAL_PROPERTY); - int entryBCI = (int) json.get("entryBCI"); - int compileId = (int) json.get("compileId"); - List list = (List) json.get("operations"); - List operations = new ArrayList<>(list.size()); - for (Object object : list) { - operations.add((OperationRecorder.RecordedOperation) deserializer.deserialize(object, proxyFactory, OperationSerializer.TAG)); - } - RecordedForeignCallLinkages linkages = (RecordedForeignCallLinkages) deserializer.deserialize(json.get("linkages"), proxyFactory, RecordedForeignCallLinkagesSerializer.TAG); - String finalGraph = (String) json.get("finalGraph"); - return new RecordedCompilationUnit(new HotSpotCompilationRequest(method, entryBCI, 0, compileId), compilerConfiguration, isLibgraal, platform, linkages, finalGraph, operations); - } - } - - private static final class RecordedForeignCallLinkagesSerializer implements ObjectSerializer { - private static final String TAG = "linkages"; - - @Override - public Class clazz() { - return RecordedForeignCallLinkages.class; - } - - @Override - public String tag() { - return TAG; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - RecordedForeignCallLinkages linkages = (RecordedForeignCallLinkages) instance; - try (JsonBuilder.ObjectBuilder builder = objectBuilder.append("map").object()) { - var cursor = linkages.linkages().getEntries(); - while (cursor.advance()) { - serializer.serialize(cursor.getValue(), builder.append(cursor.getKey()), RecordedForeignCallLinkageSerializer.TAG); - } - } - } - - @SuppressWarnings("unchecked") - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - EconomicMap linkages = EconomicMap.create(); - EconomicMap map = (EconomicMap) json.get("map"); - var cursor = map.getEntries(); - while (cursor.advance()) { - String key = cursor.getKey(); - RecordedForeignCallLinkages.RecordedForeignCallLinkage linkage = (RecordedForeignCallLinkages.RecordedForeignCallLinkage) deserializer.deserialize(cursor.getValue(), proxyFactory, - RecordedForeignCallLinkageSerializer.TAG); - linkages.put(key, linkage); - } - return new RecordedForeignCallLinkages(linkages); - } - } - - private static final class RecordedForeignCallLinkageSerializer implements ObjectSerializer { - private static final String TAG = "linkage"; - - @Override - public Class clazz() { - return RecordedForeignCallLinkages.RecordedForeignCallLinkage.class; - } - - @Override - public String tag() { - return TAG; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - RecordedForeignCallLinkages.RecordedForeignCallLinkage linkage = (RecordedForeignCallLinkages.RecordedForeignCallLinkage) instance; - objectBuilder.append("address", linkage.address()); - serializer.serialize(linkage.temporaries(), objectBuilder.append("temporaries")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - long address = ((Number) json.get("address")).longValue(); - Value[] temporaries = (Value[]) deserializer.deserialize(json.get("temporaries"), proxyFactory); - return new RecordedForeignCallLinkages.RecordedForeignCallLinkage(address, temporaries); - } - } - - private static final class RegisterValueSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return RegisterValue.class; - } - - @Override - public String tag() { - return "regVal"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - RegisterValue registerValue = (RegisterValue) instance; - serializer.serialize(registerValue.getRegister(), objectBuilder.append("register")); - serializer.serialize(registerValue.getValueKind(), objectBuilder.append("valueKind")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Register register = (Register) deserializer.deserialize(json.get("register"), proxyFactory); - ValueKind valueKind = (ValueKind) deserializer.deserialize(json.get("valueKind"), proxyFactory); - return register.asValue(valueKind); - } - } - - private static final class ExceptionHandlerSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return ExceptionHandler.class; - } - - @Override - public String tag() { - return "exceptHandler"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - ExceptionHandler handler = (ExceptionHandler) instance; - objectBuilder.append("startBCI", handler.getStartBCI()); - objectBuilder.append("endBCI", handler.getEndBCI()); - objectBuilder.append("catchBCI", handler.getHandlerBCI()); - objectBuilder.append("catchTypeCPI", handler.catchTypeCPI()); - serializer.serialize(handler.getCatchType(), objectBuilder.append("catchType")); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - int startBCI = ((Number) json.get("startBCI")).intValue(); - int endBCI = ((Number) json.get("endBCI")).intValue(); - int catchBCI = ((Number) json.get("catchBCI")).intValue(); - int catchTypeCPI = ((Number) json.get("catchTypeCPI")).intValue(); - JavaType catchType = (JavaType) deserializer.deserialize(json.get("catchType"), proxyFactory); - return new ExceptionHandler(startBCI, endBCI, catchBCI, catchTypeCPI, catchType); - } - } - - private static final class EnumSetSerializer implements ObjectSerializer { - /** - * Represents an unknown {@link Enum} type. Since the type system does not allow creating an - * {@link EnumSet} without specifying the exact enum type, we can use this type as a generic - * type parameter (which is erased anyway). - */ - private enum UnknownEnum { - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return EnumSet.class; - } - - @Override - public String tag() { - return "enumSet"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - EnumSet enumSet = (EnumSet) instance; - Class elementType; - Optional maybeElementType = enumSet.stream().findAny(); - if (maybeElementType.isPresent()) { - elementType = maybeElementType.get().getClass(); - } else { - maybeElementType = EnumSet.complementOf(enumSet).stream().findAny(); - if (maybeElementType.isPresent()) { - elementType = maybeElementType.get().getClass(); - } else { - elementType = UnknownEnum.class; - } - } - serializer.serialize(elementType, objectBuilder.append("enum")); - try (var array = objectBuilder.append("ordinals").array()) { - for (Enum element : enumSet) { - array.append(element.ordinal()); - } - } - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Class elementType = (Class) deserializer.deserialize(json.get("enum"), proxyFactory); - return asEnumSet(elementType, (List) json.get("ordinals")); - } - - private static > EnumSet asEnumSet(Class clazz, Collection ordinals) { - EnumSet enumSet = EnumSet.noneOf(clazz); - E[] enumConstants = clazz.getEnumConstants(); - for (Object ordinal : ordinals) { - enumSet.add(enumConstants[((Number) ordinal).intValue()]); - } - return enumSet; - } - } - - private static final class TargetDescriptionSerializer implements ObjectSerializer { - - @Override - public Class clazz() { - return TargetDescription.class; - } - - @Override - public String tag() { - return "targetDescription"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - TargetDescription targetDescription = (TargetDescription) instance; - serializer.serialize(targetDescription.arch, objectBuilder.append("architecture")); - objectBuilder.append("isMP", targetDescription.isMP); - objectBuilder.append("stackAlignment", targetDescription.stackAlignment); - objectBuilder.append("implicitNullCheckLimit", targetDescription.implicitNullCheckLimit); - objectBuilder.append("inlineObjects", targetDescription.inlineObjects); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Architecture arch = (Architecture) deserializer.deserialize(json.get("architecture"), proxyFactory); - boolean isMP = (boolean) json.get("isMP"); - int stackAlignment = ((Number) json.get("stackAlignment")).intValue(); - int implicitNullCheckLimit = ((Number) json.get("implicitNullCheckLimit")).intValue(); - boolean inlineObjects = (boolean) json.get("inlineObjects"); - return new TargetDescription(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects); - } - } - - private static final class ArchitectureSerializer implements ObjectSerializer { - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return Architecture.class; - } - - @Override - public String tag() { - return "architecture"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Architecture architecture = (Architecture) instance; - objectBuilder.append("name", architecture.getName()); - serializer.serialize(architecture.getFeatures(), objectBuilder.append("features")); - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - EnumSet features = (EnumSet) deserializer.deserialize(json.get("features"), proxyFactory); - return switch (name) { - case "AMD64" -> new AMD64((EnumSet) features); - case "riscv64" -> new RISCV64((EnumSet) features); - case "aarch64" -> new AArch64((EnumSet) features); - default -> throw new IllegalStateException("Unexpected value: " + name); - }; - } - } - - private static final class RegisterConfigSerializer implements ObjectSerializer { - private final boolean isHostWindowsOS; - - private final TargetDescription hostTarget; - - private RegisterConfigSerializer(Platform platform, TargetDescription hostTarget) { - this.isHostWindowsOS = platform.osName().equals("windows"); - this.hostTarget = hostTarget; - } - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return RegisterConfig.class; - } - - @Override - public String tag() { - return "registerConfig"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - RegisterConfig registerConfig = (RegisterConfig) instance; - String name = switch (registerConfig) { - case AMD64HotSpotRegisterConfig ignored -> "AMD64"; - case RISCV64HotSpotRegisterConfig ignored -> "RISCV64"; - case AArch64HotSpotRegisterConfig ignored -> "AArch64"; - default -> throw new IllegalStateException("Unexpected value: " + registerConfig); - }; - objectBuilder.append("name", name); - serializer.serialize(hostTarget, objectBuilder.append("target")); - serializer.serialize(registerConfig.getAllocatableRegisters(), objectBuilder.append("allocatable")); - objectBuilder.append("windowsOS", isHostWindowsOS); - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - String name = (String) json.get("name"); - TargetDescription targetDescription = (TargetDescription) deserializer.deserialize(json.get("target"), proxyFactory); - List allocatable = (List) deserializer.deserialize(json.get("allocatable"), proxyFactory); - switch (name) { - case "AMD64" -> { - boolean windowsOS = (boolean) json.get("windowsOS"); - return new AMD64HotSpotRegisterConfig(targetDescription, allocatable, windowsOS); - } - case "RISCV64" -> { - return new RISCV64HotSpotRegisterConfig(targetDescription, allocatable); - } - case "AArch64" -> { - return new AArch64HotSpotRegisterConfig(targetDescription, allocatable); - } - default -> throw new IllegalStateException("Unexpected kind of register config: " + name); - } - } - } - - private static final class ThrowableSerializer implements ObjectSerializer { - - @Override - public boolean serializesSubclasses() { - return true; - } - - @Override - public Class clazz() { - return Throwable.class; - } - - @Override - public String tag() { - return "throwable"; - } - - @Override - public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { - Throwable throwable = (Throwable) instance; - serializer.serialize(throwable.getClass(), objectBuilder.append("class")); - objectBuilder.append("message", throwable.getMessage()); - } - - @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { - Class clazz = (Class) deserializer.deserialize(json.get("class"), proxyFactory); - String message = (String) json.get("message"); - if (clazz == JVMCIError.class) { - return new JVMCIError(message); - } else if (clazz == GraalError.class) { - return new GraalError(message); - } else if (clazz == IllegalArgumentException.class) { - return new IllegalArgumentException(message); - } else { - return new Throwable(message); - } - } - } - - private final EconomicMap tagSerializers; - - private final EconomicMap, ObjectSerializer> exactClassSerializers; - - private final EconomicMap, ObjectSerializer> interfaceSerializers; - - /** - * Constructs a serializer/deserializer for recorded compilation units. - * - * @param declarations the definitions of the compiler interface - * @param hostPlatform the platform of the current host (for serialization) - * @param hostTarget the target of the current host (for serialization) - */ - public RecordedOperationPersistence(CompilerInterfaceDeclarations declarations, Platform hostPlatform, TargetDescription hostTarget) { - this.tagSerializers = EconomicMap.create(); - this.exactClassSerializers = EconomicMap.create(); - this.interfaceSerializers = EconomicMap.create(); - for (CompilerInterfaceDeclarations.Registration registration : declarations.getRegistrations()) { - if (registration.singleton()) { - addSerializer(new RegisteredSingletonSerializer(registration)); - } else { - addSerializer(new RegisteredInstanceSerializer(registration)); - } - } - addSerializer(new ClassSerializer()); - addSerializer(new OperationSerializer()); - addSerializer(new StringSerializer()); - addSerializer(new BooleanSerializer()); - addSerializer(new NumberSerializer()); - addSerializer(new StackTraceElementSerializer()); - addSerializer(new ResultMarkerSerializer()); - addSerializer(new EnumSerializer()); - addSerializer(new DoubleArraySerializer()); - addSerializer(new ByteArraySerializer()); - addSerializer(new ArraySerializer(declarations)); - addSerializer(new ListSerializer()); - addSerializer(new SingletonSerializer(JavaConstant.NULL_POINTER)); - addSerializer(new SingletonSerializer(HotSpotCompressedNullConstant.COMPRESSED_NULL)); - addSerializer(new SingletonSerializer(SpeculationLog.NO_SPECULATION)); - addSerializer(new SingletonSerializer(ValueKind.Illegal)); - addSerializer(new RegisterSerializer()); - addSerializer(new FieldSerializer()); - addSerializer(new AssumptionResultSerializer()); - addSerializer(new NoFinalizableSubclassAssumptionSerializer()); - addSerializer(new ConcreteSubtypeAssumptionSerializer()); - addSerializer(new LeafTypeAssumptionSerializer()); - addSerializer(new ConcreteMethodAssumptionSerializer()); - addSerializer(new CallSiteTargetValueAssumptionSerializer()); - addSerializer(new UnresolvedJavaTypeSerializer()); - addSerializer(new UnresolvedJavaMethodSerializer()); - addSerializer(new UnresolvedJavaFieldSerializer()); - addSerializer(new PrimitiveConstantSerializer()); - addSerializer(new ForeignCallDescriptorSerializer()); - addSerializer(new EncodedSpeculationReasonSerializer()); - addSerializer(new HotSpotSpeculationSerializer()); - addSerializer(new JavaTypeProfileSerializer()); - addSerializer(new ProfiledTypeSerializer()); - addSerializer(new BitSetSerializer()); - addSerializer(new VMFieldSerializer()); - addSerializer(new RecordedCompilationUnitSerializer()); - addSerializer(new RecordedForeignCallLinkagesSerializer()); - addSerializer(new RecordedForeignCallLinkageSerializer()); - addSerializer(new RegisterValueSerializer()); - addSerializer(new EnumSetSerializer()); - addSerializer(new ArchitectureSerializer()); - addSerializer(new TargetDescriptionSerializer()); - addSerializer(new RegisterConfigSerializer(hostPlatform, hostTarget)); - addSerializer(new ExceptionHandlerSerializer()); - addSerializer(new ThrowableSerializer()); - } - - private void addSerializer(ObjectSerializer serializer) { - tagSerializers.put(serializer.tag(), serializer); - if (serializer.serializesSubclasses()) { - interfaceSerializers.put(serializer.clazz(), serializer); - } else { - exactClassSerializers.put(serializer.clazz(), serializer); - } - } - - private final RecursiveSerializer recursiveSerializer = new RecursiveSerializer() { - @Override - public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder) throws IOException { - if (instance == null) { - valueBuilder.value(null); - return; - } - ObjectSerializer serializer = exactClassSerializers.get(instance.getClass()); - if (serializer == null) { - var cursor = interfaceSerializers.getEntries(); - while (cursor.advance()) { - if (cursor.getKey().isInstance(instance)) { - serializer = cursor.getValue(); - exactClassSerializers.put(instance.getClass(), serializer); - break; - } - } - if (serializer == null) { - throw new IllegalArgumentException("No serializer for " + instance.getClass() + ": " + instance); - } - } - try (JsonBuilder.ObjectBuilder builder = valueBuilder.object()) { - builder.append("tag", serializer.tag()); - serializer.serialize(instance, builder, this); - } - } - - @Override - public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder, String tag) throws IOException { - if (instance == null) { - valueBuilder.value(null); - return; - } - ObjectSerializer serializer = tagSerializers.get(tag); - if (serializer == null) { - throw new IllegalArgumentException("No serializer registered for the given tag " + tag); - } - try (JsonBuilder.ObjectBuilder builder = valueBuilder.object()) { - serializer.serialize(instance, builder, this); - } - } - }; - - /** - * Dumps the given compilation unit to the given writer. - * - * @param compilationUnit the compilation unit - * @param writer the writer - * @throws IOException if dumping fails - */ - public void dump(RecordedCompilationUnit compilationUnit, JsonWriter writer) throws IOException { - recursiveSerializer.serialize(compilationUnit, writer.valueBuilder(), RecordedCompilationUnitSerializer.TAG); - } - - private final RecursiveDeserializer recursiveDeserializer = new RecursiveDeserializer() { - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - String tag = (String) map.get("tag"); - if (tag == null) { - throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); - } - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); - } - return deserializer.deserialize(map, this, proxyFactory); - } else { - return json; - } - } - - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); - } - return deserializer.deserialize(map, this, proxyFactory); - } else { - throw new IllegalArgumentException("Expected a map."); - } - } - }; - - /** - * Loads a recorded compilation unit from the given reader. - * - * @param source the reader - * @param proxyFactory the proxy factory - * @return the loaded compilation unit - * @throws IOException if loading fails - * @throws DeserializationException if deserialization fails - */ - public RecordedCompilationUnit load(Reader source, ProxyFactory proxyFactory) throws IOException, DeserializationException { - JsonParser parser = new JsonParser(source); - return (RecordedCompilationUnit) recursiveDeserializer.deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java deleted file mode 100644 index d264db2bd57b..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; - -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; -import jdk.graal.compiler.util.EconomicHashSet; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -/** - * A holder and factory for compiler-interface proxies during a recorded compilation. - *

- * A proxy created by this class delegates method invocation to an original object (one obtained - * from the host VM). The proxy may also record the result of the invocation, which can be later - * serialized into a JSON file ({@link RecordedOperationPersistence}). The behavior of the proxy for - * individual methods is configured in {@link CompilerInterfaceDeclarations}. All subsequent method - * invocations with equal arguments produce the result computed initially. - *

- * The result of an operation is either a return value or a thrown exception. - * - * @see CompilerInterfaceDeclarations - * @see ReplayCompilationSupport - */ -class RecordingCompilationProxies implements CompilationProxies { - /** - * Records the results of method invocations and also ensures the methods return stable values. - */ - private final OperationRecorder recorder; - - /** - * Declares which objects require a proxy (registered objects) and defines the behavior of - * method invocation. - */ - private final CompilerInterfaceDeclarations declarations; - - /** - * Used to replace registered objects inside composite objects with proxies and vice versa. - */ - private final CompilationProxyMapper proxyMapper; - - RecordingCompilationProxies(CompilerInterfaceDeclarations declarations) { - this.recorder = new OperationRecorder(); - this.declarations = declarations; - this.proxyMapper = new CompilationProxyMapper(declarations, this::proxify); - } - - /** - * Collects and returns a list of operations that should be serialized for the current - * compilation unit. This list includes the global operations needed to initialize the compiler, - * the operations recorded in this compilation unit, and the operations that should be recorded - * because they could be needed during replay (e.g., to produce debug output). These operations - * are defined in {@link CompilerInterfaceDeclarations}. - *

- * Since the method calls performed and recorded by this method can return newly discovered - * objects that have operations to record of their own, this method uses a worklist to compute a - * transitive closure. - * - * @return a list of recorded compilation - */ - public List collectOperationsForSerialization() { - List worklist = new ArrayList<>(); - Set visited = new EconomicHashSet<>(); - CompilationProxyMapper worklistAdder = new CompilationProxyMapper(declarations, (input) -> { - if (!visited.contains(input)) { - visited.add(input); - worklist.add(input); - } - return proxify(input); - }); - // Add all referenced proxies to the worklist. - for (OperationRecorder.RecordedOperation operation : recorder.getCurrentRecordedOperations()) { - worklistAdder.proxifyRecursive(operation.receiver()); - worklistAdder.proxifyRecursive(operation.args()); - Object result = operation.resultOrMarker(); - if (result instanceof SpecialResultMarker.ExceptionThrownMarker thrownMarker) { - worklistAdder.proxifyRecursive(thrownMarker.getThrown()); - } else if (!(result instanceof SpecialResultMarker)) { - worklistAdder.proxifyRecursive(result); - } - } - /* - * Perform and record the calls that could be needed during replay, except those that were - * already recorded during the compilation. - */ - while (!worklist.isEmpty()) { - Object receiver = worklist.removeLast(); - CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(receiver); - for (CompilerInterfaceDeclarations.MethodCallToRecord methodCall : registration.getMethodCallsToRecord(receiver)) { - OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(methodCall.receiver(), methodCall.symbolicMethod(), methodCall.args()); - if (recorder.getRecordedResultOrMarker(key) != SpecialResultMarker.NO_RESULT_MARKER) { - // The result of the call is already recorded. - continue; - } - try { - Object result = methodCall.invokableMethod().invoke(methodCall.receiver(), methodCall.args()); - recorder.recordReturnValue(key, result); - // Make sure to record the method calls for the results of this call as well. - worklistAdder.proxifyRecursive(result); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - recorder.recordExceptionThrown(key, cause); - worklistAdder.proxifyRecursive(cause); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Recording failed due to an exception", e); - } - } - } - return recorder.getCurrentRecordedOperations(); - } - - /** - * Enters the context of a method compilation for the current compilation thread. - * - * @return a scope for the context - */ - public DebugCloseable enterCompilationContext() { - return recorder.enterCompilationContext(); - } - - @Override - public DebugCloseable enterSnippetContext() { - return recorder.enterIgnoredContext(); - } - - @Override - public Platform targetPlatform() { - return Platform.ofCurrentHost(); - } - - @Override - public DebugCloseable withDebugContext(DebugContext debugContext) { - return DebugCloseable.VOID_CLOSEABLE; - } - - @Override - public CompilationProxy proxify(Object input) { - if (input instanceof CompilationProxy compilationProxy) { - return compilationProxy; - } - CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input); - if (registration == null) { - throw new IllegalArgumentException(input + " is not an instance of a registered class."); - } - return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> { - if (method.equals(CompilationProxyBase.unproxifyMethod)) { - return input; - } - Object[] unproxifiedArgs = (Object[]) unproxifyRecursive(args); - CompilerInterfaceDeclarations.MethodStrategy methodStrategy = registration.findStrategy(method); - OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(input, method, unproxifiedArgs); - Object result; - if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { - Object resultOrMarker = recorder.getRecordedResultOrMarker(key); - if (resultOrMarker instanceof SpecialResultMarker.ExceptionThrownMarker exceptionThrownMarker) { - throw (Throwable) proxifyRecursive(exceptionThrownMarker.getThrown()); - } else if (resultOrMarker == SpecialResultMarker.NULL_RESULT_MARKER) { - return null; - } else if (resultOrMarker != SpecialResultMarker.NO_RESULT_MARKER) { - return proxifyRecursive(resultOrMarker); - } - } - try { - result = callback.invoke(input, unproxifiedArgs); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { - recorder.recordExceptionThrown(key, cause); - } - throw (Throwable) proxifyRecursive(cause); - } catch (IllegalAccessException e) { - throw new IllegalStateException("Recording failed due to an exception", e); - } - if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { - recorder.recordReturnValue(key, result); - } - return proxifyRecursive(result); - }); - } - - @Override - public CompilerInterfaceDeclarations getDeclarations() { - return declarations; - } - - private Object proxifyRecursive(Object input) { - return proxyMapper.proxifyRecursive(input); - } - - private Object unproxifyRecursive(Object input) { - return proxyMapper.unproxifyRecursive(input); - } - - private static final CompilationProxy.SymbolicMethod getProfilingInfo = new CompilationProxy.SymbolicMethod(ResolvedJavaMethod.class, "getProfilingInfo", boolean.class, boolean.class); - - /** - * Injects profiling information for the given method. - *

- * Profiles can be injected when recording a retried compilation. All subsequent calls to - * {@link ResolvedJavaMethod#getProfilingInfo()} when the receiver is a proxy representing the - * given method will return the specified profiles. - * - * @param method the method to inject profiles into - * @param includeNormal whether to include normal profiles - * @param includeOSR whether to include OSR profiles - * @param profilingInfo the profiling information to inject - */ - public void injectProfiles(ResolvedJavaMethod method, boolean includeNormal, boolean includeOSR, ProfilingInfo profilingInfo) { - recorder.recordReturnValue(new OperationRecorder.RecordedOperationKey(method, getProfilingInfo, new Object[]{includeNormal, includeOSR}), profilingInfo); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java deleted file mode 100644 index 47b6fcc4d06b..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java +++ /dev/null @@ -1,618 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.io.Serial; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.List; -import java.util.Objects; - -import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Equivalence; - -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.debug.GlobalMetrics; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.debug.TimerKey; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; -import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; -import jdk.graal.compiler.options.Option; -import jdk.graal.compiler.options.OptionKey; -import jdk.graal.compiler.options.OptionType; -import jdk.graal.compiler.options.OptionValues; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.meta.Constant; - -//JaCoCo Exclude - -/** - * A holder and factory for compiler-interface proxies during a replayed compilation. - *

- * This class creates proxies for the classes registered in {@link CompilerInterfaceDeclarations}. - * The behavior of proxy method invocation is also specified in - * {@link CompilerInterfaceDeclarations}. In general, the proxies usually try to produce the same - * results as those from the recorded compilation. - *

- * The recorded operations (from a JSON file produced during the recorded compilation) are loaded - * using {@link #loadOperationResults}. This class creates a flat representation of the data to keep - * memory usage low, which is important when replaying many compilations on libgraal and - * benchmarking compile time. - *

- * It is necessary to call {@link #findLocalMirrors()} after the operations are loaded and JVMCI - * providers are created. The local mirrors may be required during a replayed compilation to query - * information from the local VM, which is needed for snippet parsing. - * - * @see ReplayCompilationSupport - */ -@LibGraalSupport.HostedOnly(unlessTrue = ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP) -public class ReplayCompilationProxies implements CompilationProxies { - public static class Options { - // @formatter:off - @Option(help = "Fail when there is no recorded result for a JVMCI operation during compilation replay.", type = OptionType.Debug) - public static final OptionKey ReplayDivergenceIsFailure = new OptionKey<>(false); - // @formatter:on - } - - /** - * Metadata for a proxy object. - */ - private static final class ProxyInfo { - /** - * The {@link #operationResults} index where the recorded operations for this proxy begin. - */ - private int resultsBegin; - - /** - * The {@link #operationResults} index where the recorded operations for this proxy end. - */ - private int resultsEnd; - - /** - * A local mirror identified for this proxy or {@code null}. - */ - private Object localMirror; - - private ProxyInfo() { - } - - public void setLocalMirror(Object newLocalMirror) { - localMirror = newLocalMirror; - } - } - - /** - * Declares which objects require a proxy (registered objects) and defines the behavior of - * method invocation. - */ - private final CompilerInterfaceDeclarations declarations; - - /** - * A flattened representation of the recorded operations and their results. This representation - * aims to save memory when replaying a large number of compilation units as a benchmark. - *

- * The recorded operations for a given proxy are stored as a subarray from - * {@link ProxyInfo#resultsBegin} to {@link ProxyInfo#resultsEnd}. The subarray is formed by - * multiple runs, each run corresponding to a particular symbolic method. The first element in - * every run is the corresponding method. - *

    - *
  • If the method is parameterless, the next (and last element) of the run is the return - * value.
  • - *
  • If the method has {@code p > 0} parameters, the next element is the number of records - * {@code r > 0}. This is followed by {@code r} records. Every record contains {@code p} - * argument elements and a single return value.
  • - *
- */ - private Object[] operationResults; - - /** - * A map of proxies created for singleton compiler-interface classes (as defined by - * {@link #declarations}). - */ - private final EconomicMap, CompilationProxy> singletonProxies; - - /** - * A map of compiler-interface singletons. - */ - private final EconomicMap, Object> singletonObjects; - - /** - * Proxifies and unproxifies composite objects. - */ - private final CompilationProxyMapper proxyMapper; - - /** - * Maps metadata to all created proxies. - */ - private final EconomicMap createdProxies; - - /** - * Maps local objects to created proxies. - */ - private final EconomicMap localMirrorToProxy; - - /** - * The platform of the target system. - */ - private Platform targetPlatform; - - /** - * The global metrics where the metrics from the current {@link #debug} context should be - * accumulated. - */ - private final GlobalMetrics globalMetrics; - - /** - * The debug information for the current context or {@code null}. - */ - private DebugContext debug; - - /** - * {@code true} if failing to find a recorded result should throw an exception. - */ - private final boolean divergenceIsFailure; - - @SuppressWarnings("this-escape") - public ReplayCompilationProxies(CompilerInterfaceDeclarations declarations, GlobalMetrics globalMetrics, OptionValues options) { - this.declarations = declarations; - this.singletonProxies = EconomicMap.create(); - this.singletonObjects = EconomicMap.create(); - this.proxyMapper = new CompilationProxyMapper(declarations, this::proxify); - this.createdProxies = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); - this.localMirrorToProxy = EconomicMap.create(); - this.globalMetrics = globalMetrics; - this.divergenceIsFailure = Options.ReplayDivergenceIsFailure.getValue(options); - } - - /** - * Sets the target platform for replay compilation. - * - * @param platform the target platform - */ - public void setTargetPlatform(Platform platform) { - targetPlatform = platform; - } - - @Override - public Platform targetPlatform() { - return targetPlatform; - } - - @Override - public DebugCloseable withDebugContext(DebugContext debugContext) { - debug = debugContext; - return () -> { - globalMetrics.add(debug); - debug = null; - }; - } - - /** - * Loads the recorded operations from a collection. - * - * @param operations the collection of recorded operations - * @param internPool the pool of interned objects - */ - public void loadOperationResults(Collection operations, EconomicMap internPool) { - /* - * Maps a proxy to another map, which will form the subarray of the recorded operations for - * the given proxy. - */ - EconomicMap>> results = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); - int length = 0; // the length of operationResults - for (OperationRecorder.RecordedOperation operation : operations) { - CompilationProxy proxy = (CompilationProxy) operation.receiver(); - /* - * Maps a method to the flattened records for the recorded invocations of the method - * using this proxy as a receiver. - */ - EconomicMap> proxyMap = results.get(proxy); - if (proxyMap == null) { - proxyMap = EconomicMap.create(); - results.put(proxy, proxyMap); - } - // The flattened records for this proxy. - List list = proxyMap.get(operation.method()); - if (list == null) { - list = new ArrayList<>(); - proxyMap.put(operation.method(), list); - ++length; - if (operation.method().hasParams()) { - ++length; - } - } - // Add a record for the given proxy and a method. - if (operation.method().hasParams()) { - // The record starts with the argument values. - for (Object arg : operation.args()) { - list.add(arg); - ++length; - } - } else if (!list.isEmpty()) { - // Redundant recorded operation, skipping. - continue; - } - // Finish the record by adding the return value. - list.add(operation.resultOrMarker()); - ++length; - } - operationResults = new Object[length]; - int index = 0; - var proxyCursor = createdProxies.getEntries(); - while (proxyCursor.advance()) { - // Begin the subarray with recorded operations for the given proxy. - CompilationProxy proxy = proxyCursor.getKey(); - ProxyInfo proxyInfo = proxyCursor.getValue(); - proxyInfo.resultsBegin = index; - var proxyMap = results.get(proxy); - if (proxyMap != null) { - var proxyMapCursor = proxyMap.getEntries(); - while (proxyMapCursor.advance()) { - CompilationProxy.SymbolicMethod method = proxyMapCursor.getKey(); - List list = proxyMapCursor.getValue(); - // Store the method at the beginning of a run. - operationResults[index++] = intern(method, internPool); - if (method.hasParams()) { - // For a method with parameters, store the number of records. - int recordCount = list.size() / (method.paramCount() + 1); - // Intern the boxed integer. - operationResults[index++] = intern(recordCount, internPool); - } else { - GraalError.guarantee(list.size() == 1, "records for parameterless methods contain only the return value"); - } - // Write the records (or just the return value if the method is parameterless). - for (Object object : list) { - operationResults[index++] = intern(object, internPool); - } - } - } - proxyInfo.resultsEnd = index; - } - } - - /** - * Interns the given object in the provided intern pool. - * - * @param object the object to be interned - * @param internPool the map used to store interned objects - * @return the interned object - */ - private static Object intern(Object object, EconomicMap internPool) { - if (object == null) { - return null; - } - if (object instanceof CompilationProxy || object instanceof Object[] || object instanceof TargetDescription) { - return object; - } - Object interned = internPool.get(object); - if (interned == null) { - interned = object; - internPool.put(interned, interned); - } - return interned; - } - - /** - * Finds local mirrors for all created proxies. - *

- * A local mirror of a proxy is a JVMCI object obtained from the host VM that is logically - * equivalent to the proxy. For example, for a given type proxy, we can find the local type with - * the same name. Local mirrors can be used to query information about the object if the - * information was not recorded in the JSON file. This is particularly useful for snippet - * parsing, which is intentionally not recorded. - *

- * During snippet parsing, the compiler may discover a JVMCI object which has no matching proxy. - * For such objects, local-only proxies are created using {@link #proxify(Object)}. - */ - public void findLocalMirrors() { - var cursor = createdProxies.getEntries(); - while (cursor.advance()) { - CompilationProxy proxy = cursor.getKey(); - CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(proxy); - if (registration.mirrorLocator() != null) { - Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, singletonObjects); - if (localMirror != null) { - Object previousProxy = localMirrorToProxy.put(localMirror, proxy); - GraalError.guarantee(previousProxy == null, "there must be at most one proxy instance for an object"); - ProxyInfo proxyInfo = cursor.getValue(); - proxyInfo.setLocalMirror(localMirror); - registerLocalMirrorsForConstantResults(proxyInfo); - } - } - } - } - - /** - * Registers the local mirrors for constant results of a given proxy object. - *

- * This method finds whether the object has any getters that returns a proxy representing a - * constant. If so, it invokes the getters on the local mirror of the proxy object to obtain the - * local mirror of the constant proxy. - * - * @param proxyInfo metadata for the proxy object - */ - private void registerLocalMirrorsForConstantResults(ProxyInfo proxyInfo) { - for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { - CompilationProxy.SymbolicMethod method = (CompilationProxy.SymbolicMethod) operationResults[i++]; - if (method.hasParams()) { - int entries = (Integer) operationResults[i++]; - i += (method.paramCount() + 1) * entries; - } else { - Object result = operationResults[i++]; - if (!(result instanceof Constant)) { - continue; - } - Object receiver = proxyInfo.localMirror; - CompilationProxy.InvokableMethod invokable = declarations.findRegistrationForInstance(receiver).findInvokableMethod(method); - if (invokable == null) { - continue; - } - Object localMirror; - try { - localMirror = invokable.invoke(receiver, new Object[0]); - } catch (Exception ignored) { - continue; - } - createdProxies.get((CompilationProxy) result).setLocalMirror(localMirror); - } - } - } - - @Override - public CompilationProxy proxify(Object input) { - if (input instanceof CompilationProxy compilationProxy) { - return compilationProxy; - } - CompilationProxy proxy = localMirrorToProxy.get(input); - if (proxy != null) { - return proxy; - } - CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input); - GraalError.guarantee(registration != null, "the input must be an instance of a registered class"); - proxy = createProxy(registration); - ProxyInfo proxyInfo = createdProxies.get(proxy); - proxyInfo.setLocalMirror(input); - localMirrorToProxy.put(input, proxy); - if (registration.singleton()) { - singletonObjects.put(registration.clazz(), input); - } - return proxy; - } - - @Override - public CompilerInterfaceDeclarations getDeclarations() { - return declarations; - } - - @Override - public DebugCloseable enterSnippetContext() { - return DebugCloseable.VOID_CLOSEABLE; - } - - private static final TimerKey JVMCIReplayTime = DebugContext.timer("JVMCIReplayTime"); - - private static final class NotUnproxifiableException extends RuntimeException { - @Serial private static final long serialVersionUID = -4899571461334839074L; - } - - /** - * Creates a new proxy object for a specific registered compiler-interface class. - * - * @param registration a registration for a compiler-interface class - * @return a new proxy object - */ - @SuppressWarnings("try") - public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration) { - if (registration.singleton()) { - CompilationProxy found = singletonProxies.get(registration.clazz()); - if (found != null) { - return found; - } - } - ProxyInfo proxyInfo = new ProxyInfo(); - CompilationProxy instance = CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> { - try (DebugCloseable ignored = (debug == null) ? null : JVMCIReplayTime.start(debug)) { - if (method.equals(CompilationProxyBase.unproxifyMethod)) { - Object localMirror = proxyInfo.localMirror; - if (localMirror == null) { - throw new NotUnproxifiableException(); - } - return localMirror; - } else if (method.equals(CompilationProxyBase.equalsMethod)) { - return proxy == args[0]; - } else if (method.equals(CompilationProxyBase.hashCodeMethod)) { - return System.identityHashCode(proxy); - } - Object input; - if (registration.singleton()) { - input = singletonObjects.get(registration.clazz()); - } else { - input = null; - } - CompilerInterfaceDeclarations.MethodStrategy strategy = registration.findStrategy(method); - if (strategy == CompilerInterfaceDeclarations.MethodStrategy.Passthrough) { - if (proxyInfo.localMirror == null) { - CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); - if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); - } - } - GraalError.guarantee(proxyInfo.localMirror != null, "a proxy with passthrough strategy must have a local mirror or fallback handler"); - return callback.invoke(proxyInfo.localMirror, args); - } else if (strategy == CompilerInterfaceDeclarations.MethodStrategy.DefaultValue) { - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); - } - Object result = findResult(proxyInfo, method, args); - if (result != SpecialResultMarker.NO_RESULT_MARKER) { - if (result instanceof SpecialResultMarker marker) { - // We proxify the result due to objects with delayed deserialization. - return proxyMapper.proxifyRecursive(marker.materialize()); - } else { - return proxyMapper.proxifyRecursive(result); - } - } - try { - Object[] unproxifiedArgs = (Object[]) proxyMapper.unproxifyRecursive(args); - if (registration.singleton()) { - return proxyMapper.proxifyRecursive(callback.invoke(input, unproxifiedArgs)); - } - Object localMirror = proxyInfo.localMirror; - if (localMirror != null) { - return proxyMapper.proxifyRecursive(callback.invoke(localMirror, unproxifiedArgs)); - } - } catch (NotUnproxifiableException ignored2) { - // Cannot unproxify the arguments: continue. - } catch (InvocationTargetException exception) { - // The result of the invocation is a thrown exception. - throw exception.getTargetException(); - } - CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); - if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); - } - if (args != null) { - for (Object arg : args) { - if (arg instanceof CompilationProxy unproxifiable) { - GraalError.guarantee(createdProxies.containsKey(unproxifiable), "a proxy argument was not created by this instance"); - } - } - } - if (divergenceIsFailure) { - failOnDivergence(proxy, proxyInfo, method, args); - } - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); - } - }); - if (registration.singleton()) { - singletonProxies.put(registration.clazz(), instance); - } - createdProxies.put(instance, proxyInfo); - return instance; - } - - /** - * Finds the recorded result for a given method invocation on a proxy object. - *

- * This method iterates over the recorded operations for the proxy object and checks if the - * method and arguments match the recorded operation. If a match is found, it returns the - * recorded result. If no match is found, it returns - * {@link SpecialResultMarker#NO_RESULT_MARKER}. - * - * @param proxyInfo metadata for the proxy object - * @param method the symbolic method being invoked - * @param args the arguments passed to the method invocation - * @return the recorded result or {@link SpecialResultMarker#NO_RESULT_MARKER} if not found - */ - private Object findResult(ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method, Object[] args) { - for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { - CompilationProxy.SymbolicMethod resultMethod = (CompilationProxy.SymbolicMethod) operationResults[i++]; - if (resultMethod.hasParams()) { - int entries = (Integer) operationResults[i++]; - if (!method.equals(resultMethod)) { - i += (resultMethod.paramCount() + 1) * entries; - continue; - } - entry: for (int j = 0; j < entries; j++) { - for (int k = 0; k < method.paramCount(); k++) { - Object arg = operationResults[i++]; - if (!Objects.equals(args[k], arg)) { - i += method.paramCount() - k; - continue entry; - } - } - return operationResults[i]; - } - } else { - if (!method.equals(resultMethod)) { - ++i; - continue; - } - return operationResults[i]; - } - return SpecialResultMarker.NO_RESULT_MARKER; - } - return SpecialResultMarker.NO_RESULT_MARKER; - } - - /** - * Throws an exception when a recorded result is not found for a given method invocation during - * replay compilation. - * - * @param proxy the proxy object on which the method was invoked - * @param proxyInfo metadata for the proxy object - * @param method the symbolic method being invoked - * @param args the arguments passed to the method invocation - * @throws GraalError always thrown to indicate the divergence - */ - private void failOnDivergence(Object proxy, ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method, Object[] args) { - StringBuilder sb = new StringBuilder(); - sb.append("No result for ").append(method).append('[').append(Arrays.toString(args)).append(']').append(System.lineSeparator()); - formatRecordedOperations(sb, proxyInfo, method); - if (!method.equals(CompilationProxyBase.toStringMethod)) { - sb.append("Receiver: ").append(proxy).append(System.lineSeparator()); - } - sb.append("Local mirror: ").append(proxyInfo.localMirror).append(System.lineSeparator()); - throw new GraalError(sb.toString()); - } - - /** - * Formats the recorded operations for a given proxy object and method into a string builder. - *

- * This method iterates over the recorded operations for the proxy object and appends the - * available keys for the given method to the string builder. - * - * @param sb the string builder to append the formatted recorded operations to - * @param proxyInfo metadata for the proxy object - * @param method the symbolic method being invoked - */ - private void formatRecordedOperations(StringBuilder sb, ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method) { - for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { - CompilationProxy.SymbolicMethod resultMethod = (CompilationProxy.SymbolicMethod) operationResults[i++]; - if (resultMethod.hasParams()) { - int entries = (Integer) operationResults[i++]; - if (!method.equals(resultMethod)) { - i += (resultMethod.paramCount() + 1) * entries; - continue; - } - for (int j = 0; j < entries; j++) { - Object[] args = new Object[method.paramCount()]; - for (int k = 0; k < method.paramCount(); k++) { - args[k] = operationResults[i++]; - } - i++; - sb.append(" Available key: ").append(method).append('[').append(Arrays.toString(args)).append(']').append(System.lineSeparator()); - } - } else { - ++i; - } - return; - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java deleted file mode 100644 index 025e14ab43d3..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java +++ /dev/null @@ -1,495 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import java.io.Closeable; -import java.io.FileReader; -import java.io.IOException; -import java.io.PrintStream; -import java.io.Serial; -import java.nio.file.FileVisitResult; -import java.nio.file.FileVisitor; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; - -import org.graalvm.collections.EconomicMap; - -import jdk.graal.compiler.core.GraalCompilerOptions; -import jdk.graal.compiler.core.common.GraalOptions; -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.debug.GlobalMetrics; -import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; -import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; -import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; -import jdk.graal.compiler.hotspot.HotSpotGraalOptionValues; -import jdk.graal.compiler.hotspot.HotSpotGraalRuntime; -import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.util.args.BooleanValue; -import jdk.graal.compiler.util.args.IntegerValue; -import jdk.graal.compiler.util.args.OptionValue; -import jdk.graal.compiler.util.args.Program; -import jdk.graal.compiler.util.args.StringValue; -import jdk.graal.compiler.util.json.JsonParserException; -import jdk.vm.ci.code.CompilationRequest; -import jdk.vm.ci.code.CompilationRequestResult; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; - -//JaCoCo Exclude - -/** - * The entry point for running replay compilations in jargraal and libgraal. - * - * @see ReplayCompilationSupport - * @see CompilerInterfaceDeclarations - */ -@LibGraalSupport.HostedOnly(unlessTrue = ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP) -public class ReplayCompilationRunner { - /** - * The exit status of a replay compilation run. - */ - public enum ExitStatus { - /** - * Successful execution. - */ - Success(0), - - /** - * Failed execution. - */ - Failure(1); - - private final int status; - - ExitStatus(int status) { - this.status = status; - } - - /** - * Exits the virtual machine with the corresponding status code. - */ - public void exitVM() { - System.exit(status); - } - - /** - * Returns the exit status code. - */ - public int getStatus() { - return status; - } - } - - /** - * Runs the replay compilation launcher based on the provided command-line arguments. - * - * @param args command-line arguments - * @param out output stream for printing messages - * @return the exit status of the launcher - */ - @SuppressWarnings("try") - public static ExitStatus run(String[] args, PrintStream out) { - Program program = new Program("mx replaycomp", "Replay compilations from files."); - OptionValue benchmarkArg = program.addNamed("--benchmark", new BooleanValue("true|false", false, "Replay compilations as a benchmark.")); - OptionValue iterationsArg = program.addNamed("--iterations", new IntegerValue("n", 10, "The number of benchmark iterations.")); - OptionValue compareGraphsArg = program.addNamed("--compare-graphs", new BooleanValue("true|false", false, "Verify that the replayed graph equals the recorded one.")); - OptionValue inputPathArg = program.addPositional(new StringValue("TARGET", "Path to a directory with replay compilation files (or path to a single file).")); - program.parseAndValidate(args, true); - Path inputPath = Path.of(inputPathArg.getValue()); - List inputFiles; - try { - inputFiles = findJsonFiles(inputPath); - } catch (IOException e) { - out.println(e.getMessage()); - return ExitStatus.Failure; - } - if (inputFiles.isEmpty()) { - out.println("No replay files found in " + inputPath); - return ExitStatus.Failure; - } - - OptionValues systemOptions = new OptionValues(HotSpotGraalOptionValues.parseOptions()); - OptionValues options = new OptionValues(systemOptions, GraalCompilerOptions.SystemicCompilationFailureRate, 0); - CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); - HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); - CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options, runtime); - - LibGraalSupport libgraal = LibGraalSupport.INSTANCE; - GlobalMetrics globalMetrics = new GlobalMetrics(); - if (benchmarkArg.getValue()) { - List reproducers = new ArrayList<>(); - EconomicMap internPool = EconomicMap.create(); - for (Path file : inputFiles) { - try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { - try { - reproducers.add(Reproducer.initializeFromFile(file.toString(), declarations, runtime, options, - factory, globalMetrics, out, internPool)); - } catch (Exception e) { - out.println("Preparation failed for " + file + ": " + e); - } - } catch (Exception e) { - return ExitStatus.Failure; - } - } - internPool.clear(); - Runtime javaRuntime = Runtime.getRuntime(); - for (int i = 0; i < iterationsArg.getValue(); i++) { - out.printf("====== replaycomp iteration %d started ======%n", i); - double memBefore = (javaRuntime.totalMemory() - javaRuntime.freeMemory()) / 1_000_000d; - long before = System.nanoTime(); - System.gc(); - long afterGC = System.nanoTime(); - double memAfter = (javaRuntime.totalMemory() - javaRuntime.freeMemory()) / 1_000_000d; - double gcMillis = (afterGC - before) / 1_000_000d; - out.printf("GC before operation: completed in %.3f ms, heap usage %.3f MB -> %.3f MB.%n", gcMillis, memBefore, memAfter); - int codeHash = 0; - for (Reproducer reproducer : reproducers) { - try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { - ReplayResult replayResult = reproducer.compile(); - replayResult.verify(compareGraphsArg.getValue()); - codeHash = codeHash * 31 + Arrays.hashCode(replayResult.replayedArtifacts().result().getTargetCode()); - } catch (Exception e) { - out.println("Replay failed: " + e); - return ExitStatus.Failure; - } - } - out.printf("Compiled code hash: %d%n", codeHash); - long after = System.nanoTime(); - double iterMillis = (after - before) / 1_000_000d; - out.printf("====== replaycomp iteration %d completed (%.3f ms) ======%n", i, iterMillis); - } - for (Reproducer reproducer : reproducers) { - reproducer.close(); - } - } else { - ReplayCompilationStatistics statistics = new ReplayCompilationStatistics(); - for (Path file : inputFiles) { - ReplayCompilationTask task = statistics.startTask(file.toString()); - try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null; - Reproducer reproducer = Reproducer.initializeFromFile(file.toString(), declarations, runtime, - options, factory, globalMetrics, out, EconomicMap.create())) { - reproducer.compile().verify(compareGraphsArg.getValue()); - out.println("Successfully replayed " + reproducer.request); - } catch (ReplayParserFailure failure) { - out.println("Replay failed: " + failure.getMessage()); - task.setFailureReason(failure.getMessage()); - } catch (Exception e) { - out.println("Replay failed: " + e); - return ExitStatus.Failure; - } - } - out.println(); - statistics.printStatistics(out); - } - globalMetrics.print(options); - return ExitStatus.Success; - } - - /** - * Recursively searches for JSON files within the given root directory (or file) and its - * subdirectories. The returned list of paths is sorted lexicographically to ensure consistency - * between runs. - * - * @param root the root directory/file to start the search from - * @return a list of paths to JSON files found within the root directory/file and its - * subdirectories - * @throws IOException if an I/O error occurs while traversing the file tree - */ - private static List findJsonFiles(Path root) throws IOException { - List paths = new ArrayList<>(); - Files.walkFileTree(root, new FileVisitor<>() { - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { - if (Files.isRegularFile(file) && file.toString().endsWith(".json")) { - paths.add(file); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFileFailed(Path file, IOException exc) { - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) { - return FileVisitResult.CONTINUE; - } - }); - paths.sort(Path::compareTo); - return paths; - } - - public static sealed class ReplayLauncherFailure extends Exception { - @Serial private static final long serialVersionUID = -1610853593485835928L; - - public ReplayLauncherFailure(String message) { - super(message); - } - } - - private static final class ReplayParserFailure extends ReplayLauncherFailure { - @Serial private static final long serialVersionUID = 6521004798119106469L; - - ReplayParserFailure(String message) { - super(message); - } - } - - /** - * The result of a single replay compilation. - * - * @param request the compilation request for the replay compilation - * @param result the result of the replayed compilation - * @param replayedArtifacts the artifacts produced by the replayed compilation - * @param originalGraph the canonical graph string of the final original graph (if available) - */ - public record ReplayResult(CompilationRequest request, CompilationRequestResult result, ReplayCompilationSupport.CompilationArtifacts replayedArtifacts, String originalGraph) { - public void verify(boolean verifyGraphs) throws ReplayLauncherFailure { - if (result.getFailure() == null) { - if (!verifyGraphs) { - return; - } - if (originalGraph == null) { - throw new ReplayLauncherFailure("Cannot verify the replayed graph for " + request); - } else if (!originalGraph.equals(replayedArtifacts.finalCanonicalGraph())) { - throw new ReplayLauncherFailure("Replay completed but final graphs differ"); - } - } else { - throw new ReplayLauncherFailure(Objects.toString(result.getFailure())); - } - } - } - - /** - * A recorded compilation that is ready to be compiled (potentially multiple times). - */ - public static final class Reproducer implements Closeable { - /** - * The compiler instance used for replaying the compilation. - */ - private final HotSpotGraalCompiler replayCompiler; - - /** - * The compilation request for the replayed compilation. - */ - private final HotSpotCompilationRequest request; - - /** - * The final graph of the recorded compilation. - */ - private final String finalGraph; - - /** - * The compiler options for replay. - */ - private final OptionValues options; - - /** - * Whether the recorded compilation was performed on libgraal. - */ - private final boolean isLibgraal; - - private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options, - boolean isLibgraal) { - this.replayCompiler = replayCompiler; - this.request = request; - this.finalGraph = finalGraph; - this.options = options; - this.isLibgraal = isLibgraal; - } - - /** - * Creates a new reproducer instance from a JSON file. - * - * @param fileName the name of the JSON file containing the recorded compilation - * @param declarations describes the compiler interface - * @param runtime the JVMCI runtime - * @param options the options for the replay compiler - * @param factory the factory used to create the compiler configuration - * @param globalMetrics the metrics object where metrics from the replayed compilations are - * accumulated - * @param out stream for debug output - * @param internPool the pool of interned objects - * @return a new reproducer instance - * @throws ReplayLauncherFailure if an error occurs during initialization - */ - @SuppressWarnings("try") - public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDeclarations declarations, HotSpotJVMCIRuntime runtime, - OptionValues options, CompilerConfigurationFactory factory, GlobalMetrics globalMetrics, PrintStream out, EconomicMap internPool) throws ReplayLauncherFailure { - ReplayCompilationProxies proxies = new ReplayCompilationProxies(declarations, globalMetrics, options); - out.println("Loading " + fileName); - RecordedOperationPersistence.RecordedCompilationUnit compilationUnit; - try (FileReader reader = new FileReader(fileName)) { - RecordedOperationPersistence persistence = new RecordedOperationPersistence(declarations, Platform.ofCurrentHost(), - HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); - compilationUnit = persistence.load(reader, proxies::createProxy); - proxies.setTargetPlatform(compilationUnit.platform()); - proxies.loadOperationResults(compilationUnit.operations(), internPool); - } catch (Exception exception) { - if (exception instanceof JsonParserException parserException && parserException.isAtEOF().isTrue()) { - throw new ReplayParserFailure("Failed to parse an incomplete JSON file (likely caused by VM shutdown during the recorded compilation)."); - } - throw new ReplayParserFailure("Parsing failed due to " + exception.getMessage()); - } - HotSpotCompilationRequest request = compilationUnit.request(); - boolean replayingLibgraalInJargraal = !LibGraalSupport.inLibGraalRuntime() && compilationUnit.isLibgraal(); - ReplayCompilationSupport.setReplayingLibgraalInJargraal(replayingLibgraalInJargraal); - if (LibGraalSupport.inLibGraalRuntime() && !compilationUnit.isLibgraal()) { - throw new ReplayLauncherFailure("Cannot replay jargraal compilation " + request + " in libgraal"); - } - boolean encodeSnippets = replayingLibgraalInJargraal && !HotSpotReplacementsImpl.snippetsAreEncoded(); - if (encodeSnippets) { - /* - * Ensure the snippet encoder will be created and linked to the decorated providers - * created below. - */ - HotSpotReplacementsImpl.clearSnippetEncoder(); - } - OptionValues selectedOptions = options; - if (replayingLibgraalInJargraal) { - selectedOptions = new OptionValues(options, GraalOptions.EagerSnippets, true); - } - out.println("Initializing the replay compiler for " + request); - HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, selectedOptions, factory, new ReplayCompilationSupport(proxies, factory.getName())); - HotSpotGraalRuntimeProvider graalRuntime = replayCompiler.getGraalRuntime(); - if (!graalRuntime.getCompilerConfigurationName().equals(compilationUnit.compilerConfiguration())) { - throw new ReplayLauncherFailure(("Compiler configuration mismatch: the task was compiled using " + compilationUnit.compilerConfiguration() + - " but the initialized compiler is " + graalRuntime.getCompilerConfigurationName())); - } - ReplayCompilationSupport support = graalRuntime.getReplayCompilationSupport(); - support.setRecordedForeignCallLinkages(compilationUnit.linkages()); - if (encodeSnippets) { - out.println("Encoding snippets"); - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) graalRuntime.getHostProviders().getReplacements(); - replacements.encode(graalRuntime.getOptions()); - } - return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), selectedOptions, compilationUnit.isLibgraal()); - } - - /** - * Compiles (or recompiles) the method using the recorded data. - * - * @return a replay result object containing the compilation result and the replayed graph - */ - @SuppressWarnings("try") - public ReplayResult compile() { - ReplayCompilationSupport.setReplayingLibgraalInJargraal(!LibGraalSupport.inLibGraalRuntime() && isLibgraal); - ReplayCompilationSupport support = replayCompiler.getGraalRuntime().getReplayCompilationSupport(); - CompilationRequestResult result = replayCompiler.compileMethod(request, true, options); - ReplayCompilationSupport.CompilationArtifacts replayedArtifacts = support.clearCompilationArtifacts(); - return new ReplayResult(request, result, replayedArtifacts, finalGraph); - } - - /** - * Shuts down the {@link HotSpotGraalRuntime} associated with this reproducer. - */ - @Override - public void close() { - ((HotSpotGraalRuntime) replayCompiler.getGraalRuntime()).shutdown(); - } - } - - /** - * Tracks the outcome of a single replayed compilation. - */ - private static class ReplayCompilationTask { - private final String fileName; - - private boolean success; - - private String failureReason; - - ReplayCompilationTask(String fileName) { - this.fileName = fileName; - this.success = true; - } - - public void setFailureReason(String newFailureReason) { - failureReason = newFailureReason; - success = false; - } - - public boolean isSuccess() { - return success; - } - - public boolean isFailure() { - return !success; - } - } - - /** - * Tracks the outcomes of all replayed compilations, which is used to print summary statistics - * at the end. - */ - private static class ReplayCompilationStatistics { - private final List tasks; - - ReplayCompilationStatistics() { - this.tasks = new ArrayList<>(); - } - - public ReplayCompilationTask startTask(String fileName) { - ReplayCompilationTask task = new ReplayCompilationTask(fileName); - tasks.add(task); - return task; - } - - public void printStatistics(PrintStream out) { - out.printf("Completed %d replay compilation task(s)%n", tasks.size()); - out.printf("%8d task(s) succeeded%n", successCount()); - out.printf("%8d task(s) failed%n", failureCount()); - for (ReplayCompilationTask task : failedTasks()) { - out.printf(" %s %s%n", task.fileName, task.failureReason); - } - } - - private long successCount() { - return tasks.stream().filter(ReplayCompilationTask::isSuccess).count(); - } - - private long failureCount() { - return tasks.stream().filter(ReplayCompilationTask::isFailure).count(); - } - - private List failedTasks() { - return tasks.stream().filter(ReplayCompilationTask::isFailure).toList(); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java deleted file mode 100644 index 19b390fea953..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java +++ /dev/null @@ -1,502 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; - -import java.nio.file.Path; -import java.util.function.Predicate; - -import jdk.graal.compiler.code.CompilationResult; -import jdk.graal.compiler.core.common.CompilerProfiler; -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.core.common.spi.ForeignCallSignature; -import jdk.graal.compiler.debug.DebugCloseable; -import jdk.graal.compiler.debug.DebugContext; -import jdk.graal.compiler.debug.DebugOptions; -import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.debug.MethodFilter; -import jdk.graal.compiler.debug.PathUtilities; -import jdk.graal.compiler.debug.TTY; -import jdk.graal.compiler.hotspot.HotSpotBackendFactory; -import jdk.graal.compiler.hotspot.HotSpotDecoratedBackendFactory; -import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; -import jdk.graal.compiler.hotspot.Platform; -import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; -import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.nodes.StructuredGraph; -import jdk.graal.compiler.options.OptionValues; -import jdk.graal.compiler.printer.CanonicalStringGraphPrinter; -import jdk.graal.compiler.replacements.SnippetTemplate; -import jdk.graal.compiler.serviceprovider.GraalServices; -import jdk.graal.compiler.util.json.JsonWriter; -import jdk.vm.ci.hotspot.HotSpotCompilationRequest; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; - -/** - * Provides support for recording and replaying compilations, acting as an interface between the - * compiler and the internal implementation of replay compilation. - * - *

- * Recording is enabled using {@link DebugOptions#RecordForReplay}. Replay compilations are executed - * by the {@link ReplayCompilationRunner}. It is not a goal to execute the replayed code. - * - *

- * Proxies. Recording and replay require creating proxies for JVMCI objects. During - * recording, these proxies record the arguments and results of methods to serialize them into a - * JSON file ({@link RecordedOperationPersistence}). During replay, they look up and return the - * appropriate results. The behavior of every proxy and method is configured in - * {@link CompilerInterfaceDeclarations}. - * - *

- * Decorators. To enable recording and replay, we create service providers that return the - * appropriate proxies. This is achieved by decorating the backend factory - * {@link #decorateBackendFactory}. Moreover, {@link #decorateCompilationRequest}, - * {@link #decorateCompilerProfiler}, {@link #decorateVMConfigAccess}, and - * {@link #decorateIntrinsificationTrustPredicate} return proxies for additional objects. - * - *

- * Compiler Instances. Since we hijack the compiler's backend factory, a dedicated compiler - * instance must be created for recording and replay. To modify the compiler's behavior even from - * places where an instance of this class cannot be reasonably obtained, this class tracks whether - * the current compiler thread is performing a replay of a libgraal compilation in jargraal - * ({@link #isReplayingLibgraalInJargraal()}) and whether it is in a snippet context - * ({@link #isInSnippetContext()}). During recording, separate compiler instances should be used for - * the recorded methods ({@link #matchesRecordCompilationFilter}) and the methods that are not - * recorded. This ensures that the recording overhead is paid for the recorded methods only. - * - *

- * Snippets. It is possible to record a libgraal compilation and replay it on jargraal. To - * ensure the replayed compilation matches the recorded one, we replay such compilations using - * encoded snippets ({@link #isReplayingLibgraalInJargraal()}). We must never mix raw JVMCI object - * and JVMCI proxies in a single graph, so we create proxies even during snippet parsing. Due to the - * need to replay libgraal compilations on jargraal and since snippets are compiler code rather than - * application code, the proxies do not record the operations during snippet parsing (i.e., inside - * snippet context {@link #enterSnippetContext}). When snippets are parsed during replay, the - * proxies may use local mirrors to query the information required for the snippets from the host VM - * instance. - * - *

- * Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the - * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that - * was not recorded, including the information to parse snippets. There are also local-only proxies - * that do not originate from the recorded JSON but are instead created from local JVMCI objects - * (created using {@link CompilationProxies#proxify}). The exact rules when operations are delegated - * to local mirrors are dictated by the strategies defined in {@link CompilerInterfaceDeclarations}. - * - *

- * Foreign Call Linkages. During recording, we capture the addresses and killed registers of - * finalized foreign calls ({@link RecordedForeignCallLinkages}). During replay, we restore these - * linkages ({@link #finalizeForeignCallLinkage}) to ensure that the machine code compiled during - * replay is close to the code compiled during recording. - */ -public final class ReplayCompilationSupport { - /** - * Libgraal build-time system property name for enabling the replay compilation launcher. - */ - public static final String ENABLE_REPLAY_LAUNCHER_PROP = "debug.jdk.graal.enableReplayLauncher"; - - /** - * Whether the replay compilation launcher is enabled in libgraal. - */ - public static final boolean ENABLE_REPLAY_LAUNCHER = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_REPLAY_LAUNCHER_PROP)); - - /** - * Returns whether this compiler thread is replaying a libgraal compilation in jargraal. - */ - public static boolean isReplayingLibgraalInJargraal() { - return !inRuntimeCode() && isReplayingLibgraalInJargraal.get(); - } - - /** - * Sets whether the current compiler thread is replaying a libgraal compilation in jargraal. - * - * @param replayingLibgraalInJargraal true if the current compiler thread is replaying a - * libgraal compilation in jargraal, false otherwise - */ - public static void setReplayingLibgraalInJargraal(boolean replayingLibgraalInJargraal) { - if (replayingLibgraalInJargraal) { - GraalError.guarantee(!inRuntimeCode(), "this option is only valid in jargraal"); - } - ReplayCompilationSupport.isReplayingLibgraalInJargraal.set(replayingLibgraalInJargraal); - } - - /** - * Checks whether the given method's compilation should be recorded according to the given - * options. - * - * @param options the option values - * @param method the method to check against the filter - * @return true if the method's compilation should be recorded - */ - public static boolean matchesRecordCompilationFilter(OptionValues options, ResolvedJavaMethod method) { - String filter = DebugOptions.RecordForReplay.getValue(options); - if (filter == null) { - return false; - } else { - return MethodFilter.parse(filter).matches(method); - } - } - - /** - * Whether the current compiler thread is replaying a libgraal compilation in jargraal. - */ - private static final ThreadLocal isReplayingLibgraalInJargraal = ThreadLocal.withInitial(() -> false); - - /** - * The proxies used for recording/replaying the compilations. - */ - private final CompilationProxies proxies; - - /** - * The compiler's foreign call provider. - */ - private HotSpotHostForeignCallsProvider foreignCallsProvider; - - /** - * Recorded foreign call linkages used to finalize foreign calls. - */ - private RecordedForeignCallLinkages recordedForeignCallLinkages; - - /** - * Whether the compiler thread is in a snippet context. - */ - private final ThreadLocal inSnippetContext = ThreadLocal.withInitial(() -> false); - - /** - * The compilation artifacts of the current compiler thread. - */ - private final ThreadLocal compilationArtifacts = ThreadLocal.withInitial(() -> null); - - /** - * The compiler's configuration name. - */ - private final String compilerConfigurationName; - - ReplayCompilationSupport(CompilationProxies proxies, String compilerConfigurationName) { - this.proxies = proxies; - this.compilerConfigurationName = compilerConfigurationName; - } - - /** - * Creates a replay compilation support for a recording compiler. - * - * @param compilerConfigurationName the name of the compiler's configuration - * @return the support for a recording compiler - */ - public static ReplayCompilationSupport createRecording(String compilerConfigurationName) { - return new ReplayCompilationSupport(new RecordingCompilationProxies(CompilerInterfaceDeclarations.build()), compilerConfigurationName); - } - - /** - * Sets the foreign calls provider of the compiler bound to this instance. - * - * @param newForeignCallsProvider the compiler's foreign calls provider - */ - public void setForeignCallsProvider(HotSpotHostForeignCallsProvider newForeignCallsProvider) { - foreignCallsProvider = newForeignCallsProvider; - } - - /** - * Sets the recorded foreign calls linkages to be used to finalize foreign calls. - * - * @param linkages recorded linkages - */ - public void setRecordedForeignCallLinkages(RecordedForeignCallLinkages linkages) { - recordedForeignCallLinkages = linkages; - } - - /** - * Filters the given options to remove any that are not allowed during recording. - * - * @param options the options to filter - * @return the filtered options - */ - public OptionValues filterOptions(OptionValues options) { - if (proxies instanceof RecordingCompilationProxies) { - // GraalOptions.UseSnippetGraphCache can remain enabled. - return new OptionValues(options, SnippetTemplate.Options.UseSnippetTemplateCache, false); - } else { - return options; - } - } - - /** - * Enters a snippet context for the current compiler thread. In a recorded compilation, the - * proxies should not record JVMCI calls and results related to snippet parsing and - * optimization. In a replayed compilation, the proxies can delegate to the local mirrors to - * handle JVMCI calls. - * - * @return a debug closeable that should be closed when exiting the context - */ - private DebugCloseable enterSnippetContext() { - boolean previous = inSnippetContext.get(); - inSnippetContext.set(true); - DebugCloseable closeable = proxies.enterSnippetContext(); - return () -> { - inSnippetContext.set(previous); - closeable.close(); - }; - } - - /** - * Enters a snippet context for the given providers. - *

- * If the providers have a non-null {@link ReplayCompilationSupport} instance, this method - * enters a snippet context for the current compiler thread. Otherwise, it returns {@code null}. - * - * @param providers the providers to check for {@link ReplayCompilationSupport} - * @return a scope representing the snippet context, or {@code null} if not supported - */ - public static DebugCloseable enterSnippetContext(HotSpotProviders providers) { - return enterSnippetContext(providers.getReplayCompilationSupport()); - } - - /** - * Enters a snippet context for the given {@link ReplayCompilationSupport} instance. - *

- * If the provided {@code support} is not {@code null}, this method enters a snippet context for - * the current compiler thread. Otherwise, it returns {@code null}. - * - * @param support the instance to check - * @return a scope representing the snippet context, or {@code null} if not supported - */ - public static DebugCloseable enterSnippetContext(ReplayCompilationSupport support) { - if (support == null) { - return null; - } else { - return support.enterSnippetContext(); - } - } - - /** - * Returns whether this compiler thread is in a snippet context. - */ - public boolean isInSnippetContext() { - return inSnippetContext.get(); - } - - /** - * Enters a scope with a given debug context. - * - * @param debug the debug context to use in the scope - * @return an object that closes the scope - */ - public DebugCloseable withDebugContext(DebugContext debug) { - return proxies.withDebugContext(debug); - } - - /** - * Enters a compilation context for the specified compilation request. - * - * @param originalRequest the original compilation request - * @param initialOptions the initial options for the compilation - * @return a debug closeable that should be closed after the compilation - */ - public DebugCloseable enterCompilationContext(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { - if (proxies instanceof RecordingCompilationProxies recordingCompilationProxies) { - DebugCloseable context = recordingCompilationProxies.enterCompilationContext(); - return () -> { - try { - serializeRecordedCompilation(originalRequest, initialOptions); - } finally { - context.close(); - } - }; - } else { - return DebugCloseable.VOID_CLOSEABLE; - } - } - - private void serializeRecordedCompilation(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { - RecordedForeignCallLinkages linkages = RecordedForeignCallLinkages.createFrom(foreignCallsProvider); - try { - String directory = PathUtilities.getPath(DebugOptions.getDumpDirectory(initialOptions), "replaycomp"); - PathUtilities.createDirectories(directory); - String requestId = Integer.toString(originalRequest.getId()); - String fileName = requestId + ".json"; - Path path = Path.of(directory, fileName); - RecordedOperationPersistence persistence = new RecordedOperationPersistence(proxies.getDeclarations(), Platform.ofCurrentHost(), - HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); - RecordingCompilationProxies recordingCompilationProxies = (RecordingCompilationProxies) proxies; - CompilationArtifacts artifacts = clearCompilationArtifacts(); - String finalCanonicalGraph = (artifacts == null) ? null : artifacts.finalCanonicalGraph(); - RecordedOperationPersistence.RecordedCompilationUnit compilationUnit = new RecordedOperationPersistence.RecordedCompilationUnit(originalRequest, compilerConfigurationName, - LibGraalSupport.inLibGraalRuntime(), recordingCompilationProxies.targetPlatform(), linkages, finalCanonicalGraph, - recordingCompilationProxies.collectOperationsForSerialization()); - try (JsonWriter jsonWriter = new JsonWriter(path)) { - persistence.dump(compilationUnit, jsonWriter); - } - TTY.println("Serialized " + originalRequest + " to " + path); - } catch (Exception exception) { - TTY.println("Failed to serialize the recorded operations to a file."); - exception.printStackTrace(TTY.out().out()); - } - } - - /** - * Sets the address and temporaries of a foreign call linkage using the recorded linkages if - * they are available and contain the given foreign call signature. - * - * @param signature the foreign call signature - * @param callTarget the foreign call target to update - * @return true if the linkage was finalized - */ - public boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpotForeignCallLinkage callTarget) { - if (recordedForeignCallLinkages != null) { - return recordedForeignCallLinkages.finalizeForeignCallLinkage(signature, callTarget); - } - return false; - } - - /** - * Finds local mirrors for the parsed proxies during replay compilation. This should be invoked - * just after the core JVMCI providers are created because they are needed to look up the - * mirrors. - */ - public void findLocalMirrors() { - if (proxies instanceof ReplayCompilationProxies replayCompilationProxies) { - replayCompilationProxies.findLocalMirrors(); - } - } - - /** - * Decorates a backend factory. - * - * @param factory the backend factory to decorate - * @return the decorated backend factory - */ - public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory) { - return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this)); - } - - /** - * Decorates a compilation request. - * - * @param request the compilation request to decorate - * @return the decorated compilation request - */ - public HotSpotCompilationRequest decorateCompilationRequest(HotSpotCompilationRequest request) { - return new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) proxies.proxify(request.getMethod()), request.getEntryBCI(), request.getJvmciEnv(), request.getId()); - } - - /** - * Decorates a compiler profiler. - * - * @param compilerProfiler the compiler profiler to decorate - * @return the decorated compiler profiler - */ - public CompilerProfiler decorateCompilerProfiler(CompilerProfiler compilerProfiler) { - return (CompilerProfiler) proxies.proxify(compilerProfiler); - } - - /** - * Decorates an intrinsification trust predicate. - * - * @param predicate the intrinsification trust predicate to decorate - * @return the decorated intrinsification trust predicate - */ - @SuppressWarnings("unchecked") - public Predicate decorateIntrinsificationTrustPredicate(Predicate predicate) { - return (Predicate) proxies.proxify(predicate); - } - - /** - * Decorates a VM config access. - * - * @param access the VM config access to decorate - * @return the decorated VM config access - */ - public HotSpotVMConfigAccess decorateVMConfigAccess(HotSpotVMConfigAccess access) { - return (HotSpotVMConfigAccess) proxies.proxify(access); - } - - /** - * Returns the target platform. - */ - public Platform targetPlatform() { - return proxies.targetPlatform(); - } - - /** - * The artifacts produced by a compilation. - * - * @param graph the final graph - * @param result the compilation result - */ - public record CompilationArtifacts(StructuredGraph graph, CompilationResult result) { - /** - * Returns the canonical graph string for the final graph. - */ - public String finalCanonicalGraph() { - return CanonicalStringGraphPrinter.getCanonicalGraphString(graph, false, true); - } - } - - /** - * Records the artifacts produced by the last compilation of the current compiler thread. - * - * @param graph the final graph - * @param result the compilation result - */ - public void recordCompilationArtifacts(StructuredGraph graph, CompilationResult result) { - compilationArtifacts.set(new CompilationArtifacts(graph, result)); - } - - /** - * Clears and returns the artifacts produced by the last successfully completed compilation of - * the current compiler thread. May return {@code null} if the last compilation did not complete - * successfully. - * - * @return the cleared compilation artifacts or {@code null} - */ - public CompilationArtifacts clearCompilationArtifacts() { - CompilationArtifacts result = compilationArtifacts.get(); - compilationArtifacts.remove(); - return result; - } - - /** - * Injects profiles for the given method during recording. - * - * @param method the method to inject profiles into - * @param includeNormal whether to include normal profiles - * @param includeOSR whether to include OSR profiles - * @param profilingInfo the profiling information to inject - * @throws UnsupportedOperationException if called during replay - */ - public void injectProfiles(ResolvedJavaMethod method, boolean includeNormal, boolean includeOSR, ProfilingInfo profilingInfo) { - if (proxies instanceof RecordingCompilationProxies recordingProxies) { - recordingProxies.injectProfiles(method, includeNormal, includeOSR, profilingInfo); - } else { - throw new UnsupportedOperationException("injectProfiles during replay"); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java deleted file mode 100644 index 77f722b69059..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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.hotspot.replaycomp; - -/** - * A marker representing the result of a recorded operation that did not produce a non-null value: - * it may have thrown an exception, returned null, or there is no recorded result. - */ -public sealed interface SpecialResultMarker { - /** - * Marker indicating that no result was recorded. - */ - NoResultMarker NO_RESULT_MARKER = new NoResultMarker(); - - /** - * Marker indicating that a null result was recorded. - */ - NullResultMarker NULL_RESULT_MARKER = new NullResultMarker(); - - /** - * Materializes the result represented by this marker. - * - * @return the materialized result, or {@code null} if the result is null - * @throws Throwable if the recorded operation threw an exception - */ - Object materialize() throws Throwable; - - /** - * A marker indicating that no result was recorded. - */ - final class NoResultMarker implements SpecialResultMarker { - private NoResultMarker() { - } - - @Override - public String toString() { - return "[no recorded result]"; - } - - @Override - public Object materialize() throws Throwable { - throw new IllegalStateException(); - } - } - - /** - * A marker indicating that a null result was recorded. - */ - final class NullResultMarker implements SpecialResultMarker { - private NullResultMarker() { - } - - @Override - public String toString() { - return "[null result]"; - } - - @Override - public Object materialize() throws Throwable { - return null; - } - } - - /** - * A marker indicating that an exception was thrown during the operation. - */ - final class ExceptionThrownMarker implements SpecialResultMarker { - private final Throwable thrown; - - /** - * Creates a new instance of this marker with the given thrown exception. - * - * @param thrown the exception that was thrown - */ - public ExceptionThrownMarker(Throwable thrown) { - this.thrown = thrown; - } - - /** - * Returns the exception that was thrown. - * - * @return the thrown exception - */ - public Throwable getThrown() { - return thrown; - } - - @Override - public String toString() { - return "[thrown: " + thrown + "]"; - } - - @Override - public Object materialize() throws Throwable { - throw thrown; - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java deleted file mode 100644 index 35eb865bf83f..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.lang.reflect.UndeclaredThrowableException; -import java.util.Arrays; -import java.util.function.Predicate; - -import jdk.graal.compiler.core.common.CompilerProfiler; -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.debug.GraalError; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotProfilingInfo; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.MethodHandleAccessProvider; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; - -//JaCoCo Exclude - -/** - * A proxy object for a compiler-interface class. - *

- * The implementations of this interface are static proxies for JVMCI objects. We use static proxies - * instead of {@link Proxy dynamic proxies} to minimize the amount of reachable methods in a - * libgraal image and for a finer control over which interface methods need to be overridden. - *

    - *
  • {@link SymbolicMethod} and {@link InvokableMethod} are replacements for {@link Method}. Using - * an {@link InvokableMethod} instead of an invokable {@link Method} avoids marking the methods as - * compilation roots, allowing the points-to analysis to keep the reachable methods only.
  • - *
  • The {@link SymbolicMethod} and {@link InvokableMethod} instances are stored in static final - * fields and initialized at image build time. This is preferred over allocation at run time.
  • - *
  • Interface methods with a default implementation (implemented by calling other interface - * methods) do not require an overriding implementation. Omitting the implementation can make - * recording and replay more efficient. For example, many methods of {@link ResolvedJavaMethod} are - * implemented by delegating to {@link ResolvedJavaMethod#getModifiers()}, so we override - * {@link ResolvedJavaMethod#getModifiers()} but do not override - * {@link ResolvedJavaMethod#isInterface()}.
  • - *
- * - * @see jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport - * @see jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations - */ -public interface CompilationProxy { - /** - * Returns the underlying object being proxied or {@code null} if such an object was not - * identified in this VM. - * - * @return the underlying object - */ - Object unproxify(); - - /** - * Represents a compiler-interface method that can be invoked. - */ - @FunctionalInterface - interface InvokableMethod { - /** - * Invokes the method on the given receiver object with the provided arguments. - * - * @param receiver the object on which to invoke the method - * @param args the method arguments - * @return the result of the method invocation - * @throws InvocationTargetException if the method invocation fails - * @throws IllegalAccessException if access to the method is denied - */ - Object invoke(Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException; - } - - /** - * A symbolic non-invokable representation of a compiler-interface method. - * - * @param methodAndParamNames the method name and parameter class names - */ - record SymbolicMethod(String[] methodAndParamNames) { - public SymbolicMethod(String methodName, Class... params) { - this(toArray(methodName, params)); - } - - /** - * Returns {@code true} if the method has parameters. - */ - public boolean hasParams() { - return methodAndParamNames.length > 1; - } - - /** - * Returns the number of method parameters. - */ - public int paramCount() { - return methodAndParamNames.length - 1; - } - - private static String[] toArray(String methodName, Class[] params) { - String[] result = new String[params.length + 1]; - result[0] = methodName; - for (int i = 0; i < params.length; i++) { - result[i + 1] = params[i].getSimpleName(); - } - return result; - } - - /** - * Creates a new symbolic method instance from a list receiver classes, method name, and - * parameter types. At least one of the receiver classes must declare a method with the - * given signature. - * - * @param receiverClasses the receiver classes - * @param methodName the method name - * @param params the parameter types - */ - public SymbolicMethod(Class[] receiverClasses, String methodName, Class... params) { - this(methodName, params); - if (!LibGraalSupport.inLibGraalRuntime()) { - // Omit the check in the image to avoid increasing image size. - for (Class receiverClass : receiverClasses) { - try { - receiverClass.getDeclaredMethod(methodName, params); - return; - } catch (NoSuchMethodException ignored) { - } - try { - receiverClass.getMethod(methodName, params); - return; - } catch (NoSuchMethodException ignored) { - } - } - throw new GraalError("Method " + methodName + " not found"); - } - } - - /** - * Creates a new symbolic method from a receiver class, method name, and parameter types. - * The receiver class must declare a method with the given signature. - * - * @param receiverClass the receiver class - * @param methodName the method name - * @param params the parameter types - */ - public SymbolicMethod(Class receiverClass, String methodName, Class... params) { - this(new Class[]{receiverClass}, methodName, params); - } - - @Override - public boolean equals(Object o) { - if (o instanceof SymbolicMethod that) { - return Arrays.equals(methodAndParamNames, that.methodAndParamNames); - } - return false; - } - - @Override - public int hashCode() { - return Arrays.hashCode(methodAndParamNames); - } - - @Override - public String toString() { - return Arrays.toString(methodAndParamNames); - } - } - - /** - * An invocation handler for a proxy object. - */ - @FunctionalInterface - interface InvocationHandler { - /** - * Handles an invocation on the proxy object. - * - * @param proxy the proxy object - * @param method the symbolic method being invoked - * @param invokableMethod the underlying compiler-interface method - * @param args the invocation arguments - * @return the result of the invocation - * @throws Throwable thrown by the handler - */ - Object handle(Object proxy, SymbolicMethod method, InvokableMethod invokableMethod, Object[] args) throws Throwable; - } - - /** - * Handles an invocation on a proxy object using the provided invocation handler. This method - * should be invoked by the proxy implementations. - * - * @param handler the invocation handler - * @param proxy the proxy object - * @param method the symbolic method being invoked - * @param invokable the underlying compiler-interface method - * @param args the invocation arguments - * @return the result of the invocation - * @throws UndeclaredThrowableException if the handler throws a checked exception - */ - static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod method, InvokableMethod invokable, Object... args) { - try { - return handler.handle(proxy, method, (Object receiver, Object[] actualArgs) -> { - try { - return invokable.invoke(receiver, actualArgs); - } catch (Throwable e) { - throw new InvocationTargetException(e); - } - }, (args.length == 0) ? null : args); - } catch (RuntimeException | Error e) { - throw e; - } catch (Throwable e) { - throw new UndeclaredThrowableException(e); - } - } - - /** - * Creates a new compilation proxy instance for the specified class and invocation handler. - * - * @param clazz the class (interface) that the proxy must implement - * @param handler the invocation handler for the proxy - * @return a new compilation proxy instance - * @throws GraalError if no proxy class exists for the specified interfaces - */ - static CompilationProxy newProxyInstance(Class clazz, InvocationHandler handler) { - if (clazz == HotSpotResolvedObjectType.class) { - return new HotSpotResolvedObjectTypeProxy(handler); - } else if (clazz == HotSpotResolvedJavaType.class) { - return new HotSpotResolvedJavaTypeProxy(handler); - } else if (clazz == HotSpotResolvedJavaMethod.class) { - return new HotSpotResolvedJavaMethodProxy(handler); - } else if (clazz == HotSpotResolvedJavaField.class) { - return new HotSpotResolvedJavaFieldProxy(handler); - } else if (clazz == HotSpotVMConfigAccess.class) { - return new HotSpotVMConfigAccessProxy(handler); - } else if (clazz == MetaAccessProvider.class) { - return new MetaAccessProviderProxy(handler); - } else if (clazz == HotSpotConstantReflectionProvider.class) { - return new HotSpotConstantReflectionProviderProxy(handler); - } else if (clazz == MethodHandleAccessProvider.class) { - return new MethodHandleAccessProviderProxy(handler); - } else if (clazz == HotSpotMemoryAccessProvider.class) { - return new HotSpotMemoryAccessProviderProxy(handler); - } else if (clazz == HotSpotCodeCacheProvider.class) { - return new HotSpotCodeCacheProviderProxy(handler); - } else if (clazz == CompilerProfiler.class) { - return new CompilerProfilerProxy(handler); - } else if (clazz == ConstantPool.class) { - return new ConstantPoolProxy(handler); - } else if (clazz == Signature.class) { - return new SignatureProxy(handler); - } else if (clazz == HotSpotObjectConstant.class) { - return new HotSpotObjectConstantProxy(handler); - } else if (clazz == HotSpotMetaspaceConstant.class) { - return new HotSpotMetaspaceConstantProxy(handler); - } else if (clazz == HotSpotProfilingInfo.class) { - return new HotSpotProfilingInfoProxy(handler); - } else if (clazz == ProfilingInfo.class) { - return new ProfilingInfoProxy(handler); - } else if (clazz == SpeculationLog.class) { - return new SpeculationLogProxy(handler); - } else if (clazz == Predicate.class) { - return new PredicateProxy(handler); - } else { - throw new GraalError("No proxy class for " + clazz); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java deleted file mode 100644 index 7676f906701d..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; - -//JaCoCo Exclude - -/** - * A base class for compilation proxies providing implementations of shared methods. - */ -public class CompilationProxyBase implements CompilationProxy { - public static final SymbolicMethod unproxifyMethod = new SymbolicMethod(CompilationProxy.class, "unproxify"); - public static final InvokableMethod unproxifyInvokable = (receiver, args) -> ((CompilationProxy) receiver).unproxify(); - - public static final SymbolicMethod hashCodeMethod = new SymbolicMethod(Object.class, "hashCode"); - public static final InvokableMethod hashCodeInvokable = (receiver, args) -> receiver.hashCode(); - - public static final SymbolicMethod equalsMethod = new SymbolicMethod(Object.class, "equals", Object.class); - public static final InvokableMethod equalsInvokable = (receiver, args) -> receiver.equals(args[0]); - - public static final SymbolicMethod toStringMethod = new SymbolicMethod(Object.class, "toString"); - public static final InvokableMethod toStringInvokable = (receiver, args) -> receiver.toString(); - - protected final InvocationHandler handler; - - CompilationProxyBase(InvocationHandler handler) { - this.handler = handler; - } - - protected final Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { - return CompilationProxy.handle(handler, this, method, invokable, args); - } - - @Override - public final Object unproxify() { - return handle(unproxifyMethod, unproxifyInvokable); - } - - @Override - public final int hashCode() { - return (int) handle(hashCodeMethod, hashCodeInvokable); - } - - @Override - public final boolean equals(Object obj) { - return (boolean) handle(equalsMethod, equalsInvokable, obj); - } - - @Override - public final String toString() { - return (String) handle(toStringMethod, toStringInvokable); - } - - /** - * Base class to share method implementations for proxies that implement - * {@link AnnotatedElement}. - */ - public abstract static class CompilationProxyAnnotatedBase extends CompilationProxyBase implements AnnotatedElement { - CompilationProxyAnnotatedBase(InvocationHandler handler) { - super(handler); - } - - public static final SymbolicMethod getAnnotationMethod = new SymbolicMethod(AnnotatedElement.class, "getAnnotation", Class.class); - @SuppressWarnings("unchecked") public static final InvokableMethod getAnnotationInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getAnnotation((Class) args[0]); - - @Override - @SuppressWarnings("unchecked") - public final T getAnnotation(Class annotationClass) { - return (T) handle(getAnnotationMethod, getAnnotationInvokable, annotationClass); - } - - public static final SymbolicMethod getAnnotationsMethod = new SymbolicMethod(AnnotatedElement.class, "getAnnotations"); - public static final InvokableMethod getAnnotationsInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getAnnotations(); - - @Override - public final Annotation[] getAnnotations() { - return (Annotation[]) handle(getAnnotationsMethod, getAnnotationsInvokable); - } - - public static final SymbolicMethod getDeclaredAnnotationsMethod = new SymbolicMethod(AnnotatedElement.class, "getDeclaredAnnotations"); - public static final InvokableMethod getDeclaredAnnotationsInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getDeclaredAnnotations(); - - @Override - public final Annotation[] getDeclaredAnnotations() { - return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); - } - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java deleted file mode 100644 index c70d955d7d0b..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.graal.compiler.core.common.CompilerProfiler; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -//JaCoCo Exclude - -public final class CompilerProfilerProxy extends CompilationProxyBase implements CompilerProfiler { - CompilerProfilerProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(CompilerProfiler.class, name, params); - } - - public static final SymbolicMethod getTicksMethod = method("getTicks"); - private static final InvokableMethod getTicksInvokable = (receiver, args) -> ((CompilerProfiler) receiver).getTicks(); - - @Override - public long getTicks() { - return (long) handle(getTicksMethod, getTicksInvokable); - } - - public static final SymbolicMethod notifyCompilerPhaseEventMethod = method("notifyCompilerPhaseEvent", int.class, long.class, String.class, int.class); - private static final InvokableMethod notifyCompilerPhaseEventInvokable = (receiver, args) -> { - ((CompilerProfiler) receiver).notifyCompilerPhaseEvent((int) args[0], (long) args[1], (String) args[2], (int) args[3]); - return null; - }; - - @Override - public void notifyCompilerPhaseEvent(int compileId, long startTime, String name, int nestingLevel) { - handle(notifyCompilerPhaseEventMethod, notifyCompilerPhaseEventInvokable, compileId, startTime, name, nestingLevel); - } - - public static final SymbolicMethod notifyCompilerInliningEventMethod = method("notifyCompilerInliningEvent", int.class, ResolvedJavaMethod.class, ResolvedJavaMethod.class, boolean.class, - String.class, int.class); - private static final InvokableMethod notifyCompilerInliningEventInvokable = (receiver, args) -> { - ((CompilerProfiler) receiver).notifyCompilerInliningEvent((int) args[0], (ResolvedJavaMethod) args[1], (ResolvedJavaMethod) args[2], (boolean) args[3], (String) args[4], (int) args[5]); - return null; - }; - - @Override - public void notifyCompilerInliningEvent(int compileId, ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, String message, int bci) { - handle(notifyCompilerInliningEventMethod, notifyCompilerInliningEventInvokable, compileId, caller, callee, succeeded, message, bci); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java deleted file mode 100644 index 6e50b2afea42..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaField; -import jdk.vm.ci.meta.JavaMethod; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.Signature; - -import java.util.List; - -//JaCoCo Exclude - -public final class ConstantPoolProxy extends CompilationProxyBase implements ConstantPool { - ConstantPoolProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(ConstantPool.class, name, params); - } - - private static final SymbolicMethod lengthMethod = method("length"); - private static final InvokableMethod lengthInvokable = (receiver, args) -> ((ConstantPool) receiver).length(); - - @Override - public int length() { - return (int) handle(lengthMethod, lengthInvokable); - } - - private static final SymbolicMethod loadReferencedTypeMethod = method("loadReferencedType", int.class, int.class); - private static final InvokableMethod loadReferencedTypeInvokable = (receiver, args) -> { - ((ConstantPool) receiver).loadReferencedType((int) args[0], (int) args[1]); - return null; - }; - - @Override - public void loadReferencedType(int rawIndex, int opcode) { - handle(loadReferencedTypeMethod, loadReferencedTypeInvokable, rawIndex, opcode); - } - - private static final SymbolicMethod lookupReferencedTypeMethod = method("lookupReferencedType", int.class, int.class); - private static final InvokableMethod lookupReferencedTypeInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupReferencedType((int) args[0], (int) args[1]); - - @Override - public JavaType lookupReferencedType(int rawIndex, int opcode) { - return (JavaType) handle(lookupReferencedTypeMethod, lookupReferencedTypeInvokable, rawIndex, opcode); - } - - private static final SymbolicMethod lookupFieldMethod = method("lookupField", int.class, ResolvedJavaMethod.class, int.class); - private static final InvokableMethod lookupFieldInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupField((int) args[0], (ResolvedJavaMethod) args[1], (int) args[2]); - - @Override - public JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode) { - return (JavaField) handle(lookupFieldMethod, lookupFieldInvokable, rawIndex, method, opcode); - } - - public static final SymbolicMethod lookupMethodMethod = method("lookupMethod", int.class, int.class, ResolvedJavaMethod.class); - public static final InvokableMethod lookupMethodInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupMethod((int) args[0], (int) args[1], (ResolvedJavaMethod) args[2]); - - @Override - public JavaMethod lookupMethod(int cpi, int opcode, ResolvedJavaMethod caller) { - return (JavaMethod) handle(lookupMethodMethod, lookupMethodInvokable, cpi, opcode, caller); - } - - private static final SymbolicMethod lookupBootstrapMethodInvocationMethod = method("lookupBootstrapMethodInvocation", int.class, int.class); - private static final InvokableMethod lookupBootstrapMethodInvocationInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupBootstrapMethodInvocation((int) args[0], (int) args[1]); - - @Override - public BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int opcode) { - return (BootstrapMethodInvocation) handle(lookupBootstrapMethodInvocationMethod, lookupBootstrapMethodInvocationInvokable, index, opcode); - } - - private static final SymbolicMethod lookupBootstrapMethodInvocationsMethod = method("lookupBootstrapMethodInvocations", boolean.class); - private static final InvokableMethod lookupBootstrapMethodInvocationsInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupBootstrapMethodInvocations((boolean) args[0]); - - @Override - @SuppressWarnings("unchecked") - public List lookupBootstrapMethodInvocations(boolean invokeDynamic) { - return (List) handle(lookupBootstrapMethodInvocationsMethod, lookupBootstrapMethodInvocationsInvokable, invokeDynamic); - } - - private static final SymbolicMethod lookupTypeMethod = method("lookupType", int.class, int.class); - private static final InvokableMethod lookupTypeInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupType((int) args[0], (int) args[1]); - - @Override - public JavaType lookupType(int cpi, int opcode) { - return (JavaType) handle(lookupTypeMethod, lookupTypeInvokable, cpi, opcode); - } - - private static final SymbolicMethod lookupUtf8Method = method("lookupUtf8", int.class); - private static final InvokableMethod lookupUtf8Invokable = (receiver, args) -> ((ConstantPool) receiver).lookupUtf8((int) args[0]); - - @Override - public String lookupUtf8(int cpi) { - return (String) handle(lookupUtf8Method, lookupUtf8Invokable, cpi); - } - - private static final SymbolicMethod lookupSignatureMethod = method("lookupSignature", int.class); - private static final InvokableMethod lookupSignatureInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupSignature((int) args[0]); - - @Override - public Signature lookupSignature(int cpi) { - return (Signature) handle(lookupSignatureMethod, lookupSignatureInvokable, cpi); - } - - private static final SymbolicMethod lookupConstantMethod = method("lookupConstant", int.class); - private static final InvokableMethod lookupConstantInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupConstant((int) args[0]); - - @Override - public Object lookupConstant(int cpi) { - return handle(lookupConstantMethod, lookupConstantInvokable, cpi); - } - - private static final SymbolicMethod lookupConstantBooleanMethod = method("lookupConstant", int.class, boolean.class); - private static final InvokableMethod lookupConstantBooleanInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupConstant((int) args[0], (boolean) args[1]); - - @Override - public Object lookupConstant(int cpi, boolean resolve) { - return handle(lookupConstantBooleanMethod, lookupConstantBooleanInvokable, cpi, resolve); - } - - private static final SymbolicMethod lookupAppendixMethod = method("lookupAppendix", int.class, int.class); - private static final InvokableMethod lookupAppendixInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupAppendix((int) args[0], (int) args[1]); - - @Override - public JavaConstant lookupAppendix(int rawIndex, int opcode) { - return (JavaConstant) handle(lookupAppendixMethod, lookupAppendixInvokable, rawIndex, opcode); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java deleted file mode 100644 index 8117c1a6f3ae..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; - -import jdk.vm.ci.code.BytecodeFrame; -import jdk.vm.ci.code.CompiledCode; -import jdk.vm.ci.code.InstalledCode; -import jdk.vm.ci.code.RegisterConfig; -import jdk.vm.ci.code.TargetDescription; -import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.SpeculationLog; - -//JaCoCo Exclude - -public final class HotSpotCodeCacheProviderProxy extends HotSpotCodeCacheProvider implements CompilationProxy { - private final InvocationHandler handler; - - HotSpotCodeCacheProviderProxy(InvocationHandler handler) { - super(HotSpotJVMCIRuntime.runtime(), null, null); - this.handler = handler; - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotCodeCacheProvider.class, name, params); - } - - private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { - return CompilationProxy.handle(handler, this, method, invokable, args); - } - - public static final SymbolicMethod installCodeMethod = method("installCode", ResolvedJavaMethod.class, CompiledCode.class, InstalledCode.class, SpeculationLog.class, boolean.class, boolean.class); - private static final InvokableMethod installCodeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).installCode( - (ResolvedJavaMethod) args[0], (CompiledCode) args[1], (InstalledCode) args[2], (SpeculationLog) args[3], (boolean) args[4], (boolean) args[5]); - - @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { - return (InstalledCode) handle(installCodeMethod, installCodeInvokable, method, compiledCode, installedCode, log, isDefault, profileDeopt); - } - - private static final SymbolicMethod invalidateInstalledCodeMethod = method("invalidateInstalledCode", InstalledCode.class); - private static final InvokableMethod invalidateInstalledCodeInvokable = (receiver, args) -> { - ((HotSpotCodeCacheProvider) receiver).invalidateInstalledCode((InstalledCode) args[0]); - return null; - }; - - @Override - public void invalidateInstalledCode(InstalledCode installedCode) { - handle(invalidateInstalledCodeMethod, invalidateInstalledCodeInvokable, installedCode); - } - - private static final SymbolicMethod getRegisterConfigMethod = method("getRegisterConfig"); - private static final InvokableMethod getRegisterConfigInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getRegisterConfig(); - - @Override - public RegisterConfig getRegisterConfig() { - return (RegisterConfig) handle(getRegisterConfigMethod, getRegisterConfigInvokable); - } - - private static final SymbolicMethod getMinimumOutgoingSizeMethod = method("getMinimumOutgoingSize"); - private static final InvokableMethod getMinimumOutgoingSizeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getMinimumOutgoingSize(); - - @Override - public int getMinimumOutgoingSize() { - return (int) handle(getMinimumOutgoingSizeMethod, getMinimumOutgoingSizeInvokable); - } - - private static final SymbolicMethod getTargetMethod = method("getTarget"); - private static final InvokableMethod getTargetInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getTarget(); - - @Override - public TargetDescription getTarget() { - return (TargetDescription) handle(getTargetMethod, getTargetInvokable); - } - - private static final SymbolicMethod createSpeculationLogMethod = method("createSpeculationLog"); - private static final InvokableMethod createSpeculationLogInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).createSpeculationLog(); - - @Override - public SpeculationLog createSpeculationLog() { - return (SpeculationLog) handle(createSpeculationLogMethod, createSpeculationLogInvokable); - } - - private static final SymbolicMethod getMaxCallTargetOffsetMethod = method("getMaxCallTargetOffset", long.class); - private static final InvokableMethod getMaxCallTargetOffsetInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getMaxCallTargetOffset((long) args[0]); - - @Override - public long getMaxCallTargetOffset(long address) { - return (long) handle(getMaxCallTargetOffsetMethod, getMaxCallTargetOffsetInvokable, address); - } - - private static final SymbolicMethod shouldDebugNonSafepointsMethod = method("shouldDebugNonSafepoints"); - private static final InvokableMethod shouldDebugNonSafepointsInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).shouldDebugNonSafepoints(); - - @Override - public boolean shouldDebugNonSafepoints() { - return (boolean) handle(shouldDebugNonSafepointsMethod, shouldDebugNonSafepointsInvokable); - } - - private static final SymbolicMethod disassembleMethod = method("disassemble", InstalledCode.class); - private static final InvokableMethod disassembleInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).disassemble((InstalledCode) args[0]); - - @Override - public String disassemble(InstalledCode code) { - return (String) handle(disassembleMethod, disassembleInvokable, code); - } - - public static final SymbolicMethod interpreterFrameSizeMethod = method("interpreterFrameSize", BytecodeFrame.class); - private static final InvokableMethod interpreterFrameSizeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).interpreterFrameSize((BytecodeFrame) args[0]); - - @Override - public int interpreterFrameSize(BytecodeFrame pos) { - return (int) handle(interpreterFrameSizeMethod, interpreterFrameSizeInvokable, pos); - } - - private static final SymbolicMethod resetCompilationStatisticsMethod = method("resetCompilationStatistics"); - private static final InvokableMethod resetCompilationStatisticsInvokable = (receiver, args) -> { - ((HotSpotCodeCacheProvider) receiver).resetCompilationStatistics(); - return null; - }; - - @Override - public void resetCompilationStatistics() { - handle(resetCompilationStatisticsMethod, resetCompilationStatisticsInvokable); - } - - @Override - public Object unproxify() { - return handle(unproxifyMethod, unproxifyInvokable); - } - - @Override - public int hashCode() { - return (int) handle(hashCodeMethod, hashCodeInvokable); - } - - @Override - public boolean equals(Object obj) { - return (boolean) handle(equalsMethod, equalsInvokable, obj); - } - - @Override - public String toString() { - return (String) handle(toStringMethod, toStringInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java deleted file mode 100644 index b3f8470506ee..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; - -import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.MemoryAccessProvider; -import jdk.vm.ci.meta.MethodHandleAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaType; - -//JaCoCo Exclude - -public final class HotSpotConstantReflectionProviderProxy extends HotSpotConstantReflectionProvider implements CompilationProxy { - private final InvocationHandler handler; - - HotSpotConstantReflectionProviderProxy(InvocationHandler handler) { - super(null); - this.handler = handler; - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotConstantReflectionProvider.class, name, params); - } - - private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { - return CompilationProxy.handle(handler, this, method, invokable, args); - } - - private static final SymbolicMethod constantEqualsMethod = method("constantEquals", Constant.class, Constant.class); - private static final InvokableMethod constantEqualsInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).constantEquals((Constant) args[0], (Constant) args[1]); - - @Override - public Boolean constantEquals(Constant x, Constant y) { - return (Boolean) handle(constantEqualsMethod, constantEqualsInvokable, x, y); - } - - private static final SymbolicMethod readArrayLengthMethod = method("readArrayLength", JavaConstant.class); - private static final InvokableMethod readArrayLengthInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readArrayLength((JavaConstant) args[0]); - - @Override - public Integer readArrayLength(JavaConstant array) { - return (Integer) handle(readArrayLengthMethod, readArrayLengthInvokable, array); - } - - private static final SymbolicMethod readArrayElementMethod = method("readArrayElement", JavaConstant.class, int.class); - private static final InvokableMethod readArrayElementInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readArrayElement((JavaConstant) args[0], (int) args[1]); - - @Override - public JavaConstant readArrayElement(JavaConstant array, int index) { - return (JavaConstant) handle(readArrayElementMethod, readArrayElementInvokable, array, index); - } - - private static final SymbolicMethod readFieldValueMethod = method("readFieldValue", ResolvedJavaField.class, JavaConstant.class); - private static final InvokableMethod readFieldValueInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readFieldValue((ResolvedJavaField) args[0], - (JavaConstant) args[1]); - - @Override - public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant rec) { - return (JavaConstant) handle(readFieldValueMethod, readFieldValueInvokable, field, rec); - } - - private static final SymbolicMethod boxPrimitiveMethod = method("boxPrimitive", JavaConstant.class); - private static final InvokableMethod boxPrimitiveInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).boxPrimitive((JavaConstant) args[0]); - - @Override - public JavaConstant boxPrimitive(JavaConstant source) { - return (JavaConstant) handle(boxPrimitiveMethod, boxPrimitiveInvokable, source); - } - - private static final SymbolicMethod unboxPrimitiveMethod = method("unboxPrimitive", JavaConstant.class); - private static final InvokableMethod unboxPrimitiveInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).unboxPrimitive((JavaConstant) args[0]); - - @Override - public JavaConstant unboxPrimitive(JavaConstant source) { - return (JavaConstant) handle(unboxPrimitiveMethod, unboxPrimitiveInvokable, source); - } - - private static final SymbolicMethod forStringMethod = method("forString", String.class); - private static final InvokableMethod forStringInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).forString((String) args[0]); - - @Override - public JavaConstant forString(String value) { - return (JavaConstant) handle(forStringMethod, forStringInvokable, value); - } - - public static final SymbolicMethod forObjectMethod = method("forObject", Object.class); - public static final InvokableMethod forObjectInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).forObject(args[0]); - - @Override - public JavaConstant forObject(Object value) { - return (JavaConstant) handle(forObjectMethod, forObjectInvokable, value); - } - - public static final SymbolicMethod asJavaTypeMethod = method("asJavaType", Constant.class); - private static final InvokableMethod asJavaTypeInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asJavaType((Constant) args[0]); - - @Override - public ResolvedJavaType asJavaType(Constant constant) { - return (ResolvedJavaType) handle(asJavaTypeMethod, asJavaTypeInvokable, constant); - } - - private static final SymbolicMethod getMethodHandleAccessMethod = method("getMethodHandleAccess"); - private static final InvokableMethod getMethodHandleAccessInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).getMethodHandleAccess(); - - @Override - public MethodHandleAccessProvider getMethodHandleAccess() { - return (MethodHandleAccessProvider) handle(getMethodHandleAccessMethod, getMethodHandleAccessInvokable); - } - - private static final SymbolicMethod getMemoryAccessProviderMethod = method("getMemoryAccessProvider"); - private static final InvokableMethod getMemoryAccessProviderInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).getMemoryAccessProvider(); - - @Override - public MemoryAccessProvider getMemoryAccessProvider() { - return (MemoryAccessProvider) handle(getMemoryAccessProviderMethod, getMemoryAccessProviderInvokable); - } - - public static final SymbolicMethod asJavaClassMethod = method("asJavaClass", ResolvedJavaType.class); - private static final InvokableMethod asJavaClassInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asJavaClass((ResolvedJavaType) args[0]); - - @Override - public JavaConstant asJavaClass(ResolvedJavaType type) { - return (JavaConstant) handle(asJavaClassMethod, asJavaClassInvokable, type); - } - - public static final SymbolicMethod asObjectHubMethod = method("asObjectHub", ResolvedJavaType.class); - private static final InvokableMethod asObjectHubInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asObjectHub((ResolvedJavaType) args[0]); - - @Override - public Constant asObjectHub(ResolvedJavaType type) { - return (Constant) handle(asObjectHubMethod, asObjectHubInvokable, type); - } - - @Override - public Object unproxify() { - return handle(unproxifyMethod, unproxifyInvokable); - } - - @Override - public int hashCode() { - return (int) handle(hashCodeMethod, hashCodeInvokable); - } - - @Override - public boolean equals(Object obj) { - return (boolean) handle(equalsMethod, equalsInvokable, obj); - } - - @Override - public String toString() { - return (String) handle(toStringMethod, toStringInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java deleted file mode 100644 index b6048659a320..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; - -//JaCoCo Exclude - -final class HotSpotMemoryAccessProviderProxy extends CompilationProxyBase implements HotSpotMemoryAccessProvider { - HotSpotMemoryAccessProviderProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotMemoryAccessProvider.class, name, params); - } - - private static final SymbolicMethod readNarrowOopConstantMethod = method("readNarrowOopConstant", Constant.class, long.class); - private static final InvokableMethod readNarrowOopConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readNarrowOopConstant((Constant) args[0], (long) args[1]); - - @Override - public JavaConstant readNarrowOopConstant(Constant base, long displacement) { - return (JavaConstant) handle(readNarrowOopConstantMethod, readNarrowOopConstantInvokable, base, displacement); - } - - private static final SymbolicMethod readKlassPointerConstantMethod = method("readKlassPointerConstant", Constant.class, long.class); - private static final InvokableMethod readKlassPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readKlassPointerConstant((Constant) args[0], (long) args[1]); - - @Override - public Constant readKlassPointerConstant(Constant base, long displacement) { - return (Constant) handle(readKlassPointerConstantMethod, readKlassPointerConstantInvokable, base, displacement); - } - - private static final SymbolicMethod readNarrowKlassPointerConstantMethod = method("readNarrowKlassPointerConstant", Constant.class, long.class); - private static final InvokableMethod readNarrowKlassPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readNarrowKlassPointerConstant((Constant) args[0], - (long) args[1]); - - @Override - public Constant readNarrowKlassPointerConstant(Constant base, long displacement) { - return (Constant) handle(readNarrowKlassPointerConstantMethod, readNarrowKlassPointerConstantInvokable, base, displacement); - } - - private static final SymbolicMethod readMethodPointerConstantMethod = method("readMethodPointerConstant", Constant.class, long.class); - private static final InvokableMethod readMethodPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readMethodPointerConstant((Constant) args[0], - (long) args[1]); - - @Override - public Constant readMethodPointerConstant(Constant base, long displacement) { - return (Constant) handle(readMethodPointerConstantMethod, readMethodPointerConstantInvokable, base, displacement); - } - - private static final SymbolicMethod readPrimitiveConstantMethod = method("readPrimitiveConstant", JavaKind.class, Constant.class, long.class, int.class); - private static final InvokableMethod readPrimitiveConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readPrimitiveConstant((JavaKind) args[0], (Constant) args[1], - (long) args[2], (int) args[3]); - - @Override - public JavaConstant readPrimitiveConstant(JavaKind kind, Constant base, long displacement, int bits) { - return (JavaConstant) handle(readPrimitiveConstantMethod, readPrimitiveConstantInvokable, kind, base, displacement, bits); - } - - private static final SymbolicMethod readObjectConstantMethod = method("readObjectConstant", Constant.class, long.class); - private static final InvokableMethod readObjectConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readObjectConstant((Constant) args[0], (long) args[1]); - - @Override - public JavaConstant readObjectConstant(Constant base, long displacement) { - return (JavaConstant) handle(readObjectConstantMethod, readObjectConstantInvokable, base, displacement); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java deleted file mode 100644 index 52599c0f2c72..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; - -//JaCoCo Exclude - -public final class HotSpotMetaspaceConstantProxy extends CompilationProxyBase implements HotSpotMetaspaceConstant { - HotSpotMetaspaceConstantProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotMetaspaceConstant.class, name, params); - } - - private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); - private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isDefaultForKind(); - - @Override - public boolean isDefaultForKind() { - return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); - } - - public static final SymbolicMethod toValueStringMethod = method("toValueString"); - public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).toValueString(); - - @Override - public String toValueString() { - return (String) handle(toValueStringMethod, toValueStringInvokable); - } - - public static final SymbolicMethod isCompressedMethod = method("isCompressed"); - public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressed(); - - @Override - public boolean isCompressed() { - return (boolean) handle(isCompressedMethod, isCompressedInvokable); - } - - private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); - private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressible(); - - @Override - public boolean isCompressible() { - return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); - } - - public static final SymbolicMethod compressMethod = method("compress"); - private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).compress(); - - @Override - public Constant compress() { - return (Constant) handle(compressMethod, compressInvokable); - } - - public static final SymbolicMethod uncompressMethod = method("uncompress"); - private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).uncompress(); - - @Override - public Constant uncompress() { - return (Constant) handle(uncompressMethod, uncompressInvokable); - } - - public static final SymbolicMethod asResolvedJavaTypeMethod = method("asResolvedJavaType"); - public static final InvokableMethod asResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaType(); - - @Override - public HotSpotResolvedObjectType asResolvedJavaType() { - return (HotSpotResolvedObjectType) handle(asResolvedJavaTypeMethod, asResolvedJavaTypeInvokable); - } - - public static final SymbolicMethod asResolvedJavaMethodMethod = method("asResolvedJavaMethod"); - public static final InvokableMethod asResolvedJavaMethodInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaMethod(); - - @Override - public HotSpotResolvedJavaMethod asResolvedJavaMethod() { - return (HotSpotResolvedJavaMethod) handle(asResolvedJavaMethodMethod, asResolvedJavaMethodInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java deleted file mode 100644 index 034db556df9d..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotObjectConstant; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaType; - -//JaCoCo Exclude - -public final class HotSpotObjectConstantProxy extends CompilationProxyBase implements HotSpotObjectConstant { - HotSpotObjectConstantProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotObjectConstant.class, name, params); - } - - public static final SymbolicMethod compressMethod = method("compress"); - private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).compress(); - - @Override - public JavaConstant compress() { - return (JavaConstant) handle(compressMethod, compressInvokable); - } - - public static final SymbolicMethod uncompressMethod = method("uncompress"); - private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).uncompress(); - - @Override - public JavaConstant uncompress() { - return (JavaConstant) handle(uncompressMethod, uncompressInvokable); - } - - public static final SymbolicMethod getTypeMethod = method("getType"); - public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getType(); - - @Override - public HotSpotResolvedObjectType getType() { - return (HotSpotResolvedObjectType) handle(getTypeMethod, getTypeInvokable); - } - - private static final SymbolicMethod getIdentityHashCodeMethod = method("getIdentityHashCode"); - private static final InvokableMethod getIdentityHashCodeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getIdentityHashCode(); - - @Override - public int getIdentityHashCode() { - return (int) handle(getIdentityHashCodeMethod, getIdentityHashCodeInvokable); - } - - private static final SymbolicMethod getCallSiteTargetMethod = method("getCallSiteTarget"); - private static final InvokableMethod getCallSiteTargetInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getCallSiteTarget(); - - @Override - @SuppressWarnings("unchecked") - public Assumptions.AssumptionResult getCallSiteTarget() { - return (Assumptions.AssumptionResult) handle(getCallSiteTargetMethod, getCallSiteTargetInvokable); - } - - private static final SymbolicMethod isInternedStringMethod = method("isInternedString"); - private static final InvokableMethod isInternedStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isInternedString(); - - @Override - public boolean isInternedString() { - return (boolean) handle(isInternedStringMethod, isInternedStringInvokable); - } - - private static final SymbolicMethod asObjectClassMethod = method("asObject", Class.class); - private static final InvokableMethod asObjectClassInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asObject((Class) args[0]); - - @Override - @SuppressWarnings("unchecked") - public T asObject(Class type) { - return (T) handle(asObjectClassMethod, asObjectClassInvokable, type); - } - - private static final SymbolicMethod asObjectResolvedJavaTypeMethod = method("asObject", ResolvedJavaType.class); - private static final InvokableMethod asObjectResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asObject((ResolvedJavaType) args[0]); - - @Override - public Object asObject(ResolvedJavaType type) { - return handle(asObjectResolvedJavaTypeMethod, asObjectResolvedJavaTypeInvokable, type); - } - - public static final SymbolicMethod getJavaKindMethod = method("getJavaKind"); - private static final InvokableMethod getJavaKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getJavaKind(); - - @Override - public JavaKind getJavaKind() { - return (JavaKind) handle(getJavaKindMethod, getJavaKindInvokable); - } - - public static final SymbolicMethod isNullMethod = method("isNull"); - private static final InvokableMethod isNullInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isNull(); - - @Override - public boolean isNull() { - return (boolean) handle(isNullMethod, isNullInvokable); - } - - private static final SymbolicMethod asBoxedPrimitiveMethod = method("asBoxedPrimitive"); - private static final InvokableMethod asBoxedPrimitiveInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asBoxedPrimitive(); - - @Override - public Object asBoxedPrimitive() { - return handle(asBoxedPrimitiveMethod, asBoxedPrimitiveInvokable); - } - - private static final SymbolicMethod asIntMethod = method("asInt"); - private static final InvokableMethod asIntInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asInt(); - - @Override - public int asInt() { - return (int) handle(asIntMethod, asIntInvokable); - } - - private static final SymbolicMethod asBooleanMethod = method("asBoolean"); - private static final InvokableMethod asBooleanInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asBoolean(); - - @Override - public boolean asBoolean() { - return (boolean) handle(asBooleanMethod, asBooleanInvokable); - } - - private static final SymbolicMethod asLongMethod = method("asLong"); - private static final InvokableMethod asLongInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asLong(); - - @Override - public long asLong() { - return (long) handle(asLongMethod, asLongInvokable); - } - - private static final SymbolicMethod asFloatMethod = method("asFloat"); - private static final InvokableMethod asFloatInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asFloat(); - - @Override - public float asFloat() { - return (float) handle(asFloatMethod, asFloatInvokable); - } - - private static final SymbolicMethod asDoubleMethod = method("asDouble"); - private static final InvokableMethod asDoubleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asDouble(); - - @Override - public double asDouble() { - return (double) handle(asDoubleMethod, asDoubleInvokable); - } - - public static final SymbolicMethod isCompressedMethod = method("isCompressed"); - public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressed(); - - @Override - public boolean isCompressed() { - return (boolean) handle(isCompressedMethod, isCompressedInvokable); - } - - private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); - private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressible(); - - @Override - public boolean isCompressible() { - return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); - } - - private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); - private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isDefaultForKind(); - - @Override - public boolean isDefaultForKind() { - return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); - } - - public static final SymbolicMethod toValueStringMethod = method("toValueString"); - public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).toValueString(); - - @Override - public String toValueString() { - return (String) handle(toValueStringMethod, toValueStringInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java deleted file mode 100644 index 0effa426d5da..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotProfilingInfo; - -//JaCoCo Exclude - -public final class HotSpotProfilingInfoProxy extends ProfilingInfoProxy implements HotSpotProfilingInfo { - HotSpotProfilingInfoProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotProfilingInfo.class, name, params); - } - - public static final SymbolicMethod getDecompileCountMethod = method("getDecompileCount"); - public static final InvokableMethod getDecompileCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getDecompileCount(); - - @Override - public int getDecompileCount() { - return (int) handle(getDecompileCountMethod, getDecompileCountInvokable); - } - - private static final SymbolicMethod getOverflowRecompileCountMethod = method("getOverflowRecompileCount"); - private static final InvokableMethod getOverflowRecompileCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getOverflowRecompileCount(); - - @Override - public int getOverflowRecompileCount() { - return (int) handle(getOverflowRecompileCountMethod, getOverflowRecompileCountInvokable); - } - - private static final SymbolicMethod getOverflowTrapCountMethod = method("getOverflowTrapCount"); - private static final InvokableMethod getOverflowTrapCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getOverflowTrapCount(); - - @Override - public int getOverflowTrapCount() { - return (int) handle(getOverflowTrapCountMethod, getOverflowTrapCountInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java deleted file mode 100644 index 47e24ed98219..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaType; - -//JaCoCo Exclude - -public final class HotSpotResolvedJavaFieldProxy extends CompilationProxyBase.CompilationProxyAnnotatedBase implements HotSpotResolvedJavaField { - HotSpotResolvedJavaFieldProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotResolvedJavaField.class, name, params); - } - - private static final SymbolicMethod isInObjectMethod = method("isInObject", JavaConstant.class); - private static final InvokableMethod isInObjectInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isInObject((JavaConstant) args[0]); - - @Override - public boolean isInObject(JavaConstant object) { - return (boolean) handle(isInObjectMethod, isInObjectInvokable, object); - } - - public static final SymbolicMethod isStableMethod = method("isStable"); - public static final InvokableMethod isStableInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isStable(); - - @Override - public boolean isStable() { - return (boolean) handle(isStableMethod, isStableInvokable); - } - - public static final SymbolicMethod getOffsetMethod = method("getOffset"); - public static final InvokableMethod getOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getOffset(); - - @Override - public int getOffset() { - return (int) handle(getOffsetMethod, getOffsetInvokable); - } - - private static final SymbolicMethod isInternalMethod = method("isInternal"); - private static final InvokableMethod isInternalInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isInternal(); - - @Override - public boolean isInternal() { - return (boolean) handle(isInternalMethod, isInternalInvokable); - } - - public static final SymbolicMethod isSyntheticMethod = method("isSynthetic"); - public static final InvokableMethod isSyntheticInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isSynthetic(); - - @Override - public boolean isSynthetic() { - return (boolean) handle(isSyntheticMethod, isSyntheticInvokable); - } - - public static final SymbolicMethod getNameMethod = method("getName"); - public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getName(); - - @Override - public String getName() { - return (String) handle(getNameMethod, getNameInvokable); - } - - public static final SymbolicMethod getTypeMethod = method("getType"); - public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getType(); - - @Override - public JavaType getType() { - return (JavaType) handle(getTypeMethod, getTypeInvokable); - } - - public static final SymbolicMethod getDeclaringClassMethod = method("getDeclaringClass"); - public static final InvokableMethod getDeclaringClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getDeclaringClass(); - - @Override - public ResolvedJavaType getDeclaringClass() { - return (ResolvedJavaType) handle(getDeclaringClassMethod, getDeclaringClassInvokable); - } - - private static final SymbolicMethod getConstantValueMethod = method("getConstantValue"); - private static final InvokableMethod getConstantValueInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getConstantValue(); - - @Override - public JavaConstant getConstantValue() { - return (JavaConstant) handle(getConstantValueMethod, getConstantValueInvokable); - } - - public static final SymbolicMethod getModifiersMethod = method("getModifiers"); - public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getModifiers(); - - @Override - public int getModifiers() { - return (int) handle(getModifiersMethod, getModifiersInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java deleted file mode 100644 index a81654130ee6..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java +++ /dev/null @@ -1,449 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Type; -import java.util.BitSet; -import java.util.Formattable; -import java.util.Formatter; - -import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.ExceptionHandler; -import jdk.vm.ci.meta.LineNumberTable; -import jdk.vm.ci.meta.LocalVariableTable; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; - -//JaCoCo Exclude - -public final class HotSpotResolvedJavaMethodProxy extends CompilationProxyBase.CompilationProxyAnnotatedBase implements HotSpotResolvedJavaMethod, Formattable { - HotSpotResolvedJavaMethodProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotResolvedJavaMethod.class, name, params); - } - - private static final SymbolicMethod isCallerSensitiveMethod = method("isCallerSensitive"); - private static final InvokableMethod isCallerSensitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isCallerSensitive(); - - @Override - public boolean isCallerSensitive() { - return (boolean) handle(isCallerSensitiveMethod, isCallerSensitiveInvokable); - } - - public static final SymbolicMethod getCodeMethod = method("getCode"); - public static final InvokableMethod getCodeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getCode(); - - @Override - public byte[] getCode() { - return (byte[]) handle(getCodeMethod, getCodeInvokable); - } - - public static final SymbolicMethod getCodeSizeMethod = method("getCodeSize"); - private static final InvokableMethod getCodeSizeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getCodeSize(); - - @Override - public int getCodeSize() { - return (int) handle(getCodeSizeMethod, getCodeSizeInvokable); - } - - public static final SymbolicMethod getNameMethod = method("getName"); - public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getName(); - - @Override - public String getName() { - return (String) handle(getNameMethod, getNameInvokable); - } - - public static final SymbolicMethod getDeclaringClassMethod = method("getDeclaringClass"); - public static final InvokableMethod getDeclaringClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getDeclaringClass(); - - @Override - public HotSpotResolvedObjectType getDeclaringClass() { - return (HotSpotResolvedObjectType) handle(getDeclaringClassMethod, getDeclaringClassInvokable); - } - - public static final SymbolicMethod getSignatureMethod = method("getSignature"); - public static final InvokableMethod getSignatureInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getSignature(); - - @Override - public Signature getSignature() { - return (Signature) handle(getSignatureMethod, getSignatureInvokable); - } - - private static final SymbolicMethod getMaxLocalsMethod = method("getMaxLocals"); - private static final InvokableMethod getMaxLocalsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getMaxLocals(); - - @Override - public int getMaxLocals() { - return (int) handle(getMaxLocalsMethod, getMaxLocalsInvokable); - } - - private static final SymbolicMethod getMaxStackSizeMethod = method("getMaxStackSize"); - private static final InvokableMethod getMaxStackSizeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getMaxStackSize(); - - @Override - public int getMaxStackSize() { - return (int) handle(getMaxStackSizeMethod, getMaxStackSizeInvokable); - } - - private static final SymbolicMethod isSyntheticMethod = method("isSynthetic"); - private static final InvokableMethod isSyntheticInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isSynthetic(); - - @Override - public boolean isSynthetic() { - return (boolean) handle(isSyntheticMethod, isSyntheticInvokable); - } - - private static final SymbolicMethod isVarArgsMethod = method("isVarArgs"); - private static final InvokableMethod isVarArgsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isVarArgs(); - - @Override - public boolean isVarArgs() { - return (boolean) handle(isVarArgsMethod, isVarArgsInvokable); - } - - private static final SymbolicMethod isBridgeMethod = method("isBridge"); - private static final InvokableMethod isBridgeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isBridge(); - - @Override - public boolean isBridge() { - return (boolean) handle(isBridgeMethod, isBridgeInvokable); - } - - private static final SymbolicMethod isDeclaredMethod = method("isDeclared"); - private static final InvokableMethod isDeclaredInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isDeclared(); - - @Override - public boolean isDeclared() { - return (boolean) handle(isDeclaredMethod, isDeclaredInvokable); - } - - private static final SymbolicMethod isClassInitializerMethod = method("isClassInitializer"); - private static final InvokableMethod isClassInitializerInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isClassInitializer(); - - @Override - public boolean isClassInitializer() { - return (boolean) handle(isClassInitializerMethod, isClassInitializerInvokable); - } - - public static final SymbolicMethod isConstructorMethod = method("isConstructor"); - public static final InvokableMethod isConstructorInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isConstructor(); - - @Override - public boolean isConstructor() { - return (boolean) handle(isConstructorMethod, isConstructorInvokable); - } - - public static final SymbolicMethod canBeStaticallyBoundMethod = method("canBeStaticallyBound"); - public static final InvokableMethod canBeStaticallyBoundInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).canBeStaticallyBound(); - - @Override - public boolean canBeStaticallyBound() { - return (boolean) handle(canBeStaticallyBoundMethod, canBeStaticallyBoundInvokable); - } - - private static final SymbolicMethod getExceptionHandlersMethod = method("getExceptionHandlers"); - private static final InvokableMethod getExceptionHandlersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getExceptionHandlers(); - - @Override - public ExceptionHandler[] getExceptionHandlers() { - return (ExceptionHandler[]) handle(getExceptionHandlersMethod, getExceptionHandlersInvokable); - } - - public static final SymbolicMethod asStackTraceElementMethod = method("asStackTraceElement", int.class); - public static final InvokableMethod asStackTraceElementInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).asStackTraceElement((int) args[0]); - - @Override - public StackTraceElement asStackTraceElement(int bci) { - return (StackTraceElement) handle(asStackTraceElementMethod, asStackTraceElementInvokable, bci); - } - - private static final SymbolicMethod getProfilingInfoMethod = method("getProfilingInfo", boolean.class, boolean.class); - private static final InvokableMethod getProfilingInfoInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getProfilingInfo((boolean) args[0], (boolean) args[1]); - - @Override - public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) { - return (ProfilingInfo) handle(getProfilingInfoMethod, getProfilingInfoInvokable, includeNormal, includeOSR); - } - - private static final SymbolicMethod reprofileMethod = method("reprofile"); - private static final InvokableMethod reprofileInvokable = (receiver, args) -> { - ((HotSpotResolvedJavaMethod) receiver).reprofile(); - return null; - }; - - @Override - public void reprofile() { - handle(reprofileMethod, reprofileInvokable); - } - - public static final SymbolicMethod getConstantPoolMethod = method("getConstantPool"); - public static final InvokableMethod getConstantPoolInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getConstantPool(); - - @Override - public ConstantPool getConstantPool() { - return (ConstantPool) handle(getConstantPoolMethod, getConstantPoolInvokable); - } - - public static final SymbolicMethod getParametersMethod = method("getParameters"); - private static final InvokableMethod getParametersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getParameters(); - - @Override - public Parameter[] getParameters() { - return (Parameter[]) handle(getParametersMethod, getParametersInvokable); - } - - public static final SymbolicMethod getParameterAnnotationsMethod = method("getParameterAnnotations"); - private static final InvokableMethod getParameterAnnotationsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getParameterAnnotations(); - - @Override - public Annotation[][] getParameterAnnotations() { - return (Annotation[][]) handle(getParameterAnnotationsMethod, getParameterAnnotationsInvokable); - } - - public static final SymbolicMethod getGenericParameterTypesMethod = method("getGenericParameterTypes"); - private static final InvokableMethod getGenericParameterTypesInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getGenericParameterTypes(); - - @Override - public Type[] getGenericParameterTypes() { - return (Type[]) handle(getGenericParameterTypesMethod, getGenericParameterTypesInvokable); - } - - public static final SymbolicMethod canBeInlinedMethod = method("canBeInlined"); - private static final InvokableMethod canBeInlinedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).canBeInlined(); - - @Override - public boolean canBeInlined() { - return (boolean) handle(canBeInlinedMethod, canBeInlinedInvokable); - } - - private static final SymbolicMethod hasNeverInlineDirectiveMethod = method("hasNeverInlineDirective"); - private static final InvokableMethod hasNeverInlineDirectiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasNeverInlineDirective(); - - @Override - public boolean hasNeverInlineDirective() { - return (boolean) handle(hasNeverInlineDirectiveMethod, hasNeverInlineDirectiveInvokable); - } - - private static final SymbolicMethod shouldBeInlinedMethod = method("shouldBeInlined"); - private static final InvokableMethod shouldBeInlinedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).shouldBeInlined(); - - @Override - public boolean shouldBeInlined() { - return (boolean) handle(shouldBeInlinedMethod, shouldBeInlinedInvokable); - } - - private static final SymbolicMethod getLineNumberTableMethod = method("getLineNumberTable"); - private static final InvokableMethod getLineNumberTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getLineNumberTable(); - - @Override - public LineNumberTable getLineNumberTable() { - return (LineNumberTable) handle(getLineNumberTableMethod, getLineNumberTableInvokable); - } - - private static final SymbolicMethod getLocalVariableTableMethod = method("getLocalVariableTable"); - private static final InvokableMethod getLocalVariableTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getLocalVariableTable(); - - @Override - public LocalVariableTable getLocalVariableTable() { - return (LocalVariableTable) handle(getLocalVariableTableMethod, getLocalVariableTableInvokable); - } - - private static final SymbolicMethod getEncodingMethod = method("getEncoding"); - private static final InvokableMethod getEncodingInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getEncoding(); - - @Override - public Constant getEncoding() { - return (Constant) handle(getEncodingMethod, getEncodingInvokable); - } - - public static final SymbolicMethod isInVirtualMethodTableMethod = method("isInVirtualMethodTable", ResolvedJavaType.class); - private static final InvokableMethod isInVirtualMethodTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isInVirtualMethodTable((ResolvedJavaType) args[0]); - - @Override - public boolean isInVirtualMethodTable(ResolvedJavaType resolved) { - return (boolean) handle(isInVirtualMethodTableMethod, isInVirtualMethodTableInvokable, resolved); - } - - private static final SymbolicMethod isScopedMethod = method("isScoped"); - private static final InvokableMethod isScopedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isScoped(); - - @Override - public boolean isScoped() { - return (boolean) handle(isScopedMethod, isScopedInvokable); - } - - private static final SymbolicMethod getSpeculationLogMethod = method("getSpeculationLog"); - private static final InvokableMethod getSpeculationLogInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getSpeculationLog(); - - @Override - public SpeculationLog getSpeculationLog() { - return (SpeculationLog) handle(getSpeculationLogMethod, getSpeculationLogInvokable); - } - - private static final SymbolicMethod isForceInlineMethod = method("isForceInline"); - private static final InvokableMethod isForceInlineInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isForceInline(); - - @Override - public boolean isForceInline() { - return (boolean) handle(isForceInlineMethod, isForceInlineInvokable); - } - - private static final SymbolicMethod hasReservedStackAccessMethod = method("hasReservedStackAccess"); - private static final InvokableMethod hasReservedStackAccessInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasReservedStackAccess(); - - @Override - public boolean hasReservedStackAccess() { - return (boolean) handle(hasReservedStackAccessMethod, hasReservedStackAccessInvokable); - } - - private static final SymbolicMethod setNotInlinableOrCompilableMethod = method("setNotInlinableOrCompilable"); - private static final InvokableMethod setNotInlinableOrCompilableInvokable = (receiver, args) -> { - ((HotSpotResolvedJavaMethod) receiver).setNotInlinableOrCompilable(); - return null; - }; - - @Override - public void setNotInlinableOrCompilable() { - handle(setNotInlinableOrCompilableMethod, setNotInlinableOrCompilableInvokable); - } - - private static final SymbolicMethod ignoredBySecurityStackWalkMethod = method("ignoredBySecurityStackWalk"); - private static final InvokableMethod ignoredBySecurityStackWalkInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).ignoredBySecurityStackWalk(); - - @Override - public boolean ignoredBySecurityStackWalk() { - return (boolean) handle(ignoredBySecurityStackWalkMethod, ignoredBySecurityStackWalkInvokable); - } - - private static final SymbolicMethod uniqueConcreteMethodMethod = method("uniqueConcreteMethod", HotSpotResolvedObjectType.class); - private static final InvokableMethod uniqueConcreteMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).uniqueConcreteMethod((HotSpotResolvedObjectType) args[0]); - - @Override - public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType rec) { - return (ResolvedJavaMethod) handle(uniqueConcreteMethodMethod, uniqueConcreteMethodInvokable, rec); - } - - private static final SymbolicMethod hasCompiledCodeMethod = method("hasCompiledCode"); - private static final InvokableMethod hasCompiledCodeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCompiledCode(); - - @Override - public boolean hasCompiledCode() { - return (boolean) handle(hasCompiledCodeMethod, hasCompiledCodeInvokable); - } - - private static final SymbolicMethod hasCompiledCodeAtLevelMethod = method("hasCompiledCodeAtLevel", int.class); - private static final InvokableMethod hasCompiledCodeAtLevelInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCompiledCodeAtLevel((int) args[0]); - - @Override - public boolean hasCompiledCodeAtLevel(int level) { - return (boolean) handle(hasCompiledCodeAtLevelMethod, hasCompiledCodeAtLevelInvokable, level); - } - - private static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); - private static final InvokableMethod vtableEntryOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).vtableEntryOffset((ResolvedJavaType) args[0]); - - @Override - public int vtableEntryOffset(ResolvedJavaType resolved) { - return (int) handle(vtableEntryOffsetMethod, vtableEntryOffsetInvokable, resolved); - } - - public static final SymbolicMethod intrinsicIdMethod = method("intrinsicId"); - private static final InvokableMethod intrinsicIdInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).intrinsicId(); - - @Override - public int intrinsicId() { - return (int) handle(intrinsicIdMethod, intrinsicIdInvokable); - } - - private static final SymbolicMethod isIntrinsicCandidateMethod = method("isIntrinsicCandidate"); - private static final InvokableMethod isIntrinsicCandidateInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isIntrinsicCandidate(); - - @Override - public boolean isIntrinsicCandidate() { - return (boolean) handle(isIntrinsicCandidateMethod, isIntrinsicCandidateInvokable); - } - - private static final SymbolicMethod allocateCompileIdMethod = method("allocateCompileId", int.class); - private static final InvokableMethod allocateCompileIdInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).allocateCompileId((int) args[0]); - - @Override - public int allocateCompileId(int entryBCI) { - return (int) handle(allocateCompileIdMethod, allocateCompileIdInvokable, entryBCI); - } - - public static final SymbolicMethod hasCodeAtLevelMethod = method("hasCodeAtLevel", int.class, int.class); - private static final InvokableMethod hasCodeAtLevelInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCodeAtLevel((int) args[0], (int) args[1]); - - @Override - public boolean hasCodeAtLevel(int entryBCI, int level) { - return (boolean) handle(hasCodeAtLevelMethod, hasCodeAtLevelInvokable, entryBCI, level); - } - - private static final SymbolicMethod methodIdnumMethod = method("methodIdnum"); - private static final InvokableMethod methodIdnumInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).methodIdnum(); - - @Override - public int methodIdnum() { - return (int) handle(methodIdnumMethod, methodIdnumInvokable); - } - - private static final SymbolicMethod getOopMapAtMethod = method("getOopMapAt", int.class); - private static final InvokableMethod getOopMapAtInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getOopMapAt((int) args[0]); - - @Override - public BitSet getOopMapAt(int bci) { - return (BitSet) handle(getOopMapAtMethod, getOopMapAtInvokable, bci); - } - - public static final SymbolicMethod getModifiersMethod = method("getModifiers"); - public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getModifiers(); - - @Override - public int getModifiers() { - return (int) handle(getModifiersMethod, getModifiersInvokable); - } - - public static final SymbolicMethod formatToMethod = new SymbolicMethod(Formattable.class, "formatTo", Formatter.class, int.class, int.class, int.class); - private static final InvokableMethod formatToInvokable = (receiver, args) -> { - ((Formattable) receiver).formatTo((Formatter) args[0], (int) args[1], (int) args[2], (int) args[3]); - return null; - }; - - @Override - public void formatTo(Formatter formatter, int flags, int width, int precision) { - handle(formatToMethod, formatToInvokable, formatter, flags, width, precision); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java deleted file mode 100644 index a9eaefc24157..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod; - -import java.lang.annotation.Annotation; -import java.util.List; - -import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Assumptions; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.UnresolvedJavaField; -import jdk.vm.ci.meta.UnresolvedJavaType; - -//JaCoCo Exclude - -public sealed class HotSpotResolvedJavaTypeProxy extends HotSpotResolvedJavaType implements CompilationProxy permits HotSpotResolvedObjectTypeProxy { - private final InvocationHandler handler; - - protected HotSpotResolvedJavaTypeProxy(InvocationHandler handler) { - super("HotSpotResolvedJavaTypeProxy"); - this.handler = handler; - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotResolvedJavaType.class, name, params); - } - - protected final Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { - return CompilationProxy.handle(handler, this, method, invokable, args); - } - - @Override - protected final HotSpotResolvedObjectType getArrayType() { - throw new UnsupportedOperationException("getArrayType"); - } - - private static final SymbolicMethod getArrayClassMethod = method("getArrayClass"); - private static final InvokableMethod getArrayClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getArrayClass(); - - @Override - public final HotSpotResolvedObjectType getArrayClass() { - return (HotSpotResolvedObjectType) handle(getArrayClassMethod, getArrayClassInvokable); - } - - @Override - protected final boolean isBeingInitialized() { - throw new UnsupportedOperationException("isBeingInitialized"); - } - - private static final SymbolicMethod resolveMethod = method("resolve", ResolvedJavaType.class); - private static final InvokableMethod resolveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolve((ResolvedJavaType) args[0]); - - @Override - public final ResolvedJavaType resolve(ResolvedJavaType accessingClass) { - return (ResolvedJavaType) handle(resolveMethod, resolveInvokable, accessingClass); - } - - private static final SymbolicMethod resolveMethodMethod = method("resolveMethod", ResolvedJavaMethod.class, ResolvedJavaType.class); - private static final InvokableMethod resolveMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolveMethod((ResolvedJavaMethod) args[0], (ResolvedJavaType) args[1]); - - @Override - public final ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { - return (ResolvedJavaMethod) handle(resolveMethodMethod, resolveMethodInvokable, method, callerType); - } - - public static final SymbolicMethod getNameMethod = method("getName"); - public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getName(); - - @Override - public final String getName() { - return (String) handle(getNameMethod, getNameInvokable); - } - - public static final SymbolicMethod getComponentTypeMethod = method("getComponentType"); - public static final InvokableMethod getComponentTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getComponentType(); - - @Override - public final ResolvedJavaType getComponentType() { - return (ResolvedJavaType) handle(getComponentTypeMethod, getComponentTypeInvokable); - } - - private static final SymbolicMethod findLeafConcreteSubtypeMethod = method("findLeafConcreteSubtype"); - private static final InvokableMethod findLeafConcreteSubtypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findLeafConcreteSubtype(); - - @Override - @SuppressWarnings("unchecked") - public final Assumptions.AssumptionResult findLeafConcreteSubtype() { - return (Assumptions.AssumptionResult) handle(findLeafConcreteSubtypeMethod, findLeafConcreteSubtypeInvokable); - } - - private static final SymbolicMethod hasFinalizerMethod = method("hasFinalizer"); - private static final InvokableMethod hasFinalizerInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasFinalizer(); - - @Override - public final boolean hasFinalizer() { - return (boolean) handle(hasFinalizerMethod, hasFinalizerInvokable); - } - - private static final SymbolicMethod hasFinalizableSubclassMethod = method("hasFinalizableSubclass"); - private static final InvokableMethod hasFinalizableSubclassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasFinalizableSubclass(); - - @Override - @SuppressWarnings("unchecked") - public final Assumptions.AssumptionResult hasFinalizableSubclass() { - return (Assumptions.AssumptionResult) handle(hasFinalizableSubclassMethod, hasFinalizableSubclassInvokable); - } - - public static final SymbolicMethod getModifiersMethod = method("getModifiers"); - public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getModifiers(); - - @Override - public final int getModifiers() { - return (int) handle(getModifiersMethod, getModifiersInvokable); - } - - public static final SymbolicMethod isInterfaceMethod = method("isInterface"); - public static final InvokableMethod isInterfaceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInterface(); - - @Override - public final boolean isInterface() { - return (boolean) handle(isInterfaceMethod, isInterfaceInvokable); - } - - private static final SymbolicMethod isInstanceClassMethod = method("isInstanceClass"); - private static final InvokableMethod isInstanceClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstanceClass(); - - @Override - public final boolean isInstanceClass() { - return (boolean) handle(isInstanceClassMethod, isInstanceClassInvokable); - } - - private static final SymbolicMethod isEnumMethod = method("isEnum"); - private static final InvokableMethod isEnumInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isEnum(); - - @Override - public final boolean isEnum() { - return (boolean) handle(isEnumMethod, isEnumInvokable); - } - - public static final SymbolicMethod isInitializedMethod = method("isInitialized"); - private static final InvokableMethod isInitializedInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInitialized(); - - @Override - public final boolean isInitialized() { - return (boolean) handle(isInitializedMethod, isInitializedInvokable); - } - - private static final SymbolicMethod initializeMethod = method("initialize"); - private static final InvokableMethod initializeInvokable = (receiver, args) -> { - ((HotSpotResolvedJavaType) receiver).initialize(); - return null; - }; - - @Override - public final void initialize() { - handle(initializeMethod, initializeInvokable); - } - - private static final SymbolicMethod isLinkedMethod = method("isLinked"); - private static final InvokableMethod isLinkedInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isLinked(); - - @Override - public final boolean isLinked() { - return (boolean) handle(isLinkedMethod, isLinkedInvokable); - } - - private static final SymbolicMethod linkMethod = method("link"); - private static final InvokableMethod linkInvokable = (receiver, args) -> { - ((HotSpotResolvedJavaType) receiver).link(); - return null; - }; - - @Override - public final void link() { - handle(linkMethod, linkInvokable); - } - - private static final SymbolicMethod hasDefaultMethodsMethod = method("hasDefaultMethods"); - private static final InvokableMethod hasDefaultMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasDefaultMethods(); - - @Override - public final boolean hasDefaultMethods() { - return (boolean) handle(hasDefaultMethodsMethod, hasDefaultMethodsInvokable); - } - - private static final SymbolicMethod declaresDefaultMethodsMethod = method("declaresDefaultMethods"); - private static final InvokableMethod declaresDefaultMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).declaresDefaultMethods(); - - @Override - public final boolean declaresDefaultMethods() { - return (boolean) handle(declaresDefaultMethodsMethod, declaresDefaultMethodsInvokable); - } - - public static final SymbolicMethod isAssignableFromMethod = method("isAssignableFrom", ResolvedJavaType.class); - private static final InvokableMethod isAssignableFromInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isAssignableFrom((ResolvedJavaType) args[0]); - - @Override - public final boolean isAssignableFrom(ResolvedJavaType other) { - return (boolean) handle(isAssignableFromMethod, isAssignableFromInvokable, other); - } - - private static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); - private static final InvokableMethod isInstanceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstance((JavaConstant) args[0]); - - @Override - public final boolean isInstance(JavaConstant obj) { - return (boolean) handle(isInstanceMethod, isInstanceInvokable, obj); - } - - private static final SymbolicMethod getSuperclassMethod = method("getSuperclass"); - private static final InvokableMethod getSuperclassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSuperclass(); - - @Override - public final HotSpotResolvedObjectType getSuperclass() { - return (HotSpotResolvedObjectType) handle(getSuperclassMethod, getSuperclassInvokable); - } - - private static final SymbolicMethod getInterfacesMethod = method("getInterfaces"); - private static final InvokableMethod getInterfacesInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getInterfaces(); - - @Override - public final HotSpotResolvedObjectType[] getInterfaces() { - return (HotSpotResolvedObjectType[]) handle(getInterfacesMethod, getInterfacesInvokable); - } - - private static final SymbolicMethod getSingleImplementorMethod = method("getSingleImplementor"); - private static final InvokableMethod getSingleImplementorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSingleImplementor(); - - @Override - public final ResolvedJavaType getSingleImplementor() { - return (ResolvedJavaType) handle(getSingleImplementorMethod, getSingleImplementorInvokable); - } - - public static final SymbolicMethod findLeastCommonAncestorMethod = method("findLeastCommonAncestor", ResolvedJavaType.class); - private static final InvokableMethod findLeastCommonAncestorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findLeastCommonAncestor((ResolvedJavaType) args[0]); - - @Override - public final HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) { - return (HotSpotResolvedObjectType) handle(findLeastCommonAncestorMethod, findLeastCommonAncestorInvokable, otherType); - } - - private static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); - private static final InvokableMethod isPrimitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isPrimitive(); - - @Override - public final boolean isPrimitive() { - return (boolean) handle(isPrimitiveMethod, isPrimitiveInvokable); - } - - public static final SymbolicMethod getJavaKindMethod = method("getJavaKind"); - public static final InvokableMethod getJavaKindInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getJavaKind(); - - @Override - public final JavaKind getJavaKind() { - return (JavaKind) handle(getJavaKindMethod, getJavaKindInvokable); - } - - private static final SymbolicMethod findUniqueConcreteMethodMethod = method("findUniqueConcreteMethod", ResolvedJavaMethod.class); - private static final InvokableMethod findUniqueConcreteMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findUniqueConcreteMethod((ResolvedJavaMethod) args[0]); - - @Override - @SuppressWarnings("unchecked") - public final Assumptions.AssumptionResult findUniqueConcreteMethod(ResolvedJavaMethod method) { - return (Assumptions.AssumptionResult) handle(findUniqueConcreteMethodMethod, findUniqueConcreteMethodInvokable, method); - } - - public static final SymbolicMethod getInstanceFieldsMethod = method("getInstanceFields", boolean.class); - public static final InvokableMethod getInstanceFieldsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getInstanceFields((boolean) args[0]); - - @Override - public final ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { - return (ResolvedJavaField[]) handle(getInstanceFieldsMethod, getInstanceFieldsInvokable, includeSuperclasses); - } - - public static final SymbolicMethod getStaticFieldsMethod = method("getStaticFields"); - public static final InvokableMethod getStaticFieldsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getStaticFields(); - - @Override - public final ResolvedJavaField[] getStaticFields() { - return (ResolvedJavaField[]) handle(getStaticFieldsMethod, getStaticFieldsInvokable); - } - - private static final SymbolicMethod findInstanceFieldWithOffsetMethod = method("findInstanceFieldWithOffset", long.class, JavaKind.class); - private static final InvokableMethod findInstanceFieldWithOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findInstanceFieldWithOffset((long) args[0], - (JavaKind) args[1]); - - @Override - public final ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind) { - return (ResolvedJavaField) handle(findInstanceFieldWithOffsetMethod, findInstanceFieldWithOffsetInvokable, offset, expectedKind); - } - - private static final SymbolicMethod getSourceFileNameMethod = method("getSourceFileName"); - private static final InvokableMethod getSourceFileNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSourceFileName(); - - @Override - public final String getSourceFileName() { - return (String) handle(getSourceFileNameMethod, getSourceFileNameInvokable); - } - - private static final SymbolicMethod isLocalMethod = method("isLocal"); - private static final InvokableMethod isLocalInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isLocal(); - - @Override - public final boolean isLocal() { - return (boolean) handle(isLocalMethod, isLocalInvokable); - } - - private static final SymbolicMethod isMemberMethod = method("isMember"); - private static final InvokableMethod isMemberInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isMember(); - - @Override - public final boolean isMember() { - return (boolean) handle(isMemberMethod, isMemberInvokable); - } - - private static final SymbolicMethod getEnclosingTypeMethod = method("getEnclosingType"); - private static final InvokableMethod getEnclosingTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getEnclosingType(); - - @Override - public final HotSpotResolvedObjectType getEnclosingType() { - return (HotSpotResolvedObjectType) handle(getEnclosingTypeMethod, getEnclosingTypeInvokable); - } - - private static final SymbolicMethod getDeclaredConstructorsMethod = method("getDeclaredConstructors"); - private static final InvokableMethod getDeclaredConstructorsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredConstructors(); - - @Override - public final ResolvedJavaMethod[] getDeclaredConstructors() { - return (ResolvedJavaMethod[]) handle(getDeclaredConstructorsMethod, getDeclaredConstructorsInvokable); - } - - private static final SymbolicMethod getDeclaredConstructorsBooleanMethod = method("getDeclaredConstructors", boolean.class); - private static final InvokableMethod getDeclaredConstructorsBooleanInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredConstructors((Boolean) args[0]); - - @Override - public final ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) { - return (ResolvedJavaMethod[]) handle(getDeclaredConstructorsBooleanMethod, getDeclaredConstructorsBooleanInvokable, forceLink); - } - - private static final SymbolicMethod getDeclaredMethodsMethod = method("getDeclaredMethods"); - private static final InvokableMethod getDeclaredMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredMethods(); - - @Override - public final ResolvedJavaMethod[] getDeclaredMethods() { - return (ResolvedJavaMethod[]) handle(getDeclaredMethodsMethod, getDeclaredMethodsInvokable); - } - - private static final SymbolicMethod getAllMethodsMethod = method("getAllMethods", boolean.class); - private static final InvokableMethod getAllMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getAllMethods((boolean) args[0]); - - @Override - @SuppressWarnings("unchecked") - public List getAllMethods(boolean forceLink) { - return (List) handle(getAllMethodsMethod, getAllMethodsInvokable); - } - - private static final SymbolicMethod getDeclaredMethodsBooleanMethod = method("getDeclaredMethods", boolean.class); - private static final InvokableMethod getDeclaredMethodsBooleanInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredMethods((boolean) args[0]); - - @Override - public final ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { - return (ResolvedJavaMethod[]) handle(getDeclaredMethodsBooleanMethod, getDeclaredMethodsBooleanInvokable, forceLink); - } - - private static final SymbolicMethod getClassInitializerMethod = method("getClassInitializer"); - private static final InvokableMethod getClassInitializerInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getClassInitializer(); - - @Override - public final ResolvedJavaMethod getClassInitializer() { - return (ResolvedJavaMethod) handle(getClassInitializerMethod, getClassInitializerInvokable); - } - - private static final SymbolicMethod isCloneableWithAllocationMethod = method("isCloneableWithAllocation"); - private static final InvokableMethod isCloneableWithAllocationInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isCloneableWithAllocation(); - - @Override - public final boolean isCloneableWithAllocation() { - return (boolean) handle(isCloneableWithAllocationMethod, isCloneableWithAllocationInvokable); - } - - private static final SymbolicMethod lookupTypeMethod = method("lookupType", UnresolvedJavaType.class, boolean.class); - private static final InvokableMethod lookupTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).lookupType((UnresolvedJavaType) args[0], (Boolean) args[1]); - - @Override - public final ResolvedJavaType lookupType(UnresolvedJavaType unresolvedJavaType, boolean resolve) { - return (ResolvedJavaType) handle(lookupTypeMethod, lookupTypeInvokable, unresolvedJavaType, resolve); - } - - private static final SymbolicMethod resolveFieldMethod = method("resolveField", UnresolvedJavaField.class, ResolvedJavaType.class); - private static final InvokableMethod resolveFieldInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolveField((UnresolvedJavaField) args[0], (ResolvedJavaType) args[1]); - - @Override - public final ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, ResolvedJavaType accessingClass) { - return (ResolvedJavaField) handle(resolveFieldMethod, resolveFieldInvokable, unresolvedJavaField, accessingClass); - } - - @Override - @SuppressWarnings("unchecked") - public final T getAnnotation(Class annotationClass) { - return (T) handle(getAnnotationMethod, getAnnotationInvokable, annotationClass); - } - - @Override - public final Annotation[] getAnnotations() { - return (Annotation[]) handle(getAnnotationsMethod, getAnnotationsInvokable); - } - - @Override - public final Annotation[] getDeclaredAnnotations() { - return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); - } - - @Override - public final Object unproxify() { - return handle(unproxifyMethod, unproxifyInvokable); - } - - @Override - public final int hashCode() { - return (int) handle(hashCodeMethod, hashCodeInvokable); - } - - public static final SymbolicMethod getJavaMirrorMethod = method("getJavaMirror"); - public static final InvokableMethod getJavaMirrorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getJavaMirror(); - - @Override - public final JavaConstant getJavaMirror() { - return (JavaConstant) handle(getJavaMirrorMethod, getJavaMirrorInvokable); - } - - @Override - public final boolean equals(Object obj) { - return (boolean) handle(equalsMethod, equalsInvokable, obj); - } - - @Override - public final String toString() { - return (String) handle(toStringMethod, toStringInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java deleted file mode 100644 index 7e1d52812e29..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.ResolvedJavaType; - -//JaCoCo Exclude - -public final class HotSpotResolvedObjectTypeProxy extends HotSpotResolvedJavaTypeProxy implements HotSpotResolvedObjectType { - HotSpotResolvedObjectTypeProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotResolvedObjectType.class, name, params); - } - - private static final SymbolicMethod getSupertypeMethod = method("getSupertype"); - private static final InvokableMethod getSupertypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getSupertype(); - - @Override - public HotSpotResolvedObjectType getSupertype() { - return (HotSpotResolvedObjectType) handle(getSupertypeMethod, getSupertypeInvokable); - } - - private static final SymbolicMethod getConstantPoolMethod = method("getConstantPool"); - private static final InvokableMethod getConstantPoolInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getConstantPool(); - - @Override - public ConstantPool getConstantPool() { - return (ConstantPool) handle(getConstantPoolMethod, getConstantPoolInvokable); - } - - public static final SymbolicMethod instanceSizeMethod = method("instanceSize"); - public static final InvokableMethod instanceSizeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).instanceSize(); - - @Override - public int instanceSize() { - return (int) handle(instanceSizeMethod, instanceSizeInvokable); - } - - private static final SymbolicMethod getVtableLengthMethod = method("getVtableLength"); - private static final InvokableMethod getVtableLengthInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getVtableLength(); - - @Override - public int getVtableLength() { - return (int) handle(getVtableLengthMethod, getVtableLengthInvokable); - } - - private static final SymbolicMethod isDefinitelyResolvedWithRespectToMethod = method("isDefinitelyResolvedWithRespectTo", ResolvedJavaType.class); - private static final InvokableMethod isDefinitelyResolvedWithRespectToInvokable = (receiver, - args) -> ((HotSpotResolvedObjectType) receiver).isDefinitelyResolvedWithRespectTo((ResolvedJavaType) args[0]); - - @Override - public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) { - return (boolean) handle(isDefinitelyResolvedWithRespectToMethod, isDefinitelyResolvedWithRespectToInvokable, accessingClass); - } - - public static final SymbolicMethod klassMethod = method("klass"); - public static final InvokableMethod klassInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).klass(); - - @Override - public Constant klass() { - return (Constant) handle(klassMethod, klassInvokable); - } - - private static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); - private static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); - - @Override - public boolean isPrimaryType() { - return (boolean) handle(isPrimaryTypeMethod, isPrimaryTypeInvokable); - } - - private static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); - private static final InvokableMethod superCheckOffsetInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).superCheckOffset(); - - @Override - public int superCheckOffset() { - return (int) handle(superCheckOffsetMethod, superCheckOffsetInvokable); - } - - private static final SymbolicMethod prototypeMarkWordMethod = method("prototypeMarkWord"); - private static final InvokableMethod prototypeMarkWordInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).prototypeMarkWord(); - - @Override - public long prototypeMarkWord() { - return (long) handle(prototypeMarkWordMethod, prototypeMarkWordInvokable); - } - - private static final SymbolicMethod layoutHelperMethod = method("layoutHelper"); - private static final InvokableMethod layoutHelperInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).layoutHelper(); - - @Override - public int layoutHelper() { - return (int) handle(layoutHelperMethod, layoutHelperInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java deleted file mode 100644 index 08ae243616bf..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; -import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; - -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; -import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; -import jdk.vm.ci.hotspot.VMField; - -//JaCoCo Exclude - -final class HotSpotVMConfigAccessProxy extends HotSpotVMConfigAccess implements CompilationProxy { - private final InvocationHandler handler; - - HotSpotVMConfigAccessProxy(InvocationHandler handler) { - super(null); - this.handler = handler; - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(HotSpotVMConfigAccess.class, name, params); - } - - private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { - return CompilationProxy.handle(handler, this, method, invokable, args); - } - - @Override - public HotSpotVMConfigStore getStore() { - // Config store serialization is not implemented. - return HotSpotJVMCIRuntime.runtime().getConfigStore(); - } - - private static final SymbolicMethod getAddressMethod = method("getAddress", String.class, Long.class); - private static final InvokableMethod getAddressInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getAddress((String) args[0], (Long) args[1]); - - @Override - public long getAddress(String name, Long notPresent) { - return (long) handle(getAddressMethod, getAddressInvokable, name, notPresent); - } - - private static final SymbolicMethod getConstantMethod = method("getConstant", String.class, Class.class, Object.class); - @SuppressWarnings("unchecked") private static final InvokableMethod getConstantInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getConstant((String) args[0], - (Class) args[1], args[2]); - - @Override - @SuppressWarnings("unchecked") - public T getConstant(String name, Class type, T notPresent) { - return (T) handle(getConstantMethod, getConstantInvokable, name, type, notPresent); - } - - private static final SymbolicMethod getFieldMethod = method("getField", String.class, String.class, boolean.class); - private static final InvokableMethod getFieldInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getField((String) args[0], (String) args[1], (boolean) args[2]); - - @Override - public VMField getField(String name, String cppType, boolean required) { - return (VMField) handle(getFieldMethod, getFieldInvokable, name, cppType, required); - } - - private static final SymbolicMethod getFlagMethod = method("getFlag", String.class, Class.class, Object.class); - @SuppressWarnings("unchecked") private static final InvokableMethod getFlagInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getFlag((String) args[0], (Class) args[1], - args[2]); - - @Override - @SuppressWarnings("unchecked") - public T getFlag(String name, Class type, T notPresent) { - return (T) handle(getFlagMethod, getFlagInvokable, name, type, notPresent); - } - - @Override - public Object unproxify() { - return handle(unproxifyMethod, unproxifyInvokable); - } - - @Override - public int hashCode() { - return (int) handle(hashCodeMethod, hashCodeInvokable); - } - - @Override - public boolean equals(Object obj) { - return (boolean) handle(equalsMethod, equalsInvokable, obj); - } - - @Override - public String toString() { - return (String) handle(toStringMethod, toStringInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java deleted file mode 100644 index 99e5368e338c..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import java.lang.reflect.Executable; -import java.lang.reflect.Field; - -import jdk.vm.ci.meta.DeoptimizationAction; -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.MetaAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaField; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; -import jdk.vm.ci.meta.SpeculationLog; - -//JaCoCo Exclude - -public final class MetaAccessProviderProxy extends CompilationProxyBase implements MetaAccessProvider { - MetaAccessProviderProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(MetaAccessProvider.class, name, params); - } - - public static final SymbolicMethod lookupJavaTypeClassMethod = method("lookupJavaType", Class.class); - public static final InvokableMethod lookupJavaTypeClassInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaType((Class) args[0]); - - @Override - public ResolvedJavaType lookupJavaType(Class clazz) { - return (ResolvedJavaType) handle(lookupJavaTypeClassMethod, lookupJavaTypeClassInvokable, clazz); - } - - private static final SymbolicMethod lookupJavaMethodMethod = method("lookupJavaMethod", Executable.class); - private static final InvokableMethod lookupJavaMethodInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaMethod((Executable) args[0]); - - @Override - public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { - return (ResolvedJavaMethod) handle(lookupJavaMethodMethod, lookupJavaMethodInvokable, reflectionMethod); - } - - private static final SymbolicMethod lookupJavaFieldMethod = method("lookupJavaField", Field.class); - private static final InvokableMethod lookupJavaFieldInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaField((Field) args[0]); - - @Override - public ResolvedJavaField lookupJavaField(Field reflectionField) { - return (ResolvedJavaField) handle(lookupJavaFieldMethod, lookupJavaFieldInvokable, reflectionField); - } - - private static final SymbolicMethod lookupJavaTypeConstantMethod = method("lookupJavaType", JavaConstant.class); - private static final InvokableMethod lookupJavaTypeConstantInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaType((JavaConstant) args[0]); - - @Override - public ResolvedJavaType lookupJavaType(JavaConstant constant) { - return (ResolvedJavaType) handle(lookupJavaTypeConstantMethod, lookupJavaTypeConstantInvokable, constant); - } - - private static final SymbolicMethod getMemorySizeMethod = method("getMemorySize", JavaConstant.class); - private static final InvokableMethod getMemorySizeInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getMemorySize((JavaConstant) args[0]); - - @Override - public long getMemorySize(JavaConstant constant) { - return (long) handle(getMemorySizeMethod, getMemorySizeInvokable, constant); - } - - private static final SymbolicMethod parseMethodDescriptorMethod = method("parseMethodDescriptor", String.class); - private static final InvokableMethod parseMethodDescriptorInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).parseMethodDescriptor((String) args[0]); - - @Override - public Signature parseMethodDescriptor(String methodDescriptor) { - return (Signature) handle(parseMethodDescriptorMethod, parseMethodDescriptorInvokable, methodDescriptor); - } - - public static final SymbolicMethod encodeDeoptActionAndReasonMethod = method("encodeDeoptActionAndReason", DeoptimizationAction.class, DeoptimizationReason.class, int.class); - private static final InvokableMethod encodeDeoptActionAndReasonInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).encodeDeoptActionAndReason((DeoptimizationAction) args[0], - (DeoptimizationReason) args[1], (int) args[2]); - - @Override - public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { - return (JavaConstant) handle(encodeDeoptActionAndReasonMethod, encodeDeoptActionAndReasonInvokable, action, reason, debugId); - } - - public static final SymbolicMethod encodeSpeculationMethod = method("encodeSpeculation", SpeculationLog.Speculation.class); - private static final InvokableMethod encodeSpeculationInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).encodeSpeculation((SpeculationLog.Speculation) args[0]); - - @Override - public JavaConstant encodeSpeculation(SpeculationLog.Speculation speculation) { - return (JavaConstant) handle(encodeSpeculationMethod, encodeSpeculationInvokable, speculation); - } - - public static final SymbolicMethod decodeSpeculationMethod = method("decodeSpeculation", JavaConstant.class, SpeculationLog.class); - private static final InvokableMethod decodeSpeculationInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeSpeculation((JavaConstant) args[0], (SpeculationLog) args[1]); - - @Override - public SpeculationLog.Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) { - return (SpeculationLog.Speculation) handle(decodeSpeculationMethod, decodeSpeculationInvokable, constant, speculationLog); - } - - public static final SymbolicMethod decodeDeoptReasonMethod = method("decodeDeoptReason", JavaConstant.class); - private static final InvokableMethod decodeDeoptReasonInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDeoptReason((JavaConstant) args[0]); - - @Override - public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { - return (DeoptimizationReason) handle(decodeDeoptReasonMethod, decodeDeoptReasonInvokable, constant); - } - - public static final SymbolicMethod decodeDeoptActionMethod = method("decodeDeoptAction", JavaConstant.class); - private static final InvokableMethod decodeDeoptActionInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDeoptAction((JavaConstant) args[0]); - - @Override - public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { - return (DeoptimizationAction) handle(decodeDeoptActionMethod, decodeDeoptActionInvokable, constant); - } - - public static final SymbolicMethod decodeDebugIdMethod = method("decodeDebugId", JavaConstant.class); - private static final InvokableMethod decodeDebugIdInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDebugId((JavaConstant) args[0]); - - @Override - public int decodeDebugId(JavaConstant constant) { - return (int) handle(decodeDebugIdMethod, decodeDebugIdInvokable, constant); - } - - public static final SymbolicMethod getArrayBaseOffsetMethod = method("getArrayBaseOffset", JavaKind.class); - private static final InvokableMethod getArrayBaseOffsetInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getArrayBaseOffset((JavaKind) args[0]); - - @Override - public int getArrayBaseOffset(JavaKind elementKind) { - return (int) handle(getArrayBaseOffsetMethod, getArrayBaseOffsetInvokable, elementKind); - } - - public static final SymbolicMethod getArrayIndexScaleMethod = method("getArrayIndexScale", JavaKind.class); - private static final InvokableMethod getArrayIndexScaleInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getArrayIndexScale((JavaKind) args[0]); - - @Override - public int getArrayIndexScale(JavaKind elementKind) { - return (int) handle(getArrayIndexScaleMethod, getArrayIndexScaleInvokable, elementKind); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java deleted file mode 100644 index f4cf9270d93d..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.MethodHandleAccessProvider; -import jdk.vm.ci.meta.ResolvedJavaMethod; - -//JaCoCo Exclude - -final class MethodHandleAccessProviderProxy extends CompilationProxyBase implements MethodHandleAccessProvider { - MethodHandleAccessProviderProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(MethodHandleAccessProvider.class, name, params); - } - - private static final SymbolicMethod lookupMethodHandleIntrinsicMethod = method("lookupMethodHandleIntrinsic", ResolvedJavaMethod.class); - private static final InvokableMethod lookupMethodHandleIntrinsicInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).lookupMethodHandleIntrinsic((ResolvedJavaMethod) args[0]); - - @Override - public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { - return (IntrinsicMethod) handle(lookupMethodHandleIntrinsicMethod, lookupMethodHandleIntrinsicInvokable, method); - } - - private static final SymbolicMethod resolveInvokeBasicTargetMethod = method("resolveInvokeBasicTarget", JavaConstant.class, boolean.class); - private static final InvokableMethod resolveInvokeBasicTargetInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).resolveInvokeBasicTarget((JavaConstant) args[0], - (boolean) args[1]); - - @Override - public ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration) { - return (ResolvedJavaMethod) handle(resolveInvokeBasicTargetMethod, resolveInvokeBasicTargetInvokable, methodHandle, forceBytecodeGeneration); - } - - private static final SymbolicMethod resolveLinkToTargetMethod = method("resolveLinkToTarget", JavaConstant.class); - private static final InvokableMethod resolveLinkToTargetInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).resolveLinkToTarget((JavaConstant) args[0]); - - @Override - public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) { - return (ResolvedJavaMethod) handle(resolveLinkToTargetMethod, resolveLinkToTargetInvokable, memberName); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java deleted file mode 100644 index eac5dc9bcb65..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import java.util.function.Predicate; - -//JaCoCo Exclude - -final class PredicateProxy extends CompilationProxyBase implements Predicate { - PredicateProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(Predicate.class, name, params); - } - - private static final SymbolicMethod testMethod = method("test", Object.class); - @SuppressWarnings("unchecked") private static final InvokableMethod testInvokable = (receiver, args) -> ((Predicate) receiver).test(args[0]); - - @Override - @SuppressWarnings("unchecked") - public boolean test(Object t) { - return (boolean) handle(testMethod, testInvokable, t); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java deleted file mode 100644 index 81daccca5ad5..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.meta.DeoptimizationReason; -import jdk.vm.ci.meta.JavaMethodProfile; -import jdk.vm.ci.meta.JavaTypeProfile; -import jdk.vm.ci.meta.ProfilingInfo; -import jdk.vm.ci.meta.TriState; - -//JaCoCo Exclude - -public sealed class ProfilingInfoProxy extends CompilationProxyBase implements ProfilingInfo permits HotSpotProfilingInfoProxy { - ProfilingInfoProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(ProfilingInfo.class, name, params); - } - - private static final SymbolicMethod getCodeSizeMethod = method("getCodeSize"); - private static final InvokableMethod getCodeSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getCodeSize(); - - @Override - public int getCodeSize() { - return (int) handle(getCodeSizeMethod, getCodeSizeInvokable); - } - - private static final SymbolicMethod getBranchTakenProbabilityMethod = method("getBranchTakenProbability", int.class); - private static final InvokableMethod getBranchTakenProbabilityInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getBranchTakenProbability((int) args[0]); - - @Override - public double getBranchTakenProbability(int bci) { - return (double) handle(getBranchTakenProbabilityMethod, getBranchTakenProbabilityInvokable, bci); - } - - private static final SymbolicMethod getSwitchProbabilitiesMethod = method("getSwitchProbabilities", int.class); - private static final InvokableMethod getSwitchProbabilitiesInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getSwitchProbabilities((int) args[0]); - - @Override - public double[] getSwitchProbabilities(int bci) { - return (double[]) handle(getSwitchProbabilitiesMethod, getSwitchProbabilitiesInvokable, bci); - } - - private static final SymbolicMethod getTypeProfileMethod = method("getTypeProfile", int.class); - private static final InvokableMethod getTypeProfileInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getTypeProfile((int) args[0]); - - @Override - public JavaTypeProfile getTypeProfile(int bci) { - return (JavaTypeProfile) handle(getTypeProfileMethod, getTypeProfileInvokable, bci); - } - - private static final SymbolicMethod getMethodProfileMethod = method("getMethodProfile", int.class); - private static final InvokableMethod getMethodProfileInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getMethodProfile((int) args[0]); - - @Override - public JavaMethodProfile getMethodProfile(int bci) { - return (JavaMethodProfile) handle(getMethodProfileMethod, getMethodProfileInvokable, bci); - } - - private static final SymbolicMethod getExceptionSeenMethod = method("getExceptionSeen", int.class); - private static final InvokableMethod getExceptionSeenInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getExceptionSeen((int) args[0]); - - @Override - public TriState getExceptionSeen(int bci) { - return (TriState) handle(getExceptionSeenMethod, getExceptionSeenInvokable, bci); - } - - private static final SymbolicMethod getNullSeenMethod = method("getNullSeen", int.class); - private static final InvokableMethod getNullSeenInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getNullSeen((int) args[0]); - - @Override - public TriState getNullSeen(int bci) { - return (TriState) handle(getNullSeenMethod, getNullSeenInvokable, bci); - } - - private static final SymbolicMethod getExecutionCountMethod = method("getExecutionCount", int.class); - private static final InvokableMethod getExecutionCountInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getExecutionCount((int) args[0]); - - @Override - public int getExecutionCount(int bci) { - return (int) handle(getExecutionCountMethod, getExecutionCountInvokable, bci); - } - - public static final SymbolicMethod getDeoptimizationCountMethod = method("getDeoptimizationCount", DeoptimizationReason.class); - private static final InvokableMethod getDeoptimizationCountInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getDeoptimizationCount((DeoptimizationReason) args[0]); - - @Override - public int getDeoptimizationCount(DeoptimizationReason reason) { - return (int) handle(getDeoptimizationCountMethod, getDeoptimizationCountInvokable, reason); - } - - public static final SymbolicMethod setCompilerIRSizeMethod = method("setCompilerIRSize", Class.class, int.class); - private static final InvokableMethod setCompilerIRSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).setCompilerIRSize((Class) args[0], (int) args[1]); - - @Override - public boolean setCompilerIRSize(Class irType, int irSize) { - return (boolean) handle(setCompilerIRSizeMethod, setCompilerIRSizeInvokable, irType, irSize); - } - - private static final SymbolicMethod getCompilerIRSizeMethod = method("getCompilerIRSize", Class.class); - private static final InvokableMethod getCompilerIRSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getCompilerIRSize((Class) args[0]); - - @Override - public int getCompilerIRSize(Class irType) { - return (int) handle(getCompilerIRSizeMethod, getCompilerIRSizeInvokable, irType); - } - - public static final SymbolicMethod isMatureMethod = method("isMature"); - private static final InvokableMethod isMatureInvokable = (receiver, args) -> ((ProfilingInfo) receiver).isMature(); - - @Override - public boolean isMature() { - return (boolean) handle(isMatureMethod, isMatureInvokable); - } - - private static final SymbolicMethod setMatureMethod = method("setMature"); - private static final InvokableMethod setMatureInvokable = (receiver, args) -> { - ((ProfilingInfo) receiver).setMature(); - return null; - }; - - @Override - public void setMature() { - handle(setMatureMethod, setMatureInvokable); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java deleted file mode 100644 index 935e03bf1934..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.Signature; - -//JaCoCo Exclude - -public final class SignatureProxy extends CompilationProxyBase implements Signature { - SignatureProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(Signature.class, name, params); - } - - public static final SymbolicMethod getParameterCountMethod = method("getParameterCount", boolean.class); - public static final InvokableMethod getParameterCountInvokable = (receiver, args) -> ((Signature) receiver).getParameterCount((boolean) args[0]); - - @Override - public int getParameterCount(boolean rec) { - return (int) handle(getParameterCountMethod, getParameterCountInvokable, rec); - } - - private static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); - private static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); - - @Override - public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { - return (JavaType) handle(getParameterTypeMethod, getParameterTypeInvokable, index, accessingClass); - } - - public static final SymbolicMethod getReturnTypeMethod = method("getReturnType", ResolvedJavaType.class); - public static final InvokableMethod getReturnTypeInvokable = (receiver, args) -> ((Signature) receiver).getReturnType((ResolvedJavaType) args[0]); - - @Override - public JavaType getReturnType(ResolvedJavaType accessingClass) { - return (JavaType) handle(getReturnTypeMethod, getReturnTypeInvokable, accessingClass); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java deleted file mode 100644 index d688787e35ee..000000000000 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.graal.compiler.hotspot.replaycomp.proxy; - -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.SpeculationLog; - -//JaCoCo Exclude - -public final class SpeculationLogProxy extends CompilationProxyBase implements SpeculationLog { - SpeculationLogProxy(InvocationHandler handler) { - super(handler); - } - - private static SymbolicMethod method(String name, Class... params) { - return new SymbolicMethod(SpeculationLog.class, name, params); - } - - private static final SymbolicMethod collectFailedSpeculationsMethod = method("collectFailedSpeculations"); - private static final InvokableMethod collectFailedSpeculationsInvokable = (receiver, args) -> { - ((SpeculationLog) receiver).collectFailedSpeculations(); - return null; - }; - - @Override - public void collectFailedSpeculations() { - handle(collectFailedSpeculationsMethod, collectFailedSpeculationsInvokable); - } - - public static final SymbolicMethod maySpeculateMethod = method("maySpeculate", SpeculationReason.class); - private static final InvokableMethod maySpeculateInvokable = (receiver, args) -> ((SpeculationLog) receiver).maySpeculate((SpeculationReason) args[0]); - - @Override - public boolean maySpeculate(SpeculationReason reason) { - return (boolean) handle(maySpeculateMethod, maySpeculateInvokable, reason); - } - - public static final SymbolicMethod speculateMethod = method("speculate", SpeculationReason.class); - private static final InvokableMethod speculateInvokable = (receiver, args) -> ((SpeculationLog) receiver).speculate((SpeculationReason) args[0]); - - @Override - public Speculation speculate(SpeculationReason reason) { - return (Speculation) handle(speculateMethod, speculateInvokable, reason); - } - - private static final SymbolicMethod hasSpeculationsMethod = method("hasSpeculations"); - private static final InvokableMethod hasSpeculationsInvokable = (receiver, args) -> ((SpeculationLog) receiver).hasSpeculations(); - - @Override - public boolean hasSpeculations() { - return (boolean) handle(hasSpeculationsMethod, hasSpeculationsInvokable); - } - - private static final SymbolicMethod lookupSpeculationMethod = method("lookupSpeculation", JavaConstant.class); - private static final InvokableMethod lookupSpeculationInvokable = (receiver, args) -> ((SpeculationLog) receiver).lookupSpeculation((JavaConstant) args[0]); - - @Override - public Speculation lookupSpeculation(JavaConstant constant) { - return (Speculation) handle(lookupSpeculationMethod, lookupSpeculationInvokable, constant); - } -} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java index 8769854534e2..fabfcbff2f2e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java @@ -27,7 +27,6 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; -import java.util.function.BiConsumer; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; @@ -196,7 +195,7 @@ public ProfilingInfo getProfilingInfo(ResolvedJavaMethod method) { return getProfilingInfo(method, true, true); } - public static class ProfileKey { + static class ProfileKey { final ResolvedJavaMethod method; final boolean includeNormal; final boolean includeOSR; @@ -207,18 +206,6 @@ public static class ProfileKey { this.includeOSR = includeOSR; } - public ResolvedJavaMethod method() { - return method; - } - - public boolean includeNormal() { - return includeNormal; - } - - public boolean includeOSR() { - return includeOSR; - } - @Override public boolean equals(Object o) { if (this == o) { @@ -693,18 +680,4 @@ public EconomicMap recordProfiles(EconomicMap ma } return map; } - - /** - * Iterates over all queried profiles and invokes the provided consumer for each pair of - * {@link ProfileKey} and corresponding {@link ProfilingInfo}. - * - * @param consumer a callback function that accepts a {@link ProfileKey} and a - * {@link ProfilingInfo} as input parameters - */ - public void forQueriedProfiles(BiConsumer consumer) { - var cursor = profiles.getEntries(); - while (cursor.advance()) { - consumer.accept(cursor.getKey(), cursor.getValue()); - } - } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java index 240d54a188b9..81d39255ff60 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java @@ -2929,34 +2929,19 @@ public String toString() { return buf.append(')').toString(); } - /** - * {@code true} if encoded snippets are in use in a hosted context. This is needed to disable - * assertions that are not supported with encoded snippets. {@code EncodedSnippets} is not - * referencable from this context, so this is the only way to check this fact. - */ - private static volatile boolean hostedEncodedSnippets = false; - - /** - * Notifies snippet templates whether snippets are encoded in a hosted context. If {@code true}, - * this call disables assertions that are not supported with encoded snippets. - * - * @param value whether snippets are encoded in a hosted context - */ - public static void setHostedEncodedSnippets(boolean value) { - hostedEncodedSnippets = value; - } - private static boolean checkTemplate(MetaAccessProvider metaAccess, Arguments args, ResolvedJavaMethod method) { Signature signature = method.getSignature(); int offset = args.info.hasReceiver() ? 1 : 0; for (int i = offset; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { JavaKind kind = signature.getParameterKind(i - offset); - assert inRuntimeCode() || hostedEncodedSnippets || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); + assert inRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); + } else if (args.info.isVarargsParameter(i)) { assert args.values[i] instanceof Varargs : Assertions.errorMessage(args.values[i], args, method); Varargs varargs = (Varargs) args.values[i]; - assert inRuntimeCode() || hostedEncodedSnippets || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); + assert inRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); + } else if (args.info.isNonNullParameter(i)) { assert checkNonNull(method, args.info.getParameterName(i), args.values[i]); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java index 9e659a32e1a4..790ec771a34a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java @@ -26,8 +26,7 @@ import java.util.Arrays; import java.util.Set; - -import org.graalvm.collections.EconomicMap; +import java.util.concurrent.atomic.AtomicInteger; import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.code.BytecodePosition; @@ -44,14 +43,18 @@ public final class SpeculationReasonGroup { private final String name; private final Class[] signature; + private static final AtomicInteger nextId = new AtomicInteger(1); + /** * Creates a speculation group whose context will always match {@code signature}. - *

- * The group ID is {@code name.hashCode()}, which ensures the IDs are stable regardless the - * order in which these objects are constructed. + * + * This constructor is deleted in libgraal to ensure group ids are allocated during build time. + * Without this invariant, it would possible for 2 different groups to have the same id if the + * groups are allocated in different libgraal isolates (since static variables are + * isolate-local). */ public SpeculationReasonGroup(String name, Class... signature) { - this.id = name.hashCode(); + this.id = nextId.getAndIncrement(); this.name = name; this.signature = signature; for (Class c : signature) { @@ -59,20 +62,6 @@ public SpeculationReasonGroup(String name, Class... signature) { throw new IllegalArgumentException("Unsupported speculation context type: " + c.getName()); } } - assert UniqueGroupIDVerification.checkUniqueGroupID(this.id, name) : "each created group must have a unique ID"; - } - - private static final class UniqueGroupIDVerification { - private static final EconomicMap groupNamesByID = EconomicMap.create(); - - private static synchronized boolean checkUniqueGroupID(int groupID, String groupName) { - String previousName = groupNamesByID.put(groupID, groupName); - if (previousName != null) { - throw new AssertionError("The speculation reason groups " + groupName + " and " + previousName + - " have the exact same hash of group names, which is used as the group ID. Changing either name should resolve the collision."); - } - return true; - } } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java index 38cb88f0eeb2..3f06b88485c2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java @@ -240,7 +240,7 @@ static GraalJVMCICompiler getCompiler(OptionValues options) { } } CompilerConfigurationFactory compilerConfigurationFactory = CompilerConfigurationFactory.selectFactory(Options.TruffleCompilerConfiguration.getValue(options), options, runtime); - return HotSpotGraalCompilerFactory.createCompiler("Truffle", runtime, options, compilerConfigurationFactory, null); + return HotSpotGraalCompilerFactory.createCompiler("Truffle", runtime, options, compilerConfigurationFactory); } public HotSpotTruffleCompilerImpl(HotSpotGraalRuntimeProvider hotspotGraalRuntime, TruffleCompilerConfiguration config) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java index 5d34107e99ac..c5fe5645a893 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java @@ -498,11 +498,6 @@ private int next() throws IOException { if (buffer.isEmpty()) { buffer.clear(); // resets position and limit if (source.read(buffer) == -1) { // eof - /* - * Set the limit to 0 to ensure that subsequent next() calls do not start re-reading - * the cleared buffer. - */ - buffer.limit(0); next = -1; return cur; } @@ -542,7 +537,7 @@ private static String toString(final int c) { private JsonParserException error(final String message, final int position) { final int columnNum = position - beginningOfLine; final String formatted = format(message, line, columnNum); - return new JsonParserException(formatted, peek() == EOF); + return new JsonParserException(formatted); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java index 9a058a275f67..e9df2d25a84b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java @@ -24,47 +24,12 @@ */ package jdk.graal.compiler.util.json; -import jdk.vm.ci.meta.TriState; - /** * Thrown by {@link JsonParser} if an error is encountered during parsing. */ @SuppressWarnings("serial") public final class JsonParserException extends RuntimeException { - /** - * Whether the parser was at the end of the input when the exception occurred. This may be - * {@link TriState#UNKNOWN} for exceptions that were not thrown by {@link JsonParser}. - */ - private final TriState isAtEOF; - - /** - * Constructs a new JSON parser exception with the specified detail message. The state of - * whether the parser was at the end of the input when the exception occurred is unknown. - * - * @param msg the detail message - */ public JsonParserException(final String msg) { super(msg); - this.isAtEOF = TriState.UNKNOWN; - } - - /** - * Constructs a new JSON parser exception with the specified detail message and information - * about whether the parser was at the end of the input when the exception occurred. - * - * @param msg the detail message - * @param isAtEOF whether the parser was at the end of the input when the exception occurred - */ - public JsonParserException(String msg, boolean isAtEOF) { - super(msg); - this.isAtEOF = TriState.get(isAtEOF); - } - - /** - * Returns whether the parser was at the end of the input when the exception occurred. This may - * be {@link TriState#UNKNOWN} for exceptions that were not thrown by {@link JsonParser}. - */ - public TriState isAtEOF() { - return isAtEOF; } } From 106619b97c4ed1dc18ddfadb4be8cd0ff5d40e59 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 15:44:45 +0200 Subject: [PATCH 14/49] Workaround for missing JDK-8361355 --- .../graal/pointsto/infrastructure/WrappedJavaType.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java index 7bad26395435..02f4d5f7c502 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java @@ -30,4 +30,13 @@ public interface WrappedJavaType extends WrappedElement, ResolvedJavaType { @Override ResolvedJavaType getWrapped(); + + /** + * Returns true if this type represents an annotation interface. + * + * @return {@code true} if this type represents an annotation interface + */ + default boolean isAnnotation() { + return (getModifiers() & java.lang.reflect.AccessFlag.ANNOTATION.mask()) != 0; + } } From 22ee0005299dd495ad28c16228244d922dec5e65 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 16:28:23 +0200 Subject: [PATCH 15/49] Revert "[GR-66940] Update labsjdk to 26+5-jvmci-b01." This reverts commit 6cbebefa1a8449121c9b8a0b0b87e8c676a8d17d, reversing changes made to 1d7170b58db122ed87372a701a299c04cb7efbe6. --- common.json | 16 +- .../core/test/CountedLoopOverflowTest.java | 8 +- .../compiler/core/test/GraalCompilerTest.java | 44 +--- .../compiler/core/test/SubWordInputTest.java | 3 +- .../compiler/core/test/SubWordInputTest2.java | 3 +- .../test/BenchmarkCounterOverflowTest.java | 20 +- .../test/DeoptimizeReasonAccountingTest.java | 2 +- .../compiler/hotspot/test/MonitorPEATest.java | 8 + .../test/RangeCheckPredicatesTest.java | 4 +- .../src/jdk/graal/compiler/jtt/JTTTest.java | 4 +- .../compiler/jtt/except/BC_getfield1.java | 4 +- .../jdk/Unsafe_compareAndSwapNullCheck.java | 4 +- .../compiler/jtt/lang/LambdaEagerTest.java | 10 +- .../jdk/graal/compiler/jtt/lang/Math_pow.java | 4 +- .../graal/compiler/jtt/lang/UnaryMath.java | 2 +- .../test/ArrayCopyExceptionSeenTest.java | 2 +- .../replacements/test/CountPositivesTest.java | 8 +- .../hotspot/GraalHotSpotVMConfig.java | 10 + .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- .../meta/DefaultHotSpotLoweringProvider.java | 18 +- .../HotSpotPlatformConfigurationProvider.java | 8 +- .../replacements/HotSpotHashCodeSnippets.java | 6 +- .../replacements/HotSpotReplacementsUtil.java | 25 ++ .../hotspot/replacements/MonitorSnippets.java | 245 +++++++++++++++--- ..._jdk_internal_misc_ScopedMemoryAccess.java | 2 +- .../genscavenge/AdaptiveCollectionPolicy.java | 2 +- .../svm/core/aarch64/AArch64LibCHelper.java | 4 - .../svm/core/container/ContainerLibrary.java | 14 +- .../svm/hosted/util/IdentityHashCodeUtil.java | 10 +- .../include/aarch64cpufeatures.h | 1 - .../src/cpuid.c | 5 - 31 files changed, 358 insertions(+), 142 deletions(-) diff --git a/common.json b/common.json index 5d978eadf36b..b1c47ca285c4 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+5-361", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+4-323", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+5", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+5-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+5-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+4", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java index 2a386e4c4411..bc782de60aab 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/CountedLoopOverflowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,7 @@ public void testDownOverflow() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { @@ -142,7 +142,7 @@ public void testDownOverflowUnsigned() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { @@ -163,7 +163,7 @@ public void testUpOverflow() { // first should deopt with a failed speculation, second not Map deoptCountsBefore = getDeoptCounts(method); try { - executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, true, CollectionsUtil.setOf(), null); + executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, CollectionsUtil.setOf(), null); deoptCountsBefore = getDeoptCounts(method); executeActualCheckDeopt(new OptionValues(getInitialOptions(), GraalOptions.LoopPeeling, false, GraalOptions.FullUnroll, false), method, EnumSet.allOf(DeoptimizationReason.class), null); } catch (Throwable t) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java index 517427889029..a60f09de8c86 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java @@ -903,25 +903,17 @@ protected Result executeActual(ResolvedJavaMethod method, Object receiver, Objec } protected Result executeActual(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { - return executeActual(options, method, false, receiver, args); - } - - protected Result executeActual(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Object receiver, Object... args) { before(method); Object[] executeArgs = argsWithReceiver(receiver, args); checkArgs(method, executeArgs); - InstalledCode compiledMethod = getCode(method, null, false, installAsDefault, options); + InstalledCode compiledMethod = getCode(method, options); try { return new Result(compiledMethod.executeVarargs(executeArgs), null); } catch (Throwable e) { return new Result(null, e); } finally { - // Prevent a subsequent `executeExpected' call from entering the compiled method - if (installAsDefault) { - compiledMethod.invalidate(); - } after(); } } @@ -1015,13 +1007,9 @@ protected Result test(ResolvedJavaMethod method, Object receiver, Object... args } protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { - return test(options, method, false, receiver, args); - } - - protected final Result test(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); if (getCodeCache() != null) { - testAgainstExpected(options, method, installAsDefault, expect, CollectionsUtil.setOf(), receiver, args); + testAgainstExpected(options, method, expect, receiver, args); } return expect; } @@ -1044,36 +1032,29 @@ protected Object[] applyArgSuppliers(Object... args) { } protected final void testAgainstExpected(ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(getInitialOptions(), method, false, expect, CollectionsUtil.setOf(), receiver, args); + testAgainstExpected(getInitialOptions(), method, expect, CollectionsUtil.setOf(), receiver, args); } - protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { - testAgainstExpected(options, method, false, expect, CollectionsUtil.setOf(), receiver, args); + protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + testAgainstExpected(getInitialOptions(), method, expect, shouldNotDeopt, receiver, args); } - protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - testAgainstExpected(options, method, true, expect, shouldNotDeopt, receiver, args); + protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { + testAgainstExpected(options, method, expect, CollectionsUtil.setOf(), receiver, args); } - private void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Result expect, Set shouldNotDeopt, Object receiver, - Object... args) { - Result actual = executeActualCheckDeopt(options, method, installAsDefault, shouldNotDeopt, receiver, args); + protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + Result actual = executeActualCheckDeopt(options, method, shouldNotDeopt, receiver, args); assertEquals(expect, actual); } - protected final Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, - Object... args) { - return executeActualCheckDeopt(options, method, !shouldNotDeopt.isEmpty(), shouldNotDeopt, receiver, args); - } - - protected final Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, boolean installAsDefault, Set shouldNotDeopt, Object receiver, - Object... args) { + protected Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { deoptCounts.put(reason, profile.getDeoptimizationCount(reason)); } - Result actual = executeActual(options, method, installAsDefault, receiver, args); + Result actual = executeActual(options, method, receiver, args); profile = method.getProfilingInfo(); // profile can change after execution for (DeoptimizationReason reason : shouldNotDeopt) { Assert.assertEquals("wrong number of deopt counts for " + reason, (int) deoptCounts.get(reason), profile.getDeoptimizationCount(reason)); @@ -1206,7 +1187,8 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str } catch (Throwable e) { throw debug.handle(e); } - if (useCache && !installAsDefault) { + + if (useCache) { cache.get().put(installedCodeOwner, Pair.create(options, installedCode)); } return installedCode; diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java index 98e57026c802..c2866623c904 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java @@ -33,6 +33,7 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.junit.Test; @@ -77,7 +78,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, null, new Object[]{value}); + testAgainstExpected(wrapper, expected, Collections.emptySet(), null, value); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java index 2aa030f3ded3..5256b17ef227 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java @@ -33,6 +33,7 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import org.junit.Test; @@ -75,7 +76,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, null, new Object[]{value}); + testAgainstExpected(wrapper, expected, Collections.emptySet(), null, value); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java index f760b1200473..4499e640862b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,20 +35,22 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.jtt.JTTTest; +import jdk.graal.compiler.lir.jtt.LIRTest; +import jdk.graal.compiler.lir.jtt.LIRTestSpecification; import jdk.graal.compiler.core.common.LIRKind; import jdk.graal.compiler.hotspot.HotSpotBackend; import jdk.graal.compiler.hotspot.debug.BenchmarkCounters; import jdk.graal.compiler.lir.ConstantValue; import jdk.graal.compiler.lir.gen.LIRGeneratorTool; -import jdk.graal.compiler.lir.jtt.LIRTest; -import jdk.graal.compiler.lir.jtt.LIRTestSpecification; import jdk.graal.compiler.test.SubprocessUtil; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -95,7 +97,7 @@ public void incrementCounter() { Object[] args = new Object[]{Integer.MAX_VALUE * 4L}; ResolvedJavaMethod method = getResolvedJavaMethod("test"); - executeActual(method, null, args); + executeActualCheckDeopt(GraalCompilerTest.getInitialOptions(), method, JTTTest.EMPTY, null, args); } @Test diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java index 79ffca9ad5d6..7839506a4d40 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java @@ -124,7 +124,7 @@ public void testDeoptimize() { for (boolean osr : new boolean[]{false}) { this.reason = r; this.isOSR = osr; - test(getInitialOptions(), getResolvedJavaMethod("deoptimizeSnippet"), true, null, new Object[0]); + test("deoptimizeSnippet"); ProfilingInfo info = lastCompiledGraph.method().getProfilingInfo(!isOSR, isOSR); int count = info.getDeoptimizationCount(reason); Assert.assertEquals(String.format("reason:%s, osr:%s", r, osr), 1, count); 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 767b155605dd..1be953c283b4 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 @@ -28,15 +28,23 @@ import static jdk.graal.compiler.api.directives.GraalDirectives.deoptimize; import static jdk.graal.compiler.api.directives.GraalDirectives.injectBranchProbability; +import org.junit.Assume; +import org.junit.Before; import org.junit.Test; import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil; /** * Tests that PEA preserves the monitorenter order. This is essential for lightweight locking. */ public final class MonitorPEATest extends HotSpotGraalCompilerTest { + @Before + public void checkUseLightweightLocking() { + Assume.assumeTrue(HotSpotReplacementsUtil.useLightweightLocking(runtime().getVMConfig())); + } + static int staticInt = 0; static Object staticObj; static Object staticObj1; diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java index b913fe09e5ee..2cdf8a706b4b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/RangeCheckPredicatesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -103,7 +103,7 @@ private void runOutOfBound(String methodName, int size, boolean loopLimitCheck, Object[] args = new Object[testParameters.length + 1]; args[0] = array; System.arraycopy(testParameters, 0, args, 1, testParameters.length); - Result result = executeActual(getOptionsMainPath(), method, true, null, args); + Result result = executeActual(getOptionsMainPath(), method, null, args); Assert.assertNotNull(result.exception); Assert.assertTrue(result.exception instanceof ArrayIndexOutOfBoundsException); profile = method.getProfilingInfo(); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java index 79a95ff5646e..6b36d08534e4 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java @@ -30,6 +30,7 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; +import java.util.Collections; import java.util.Formatter; import java.util.ListIterator; import java.util.Optional; @@ -80,6 +81,7 @@ public class JTTTest extends GraalCompilerTest { public static final class DummyTestClass { } + protected static final Set EMPTY = Collections. emptySet(); /** * The arguments which, if non-null, will replace the Locals in the test method's graph. */ @@ -190,7 +192,7 @@ protected void runTest(OptionValues options, Set shouldNot * to the usual compilation using {@link GraalCompilerTest#testAgainstExpected}. */ @Override - protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { if (Boolean.getBoolean(COMPILATION_PLAN_FUZZING_SYSTEM_PROPERTY)) { testAgainstExpectedWithFuzzedCompilationPlan(options, method, expect, shouldNotDeopt, receiver, args); } else { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java index 86b966d16509..148c772bf71d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ public void run0() throws Throwable { @Test public void run1() throws Throwable { // tests that the null check isn't removed along with the read - runTest("test", (Object) null); + runTest(EMPTY, "test", (Object) null); } @Test diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index e81dc3a45a95..9e23d4233090 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -57,6 +57,6 @@ public static void test(Unsafe_compareAndSwapNullCheck u, long expected, long ne @Test public void run0() throws Throwable { - runTest("test", null, 1L, 2L); + runTest(EMPTY, "test", null, 1L, 2L); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java index 139ff653bce5..8fda9b6f40c5 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java @@ -29,11 +29,11 @@ import java.util.EnumSet; import java.util.function.IntBinaryOperator; -import org.junit.Test; - import jdk.graal.compiler.core.test.GraalCompilerTest; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; +import org.junit.Test; + import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -65,19 +65,19 @@ public static int capturing(int x, int y, int z) { @Test public void testEagerResolveNonCapturing01() { Result expected = new Result(3, null); - testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2); + testAgainstExpected(getResolvedJavaMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2); } @Test public void testEagerResolveNonCapturing02() { Result expected = new Result(3, null); - testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2); + testAgainstExpected(getResolvedJavaMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2); } @Test public void testEagerResolveCapturing() { Result expected = new Result(0, null); - testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3); + testAgainstExpected(getResolvedJavaMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java index 2c65f078588e..3cc1f05c1d1d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -137,7 +137,7 @@ public void run12() { private void testOne(OptionValues options, ResolvedJavaMethod method, Object receiver, long testIteration, long l, double x, double y) throws AssertionError { Result expect = executeExpected(method, receiver, x, y); try { - testAgainstExpected(options, method, expect, receiver, x, y); + testAgainstExpected(options, method, expect, EMPTY, receiver, x, y); } catch (AssertionError e) { throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, x, l, l), e); } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java index f249091ddb5f..5fc61533c61a 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java @@ -60,7 +60,7 @@ void testManyValues(OptionValues options, ResolvedJavaMethod method) throws Asse double d = Double.longBitsToDouble(l); Result expect = executeExpected(method, receiver, d); try { - testAgainstExpected(options, method, expect, receiver, d); + testAgainstExpected(options, method, expect, EMPTY, receiver, d); testIteration++; } catch (AssertionError e) { throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, d, l, l), e); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java index bbdbd6f4681d..e0424a60061d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/ArrayCopyExceptionSeenTest.java @@ -88,7 +88,7 @@ public void testCopy() { public void testFailingCopy() throws InvalidInstalledCodeException { var method = getResolvedJavaMethod("copyWithHandler"); Assert.assertEquals("No recorded deopt expected before first invocation.", 0, method.getProfilingInfo().getDeoptimizationCount(DeoptimizationReason.BoundsCheckException)); - test(getInitialOptions(), method, true, null, new Object[]{new Object[3], -1, new Object[3], 0, 1}); + test(method, null, new Object[3], -1, new Object[3], 0, 1); Assert.assertEquals("Single deopt expected after first invocation.", 1, method.getProfilingInfo().getDeoptimizationCount(DeoptimizationReason.BoundsCheckException)); /* * Force a recompile which should create an explicit exception edge for the System.arraycopy diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java index 44f2529ef412..985f71df7a09 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -24,13 +24,15 @@ */ package jdk.graal.compiler.replacements.test; -import org.junit.Test; +import java.util.Collections; import jdk.graal.compiler.core.common.CompilationIdentifier; import jdk.graal.compiler.hotspot.test.HotSpotGraalCompilerTest; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.test.AddExports; +import org.junit.Test; + import jdk.vm.ci.meta.ResolvedJavaMethod; @AddExports("java.base/java.lang") @@ -68,7 +70,7 @@ public void testStringCoding() throws ClassNotFoundException { for (int off : new int[]{0, 2, -2}) { for (int len : new int[]{bytes.length, 2, 0, -2}) { Result expect = executeExpected(method, null, bytes, off, len); - Result actual = executeActual(method, null, bytes, off, len); + Result actual = executeActualCheckDeopt(getInitialOptions(), method, Collections.emptySet(), null, bytes, off, len); if (expect.returnValue == null) { assertEquals(expect, actual); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 47465b8db293..2cb1aa6bde4c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -135,6 +135,16 @@ private HotSpotGraalRuntime.HotSpotGC getSelectedGC() throws GraalError { public final boolean printInlining = getFlag("PrintInlining", Boolean.class); public final boolean inline = getFlag("Inline", Boolean.class); + // There are 3 available locking modes: + // LM_MONITOR uses only heavy monitors for locking; + // LM_LEGACY uses stack-locking, with monitors as 2nd tier; + // LM_LIGHTWEIGHT uses thread-local space for storing locked objects. This avoids the overload + // of the mark word. + public final int lockingMode = getFlag("LockingMode", Integer.class); + + public final int lockingModeStack = getConstant("LockingMode::LM_LEGACY", Integer.class); + public final int lockingModeLightweight = getConstant("LockingMode::LM_LIGHTWEIGHT", Integer.class); + public final boolean foldStableValues = getFlag("FoldStableValues", Boolean.class); public final int maxVectorSize = getFlag("MaxVectorSize", Integer.class); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 4c4bb11e4736..3d3ca5d567fa 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+5", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+5", 1))); + "Oracle Corporation", createLabsJDKVersion("26+4", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+4", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java index 333d033d45fc..9abe6ef6fed9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/DefaultHotSpotLoweringProvider.java @@ -35,6 +35,7 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.HUB_WRITE_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.MARK_WORD_LOCATION; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useLightweightLocking; import static org.graalvm.word.LocationIdentity.any; import java.util.Arrays; @@ -329,7 +330,7 @@ public void initialize(OptionValues options, Iterable assert target == providers.getCodeCache().getTarget() : Assertions.errorMessage(target, providers.getCodeCache().getTarget()); instanceofSnippets = new InstanceOfSnippets.Templates(options, runtime, providers); allocationSnippets = allocationSnippetTemplates; - monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers); + monitorSnippets = new MonitorSnippets.Templates(options, runtime, providers, config); g1WriteBarrierSnippets = new HotSpotG1WriteBarrierSnippets.Templates(options, runtime, providers, config); serialWriteBarrierSnippets = new HotSpotSerialWriteBarrierSnippets.Templates(options, runtime, providers); exceptionObjectSnippets = new LoadExceptionObjectSnippets.Templates(options, providers); @@ -396,11 +397,14 @@ public MonitorSnippets.Templates getMonitorSnippets() { @Override protected FixedWithNextNode maybeEmitLockingCheck(List locks, FixedWithNextNode insertionPoint, FrameState stateBefore) { if (!locks.isEmpty()) { - StructuredGraph graph = insertionPoint.graph(); - CheckFastPathMonitorEnterNode check = graph.add(new CheckFastPathMonitorEnterNode(locks)); - graph.addAfterFixed(insertionPoint, check); - check.setStateBefore(stateBefore.duplicate()); - return check; + if (useLightweightLocking(getVMConfig())) { + StructuredGraph graph = insertionPoint.graph(); + CheckFastPathMonitorEnterNode check = graph.add(new CheckFastPathMonitorEnterNode(locks)); + graph.addAfterFixed(insertionPoint, check); + check.setStateBefore(stateBefore.duplicate()); + return check; + } + // The stack lock and heavyweight monitors cases don't need any checks. } return insertionPoint; } @@ -526,7 +530,7 @@ private boolean lowerWithoutDelegation(Node n, LoweringTool tool) { } } else if (n instanceof CheckFastPathMonitorEnterNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { - monitorSnippets.lower((CheckFastPathMonitorEnterNode) n, registers, tool); + monitorSnippets.lower((CheckFastPathMonitorEnterNode) n, registers, runtime.getVMConfig(), tool); } } else if (n instanceof MonitorExitNode) { if (graph.getGuardsStage().areFrameStatesAtDeopts()) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java index 8c33ff12857d..f5ac6a18aca2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotPlatformConfigurationProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,6 +25,7 @@ package jdk.graal.compiler.hotspot.meta; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; +import jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil; import jdk.graal.compiler.nodes.gc.BarrierSet; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -33,9 +34,12 @@ public class HotSpotPlatformConfigurationProvider implements PlatformConfigurati private final boolean canVirtualizeLargeByteArrayAccess; + private final boolean useLightweightLocking; + public HotSpotPlatformConfigurationProvider(GraalHotSpotVMConfig config, BarrierSet barrierSet) { this.barrierSet = barrierSet; this.canVirtualizeLargeByteArrayAccess = config.deoptimizationSupportLargeAccessByteArrayVirtualization; + this.useLightweightLocking = HotSpotReplacementsUtil.useLightweightLocking(config); } @Override @@ -45,7 +49,7 @@ public boolean canVirtualizeLargeByteArrayAccess() { @Override public boolean requiresStrictLockOrder() { - return true; + return useLightweightLocking; } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java index 41f25813ff4f..cd78efdfa901 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotHashCodeSnippets.java @@ -34,6 +34,8 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.markWordLockMaskInPlace; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.monitorValue; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.uninitializedIdentityHashCodeValue; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedValue; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useLightweightLocking; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useObjectMonitorTable; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.FAST_PATH_PROBABILITY; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.probability; @@ -73,7 +75,9 @@ protected int computeIdentityHashCode(final Object x) { // // See src/hotspot/share/oops/markWord.hpp for more details. final Word lockBits = mark.and(Word.unsigned(markWordLockMaskInPlace(INJECTED_VMCONFIG))); - if (useObjectMonitorTable(INJECTED_VMCONFIG) || probability(FAST_PATH_PROBABILITY, lockBits.notEqual(Word.unsigned(monitorValue(INJECTED_VMCONFIG))))) { + if (useObjectMonitorTable(INJECTED_VMCONFIG) || probability(FAST_PATH_PROBABILITY, + useLightweightLocking(INJECTED_VMCONFIG) ? lockBits.notEqual(Word.unsigned(monitorValue(INJECTED_VMCONFIG))) + : lockBits.equal(Word.unsigned(unlockedValue(INJECTED_VMCONFIG))))) { // `& markWord::hash_mask' is essential with -XX:+UseCompactObjectHeaders, because bit // 42 might be set. int hash = (int) mark.unsignedShiftRight(markWordHashCodeShift(INJECTED_VMCONFIG)).and((int) markWordHashMark(INJECTED_VMCONFIG)).rawValue(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java index 99b63e917cec..d6ff8f1acbe9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/HotSpotReplacementsUtil.java @@ -363,6 +363,11 @@ public static int wordSize() { return runtime().getHostJVMCIBackend().getCodeCache().getTarget().wordSize; } + @Fold + public static int pageSize(@InjectedParameter GraalHotSpotVMConfig config) { + return config.vmPageSize; + } + public static final LocationIdentity PROTOTYPE_MARK_WORD_LOCATION = NamedLocationIdentity.mutable("PrototypeMarkWord"); public static final LocationIdentity KLASS_ACCESS_FLAGS_LOCATION = NamedLocationIdentity.immutable("Klass::_access_flags"); @@ -530,6 +535,16 @@ public static void initializeObjectHeader(Word memory, Word markWord, KlassPoint } } + @Fold + public static boolean useStackLocking(@InjectedParameter GraalHotSpotVMConfig config) { + return config.lockingMode == config.lockingModeStack; + } + + @Fold + public static boolean useLightweightLocking(@InjectedParameter GraalHotSpotVMConfig config) { + return config.lockingMode == config.lockingModeLightweight; + } + @Fold public static boolean useObjectMonitorTable(@InjectedParameter GraalHotSpotVMConfig config) { return config.useObjectMonitorTable; @@ -545,6 +560,11 @@ public static int monitorValue(@InjectedParameter GraalHotSpotVMConfig config) { return config.monitorValue; } + @Fold + public static int unusedMark(@InjectedParameter GraalHotSpotVMConfig config) { + return config.unusedMark; + } + @Fold public static int objectMonitorOwnerOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.objectMonitorOwner; @@ -775,6 +795,11 @@ public static int lockMetadataOffset(@InjectedParameter GraalHotSpotVMConfig con return config.basicLockMetadataOffset; } + @Fold + static int heldMonitorCountOffset(@InjectedParameter GraalHotSpotVMConfig config) { + return config.threadHeldMonitorCountOffset; + } + @Fold static int javaThreadMonitorOwnerIDOffset(@InjectedParameter GraalHotSpotVMConfig config) { return config.javaThreadMonitorOwnerIDOffset; 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 8f17ebeab8b5..dbc2c93a1c50 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 @@ -48,6 +48,7 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_STACK_LOCKER_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.OBJECT_MONITOR_SUCC_LOCATION; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.diagnoseSyncOnValueBasedClasses; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.heldMonitorCountOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.isCAssertEnabled; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackEndOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.javaThreadLockStackTopOffset; @@ -67,9 +68,13 @@ import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.objectMonitorSuccOffset; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.omCacheOopToMonitorDifference; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.omCacheOopToOopDifference; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.pageSize; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.registerAsWord; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unlockedValue; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.unusedMark; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useLightweightLocking; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useObjectMonitorTable; +import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.useStackLocking; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.verifyOop; import static jdk.graal.compiler.hotspot.replacements.HotSpotReplacementsUtil.wordSize; import static jdk.graal.compiler.hotspot.replacements.HotspotSnippetsOptions.ProfileMonitors; @@ -79,11 +84,13 @@ import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.NOT_FREQUENT_PROBABILITY; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.NOT_LIKELY_PROBABILITY; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.SLOW_PATH_PROBABILITY; +import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.VERY_FAST_PATH_PROBABILITY; import static jdk.graal.compiler.nodes.extended.BranchProbabilityNode.probability; import static jdk.graal.compiler.nodes.extended.MembarNode.memoryBarrier; import static jdk.graal.compiler.replacements.SnippetTemplate.DEFAULT_REPLACER; import static jdk.graal.compiler.replacements.nodes.CStringConstant.cstring; import static jdk.graal.compiler.word.Word.nullPointer; +import static jdk.graal.compiler.word.Word.unsigned; import static jdk.graal.compiler.word.Word.zero; import static org.graalvm.word.LocationIdentity.any; @@ -107,6 +114,7 @@ import jdk.graal.compiler.graph.Node.ConstantNodeParameter; import jdk.graal.compiler.graph.Node.NodeIntrinsic; import jdk.graal.compiler.graph.iterators.NodeIterable; +import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.meta.HotSpotRegistersProvider; @@ -199,6 +207,12 @@ // @formatter:off @SyncPort(from = "https://github.com/openjdk/jdk/blob/c2d76f9844aadf77a0b213a9169a7c5c8c8f1ffb/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L149-L578", sha1 = "ee04c86e8b12a9f8331c5e79f95a17b27615c845") +@SyncPort(from = "https://github.com/openjdk/jdk/blob/9eeb86d972ac4cc38d923b2b868b426bbd27a4e8/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L465-L625", + sha1 = "2d66e0ccf8dbf69f575be2633d5a17f77a20131d") +@SyncPort(from = "https://github.com/openjdk/jdk/blob/250eb743c112fbcc45bf2b3ded1c644b19893577/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L627-L788", + sha1 = "e88d7b8c4bb85358c6a810ee1d7d92fde5db42e6") +@SyncPort(from = "https://github.com/openjdk/jdk/blob/c2d76f9844aadf77a0b213a9169a7c5c8c8f1ffb/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L149-L455", + sha1 = "223a88b7bdd10862cd3b112181e1d17682b0fbe2") // @formatter:on public class MonitorSnippets implements Snippets { @@ -252,8 +266,10 @@ public static void monitorenter(Object object, KlassPointer hub, @ConstantParame } } - if (!tryLightweightLocking(object, lock, mark, thread, trace, counters, stackPointerRegister)) { - if (synthetic) { + if (tryFastPathLocking(object, stackPointerRegister, trace, counters, mark, lock, thread)) { + maybeUpdateHeldMonitorCount(thread, 1); + } else { + if (synthetic && (useLightweightLocking(INJECTED_VMCONFIG) || useStackLocking(INJECTED_VMCONFIG))) { // The fast locking cases are never permitted to use the slow path. throw UnreachableNode.unreachable(); } else { @@ -263,6 +279,20 @@ public static void monitorenter(Object object, KlassPointer hub, @ConstantParame } } + /** + * Dispatch to the appropriate locking strategy based on the {@code LockingMode} flag value. + */ + private static boolean tryFastPathLocking(Object object, Register stackPointerRegister, boolean trace, Counters counters, Word mark, Word lock, Word thread) { + if (useLightweightLocking(INJECTED_VMCONFIG)) { + return tryLightweightLocking(object, lock, mark, thread, trace, counters, stackPointerRegister); + } else if (useStackLocking(INJECTED_VMCONFIG)) { + return tryStackLocking(object, lock, mark, thread, trace, counters, stackPointerRegister); + } else { + // LM_MONITOR case + return false; + } + } + // Cache the monitor for unlock private static void writeMonitorCache(Word lock, Word monitor) { if (useObjectMonitorTable(INJECTED_VMCONFIG)) { @@ -344,6 +374,69 @@ private static boolean tryEnterInflated(Object object, Word lock, Word mark, Wor return false; } + private static boolean tryStackLocking(Object object, Word lock, Word mark, Word thread, boolean trace, Counters counters, Register stackPointerRegister) { + if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) { + // Inflated case + // Set the lock slot's displaced mark to unused. Any non-0 value suffices. + lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), Word.unsigned(unusedMark(INJECTED_VMCONFIG)), BASICLOCK_METADATA_LOCATION); + return tryEnterInflated(object, lock, mark, thread, trace, counters); + } + + Pointer objectPointer = Word.objectToTrackedPointer(object); + + // Create the unlocked mark word pattern + Word unlockedMark = mark.or(unlockedValue(INJECTED_VMCONFIG)); + trace(trace, " unlockedMark: 0x%016lx\n", unlockedMark); + + // Copy this unlocked mark word into the lock slot on the stack + lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), unlockedMark, BASICLOCK_METADATA_LOCATION); + + // Test if the object's mark word is unlocked, and if so, store the (address of) the + // lock slot into the object's mark word. + // + // Since pointer cas operations are volatile accesses, previous stores cannot float + // below it. + Word currentMark = objectPointer.compareAndSwapWord(markOffset(INJECTED_VMCONFIG), unlockedMark, lock, MARK_WORD_LOCATION); + if (probability(FAST_PATH_PROBABILITY, currentMark.equal(unlockedMark))) { + traceObject(trace, "+lock{stack:cas}", object, true); + counters.lockFastCas.inc(); + return true; + } else { + trace(trace, " currentMark: 0x%016lx\n", currentMark); + // The mark word in the object header was not the same. + // Either the object is locked by another thread or is already locked + // by the current thread. The latter is true if the mark word + // is a stack pointer into the current thread's stack, i.e.: + // + // 1) (currentMark & aligned_mask) == 0 + // 2) rsp <= currentMark + // 3) currentMark <= rsp + page_size + // + // These 3 tests can be done by evaluating the following expression: + // + // (currentMark - rsp) & (aligned_mask - page_size) + // + // assuming both the stack pointer and page_size have their least + // significant 2 bits cleared and page_size is a power of 2 + final Word alignedMask = unsigned(wordSize() - 1); + final Word stackPointer = registerAsWord(stackPointerRegister); + if (probability(FAST_PATH_PROBABILITY, currentMark.subtract(stackPointer).and(alignedMask.subtract(pageSize(INJECTED_VMCONFIG))).equal(0))) { + // Recursively locked => write 0 to the lock slot + lock.writeWord(lockMetadataOffset(INJECTED_VMCONFIG), zero(), BASICLOCK_METADATA_LOCATION); + traceObject(trace, "+lock{stack:recursive}", object, true); + counters.lockFastRecursive.inc(); + return true; + } + traceObject(trace, "+lock{stack:failed-cas}", object, true); + counters.lockFastFailedCas.inc(); + } + return false; + } + + // @formatter:off + @SyncPort(from = "https://github.com/openjdk/jdk/blob/c2d76f9844aadf77a0b213a9169a7c5c8c8f1ffb/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L457-L617", + sha1 = "2d66e0ccf8dbf69f575be2633d5a17f77a20131d") + // @formatter:on @SuppressWarnings("unused") private static boolean tryLightweightLocking(Object object, Word lock, Word mark, Word thread, boolean trace, Counters counters, Register stackPointerRegister) { writeMonitorCache(lock, Word.nullPointer()); @@ -416,13 +509,62 @@ public static void monitorexit(Object object, @ConstantParameter int lockDepth, trace(trace, " object: 0x%016lx\n", Word.objectToTrackedPointer(object)); trace(trace, " lock: 0x%016lx\n", lock); - if (!tryLightweightUnlocking(object, thread, lock, trace, counters)) { + if (tryFastPathUnlocking(object, trace, counters, thread, lock)) { + maybeUpdateHeldMonitorCount(thread, -1); + } else { monitorexitStubC(MONITOREXIT, object, lock); } endLockScope(); decCounter(); } + /** + * Dispatch to the appropriate unlocking strategy based on the {@code LockingMode} flag value. + */ + private static boolean tryFastPathUnlocking(Object object, boolean trace, Counters counters, Word thread, Word lock) { + if (useLightweightLocking(INJECTED_VMCONFIG)) { + return tryLightweightUnlocking(object, thread, lock, trace, counters); + } else if (useStackLocking(INJECTED_VMCONFIG)) { + return tryStackUnlocking(object, thread, lock, trace, counters); + } else { + // LM_MONITOR case, i.e., use heavy monitor directly + return false; + } + } + + private static boolean tryStackUnlocking(Object object, Word thread, Word lock, boolean trace, Counters counters) { + final Word displacedMark = lock.readWord(lockMetadataOffset(INJECTED_VMCONFIG), BASICLOCK_METADATA_LOCATION); + + if (probability(NOT_LIKELY_PROBABILITY, displacedMark.equal(0))) { + // Recursive locking => done + traceObject(trace, "-lock{stack:recursive}", object, false); + counters.unlockFastRecursive.inc(); + return true; + } + + Word mark = loadWordFromObject(object, markOffset(INJECTED_VMCONFIG)); + + if (probability(SLOW_PATH_PROBABILITY, mark.and(monitorValue(INJECTED_VMCONFIG)).notEqual(0))) { + return tryExitInflated(object, mark, thread, lock, trace, counters); + } + + if (probability(VERY_FAST_PATH_PROBABILITY, Word.objectToTrackedPointer(object).logicCompareAndSwapWord(markOffset(INJECTED_VMCONFIG), + lock, displacedMark, MARK_WORD_LOCATION))) { + traceObject(trace, "-lock{stack:cas}", object, false); + counters.unlockFastCas.inc(); + return true; + } + + // The object's mark word was not pointing to the displaced header + traceObject(trace, "-lock{stack:failed-cas}", object, false); + counters.unlockFastFailedCas.inc(); + return false; + } + + // @formatter:off + @SyncPort(from = "https://github.com/openjdk/jdk/blob/c2d76f9844aadf77a0b213a9169a7c5c8c8f1ffb/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp#L619-L780", + sha1 = "e88d7b8c4bb85358c6a810ee1d7d92fde5db42e6") + // @formatter:on private static boolean tryLightweightUnlocking(Object object, Word thread, Word lock, boolean trace, Counters counters) { // Load top Word lockStackTop = Word.unsigned(thread.readInt(javaThreadLockStackTopOffset(INJECTED_VMCONFIG), JAVA_THREAD_LOCK_STACK_TOP_LOCATION)); @@ -536,6 +678,13 @@ private static boolean tryExitInflated(Object object, Word mark, Word thread, Wo return false; } + private static void maybeUpdateHeldMonitorCount(Word thread, int increment) { + if (useStackLocking(INJECTED_VMCONFIG)) { + Word heldMonitorCount = thread.readWord(heldMonitorCountOffset(INJECTED_VMCONFIG), JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION); + thread.writeWord(heldMonitorCountOffset(INJECTED_VMCONFIG), heldMonitorCount.add(increment), JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION); + } + } + @Fold static boolean doProfile(@Fold.InjectedParameter OptionValues options) { return ProfileMonitors.getValue(options); @@ -650,28 +799,49 @@ public static class Templates extends AbstractTemplates { public final Counters counters; + private final boolean requiresStrictLockOrder; + @SuppressWarnings("this-escape") - public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers) { + public Templates(OptionValues options, SnippetCounter.Group.Factory factory, HotSpotProviders providers, GraalHotSpotVMConfig config) { super(options, providers); - LocationIdentity[] enterLocations = new LocationIdentity[]{ - JAVA_THREAD_LOCK_STACK_LOCATION, - JAVA_THREAD_LOCK_STACK_TOP_LOCATION, - JAVA_THREAD_OM_CACHE_LOCATION, - JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION, - JAVA_THREAD_MONITOR_OWNER_ID_LOCATION}; - LocationIdentity[] exitLocations = new LocationIdentity[]{ - JAVA_THREAD_LOCK_STACK_LOCATION, - JAVA_THREAD_LOCK_STACK_TOP_LOCATION, - BASICLOCK_METADATA_LOCATION, - OBJECT_MONITOR_OWNER_LOCATION, - OBJECT_MONITOR_CXQ_LOCATION, - OBJECT_MONITOR_ENTRY_LIST_LOCATION, - OBJECT_MONITOR_RECURSION_LOCATION, - OBJECT_MONITOR_SUCC_LOCATION, - OBJECT_MONITOR_STACK_LOCKER_LOCATION, - MARK_WORD_LOCATION, - JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; + LocationIdentity[] enterLocations; + LocationIdentity[] exitLocations; + + if (useLightweightLocking(config)) { + enterLocations = new LocationIdentity[]{ + JAVA_THREAD_LOCK_STACK_LOCATION, + JAVA_THREAD_LOCK_STACK_TOP_LOCATION, + JAVA_THREAD_OM_CACHE_LOCATION, + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION, + JAVA_THREAD_MONITOR_OWNER_ID_LOCATION}; + exitLocations = new LocationIdentity[]{ + JAVA_THREAD_LOCK_STACK_LOCATION, + JAVA_THREAD_LOCK_STACK_TOP_LOCATION, + BASICLOCK_METADATA_LOCATION, + OBJECT_MONITOR_OWNER_LOCATION, + OBJECT_MONITOR_CXQ_LOCATION, + OBJECT_MONITOR_ENTRY_LIST_LOCATION, + OBJECT_MONITOR_RECURSION_LOCATION, + OBJECT_MONITOR_SUCC_LOCATION, + OBJECT_MONITOR_STACK_LOCKER_LOCATION, + MARK_WORD_LOCATION, + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; + } else { + enterLocations = new LocationIdentity[]{ + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION, + JAVA_THREAD_MONITOR_OWNER_ID_LOCATION}; + exitLocations = new LocationIdentity[]{ + BASICLOCK_METADATA_LOCATION, + OBJECT_MONITOR_OWNER_LOCATION, + OBJECT_MONITOR_CXQ_LOCATION, + OBJECT_MONITOR_ENTRY_LIST_LOCATION, + OBJECT_MONITOR_RECURSION_LOCATION, + OBJECT_MONITOR_SUCC_LOCATION, + OBJECT_MONITOR_STACK_LOCKER_LOCATION, + MARK_WORD_LOCATION, + JAVA_THREAD_HOLD_MONITOR_COUNT_LOCATION}; + } this.checkMonitorenter = snippet(providers, MonitorSnippets.class, "checkMonitorenter", enterLocations); this.monitorenter = snippet(providers, MonitorSnippets.class, "monitorenter", enterLocations); @@ -680,9 +850,12 @@ public Templates(OptionValues options, SnippetCounter.Group.Factory factory, Hot this.checkCounter = snippet(providers, MonitorSnippets.class, "checkCounter"); this.counters = new Counters(factory); + this.requiresStrictLockOrder = providers.getPlatformConfigurationProvider().requiresStrictLockOrder(); } - public void lower(CheckFastPathMonitorEnterNode checkFastPathMonitorEnterNode, HotSpotRegistersProvider registers, LoweringTool tool) { + public void lower(CheckFastPathMonitorEnterNode checkFastPathMonitorEnterNode, HotSpotRegistersProvider registers, GraalHotSpotVMConfig config, LoweringTool tool) { + GraalError.guarantee(HotSpotReplacementsUtil.useLightweightLocking(config), "should only be used with lightweight locking"); + StructuredGraph graph = checkFastPathMonitorEnterNode.graph(); Arguments args = new Arguments(checkMonitorenter, graph, tool.getLoweringStage()); // Speculation.equals is too weak so it can incorrectly cache snippet graphs so just @@ -718,17 +891,19 @@ private static boolean isVirtualLock(FrameState frameState, int lockIdx) { return false; } - private static boolean verifyLockOrder(MonitorEnterNode monitorenterNode) { - FrameState state = monitorenterNode.stateAfter(); - boolean subsequentLocksMustBeEliminated = false; - for (int lockIdx = 0; lockIdx < state.locksSize(); lockIdx++) { - if (subsequentLocksMustBeEliminated) { - if (!isVirtualLock(state, lockIdx)) { - return false; + private boolean verifyLockOrder(MonitorEnterNode monitorenterNode) { + if (requiresStrictLockOrder) { + FrameState state = monitorenterNode.stateAfter(); + boolean subsequentLocksMustBeEliminated = false; + for (int lockIdx = 0; lockIdx < state.locksSize(); lockIdx++) { + if (subsequentLocksMustBeEliminated) { + if (!isVirtualLock(state, lockIdx)) { + return false; + } + } + if (state.monitorIdAt(lockIdx) == monitorenterNode.getMonitorId()) { + subsequentLocksMustBeEliminated = true; } - } - if (state.monitorIdAt(lockIdx) == monitorenterNode.getMonitorId()) { - subsequentLocksMustBeEliminated = true; } } return true; @@ -774,7 +949,7 @@ public static boolean isTracingEnabledForType(ValueNode object) { if (filter == null) { return false; } else { - if (filter.isEmpty()) { + if (filter.length() == 0) { return true; } if (type == null) { @@ -789,7 +964,7 @@ public static boolean isTracingEnabledForMethod(StructuredGraph graph) { if (filter == null) { return false; } else { - if (filter.isEmpty()) { + if (filter.length() == 0) { return true; } if (graph.method() == null) { diff --git a/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java b/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java index fd1a248a1bf8..1a4c72f5eb60 100644 --- a/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java +++ b/substratevm/src/com.oracle.svm.core.foreign/src/com/oracle/svm/core/foreign/Target_jdk_internal_misc_ScopedMemoryAccess.java @@ -248,7 +248,7 @@ public static , E, M extends VectorSupport.Vec * {@link SyncCloseScopeOperation}) is essentially an empty operation but kills the field * location of {@link Target_jdk_internal_foreign_MemorySessionImpl#state}. */ - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/prims/scopedMemoryAccess.cpp#L215-L218") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/prims/scopedMemoryAccess.cpp#L215-L218") @SuppressWarnings("static-method") @Substitute @TargetElement(onlyWith = SharedArenasEnabled.class) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index ccef7cb2a6fa..9d83e35ef955 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -50,7 +50,7 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+1/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+20/src/hotspot/share/gc/parallel/psAdaptiveSizePolicy.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/parallel/psParallelCompact.cpp#L964-L1181") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/gc/parallel/psScavenge.cpp#L319-L634") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/gc/parallel/psScavenge.cpp#L319-L635") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/gc/shared/gc_globals.hpp#L303-L407") class AdaptiveCollectionPolicy extends AbstractCollectionPolicy { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java index 14e0f6dfd261..86c549c9dfff 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java @@ -139,10 +139,6 @@ public interface CPUFeatures extends PointerBase { @AllowNarrowingCast @CField boolean fASIMDHP(); - - @AllowNarrowingCast - @CField - boolean fSB(); } // Checkstyle: resume } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index d7cd5b301ad5..0d5021fed17e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -60,25 +60,25 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/os/linux/os_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/os/posix/os_posix.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/posix/os_posix.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allStatic.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/nmt/memTag.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/os.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/os.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/nmt/memTag.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.hpp") @@ -86,7 +86,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+5/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/IdentityHashCodeUtil.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/IdentityHashCodeUtil.java index 759b73b6f283..8fa1b77b6bc7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/IdentityHashCodeUtil.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/util/IdentityHashCodeUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -117,7 +117,13 @@ private static int readIdentityHashCode(long markWord) { * See HotSpotHashCodeSnippets for explanation. */ long lockBits = markWord & config.markWordLockMaskInPlace; - if (lockBits != config.monitorValue) { + boolean containsHashCode; + if (config.lockingMode == config.lockingModeLightweight) { + containsHashCode = lockBits != config.monitorValue; + } else { + containsHashCode = lockBits == config.unlockedValue; + } + if (containsHashCode) { int hashcode = (int) ((markWord & hashCodeMask) >>> config.markWordHashCodeShift); if (hashcode == config.uninitializedIdentityHashCodeValue) { return UNINITIALIZED; diff --git a/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h b/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h index 4bbd44f63fdf..a6092e4a05a9 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h +++ b/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h @@ -48,5 +48,4 @@ typedef struct { uint8_t fSVEBITPERM; uint8_t fFPHP; uint8_t fASIMDHP; - uint8_t fSB; } CPUFeatures; diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c index 2316e248fc02..193fb145c62d 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c @@ -690,7 +690,6 @@ void determineCPUFeatures(CPUFeatures* features) { features->fLSE = !!(cpu_has("hw.optional.arm.FEAT_LSE")) | !!(cpu_has("hw.optional.armv8_1_atomics")); features->fSHA512 = !!(cpu_has("hw.optional.arm.FEAT_SHA512")) | !!(cpu_has("hw.optional.armv8_2_sha512")); features->fSHA3 = !!(cpu_has("hw.optional.arm.FEAT_SHA3")) | !!(cpu_has("hw.optional.armv8_2_sha3")); - features->fSB = !!(cpu_has("hw.optional.arm.FEAT_SB")); // Not (yet) checked in the Hotspot code. features->fDCPOP = 0; features->fSVE = 0; @@ -752,9 +751,6 @@ void determineCPUFeatures(CPUFeatures* features) { #ifndef HWCAP_SVE #define HWCAP_SVE (1L << 22) #endif -#ifndef HWCAP_SB -#define HWCAP_SB (1L << 29) -#endif #ifndef HWCAP_PACA #define HWCAP_PACA (1L << 30) #endif @@ -799,7 +795,6 @@ void determineCPUFeatures(CPUFeatures* features) { features->fSTXR_PREFETCH = 0; features->fA53MAC = 0; features->fDMB_ATOMICS = 0; - features->fSB = !!(auxv & HWCAP_SB); features->fPACA = !!(auxv & HWCAP_PACA); features->fSVEBITPERM = !!(auxv2 & HWCAP2_SVEBITPERM); features->fFPHP = !!(auxv & HWCAP_FPHP); From 64dcb79c912b611dfc5559abacacdfb5248168ec Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 17:28:29 +0200 Subject: [PATCH 16/49] Revert "Do not emit speculation barrier instruction if the relevant CPU feature is not supported" This reverts commit 2ce32efe8a23a10f15c284ff630abe7f4b1dfb71. --- .../src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java index 4a68164320e5..df6ed99d8712 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java @@ -4096,9 +4096,7 @@ public void msr(SystemRegister systemRegister, Register src) { * C6.2.230 Speculation barrier. */ public void sb() { - if (supports(CPUFeature.SB)) { - emitInt(SB.encoding | BarrierOp); - } + emitInt(SB.encoding | BarrierOp); } public void annotatePatchingImmediate(int pos, Instruction instruction, int operandSizeBits, int offsetBits, int shift) { From 5772b9c51529e1ee029e3211ec09bf320bf3c41b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 17:29:17 +0200 Subject: [PATCH 17/49] Revert "Adopt JDK-8359435 AArch64: add support for SB instruction to MacroAssembler::spin_wait" This reverts commit f56eb9a9237e345c5258c751ac61e4daa8dd01c8. --- .../asm/aarch64/AArch64Assembler.java | 19 +++++-------------- .../aarch64/AArch64HotSpotLIRGenerator.java | 2 -- .../lir/aarch64/AArch64SpinWaitOp.java | 6 +++++- 3 files changed, 10 insertions(+), 17 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java index df6ed99d8712..4cd9a4d89097 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/aarch64/AArch64Assembler.java @@ -138,7 +138,6 @@ import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.REVW; import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.REVX; import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.RORV; -import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.SB; import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.SBC; import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.SBCS; import static jdk.graal.compiler.asm.aarch64.AArch64Assembler.Instruction.SBFM; @@ -1058,7 +1057,6 @@ public enum Instruction { MSR(0xD5100000), DC(0xD5087000), ISB(0x000000C0), - SB(0x000000E0), PACIA(0b00001 << 16 | 0b000000 << 10), AUTIA(0b00001 << 16 | 0b000100 << 10), @@ -4036,15 +4034,6 @@ public enum BarrierKind { } } - /** - * C6.2.75 Data Cache operation. - */ - public void dc(DataCacheOperationType type, Register src) { - assert verifyRegistersR(src); - - emitInt(DC.encoding | type.encoding() | rt(src)); - } - /** * C6.2.80 Data Memory Barrier. * @@ -4093,10 +4082,12 @@ public void msr(SystemRegister systemRegister, Register src) { } /** - * C6.2.230 Speculation barrier. + * C6.2.75 Data Cache operation. */ - public void sb() { - emitInt(SB.encoding | BarrierOp); + public void dc(DataCacheOperationType type, Register src) { + assert verifyRegistersR(src); + + emitInt(DC.encoding | type.encoding() | rt(src)); } public void annotatePatchingImmediate(int pos, Instruction instruction, int operandSizeBits, int offsetBits, int shift) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java index 515d2683e5a1..6317a8cb22b1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotLIRGenerator.java @@ -40,7 +40,6 @@ import jdk.graal.compiler.asm.Label; import jdk.graal.compiler.asm.aarch64.AArch64Address; -import jdk.graal.compiler.asm.aarch64.AArch64Assembler; import jdk.graal.compiler.asm.aarch64.AArch64Assembler.ConditionFlag; import jdk.graal.compiler.asm.aarch64.AArch64Assembler.PrefetchMode; import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler; @@ -486,7 +485,6 @@ private Consumer onSpinWaitInst() { case "nop" -> AArch64MacroAssembler::nop; case "isb" -> AArch64MacroAssembler::isb; case "yield" -> AArch64MacroAssembler::pause; - case "sb" -> AArch64Assembler::sb; default -> throw GraalError.shouldNotReachHere("Unknown OnSpinWaitInst " + config.onSpinWaitInst); }; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64SpinWaitOp.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64SpinWaitOp.java index 14b3f7bcc505..2b4df6705d2e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64SpinWaitOp.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/lir/aarch64/AArch64SpinWaitOp.java @@ -28,10 +28,10 @@ import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import jdk.graal.compiler.lir.LIRInstructionClass; import jdk.graal.compiler.lir.Opcode; import jdk.graal.compiler.lir.SyncPort; +import jdk.graal.compiler.lir.asm.CompilationResultBuilder; /** * Emits spin wait instruction(s). @@ -41,6 +41,10 @@ sha1 = "874fea5e6191c9c19947b4dc818a434a24b33358") @SyncPort(from = "https://github.com/openjdk/jdk/blob/23985c29b44b489472dcd3aad2cb98d9ce003a7b/src/hotspot/cpu/aarch64/spin_wait_aarch64.cpp#L38-L52", sha1 = "9a1f313aa92ab513f5e8cd20fd3b037469455b77") +@SyncPort(from = "https://github.com/openjdk/jdk/blob/ecd2d83096a1fea7d5086736306770bcffa4fdb6/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp#L53-L74", + sha1 = "6bd5ba27c0b3a8416ee5d8d495a55d86cfe1fad1") +@SyncPort(from = "https://github.com/openjdk/jdk/blob/98a93e115137a305aed6b7dbf1d4a7d5906fe77c/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp#L53-L69", + sha1 = "92f81ed500658553a2ef2e7c48633094d95ba974") // @formatter:on @Opcode("SPIN_WAIT") public final class AArch64SpinWaitOp extends AArch64LIRInstruction { From 61c6b8433a2d6747a15fe553e10484bac4c16d03 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 17:39:51 +0200 Subject: [PATCH 18/49] Revert "[GR-66564] Adopt JDK-8356868: Not all cgroup parameters are made available" This reverts commit b887f2df83cedb487ebc5d7227f739a929f0d7e2, reversing changes made to 3d65c5ca529c1cfc5b4a859986d5b15009e03a46. --- .../svm/core/container/ContainerLibrary.java | 55 +++--- .../os/linux/cgroupSubsystem_linux.cpp | 20 +- .../os/linux/cgroupSubsystem_linux.hpp | 19 +- .../os/linux/cgroupV1Subsystem_linux.cpp | 15 +- .../os/linux/cgroupV1Subsystem_linux.hpp | 37 +--- .../os/linux/cgroupV2Subsystem_linux.cpp | 27 +-- .../os/linux/cgroupV2Subsystem_linux.hpp | 35 +--- .../hotspot/os/linux/osContainer_linux.cpp | 12 +- .../hotspot/os/linux/osContainer_linux.hpp | 5 +- .../src/hotspot/os/linux/os_linux.cpp | 185 ++++++++++++++---- .../src/hotspot/os/posix/os_posix.cpp | 124 ++---------- .../src/hotspot/os/posix/os_posix.hpp | 7 +- .../src/hotspot/share/memory/allocation.hpp | 9 +- .../share/memory/allocation.inline.hpp | 4 +- .../src/hotspot/share/runtime/os.cpp | 95 ++------- .../src/hotspot/share/runtime/os.hpp | 22 +-- .../share/utilities/compilerWarnings.hpp | 67 ++----- .../share/utilities/compilerWarnings_gcc.hpp | 91 +++------ .../share/utilities/globalDefinitions.hpp | 44 ++++- .../src/hotspot/share/utilities/macros.hpp | 3 + .../src/hotspot/share/utilities/ostream.cpp | 22 ++- .../src/hotspot/share/utilities/ostream.hpp | 54 ++--- .../utilities/permitForbiddenFunctions.hpp | 86 -------- 23 files changed, 354 insertions(+), 684 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/permitForbiddenFunctions.hpp diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 0d5021fed17e..de197ccd459d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -48,12 +48,12 @@ @CContext(ContainerLibraryDirectives.class) @CLibrary(value = "svm_container", requireStatic = true, dependsOn = "m") // The following annotations are for files in `src/hotspot`, which are copied from the JDK -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/java.base/share/native/include/jni.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/java.base/unix/native/include/jni_md.h") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/share/native/include/jni.h") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/unix/native/include/jni_md.h") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupSubsystem_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupSubsystem_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupUtil_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupUtil_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupUtil_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupUtil_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp") @@ -61,34 +61,33 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.inline.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/include/jvm_md.h") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.inline.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/posix/include/jvm_md.h") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/posix/os_posix.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/posix/os_posix.inline.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.inline.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allStatic.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/nmt/memTag.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/os.inline.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/checkedCast.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/compilerWarnings.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/globalDefinitions.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/macros.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/ostream.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/permitForbiddenFunctions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/os/posix/os_posix.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/posix/os_posix.inline.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/memory/allocation.inline.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/memory/allStatic.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/nmt/memTag.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+22/src/hotspot/share/runtime/os.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/share/runtime/os.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/runtime/os.inline.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/checkedCast.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+22/src/hotspot/share/utilities/compilerWarnings_gcc.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+22/src/hotspot/share/utilities/compilerWarnings.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/globalDefinitions_gcc.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/share/utilities/globalDefinitions.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/utilities/macros.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/share/utilities/ostream.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/share/utilities/ostream.hpp") // The following annotations are for files in `src/svm`, which are completely customized for SVM -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/logging/log.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/memory/allocation.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/logging/log.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/utilities/debug.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { static final int VERSION = 240100; diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index 3e74f42f618c..8c671388f573 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, 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 @@ -66,7 +66,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV1MemoryController* memory = nullptr; CgroupV1Controller* cpuset = nullptr; CgroupV1CpuController* cpu = nullptr; - CgroupV1CpuacctController* cpuacct = nullptr; + CgroupV1Controller* cpuacct = nullptr; CgroupV1Controller* pids = nullptr; CgroupInfo cg_infos[CG_INFO_LENGTH]; u1 cg_type_flags = INVALID_CGROUPS_GENERIC; @@ -109,10 +109,9 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { CgroupV2CpuController* cpu = new CgroupV2CpuController(CgroupV2Controller(cg_infos[CPU_IDX]._mount_path, cg_infos[CPU_IDX]._cgroup_path, cg_infos[CPU_IDX]._read_only)); - CgroupV2CpuacctController* cpuacct = new CgroupV2CpuacctController(cpu); log_debug(os, container)("Detected cgroups v2 unified hierarchy"); cleanup(cg_infos); - return new CgroupV2Subsystem(memory, cpu, cpuacct, mem_other); + return new CgroupV2Subsystem(memory, cpu, mem_other); } /* @@ -155,7 +154,7 @@ CgroupSubsystem* CgroupSubsystemFactory::create() { cpu = new CgroupV1CpuController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); cpu->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "cpuacct") == 0) { - cpuacct = new CgroupV1CpuacctController(CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only)); + cpuacct = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); cpuacct->set_subsystem_path(info._cgroup_path); } else if (strcmp(info._name, "pids") == 0) { pids = new CgroupV1Controller(info._root_mount_path, info._mount_path, info._read_only); @@ -302,7 +301,6 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, } else { log_debug(os, container)("Can't read %s, %s", controllers_file, os::strerror(errno)); *flags = INVALID_CGROUPS_V2; - fclose(controllers); return false; } for (int i = 0; i < CG_INFO_LENGTH; i++) { @@ -363,7 +361,7 @@ bool CgroupSubsystemFactory::determine_type(CgroupInfo* cg_infos, all_required_controllers_enabled = all_required_controllers_enabled && cg_infos[i]._enabled; } if (log_is_enabled(Debug, os, container) && !cg_infos[i]._enabled) { - log_debug(os, container)("controller %s is not enabled", cg_controller_name[i]); + log_debug(os, container)("controller %s is not enabled\n", cg_controller_name[i]); } } } @@ -861,10 +859,6 @@ jlong CgroupSubsystem::memory_soft_limit_in_bytes() { return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); } -jlong CgroupSubsystem::memory_throttle_limit_in_bytes() { - return memory_controller()->controller()->memory_throttle_limit_in_bytes(); -} - jlong CgroupSubsystem::memory_usage_in_bytes() { return memory_controller()->controller()->memory_usage_in_bytes(); } @@ -893,10 +887,6 @@ int CgroupSubsystem::cpu_shares() { return cpu_controller()->controller()->cpu_shares(); } -jlong CgroupSubsystem::cpu_usage_in_micros() { - return cpuacct_controller()->cpu_usage_in_micros(); -} - #ifndef NATIVE_IMAGE void CgroupSubsystem::print_version_specific_info(outputStream* st) { julong phys_mem = os::Linux::physical_memory(); diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 514d84c786bc..a2ea1476d09a 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, 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 @@ -227,18 +227,6 @@ class CgroupCpuController: public CHeapObj { virtual const char* cgroup_path() = 0; }; -// Pure virtual class representing version agnostic CPU accounting controllers -class CgroupCpuacctController: public CHeapObj { - public: - virtual jlong cpu_usage_in_micros() = 0; - virtual bool needs_hierarchy_adjustment() = 0; - virtual bool is_read_only() = 0; - virtual const char* subsystem_path() = 0; - virtual void set_subsystem_path(const char* cgroup_path) = 0; - virtual const char* mount_point() = 0; - virtual const char* cgroup_path() = 0; -}; - // Pure virtual class representing version agnostic memory controllers class CgroupMemoryController: public CHeapObj { public: @@ -247,7 +235,6 @@ class CgroupMemoryController: public CHeapObj { virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0; virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; - virtual jlong memory_throttle_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; virtual jlong rss_usage_in_bytes() = 0; virtual jlong cache_usage_in_bytes() = 0; @@ -276,19 +263,15 @@ class CgroupSubsystem: public CHeapObj { virtual const char * container_type() = 0; virtual CachingCgroupController* memory_controller() = 0; virtual CachingCgroupController* cpu_controller() = 0; - virtual CgroupCpuacctController* cpuacct_controller() = 0; int cpu_quota(); int cpu_period(); int cpu_shares(); - jlong cpu_usage_in_micros(); - jlong memory_usage_in_bytes(); jlong memory_and_swap_limit_in_bytes(); jlong memory_and_swap_usage_in_bytes(); jlong memory_soft_limit_in_bytes(); - jlong memory_throttle_limit_in_bytes(); jlong memory_max_usage_in_bytes(); jlong rss_usage_in_bytes(); jlong cache_usage_in_bytes(); diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index ee5c09bd51c2..a21f4ab8446d 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -252,16 +252,10 @@ jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { } } -jlong CgroupV1MemoryController::memory_throttle_limit_in_bytes() { - // Log this string at trace level so as to make tests happy. - log_trace(os, container)("Memory Throttle Limit is not supported."); - return OSCONTAINER_ERROR; // not supported -} - // Constructor CgroupV1Subsystem::CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1CpuacctController* cpuacct, + CgroupV1Controller* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory) : _cpuset(cpuset), @@ -428,13 +422,6 @@ int CgroupV1CpuController::cpu_shares() { return shares_int; } -jlong CgroupV1CpuacctController::cpu_usage_in_micros() { - julong cpu_usage; - CONTAINER_READ_NUMBER_CHECKED(reader(), "/cpuacct.usage", "CPU Usage", cpu_usage); - // Output is in nanoseconds, convert to microseconds. - return (jlong)cpu_usage / 1000; -} - /* pids_max * * Return the maximum number of tasks available to the process diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 4019e46d52e5..28c9a8166e61 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, 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 @@ -86,7 +86,6 @@ class CgroupV1MemoryController final : public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; - jlong memory_throttle_limit_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; @@ -147,41 +146,12 @@ class CgroupV1CpuController final : public CgroupCpuController { } }; -class CgroupV1CpuacctController final : public CgroupCpuacctController { - - private: - CgroupV1Controller _reader; - CgroupV1Controller* reader() { return &_reader; } - public: - jlong cpu_usage_in_micros() override; - void set_subsystem_path(const char *cgroup_path) override { - reader()->set_subsystem_path(cgroup_path); - } - bool is_read_only() override { - return reader()->is_read_only(); - } - const char* subsystem_path() override { - return reader()->subsystem_path(); - } - const char* mount_point() override { - return reader()->mount_point(); - } - bool needs_hierarchy_adjustment() override { - return reader()->needs_hierarchy_adjustment(); - } - const char* cgroup_path() override { return reader()->cgroup_path(); } - - public: - CgroupV1CpuacctController(const CgroupV1Controller& reader) : _reader(reader) { - } -}; - class CgroupV1Subsystem: public CgroupSubsystem { public: CgroupV1Subsystem(CgroupV1Controller* cpuset, CgroupV1CpuController* cpu, - CgroupV1CpuacctController* cpuacct, + CgroupV1Controller* cpuacct, CgroupV1Controller* pids, CgroupV1MemoryController* memory); @@ -201,14 +171,13 @@ class CgroupV1Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() { return _memory; } CachingCgroupController* cpu_controller() { return _cpu; } - CgroupCpuacctController* cpuacct_controller() { return _cpuacct; } private: /* controllers */ CachingCgroupController* _memory = nullptr; CgroupV1Controller* _cpuset = nullptr; CachingCgroupController* _cpu = nullptr; - CgroupV1CpuacctController* _cpuacct = nullptr; + CgroupV1Controller* _cpuacct = nullptr; CgroupV1Controller* _pids = nullptr; }; diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 7015bc6c9206..519f3eef814d 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2025, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -119,14 +119,12 @@ int CgroupV2CpuController::cpu_quota() { // Constructor CgroupV2Subsystem::CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, - CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified) : _unified(unified) { CgroupUtil::adjust_controller(memory); CgroupUtil::adjust_controller(cpu); _memory = new CachingCgroupController(memory); _cpu = new CachingCgroupController(cpu); - _cpuacct = cpuacct; } bool CgroupV2Subsystem::is_containerized() { @@ -159,17 +157,6 @@ int CgroupV2CpuController::cpu_period() { return period; } -jlong CgroupV2CpuController::cpu_usage_in_micros() { - julong cpu_usage; - bool is_ok = reader()->read_numerical_key_value("/cpu.stat", "usage_usec", &cpu_usage); - if (!is_ok) { - log_trace(os, container)("CPU Usage failed: %d", OSCONTAINER_ERROR); - return OSCONTAINER_ERROR; - } - log_trace(os, container)("CPU Usage is: " JULONG_FORMAT, cpu_usage); - return (jlong)cpu_usage; -} - /* memory_usage_in_bytes * * Return the amount of used memory used by this cgroup and descendents @@ -191,16 +178,10 @@ jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { return mem_soft_limit; } -jlong CgroupV2MemoryController::memory_throttle_limit_in_bytes() { - jlong mem_throttle_limit; - CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.high", "Memory Throttle Limit", mem_throttle_limit); - return mem_throttle_limit; -} - jlong CgroupV2MemoryController::memory_max_usage_in_bytes() { - julong mem_max_usage; - CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.peak", "Maximum Memory Usage", mem_max_usage); - return mem_max_usage; + // Log this string at trace level so as to make tests happy. + log_trace(os, container)("Maximum Memory Usage is not supported."); + return OSCONTAINER_ERROR; // not supported } jlong CgroupV2MemoryController::rss_usage_in_bytes() { diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index 1d754321265f..3dd6000d4202 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2024, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -66,34 +66,6 @@ class CgroupV2CpuController: public CgroupCpuController { int cpu_quota() override; int cpu_period() override; int cpu_shares() override; - jlong cpu_usage_in_micros(); - bool is_read_only() override { - return reader()->is_read_only(); - } - const char* subsystem_path() override { - return reader()->subsystem_path(); - } - bool needs_hierarchy_adjustment() override { - return reader()->needs_hierarchy_adjustment(); - } - void set_subsystem_path(const char* cgroup_path) override { - reader()->set_subsystem_path(cgroup_path); - } - const char* mount_point() override { return reader()->mount_point(); } - const char* cgroup_path() override { return reader()->cgroup_path(); } -}; - -class CgroupV2CpuacctController: public CgroupCpuacctController { - private: - CgroupV2CpuController* _reader; - CgroupV2CpuController* reader() { return _reader; } - public: - CgroupV2CpuacctController(CgroupV2CpuController* reader) : _reader(reader) { - } - // In cgroup v2, cpu usage is a part of the cpu controller. - jlong cpu_usage_in_micros() override { - return reader()->cpu_usage_in_micros(); - } bool is_read_only() override { return reader()->is_read_only(); } @@ -122,7 +94,6 @@ class CgroupV2MemoryController final: public CgroupMemoryController { jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; - jlong memory_throttle_limit_in_bytes() override; jlong memory_usage_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; @@ -154,14 +125,11 @@ class CgroupV2Subsystem: public CgroupSubsystem { CachingCgroupController* _memory = nullptr; CachingCgroupController* _cpu = nullptr; - CgroupCpuacctController* _cpuacct = nullptr; - CgroupV2Controller* unified() { return &_unified; } public: CgroupV2Subsystem(CgroupV2MemoryController * memory, CgroupV2CpuController* cpu, - CgroupV2CpuacctController* cpuacct, CgroupV2Controller unified); char * cpu_cpuset_cpus() override; @@ -176,7 +144,6 @@ class CgroupV2Subsystem: public CgroupSubsystem { } CachingCgroupController* memory_controller() override { return _memory; } CachingCgroupController* cpu_controller() override { return _cpu; } - CgroupCpuacctController* cpuacct_controller() override { return _cpuacct; }; }; diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.cpp index 9c8c2ee1eeee..5f18730f1d0f 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, 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. * * This code is free software; you can redistribute it and/or modify it @@ -126,11 +126,6 @@ jlong OSContainer::memory_soft_limit_in_bytes() { return cgroup_subsystem->memory_soft_limit_in_bytes(); } -jlong OSContainer::memory_throttle_limit_in_bytes() { - assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_throttle_limit_in_bytes(); -} - jlong OSContainer::memory_usage_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->memory_usage_in_bytes(); @@ -188,11 +183,6 @@ int OSContainer::cpu_shares() { return cgroup_subsystem->cpu_shares(); } -jlong OSContainer::cpu_usage_in_micros() { - assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->cpu_usage_in_micros(); -} - jlong OSContainer::pids_max() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); return cgroup_subsystem->pids_max(); diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.hpp index 50437e8649f6..1e9484c40d8f 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/osContainer_linux.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, 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. * * This code is free software; you can redistribute it and/or modify it @@ -60,7 +60,6 @@ class OSContainer: AllStatic { static jlong memory_and_swap_limit_in_bytes(); static jlong memory_and_swap_usage_in_bytes(); static jlong memory_soft_limit_in_bytes(); - static jlong memory_throttle_limit_in_bytes(); static jlong memory_usage_in_bytes(); static jlong memory_max_usage_in_bytes(); static jlong rss_usage_in_bytes(); @@ -76,8 +75,6 @@ class OSContainer: AllStatic { static int cpu_shares(); - static jlong cpu_usage_in_micros(); - static jlong pids_max(); static jlong pids_current(); }; diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/os_linux.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/os_linux.cpp index d78947241ad8..b5d5bc1bd235 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/os_linux.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/linux/os_linux.cpp @@ -64,7 +64,9 @@ #include "runtime/osThread.hpp" #include "runtime/perfMemory.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/statSampler.hpp" #include "runtime/stubRoutines.hpp" +#include "runtime/threadCritical.hpp" #include "runtime/threads.hpp" #include "runtime/threadSMR.hpp" #include "runtime/timer.hpp" @@ -149,6 +151,11 @@ #define MAX_PATH (2 * K) +#define MAX_SECS 100000000 + +// for timer info max values which include all bits +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) + #ifdef MUSL_LIBC // dlvsym is not a part of POSIX // and musl libc doesn't implement it. @@ -237,6 +244,8 @@ typedef int (*malloc_info_func_t)(int options, FILE *stream); static malloc_info_func_t g_malloc_info = nullptr; #endif // __GLIBC__ +static int clock_tics_per_sec = 100; + // If the VM might have been created on the primordial thread, we need to resolve the // primordial thread stack bounds and check if the current thread might be the // primordial thread in places. If we know that the primordial thread is never used, @@ -1092,23 +1101,10 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, ResourceMark rm; pthread_t tid; int ret = 0; - int trials_remaining = 4; - useconds_t next_delay = 1000; - while (true) { + int limit = 3; + do { ret = pthread_create(&tid, &attr, (void* (*)(void*)) thread_native_entry, thread); - - if (ret != EAGAIN) { - break; - } - - if (--trials_remaining <= 0) { - break; - } - - log_debug(os, thread)("Failed to start native thread (%s), retrying after %dus.", os::errno_name(ret), next_delay); - ::usleep(next_delay); - next_delay *= 2; - } + } while (ret == EAGAIN && limit-- > 0); char buf[64]; if (ret == 0) { @@ -1710,7 +1706,7 @@ void * os::dll_load(const char *filename, char *ebuf, int ebuflen) { } ThreadInVMfromNative tiv(jt); - DEBUG_ONLY(VMNativeEntryWrapper vew;) + debug_only(VMNativeEntryWrapper vew;) VM_LinuxDllLoad op(filename, ebuf, ebuflen); VMThread::execute(&op); @@ -2524,18 +2520,9 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("%s", i == OSCONTAINER_ERROR ? "not supported" : "no shares"); } - jlong j = OSContainer::cpu_usage_in_micros(); - st->print("cpu_usage_in_micros: "); - if (j >= 0) { - st->print_cr(JLONG_FORMAT, j); - } else { - st->print_cr("%s", j == OSCONTAINER_ERROR ? "not supported" : "no usage"); - } - OSContainer::print_container_helper(st, OSContainer::memory_limit_in_bytes(), "memory_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_and_swap_limit_in_bytes(), "memory_and_swap_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_soft_limit_in_bytes(), "memory_soft_limit_in_bytes"); - OSContainer::print_container_helper(st, OSContainer::memory_throttle_limit_in_bytes(), "memory_throttle_limit_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_usage_in_bytes(), "memory_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::memory_max_usage_in_bytes(), "memory_max_usage_in_bytes"); OSContainer::print_container_helper(st, OSContainer::rss_usage_in_bytes(), "rss_usage_in_bytes"); @@ -2543,7 +2530,7 @@ bool os::Linux::print_container_info(outputStream* st) { OSContainer::print_version_specific_info(st); - j = OSContainer::pids_max(); + jlong j = OSContainer::pids_max(); st->print("maximum number of tasks: "); if (j > 0) { st->print_cr(JLONG_FORMAT, j); @@ -2792,9 +2779,139 @@ void os::get_summary_cpu_info(char* cpuinfo, size_t length) { #endif } +static char saved_jvm_path[MAXPATHLEN] = {0}; + +// Find the full path to the current module, libjvm.so +void os::jvm_path(char *buf, jint buflen) { + // Error checking. + if (buflen < MAXPATHLEN) { + assert(false, "must use a large-enough buffer"); + buf[0] = '\0'; + return; + } + // Lazy resolve the path to current module. + if (saved_jvm_path[0] != 0) { + strcpy(buf, saved_jvm_path); + return; + } + + char dli_fname[MAXPATHLEN]; + dli_fname[0] = '\0'; + bool ret = dll_address_to_library_name( + CAST_FROM_FN_PTR(address, os::jvm_path), + dli_fname, sizeof(dli_fname), nullptr); + assert(ret, "cannot locate libjvm"); + char *rp = nullptr; + if (ret && dli_fname[0] != '\0') { + rp = os::realpath(dli_fname, buf, buflen); + } + if (rp == nullptr) { + return; + } + + if (Arguments::sun_java_launcher_is_altjvm()) { + // Support for the java launcher's '-XXaltjvm=' option. Typical + // value for buf is "/jre/lib//libjvm.so". + // If "/jre/lib/" appears at the right place in the string, then + // assume we are installed in a JDK and we're done. Otherwise, check + // for a JAVA_HOME environment variable and fix up the path so it + // looks like libjvm.so is installed there (append a fake suffix + // hotspot/libjvm.so). + const char *p = buf + strlen(buf) - 1; + for (int count = 0; p > buf && count < 5; ++count) { + for (--p; p > buf && *p != '/'; --p) + /* empty */ ; + } + + if (strncmp(p, "/jre/lib/", 9) != 0) { + // Look for JAVA_HOME in the environment. + char* java_home_var = ::getenv("JAVA_HOME"); + if (java_home_var != nullptr && java_home_var[0] != 0) { + char* jrelib_p; + int len; + + // Check the current module name "libjvm.so". + p = strrchr(buf, '/'); + if (p == nullptr) { + return; + } + assert(strstr(p, "/libjvm") == p, "invalid library name"); + + rp = os::realpath(java_home_var, buf, buflen); + if (rp == nullptr) { + return; + } + + // determine if this is a legacy image or modules image + // modules image doesn't have "jre" subdirectory + len = checked_cast(strlen(buf)); + assert(len < buflen, "Ran out of buffer room"); + jrelib_p = buf + len; + snprintf(jrelib_p, buflen-len, "/jre/lib"); + if (0 != access(buf, F_OK)) { + snprintf(jrelib_p, buflen-len, "/lib"); + } + + if (0 == access(buf, F_OK)) { + // Use current module name "libjvm.so" + len = (int)strlen(buf); + snprintf(buf + len, buflen-len, "/hotspot/libjvm.so"); + } else { + // Go back to path of .so + rp = os::realpath(dli_fname, buf, buflen); + if (rp == nullptr) { + return; + } + } + } + } + } + + strncpy(saved_jvm_path, buf, MAXPATHLEN); + saved_jvm_path[MAXPATHLEN - 1] = '\0'; +} + //////////////////////////////////////////////////////////////////////////////// // Virtual Memory +// Rationale behind this function: +// current (Mon Apr 25 20:12:18 MSD 2005) oprofile drops samples without executable +// mapping for address (see lookup_dcookie() in the kernel module), thus we cannot get +// samples for JITted code. Here we create private executable mapping over the code cache +// and then we can use standard (well, almost, as mapping can change) way to provide +// info for the reporting script by storing timestamp and location of symbol +void linux_wrap_code(char* base, size_t size) { + static volatile jint cnt = 0; + + static_assert(sizeof(off_t) == 8, "Expected Large File Support in this file"); + + if (!UseOprofile) { + return; + } + + char buf[PATH_MAX+1]; + int num = Atomic::add(&cnt, 1); + + snprintf(buf, sizeof(buf), "%s/hs-vm-%d-%d", + os::get_temp_directory(), os::current_process_id(), num); + unlink(buf); + + int fd = ::open(buf, O_CREAT | O_RDWR, S_IRWXU); + + if (fd != -1) { + off_t rv = ::lseek(fd, size-2, SEEK_SET); + if (rv != (off_t)-1) { + if (::write(fd, "", 1) == 1) { + mmap(base, size, + PROT_READ|PROT_WRITE|PROT_EXEC, + MAP_PRIVATE|MAP_FIXED|MAP_NORESERVE, fd, 0); + } + } + ::close(fd); + unlink(buf); + } +} + static bool recoverable_mmap_error(int err) { // See if the error is one we can let the caller handle. This // list of errno values comes from JBS-6843484. I can't find a @@ -4324,6 +4441,8 @@ static void check_pax(void) { // this is called _before_ most of the global arguments have been parsed void os::init(void) { char dummy; // used to get a guess on initial stack address + + clock_tics_per_sec = checked_cast(sysconf(_SC_CLK_TCK)); int sys_pg_size = checked_cast(sysconf(_SC_PAGESIZE)); if (sys_pg_size < 0) { fatal("os_linux.cpp: os::init: sysconf failed (%s)", @@ -4516,7 +4635,7 @@ static void workaround_expand_exec_shield_cs_limit() { */ char* hint = (char*)(os::Linux::initial_thread_stack_bottom() - (StackOverflow::stack_guard_zone_size() + page_size)); - char* codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread); + char* codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread); if (codebuf == nullptr) { // JDK-8197429: There may be a stack gap of one megabyte between @@ -4524,7 +4643,7 @@ static void workaround_expand_exec_shield_cs_limit() { // Linux kernel workaround for CVE-2017-1000364. If we failed to // map our codebuf, try again at an address one megabyte lower. hint -= 1 * M; - codebuf = os::attempt_reserve_memory_at(hint, page_size, mtThread); + codebuf = os::attempt_reserve_memory_at(hint, page_size, false, mtThread); } if ((codebuf == nullptr) || (!os::commit_memory(codebuf, page_size, true))) { @@ -5078,21 +5197,21 @@ static jlong slow_thread_cpu_time(Thread *thread, bool user_sys_cpu_time) { &user_time, &sys_time); if (count != 13) return -1; if (user_sys_cpu_time) { - return ((jlong)sys_time + (jlong)user_time) * (1000000000 / os::Posix::clock_tics_per_second()); + return ((jlong)sys_time + (jlong)user_time) * (1000000000 / clock_tics_per_sec); } else { - return (jlong)user_time * (1000000000 / os::Posix::clock_tics_per_second()); + return (jlong)user_time * (1000000000 / clock_tics_per_sec); } } void os::current_thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { - info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits info_ptr->may_skip_backward = false; // elapsed time not wall time info_ptr->may_skip_forward = false; // elapsed time not wall time info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned } void os::thread_cpu_time_info(jvmtiTimerInfo *info_ptr) { - info_ptr->max_value = all_bits_jlong; // will not wrap in less than 64 bits + info_ptr->max_value = ALL_64_BITS; // will not wrap in less than 64 bits info_ptr->may_skip_backward = false; // elapsed time not wall time info_ptr->may_skip_forward = false; // elapsed time not wall time info_ptr->kind = JVMTI_TIMER_TOTAL_CPU; // user+system time is returned diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.cpp index dc1026104838..08f1fed53010 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.cpp @@ -25,7 +25,6 @@ #ifndef NATIVE_IMAGE #include "classfile/classLoader.hpp" -#include "interpreter/interpreter.hpp" #include "jvm.h" #include "jvmtifiles/jvmti.h" #include "logging/log.hpp" @@ -56,7 +55,6 @@ #include "utilities/formatBuffer.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#include "utilities/permitForbiddenFunctions.hpp" #include "utilities/vmError.hpp" #if INCLUDE_JFR #include "jfr/support/jfrNativeLibraryLoadEvent.hpp" @@ -65,7 +63,6 @@ #ifdef AIX #include "loadlib_aix.hpp" #include "os_aix.hpp" -#include "porting_aix.hpp" #endif #ifdef LINUX #include "os_linux.hpp" @@ -503,9 +500,9 @@ static char* chop_extra_memory(size_t size, size_t alignment, char* extra_base, // Multiple threads can race in this code, and can remap over each other with MAP_FIXED, // so on posix, unmap the section at the start and at the end of the chunk that we mapped // rather than unmapping and remapping the whole chunk to get requested alignment. -char* os::reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool exec) { +char* os::reserve_memory_aligned(size_t size, size_t alignment, bool exec) { size_t extra_size = calculate_aligned_extra_size(size, alignment); - char* extra_base = os::reserve_memory(extra_size, mem_tag, exec); + char* extra_base = os::reserve_memory(extra_size, exec); if (extra_base == nullptr) { return nullptr; } @@ -942,11 +939,11 @@ ssize_t os::connect(int fd, struct sockaddr* him, socklen_t len) { } void os::exit(int num) { - permit_forbidden_function::exit(num); + ALLOW_C_FUNCTION(::exit, ::exit(num);) } void os::_exit(int num) { - permit_forbidden_function::_exit(num); + ALLOW_C_FUNCTION(::_exit, ::_exit(num);) } void os::naked_yield() { @@ -1003,7 +1000,7 @@ char* os::realpath(const char* filename, char* outbuf, size_t outbuflen) { // This assumes platform realpath() is implemented according to POSIX.1-2008. // POSIX.1-2008 allows to specify null for the output buffer, in which case // output buffer is dynamically allocated and must be ::free()'d by the caller. - char* p = permit_forbidden_function::realpath(filename, nullptr); + ALLOW_C_FUNCTION(::realpath, char* p = ::realpath(filename, nullptr);) if (p != nullptr) { if (strlen(p) < outbuflen) { strcpy(outbuf, p); @@ -1011,7 +1008,7 @@ char* os::realpath(const char* filename, char* outbuf, size_t outbuflen) { } else { errno = ENAMETOOLONG; } - permit_forbidden_function::free(p); // *not* os::free + ALLOW_C_FUNCTION(::free, ::free(p);) // *not* os::free } else { // Fallback for platforms struggling with modern Posix standards (AIX 5.3, 6.1). If realpath // returns EINVAL, this may indicate that realpath is not POSIX.1-2008 compatible and @@ -1020,7 +1017,7 @@ char* os::realpath(const char* filename, char* outbuf, size_t outbuflen) { // a memory overwrite. if (errno == EINVAL) { outbuf[outbuflen - 1] = '\0'; - p = permit_forbidden_function::realpath(filename, outbuf); + ALLOW_C_FUNCTION(::realpath, p = ::realpath(filename, outbuf);) if (p != nullptr) { guarantee(outbuf[outbuflen - 1] == '\0', "realpath buffer overwrite detected."); result = p; @@ -1080,95 +1077,6 @@ bool os::same_files(const char* file1, const char* file2) { return is_same; } -static char saved_jvm_path[MAXPATHLEN] = {0}; - -// Find the full path to the current module, libjvm.so -void os::jvm_path(char *buf, jint buflen) { - // Error checking. - if (buflen < MAXPATHLEN) { - assert(false, "must use a large-enough buffer"); - buf[0] = '\0'; - return; - } - // Lazy resolve the path to current module. - if (saved_jvm_path[0] != 0) { - strcpy(buf, saved_jvm_path); - return; - } - - const char* fname; -#ifdef AIX - Dl_info dlinfo; - int ret = dladdr(CAST_FROM_FN_PTR(void *, os::jvm_path), &dlinfo); - assert(ret != 0, "cannot locate libjvm"); - if (ret == 0) { - return; - } - fname = dlinfo.dli_fname; -#else - char dli_fname[MAXPATHLEN]; - dli_fname[0] = '\0'; - bool ret = dll_address_to_library_name( - CAST_FROM_FN_PTR(address, os::jvm_path), - dli_fname, sizeof(dli_fname), nullptr); - assert(ret, "cannot locate libjvm"); - if (!ret) { - return; - } - fname = dli_fname; -#endif // AIX - char* rp = nullptr; - if (fname[0] != '\0') { - rp = os::realpath(fname, buf, buflen); - } - if (rp == nullptr) { - return; - } - - // If executing unit tests we require JAVA_HOME to point to the real JDK. - if (Arguments::executing_unit_tests()) { - // Look for JAVA_HOME in the environment. - char* java_home_var = ::getenv("JAVA_HOME"); - if (java_home_var != nullptr && java_home_var[0] != 0) { - - // Check the current module name "libjvm.so". - const char* p = strrchr(buf, '/'); - if (p == nullptr) { - return; - } - assert(strstr(p, "/libjvm") == p, "invalid library name"); - - stringStream ss(buf, buflen); - rp = os::realpath(java_home_var, buf, buflen); - if (rp == nullptr) { - return; - } - - assert((int)strlen(buf) < buflen, "Ran out of buffer room"); - ss.print("%s/lib", buf); - - // If the path exists within JAVA_HOME, add the VM variant directory and JVM - // library name to complete the path to JVM being overridden. Otherwise fallback - // to the path to the current library. - if (0 == access(buf, F_OK)) { - // Use current module name "libjvm.so" - ss.print("/%s/libjvm%s", Abstract_VM_Version::vm_variant(), JNI_LIB_SUFFIX); - assert(strcmp(buf + strlen(buf) - strlen(JNI_LIB_SUFFIX), JNI_LIB_SUFFIX) == 0, - "buf has been truncated"); - } else { - // Go back to path of .so - rp = os::realpath(fname, buf, buflen); - if (rp == nullptr) { - return; - } - } - } - } - - strncpy(saved_jvm_path, buf, MAXPATHLEN); - saved_jvm_path[MAXPATHLEN - 1] = '\0'; -} - // Called when creating the thread. The minimum stack sizes have already been calculated size_t os::Posix::get_initial_stack_size(ThreadType thr_type, size_t req_stack_size) { size_t stack_size; @@ -1436,19 +1344,6 @@ void os::Posix::init_2(void) { _use_clock_monotonic_condattr ? "CLOCK_MONOTONIC" : "the default clock"); } -int os::Posix::clock_tics_per_second() { - return clock_tics_per_sec; -} - -#ifdef ASSERT -bool os::Posix::ucontext_is_interpreter(const ucontext_t* uc) { - assert(uc != nullptr, "invariant"); - address pc = os::Posix::ucontext_get_pc(uc); - assert(pc != nullptr, "invariant"); - return Interpreter::contains(pc); -} -#endif - // Utility to convert the given timeout to an absolute timespec // (based on the appropriate clock) to use with pthread_cond_timewait, // and sem_timedwait(). @@ -1596,9 +1491,12 @@ jlong os::javaTimeNanos() { return result; } +// for timer info max values which include all bits +#define ALL_64_BITS CONST64(0xFFFFFFFFFFFFFFFF) + void os::javaTimeNanos_info(jvmtiTimerInfo *info_ptr) { // CLOCK_MONOTONIC - amount of time since some arbitrary point in the past - info_ptr->max_value = all_bits_jlong; + info_ptr->max_value = ALL_64_BITS; info_ptr->may_skip_backward = false; // not subject to resetting or drifting info_ptr->may_skip_forward = false; // not subject to resetting or drifting info_ptr->kind = JVMTI_TIMER_ELAPSED; // elapsed not CPU time diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.hpp index bd92702bd097..b6dae92257c5 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/os/posix/os_posix.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -94,13 +94,8 @@ class os::Posix { static address ucontext_get_pc(const ucontext_t* ctx); static void ucontext_set_pc(ucontext_t* ctx, address pc); - DEBUG_ONLY(static bool ucontext_is_interpreter(const ucontext_t* ctx);) - static void to_RTC_abstime(timespec* abstime, int64_t millis); - // clock ticks per second of the system - static int clock_tics_per_second(); - static bool handle_stack_overflow(JavaThread* thread, address addr, address pc, const void* ucVoid, address* stub); diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.hpp index 970446354c0e..092e55a722ea 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.hpp @@ -319,12 +319,7 @@ class MetaspaceObj { f(ConstantPoolCache) \ f(Annotations) \ f(MethodCounters) \ - f(RecordComponent) \ - f(KlassTrainingData) \ - f(MethodTrainingData) \ - f(CompileTrainingData) \ - f(AdapterHandlerEntry) \ - f(AdapterFingerPrint) + f(RecordComponent) #define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type, #define METASPACE_OBJ_TYPE_NAME_CASE(name) case name ## Type: return #name; @@ -362,8 +357,6 @@ class MetaspaceObj { void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, Type type) throw(); - // This is used for allocating training data. We are allocating training data in many cases where a GC cannot be triggered. - void* operator new(size_t size, MemTag flags); void operator delete(void* p) = delete; // Declare a *static* method with the same signature in any subclass of MetaspaceObj diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.inline.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.inline.hpp index 9304d21b704b..39047a40e010 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.inline.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/memory/allocation.inline.hpp @@ -69,7 +69,7 @@ template E* MmapArrayAllocator::allocate_or_null(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, mem_tag); + char* addr = os::reserve_memory(size, !ExecMem, mem_tag); if (addr == nullptr) { return nullptr; } @@ -86,7 +86,7 @@ template E* MmapArrayAllocator::allocate(size_t length, MemTag mem_tag) { size_t size = size_for(length); - char* addr = os::reserve_memory(size, mem_tag); + char* addr = os::reserve_memory(size, !ExecMem, mem_tag); if (addr == nullptr) { vm_exit_out_of_memory(size, OOM_MMAP_ERROR, "Allocator (reserve)"); } diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.cpp index 714fcc806931..d4f7b258f954 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.cpp @@ -84,11 +84,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/fastrand.hpp" -#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" -#endif // !NATIVE_IMAGE -#include "utilities/permitForbiddenFunctions.hpp" -#ifndef NATIVE_IMAGE #include "utilities/powerOfTwo.hpp" #ifdef LINUX @@ -141,7 +137,7 @@ int os::snprintf_checked(char* buf, size_t len, const char* fmt, ...) { } int os::vsnprintf(char* buf, size_t len, const char* fmt, va_list args) { - int result = permit_forbidden_function::vsnprintf(buf, len, fmt, args); + ALLOW_C_FUNCTION(::vsnprintf, int result = ::vsnprintf(buf, len, fmt, args);) // If an encoding error occurred (result < 0) then it's not clear // whether the buffer is NUL terminated, so ensure it is. if ((result < 0) && (len > 0)) { @@ -266,7 +262,7 @@ char* os::iso8601_time(jlong milliseconds_since_19700101, char* buffer, size_t b } OSReturn os::set_priority(Thread* thread, ThreadPriority p) { - DEBUG_ONLY(Thread::check_for_dangling_thread_pointer(thread);) + debug_only(Thread::check_for_dangling_thread_pointer(thread);) if ((p >= MinPriority && p <= MaxPriority) || (p == CriticalPriority && thread->is_ConcurrentGC_thread())) { @@ -622,7 +618,7 @@ char *os::strdup(const char *str, MemTag mem_tag) { size_t size = strlen(str); char *dup_str = (char *)malloc(size + 1, mem_tag); if (dup_str == nullptr) return nullptr; - memcpy(dup_str, str, size + 1); + strcpy(dup_str, str); return dup_str; } @@ -710,7 +706,7 @@ void* os::malloc(size_t size, MemTag mem_tag, const NativeCallStack& stack) { return nullptr; } - void* const outer_ptr = permit_forbidden_function::malloc(outer_size); + ALLOW_C_FUNCTION(::malloc, void* const outer_ptr = ::malloc(outer_size);) if (outer_ptr == nullptr) { return nullptr; } @@ -777,7 +773,7 @@ void* os::realloc(void *memblock, size_t size, MemTag mem_tag, const NativeCallS header->mark_block_as_dead(); // the real realloc - void* const new_outer_ptr = permit_forbidden_function::realloc(header, new_outer_size); + ALLOW_C_FUNCTION(::realloc, void* const new_outer_ptr = ::realloc(header, new_outer_size);) if (new_outer_ptr == nullptr) { // realloc(3) failed and the block still exists. @@ -805,7 +801,7 @@ void* os::realloc(void *memblock, size_t size, MemTag mem_tag, const NativeCallS } else { // NMT disabled. - rc = permit_forbidden_function::realloc(memblock, size); + ALLOW_C_FUNCTION(::realloc, rc = ::realloc(memblock, size);) if (rc == nullptr) { return nullptr; } @@ -833,7 +829,7 @@ void os::free(void *memblock) { // When NMT is enabled this checks for heap overwrites, then deaccounts the old block. void* const old_outer_ptr = MemTracker::record_free(memblock); - permit_forbidden_function::free(old_outer_ptr); + ALLOW_C_FUNCTION(::free, ::free(old_outer_ptr);) } void os::init_random(unsigned int initval) { @@ -1222,7 +1218,7 @@ void os::print_cpu_info(outputStream* st, char* buf, size_t buflen) { // We access the raw value here because the assert in the accessor will // fail if the crash occurs before initialization of this value. st->print(" (initial active %d)", _initial_active_processor_count); - st->print(" %s", VM_Version::cpu_info_string()); + st->print(" %s", VM_Version::features_string()); st->cr(); pd_print_cpu_info(st, buf, buflen); } @@ -1592,57 +1588,6 @@ bool os::set_boot_path(char fileSep, char pathSep) { return false; } -static char* _image_release_file_content = nullptr; - -void os::read_image_release_file() { - assert(_image_release_file_content == nullptr, "release file content must not be already set"); - const char* home = Arguments::get_java_home(); - stringStream ss; - ss.print("%s/release", home); - - FILE* file = fopen(ss.base(), "rb"); - if (file == nullptr) { - return; - } - fseek(file, 0, SEEK_END); - long sz = ftell(file); - if (sz == -1) { - fclose(file); - return; - } - fseek(file, 0, SEEK_SET); - - char* tmp = (char*) os::malloc(sz + 1, mtInternal); - if (tmp == nullptr) { - fclose(file); - return; - } - - size_t elements_read = fread(tmp, 1, sz, file); - if (elements_read < (size_t)sz) { - tmp[elements_read] = '\0'; - } else { - tmp[sz] = '\0'; - } - // issues with \r in line endings on Windows, so better replace those - for (size_t i = 0; i < elements_read; i++) { - if (tmp[i] == '\r') { - tmp[i] = ' '; - } - } - Atomic::release_store(&_image_release_file_content, tmp); - fclose(file); -} - -void os::print_image_release_file(outputStream* st) { - char* ifrc = Atomic::load_acquire(&_image_release_file_content); - if (ifrc != nullptr) { - st->print_cr("%s", ifrc); - } else { - st->print_cr(""); - } -} - #endif // !NATIVE_IMAGE bool os::file_exists(const char* filename) { struct stat statbuf; @@ -2029,7 +1974,7 @@ bool os::create_stack_guard_pages(char* addr, size_t bytes) { return os::pd_create_stack_guard_pages(addr, bytes); } -char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) { +char* os::reserve_memory(size_t bytes, bool executable, MemTag mem_tag) { char* result = pd_reserve_memory(bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve(result, bytes, CALLER_PC, mem_tag); @@ -2040,7 +1985,7 @@ char* os::reserve_memory(size_t bytes, MemTag mem_tag, bool executable) { return result; } -char* os::attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable) { +char* os::attempt_reserve_memory_at(char* addr, size_t bytes, bool executable, MemTag mem_tag) { char* result = SimulateFullAddressSpace ? nullptr : pd_attempt_reserve_memory_at(addr, bytes, executable); if (result != nullptr) { MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, mem_tag); @@ -2246,7 +2191,7 @@ char* os::attempt_reserve_memory_between(char* min, char* max, size_t bytes, siz assert(is_aligned(result, alignment), "alignment invalid (" ERRFMT ")", ERRFMTARGS); log_trace(os, map)(ERRFMT, ERRFMTARGS); log_debug(os, map)("successfully attached at " PTR_FORMAT, p2i(result)); - MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC, mtNone); + MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC); } else { log_debug(os, map)("failed to attach anywhere in [" PTR_FORMAT "-" PTR_FORMAT ")", p2i(min), p2i(max)); } @@ -2314,11 +2259,6 @@ void os::commit_memory_or_exit(char* addr, size_t size, size_t alignment_hint, MemTracker::record_virtual_memory_commit((address)addr, size, CALLER_PC); } -// The scope of NmtVirtualMemoryLocker covers both pd_uncommit_memory and record_virtual_memory_uncommit because -// these operations must happen atomically to avoid races causing NMT to fall out os sync with the OS reality. -// We do not have the same lock protection for pd_commit_memory and record_virtual_memory_commit. -// We assume that there is some external synchronization that prevents a region from being uncommitted -// before it is finished being committed. bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { assert_nonempty_range(addr, bytes); bool res; @@ -2341,11 +2281,6 @@ bool os::uncommit_memory(char* addr, size_t bytes, bool executable) { return res; } -// The scope of NmtVirtualMemoryLocker covers both pd_release_memory and record_virtual_memory_release because -// these operations must happen atomically to avoid races causing NMT to fall out os sync with the OS reality. -// We do not have the same lock protection for pd_reserve_memory and record_virtual_memory_reserve. -// We assume that there is some external synchronization that prevents a region from being released -// before it is finished being reserved. bool os::release_memory(char* addr, size_t bytes) { assert_nonempty_range(addr, bytes); bool res; @@ -2423,8 +2358,8 @@ char* os::attempt_map_memory_to_file_at(char* addr, size_t bytes, int file_desc, } char* os::map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, MemTag mem_tag, - bool read_only, bool allow_exec) { + char *addr, size_t bytes, bool read_only, + bool allow_exec, MemTag mem_tag) { char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec); if (result != nullptr) { MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC, mem_tag); @@ -2462,7 +2397,7 @@ char* os::reserve_memory_special(size_t size, size_t alignment, size_t page_size char* result = pd_reserve_memory_special(size, alignment, page_size, addr, executable); if (result != nullptr) { // The memory is committed - MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC, mtNone); + MemTracker::record_virtual_memory_reserve_and_commit((address)result, size, CALLER_PC); log_debug(os, map)("Reserved and committed " RANGEFMT, RANGEFMTARGS(result, size)); } else { log_info(os, map)("Reserve and commit failed (%zu bytes)", size); @@ -2658,7 +2593,7 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name, if ((start = strrchr(lib_name, *os::file_separator())) != nullptr) { lib_name = ++start; } -#ifdef _WINDOWS +#ifdef WINDOWS else { // Need to check for drive prefix e.g. C:L.dll if ((start = strchr(lib_name, ':')) != nullptr) { lib_name = ++start; diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.hpp index 187f48caccac..c443cd12adaa 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/runtime/os.hpp @@ -478,14 +478,14 @@ class os: AllStatic { inline static size_t cds_core_region_alignment(); // Reserves virtual memory. - static char* reserve_memory(size_t bytes, MemTag mem_tag, bool executable = false); + static char* reserve_memory(size_t bytes, bool executable = false, MemTag mem_tag = mtNone); // Reserves virtual memory that starts at an address that is aligned to 'alignment'. - static char* reserve_memory_aligned(size_t size, size_t alignment, MemTag mem_tag, bool executable = false); + static char* reserve_memory_aligned(size_t size, size_t alignment, bool executable = false); // Attempts to reserve the virtual memory at [addr, addr + bytes). // Does not overwrite existing mappings. - static char* attempt_reserve_memory_at(char* addr, size_t bytes, MemTag mem_tag, bool executable = false); + static char* attempt_reserve_memory_at(char* addr, size_t bytes, bool executable = false, MemTag mem_tag = mtNone); // Given an address range [min, max), attempts to reserve memory within this area, with the given alignment. // If randomize is true, the location will be randomized. @@ -537,16 +537,16 @@ class os: AllStatic { static int create_file_for_heap(const char* dir); // Map memory to the file referred by fd. This function is slightly different from map_memory() // and is added to be used for implementation of -XX:AllocateHeapAt - static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag); - static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag); + static char* map_memory_to_file(size_t size, int fd, MemTag mem_tag = mtNone); + static char* map_memory_to_file_aligned(size_t size, size_t alignment, int fd, MemTag mem_tag = mtNone); static char* map_memory_to_file(char* base, size_t size, int fd); - static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag); + static char* attempt_map_memory_to_file_at(char* base, size_t size, int fd, MemTag mem_tag = mtNone); // Replace existing reserved memory with file mapping static char* replace_existing_mapping_with_file_mapping(char* base, size_t size, int fd); static char* map_memory(int fd, const char* file_name, size_t file_offset, - char *addr, size_t bytes, MemTag mem_tag, bool read_only = false, - bool allow_exec = false); + char *addr, size_t bytes, bool read_only = false, + bool allow_exec = false, MemTag mem_tag = mtNone); static bool unmap_memory(char *addr, size_t bytes); static void disclaim_memory(char *addr, size_t bytes); static void realign_memory(char *addr, size_t bytes, size_t alignment_hint); @@ -644,7 +644,6 @@ class os: AllStatic { static address fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp); static frame fetch_frame_from_context(const void* ucVoid); static frame fetch_compiled_frame_from_context(const void* ucVoid); - static intptr_t* fetch_bcp_from_context(const void* ucVoid); // For saving an os specific context generated by an assert or guarantee. static void save_assert_context(const void* ucVoid); @@ -695,12 +694,7 @@ class os: AllStatic { static jlong lseek(int fd, jlong offset, int whence); #endif // !NATIVE_IMAGE static bool file_exists(const char* file); - #ifndef NATIVE_IMAGE - // read/store and print the release file of the image - static void read_image_release_file(); - static void print_image_release_file(outputStream* st); - // This function, on Windows, canonicalizes a given path (see os_windows.cpp for details). // On Posix, this function is a noop: it does not change anything and just returns // the input pointer. diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings.hpp index 56f19cb5f4f6..a71f641b3311 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, 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. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,9 @@ #ifndef PRAGMA_FORMAT_NONLITERAL_IGNORED #define PRAGMA_FORMAT_NONLITERAL_IGNORED #endif +#ifndef PRAGMA_FORMAT_IGNORED +#define PRAGMA_FORMAT_IGNORED +#endif #ifndef PRAGMA_STRINGOP_TRUNCATION_IGNORED #define PRAGMA_STRINGOP_TRUNCATION_IGNORED @@ -86,61 +89,23 @@ // Support warnings for use of certain C functions, except where explicitly // permitted. - -// FORBID_C_FUNCTION(Signature, Alternative) -// - Signature: the function that should not normally be used. -// - Alternative: a string literal that may be used in a warning about a use, -// often suggesting an alternative. -// Declares the C-linkage function designated by Signature to be deprecated, -// using the `deprecated` attribute with Alternative as an argument. // -// The variants with IMPORTED in the name are to deal with Windows -// requirements, using FORBIDDEN_FUNCTION_IMPORT_SPEC. See the Visual -// Studio definition of that macro for more details. The default has -// an empty expansion. The potentially added spec must precede the -// base signature but follow all attributes. +// FORBID_C_FUNCTION(signature, alternative) +// - signature: the function that should not normally be used. +// - alternative: a string that may be used in a warning about a use, typically +// suggesting an alternative. // -// FORBID_NORETURN_C_FUNCTION deals with a clang issue. See the clang -// definition of FORBIDDEN_FUNCTION_NORETURN_ATTRIBUTE for more -// details. The default expands to `[[noreturn]]`. -#define FORBID_C_FUNCTION(Signature, Alternative) \ - extern "C" { [[deprecated(Alternative)]] Signature; } +// ALLOW_C_FUNCTION(name, ... using statement ...) +// - name: the name of a forbidden function whose use is permitted in statement. +// - statement: a use of the otherwise forbidden function. Using a variadic +// tail allows the statement to contain non-nested commas. -#ifndef FORBIDDEN_FUNCTION_IMPORT_SPEC -#define FORBIDDEN_FUNCTION_IMPORT_SPEC +#ifndef FORBID_C_FUNCTION +#define FORBID_C_FUNCTION(signature, alternative) #endif -#ifndef FORBIDDEN_FUNCTION_NORETURN_ATTRIBUTE -#define FORBIDDEN_FUNCTION_NORETURN_ATTRIBUTE [[noreturn]] +#ifndef ALLOW_C_FUNCTION +#define ALLOW_C_FUNCTION(name, ...) __VA_ARGS__ #endif -#ifndef FORBIDDEN_FUNCTION_IGNORE_CLANG_FORTIFY_WARNING -#define FORBIDDEN_FUNCTION_IGNORE_CLANG_FORTIFY_WARNING -#endif - -#define FORBID_IMPORTED_C_FUNCTION(Signature, Alternative) \ - FORBID_C_FUNCTION(FORBIDDEN_FUNCTION_IMPORT_SPEC Signature, Alternative) - -#define FORBID_NORETURN_C_FUNCTION(Signature, Alternative) \ - FORBID_C_FUNCTION(FORBIDDEN_FUNCTION_NORETURN_ATTRIBUTE Signature, Alternative) - -#define FORBID_IMPORTED_NORETURN_C_FUNCTION(Signature, Alternative) \ - FORBID_NORETURN_C_FUNCTION(FORBIDDEN_FUNCTION_IMPORT_SPEC Signature, Alternative) - -// A BEGIN/END_ALLOW_FORBIDDEN_FUNCTIONS pair establishes a scope in which the -// deprecation warnings used to forbid the use of certain functions are -// suppressed. These macros are not intended for warning suppression at -// individual call sites; see permitForbiddenFunctions.hpp for the approach -// taken for that where needed. Rather, these are used to suppress warnings -// from 3rd-party code included by HotSpot, such as the gtest framework and -// C++ Standard Library headers, which may refer to functions that are -// disallowed in other parts of HotSpot. They are also used in the -// implementation of the "permit" mechanism. -#define BEGIN_ALLOW_FORBIDDEN_FUNCTIONS \ - PRAGMA_DIAG_PUSH \ - PRAGMA_DEPRECATED_IGNORED - -#define END_ALLOW_FORBIDDEN_FUNCTIONS \ - PRAGMA_DIAG_POP - #endif // SHARE_UTILITIES_COMPILERWARNINGS_HPP diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings_gcc.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings_gcc.hpp index 0687b784399a..f11b4eb8af24 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings_gcc.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/compilerWarnings_gcc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, 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. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,8 @@ PRAGMA_DISABLE_GCC_WARNING("-Wformat-nonliteral") \ PRAGMA_DISABLE_GCC_WARNING("-Wformat-security") +#define PRAGMA_FORMAT_IGNORED PRAGMA_DISABLE_GCC_WARNING("-Wformat") + // Disable -Wstringop-truncation which is introduced in GCC 8. // https://gcc.gnu.org/gcc-8/changes.html #if !defined(__clang_major__) && (__GNUC__ >= 8) @@ -69,71 +71,32 @@ #define PRAGMA_ZERO_AS_NULL_POINTER_CONSTANT_IGNORED \ PRAGMA_DISABLE_GCC_WARNING("-Wzero-as-null-pointer-constant") -#define PRAGMA_DEPRECATED_IGNORED \ - PRAGMA_DISABLE_GCC_WARNING("-Wdeprecated-declarations") - -// This macro is used by the NORETURN variants of FORBID_C_FUNCTION. -// -// The [[noreturn]] attribute requires that the first declaration of a -// function has it if any have it. -// -// gcc, clang, and MSVC all provide compiler-specific alternatives to that -// attribute: __attribute__((noreturn)) for gcc and clang, -// __declspec(noreturn) for MSVC and clang. gcc and MSVC treat their -// respective compiler-specific alternatives as satisfying that requirement. -// clang does not. -// -// So clang warns if we use [[noreturn]] in the forbidding declaration and the -// library header has already been included and uses the compiler-specific -// attribute. Similarly, clang warns if we use the compiler-specific attribute -// while the library uses [[noreturn]] and the library header is included -// after the forbidding declaration. -// -// For now, we're only going to worry about the standard library, and not -// noreturn functions in some other library that we might want to forbid in -// the future. If there's more than one library to be accounted for, then -// things may get more complicated. -// -// There are several ways we could deal with this. -// -// Probably the most robust is to use the same style of noreturn attribute as -// is used by the library providing the function. That way it doesn't matter -// in which order the inclusion of the library header and the forbidding are -// performed. We could use configure to determine which to use and provide a -// macro to select on here. -// -// Another approach is to always use __attribute__ noreturn in the forbidding -// declaration, but ensure the relevant library header has been included -// before the forbidding declaration. Since there are currently only a couple -// of affected functions, this is easier to implement. So this is the -// approach being taken for now. -// -// clang's failure to treat the compiler-specific form as counting toward the -// [[noreturn]] requirement is arguably a clang bug. -// https://github.com/llvm/llvm-project/issues/131700 - -#ifdef __clang__ -#define FORBIDDEN_FUNCTION_NORETURN_ATTRIBUTE __attribute__((__noreturn__)) -#endif +#if (__GNUC__ >= 10) +// TODO: Re-enable warning attribute for Clang once +// https://github.com/llvm/llvm-project/issues/56519 is fixed and released. +// || (defined(__clang_major__) && (__clang_major__ >= 14)) -// This macro is used to suppress a warning for some uses of FORBID_C_FUNCTION. +// Use "warning" attribute to detect uses of "forbidden" functions. // -// libstdc++ provides inline definitions of some functions to support -// _FORTIFY_SOURCE. clang warns about our forbidding declaration adding the -// [[deprecated]] attribute following such a definition: -// "warning: attribute declaration must precede definition [-Wignored-attributes]" -// Use this macro to suppress the warning, not getting protection when using -// that combination. Other build combinations should provide sufficient -// coverage. +// Note: The warning attribute is available since GCC 9, but disabling pragmas +// does not work reliably in ALLOW_C_FUNCTION. GCC 10+ and up work fine. // -// clang's warning in this case is arguably a clang bug. -// https://github.com/llvm/llvm-project/issues/135481 -// This issue has been fixed, with the fix probably appearing in clang 21. -#if defined(__clang__) && defined(_FORTIFY_SOURCE) -#if _FORTIFY_SOURCE > 0 -#define FORBIDDEN_FUNCTION_IGNORE_CLANG_FORTIFY_WARNING \ - PRAGMA_DISABLE_GCC_WARNING("-Wignored-attributes") -#endif -#endif +// Note: _FORTIFY_SOURCE transforms calls to certain functions into calls to +// associated "checking" functions, and that transformation seems to occur +// *before* the attribute check. We use fortification in fastdebug builds, +// so uses of functions that are both forbidden and fortified won't cause +// forbidden warnings in such builds. +#define FORBID_C_FUNCTION(signature, alternative) \ + extern "C" __attribute__((__warning__(alternative))) signature; + +// Disable warning attribute over the scope of the affected statement. +// The name serves only to document the intended function. +#define ALLOW_C_FUNCTION(name, ...) \ + PRAGMA_DIAG_PUSH \ + PRAGMA_DISABLE_GCC_WARNING("-Wattribute-warning") \ + __VA_ARGS__ \ + PRAGMA_DIAG_POP + +#endif // gcc10+ #endif // SHARE_UTILITIES_COMPILERWARNINGS_GCC_HPP diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/globalDefinitions.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/globalDefinitions.hpp index b475b02dbcee..5223f0f8ed4b 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/globalDefinitions.hpp @@ -28,9 +28,6 @@ #include "utilities/compilerWarnings.hpp" #include "utilities/debug.hpp" -#ifndef NATIVE_IMAGE -#include "utilities/forbiddenFunctions.hpp" -#endif // !NATIVE_IMAGE #include "utilities/macros.hpp" #ifndef NATIVE_IMAGE @@ -193,6 +190,35 @@ inline uintptr_t p2u(const volatile void* p) { #define BOOL_TO_STR(_b_) ((_b_) ? "true" : "false") +//---------------------------------------------------------------------------------------------------- +// Forbid the use of various C library functions. +// Some of these have os:: replacements that should normally be used instead. +// Others are considered security concerns, with preferred alternatives. + +FORBID_C_FUNCTION(void exit(int), "use os::exit"); +FORBID_C_FUNCTION(void _exit(int), "use os::exit"); +FORBID_C_FUNCTION(char* strerror(int), "use os::strerror"); +FORBID_C_FUNCTION(char* strtok(char*, const char*), "use strtok_r"); +FORBID_C_FUNCTION(int sprintf(char*, const char*, ...), "use os::snprintf"); +FORBID_C_FUNCTION(int vsprintf(char*, const char*, va_list), "use os::vsnprintf"); +FORBID_C_FUNCTION(int vsnprintf(char*, size_t, const char*, va_list), "use os::vsnprintf"); + +// All of the following functions return raw C-heap pointers (sometimes as an option, e.g. realpath or getwd) +// or, in case of free(), take raw C-heap pointers. Don't use them unless you are really sure you must. +FORBID_C_FUNCTION(void* malloc(size_t size), "use os::malloc"); +FORBID_C_FUNCTION(void* calloc(size_t nmemb, size_t size), "use os::malloc and zero out manually"); +FORBID_C_FUNCTION(void free(void *ptr), "use os::free"); +FORBID_C_FUNCTION(void* realloc(void *ptr, size_t size), "use os::realloc"); +FORBID_C_FUNCTION(char* strdup(const char *s), "use os::strdup"); +FORBID_C_FUNCTION(char* strndup(const char *s, size_t n), "don't use"); +FORBID_C_FUNCTION(int posix_memalign(void **memptr, size_t alignment, size_t size), "don't use"); +FORBID_C_FUNCTION(void* aligned_alloc(size_t alignment, size_t size), "don't use"); +FORBID_C_FUNCTION(char* realpath(const char* path, char* resolved_path), "use os::realpath"); +FORBID_C_FUNCTION(char* get_current_dir_name(void), "use os::get_current_directory()"); +FORBID_C_FUNCTION(char* getwd(char *buf), "use os::get_current_directory()"); +FORBID_C_FUNCTION(wchar_t* wcsdup(const wchar_t *s), "don't use"); +FORBID_C_FUNCTION(void* reallocf(void *ptr, size_t size), "don't use"); + //---------------------------------------------------------------------------------------------------- // Constants @@ -295,9 +321,6 @@ namespace svm_container { const jlong min_jlong = CONST64(0x8000000000000000); const jlong max_jlong = CONST64(0x7fffffffffffffff); -// for timer info max values which include all bits, 0xffffffffffffffff -const jlong all_bits_jlong = ~jlong(0); - #ifndef NATIVE_IMAGE //------------------------------------------- // Constant for jdouble @@ -311,6 +334,7 @@ const size_t K = 1024; const size_t M = K*K; const size_t G = M*K; #ifndef NATIVE_IMAGE +const size_t HWperKB = K / sizeof(HeapWord); // Constants for converting from a base unit to milli-base units. For // example from seconds to milliseconds and microseconds @@ -1183,7 +1207,7 @@ inline bool is_even(intx x) { return !is_odd(x); } // abs methods which cannot overflow and so are well-defined across // the entire domain of integer types. -static inline unsigned int g_uabs(unsigned int n) { +static inline unsigned int uabs(unsigned int n) { union { unsigned int result; int value; @@ -1192,7 +1216,7 @@ static inline unsigned int g_uabs(unsigned int n) { if (value < 0) result = 0-result; return result; } -static inline julong g_uabs(julong n) { +static inline julong uabs(julong n) { union { julong result; jlong value; @@ -1201,8 +1225,8 @@ static inline julong g_uabs(julong n) { if (value < 0) result = 0-result; return result; } -static inline julong g_uabs(jlong n) { return g_uabs((julong)n); } -static inline unsigned int g_uabs(int n) { return g_uabs((unsigned int)n); } +static inline julong uabs(jlong n) { return uabs((julong)n); } +static inline unsigned int uabs(int n) { return uabs((unsigned int)n); } // "to" should be greater than "from." inline size_t byte_size(void* from, void* to) { diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/macros.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/macros.hpp index 876af4e1e74c..5dbec43da020 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/macros.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/macros.hpp @@ -378,10 +378,13 @@ #define DEBUG_ONLY(code) code #define NOT_DEBUG(code) #define NOT_DEBUG_RETURN /*next token must be ;*/ +// Historical. +#define debug_only(code) code #else // ASSERT #define DEBUG_ONLY(code) #define NOT_DEBUG(code) code #define NOT_DEBUG_RETURN {} +#define debug_only(code) #endif // ASSERT #ifdef _LP64 diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.cpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.cpp index d1b72989cb67..812c6ba19afb 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.cpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.cpp @@ -170,12 +170,6 @@ void outputStream::do_vsnprintf_and_write(const char* format, va_list ap, bool a } } -bool outputStream::set_autoindent(bool value) { - const bool old = _autoindent; - _autoindent = value; - return old; -} - void outputStream::print(const char* format, ...) { va_list ap; va_start(ap, format); @@ -250,6 +244,10 @@ void outputStream::cr() { this->write("\n", 1); } +void outputStream::cr_indent() { + cr(); indent(); +} + void outputStream::stamp() { if (! _stamp.is_updated()) { _stamp.update(); // start at 0 on first call to stamp() @@ -298,6 +296,12 @@ outputStream& outputStream::indent() { return *this; } +bool outputStream::set_autoindent(bool value) { + const bool old = _autoindent; + _autoindent = value; + return old; +} + void outputStream::print_jlong(jlong value) { print(JLONG_FORMAT, value); } @@ -315,16 +319,16 @@ void outputStream::print_julong(julong value) { * 0000020: 0000 0000 0000 0040 0000 0000 0000 015d .......@.......] * ... * - * Ends with a CR. + * indent is applied to each line. Ends with a CR. */ void outputStream::print_data(void* data, size_t len, bool with_ascii, bool rel_addr) { size_t limit = (len + 16) / 16 * 16; for (size_t i = 0; i < limit; ++i) { if (i % 16 == 0) { if (rel_addr) { - print("%07" PRIxPTR ":", i); + indent().print("%07" PRIxPTR ":", i); } else { - print(PTR_FORMAT ":", p2i((unsigned char*)data + i)); + indent().print(PTR_FORMAT ":", p2i((unsigned char*)data + i)); } } if (i % 2 == 0) { diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.hpp index 24c66ca59d74..494d90d5ce8d 100644 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.hpp +++ b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/ostream.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -58,8 +58,6 @@ DEBUG_ONLY(class ResourceMark;) namespace svm_container { class outputStream : public CHeapObjBase { - friend class StreamIndentor; - #ifndef NATIVE_IMAGE private: NONCOPYABLE(outputStream); @@ -105,9 +103,6 @@ class outputStream : public CHeapObjBase { void do_vsnprintf_and_write(const char* format, va_list ap, bool add_cr) ATTRIBUTE_PRINTF(2, 0); #endif // !NATIVE_IMAGE - // Automatic indentation. Returns old autoindent state. - bool set_autoindent(bool value); - public: #ifndef NATIVE_IMAGE class TestSupport; // Unit test support @@ -126,6 +121,14 @@ class outputStream : public CHeapObjBase { int fill_to(int col); void move_to(int col, int slop = 6, int min_space = 2); + // Automatic indentation: + // If autoindent mode is on, the following APIs will automatically indent + // line starts depending on the current indentation level: + // print(), print_cr(), print_raw(), print_raw_cr() + // Other APIs are unaffected + // Returns old autoindent state. + bool set_autoindent(bool value); + // sizing int position() const { return _position; } julong count() const { return _precount + _position; } @@ -151,6 +154,7 @@ class outputStream : public CHeapObjBase { void put(char ch); void sp(int count = 1); void cr(); + void cr_indent(); void bol() { if (_position > 0) cr(); } @@ -194,29 +198,25 @@ class outputStream : public CHeapObjBase { // ANSI C++ name collision extern outputStream* tty; // tty output -// outputStream indentation. When used, indentation is automatically applied -// when printing on the stream using the following APIs: -// print(), print_cr(), print_raw(), print_raw_cr() -class StreamIndentor { - private: - outputStream* const _stream; - const int _indentation; - const bool _old_autoindent; - NONCOPYABLE(StreamIndentor); - - public: - StreamIndentor(outputStream* os, int indentation) : - _stream(os), - _indentation(indentation), - _old_autoindent(_stream->set_autoindent(true)) { - - _stream->inc(_indentation); +class streamIndentor : public StackObj { + outputStream* const _str; + const int _amount; + NONCOPYABLE(streamIndentor); +public: + streamIndentor(outputStream* str, int amt = 2) : _str(str), _amount(amt) { + _str->inc(_amount); } + ~streamIndentor() { _str->dec(_amount); } +}; - ~StreamIndentor() { - _stream->dec(_indentation); - _stream->set_autoindent(_old_autoindent); - } +class StreamAutoIndentor : public StackObj { + outputStream* const _os; + const bool _old; + NONCOPYABLE(StreamAutoIndentor); + public: + StreamAutoIndentor(outputStream* os) : + _os(os), _old(os->set_autoindent(true)) {} + ~StreamAutoIndentor() { _os->set_autoindent(_old); } }; // advisory locking for the shared tty stream: diff --git a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/permitForbiddenFunctions.hpp b/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/permitForbiddenFunctions.hpp deleted file mode 100644 index 6b9e406bcdee..000000000000 --- a/substratevm/src/com.oracle.svm.native.libcontainer/src/hotspot/share/utilities/permitForbiddenFunctions.hpp +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. 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. - */ - -#ifndef SHARE_UTILITIES_PERMITFORBIDDENFUNCTIONS_HPP -#define SHARE_UTILITIES_PERMITFORBIDDENFUNCTIONS_HPP - -#include "utilities/compilerWarnings.hpp" -#include "utilities/globalDefinitions.hpp" - -#ifndef NATIVE_IMAGE -#ifdef _WINDOWS -#include "permitForbiddenFunctions_windows.hpp" -#else -#include "permitForbiddenFunctions_posix.hpp" -#endif -#endif // !NATIVE_IMAGE - -// Provide wrappers for some functions otherwise forbidden from use in HotSpot. -// -// There may be special circumstances where an otherwise forbidden function -// really does need to be used. One example is in the implementation of a -// corresponding os:: function. -// -// Wrapper functions are provided for such forbidden functions. These -// wrappers are defined in a context where the forbidding warnings are -// suppressed. They are defined in a special namespace, to highlight uses as -// unusual and requiring increased scrutiny. -// -// Note that there are several seemingly plausible shorter alternatives to -// these written-out wrapper functions. All that have been tried don't work -// for one reason or another. - - -namespace svm_container { - -namespace permit_forbidden_function { -BEGIN_ALLOW_FORBIDDEN_FUNCTIONS - -#ifndef NATIVE_IMAGE -[[noreturn]] inline void exit(int status) { ::exit(status); } -[[noreturn]] inline void _exit(int status) { ::_exit(status); } -#endif // !NATIVE_IMAGE - -ATTRIBUTE_PRINTF(3, 0) -inline int vsnprintf(char* str, size_t size, const char* format, va_list ap) { - return ::vsnprintf(str, size, format, ap); -} - -#ifndef NATIVE_IMAGE -inline void* malloc(size_t size) { return ::malloc(size); } -inline void free(void* ptr) { return ::free(ptr); } -inline void* calloc(size_t nmemb, size_t size) { return ::calloc(nmemb, size); } -inline void* realloc(void* ptr, size_t size) { return ::realloc(ptr, size); } - -inline char* strdup(const char* s) { return ::strdup(s); } -#endif // !NATIVE_IMAGE - -END_ALLOW_FORBIDDEN_FUNCTIONS -} // namespace permit_forbidden_function - - -} // namespace svm_container - -#endif // SHARE_UTILITIES_PERMITFORBIDDENFUNCTIONS_HPP From a65654f10b697cf7b1537819ca0999dffcb285f6 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 17:41:48 +0200 Subject: [PATCH 19/49] Revert "[GR-66545] Update labsjdk to 26+4-jvmci-b01." This reverts commit fa4c96285904a7701b4e7bafeb1e86bc6858e656, reversing changes made to 75f6db758b7b6c3530dc15162c5f8313d393bac8. --- common.json | 16 ++++----- .../compiler/hotspot/JVMCIVersionCheck.java | 4 +-- .../meta/HotSpotGraphBuilderPlugins.java | 13 ------- .../meta/UnimplementedGraalIntrinsics.java | 2 ++ .../svm/core/container/ContainerLibrary.java | 20 +++++------ .../heap/Target_java_lang_ref_Reference.java | 6 ---- ...rget_jdk_internal_util_StaticProperty.java | 34 ------------------- 7 files changed, 22 insertions(+), 73 deletions(-) diff --git a/common.json b/common.json index b1c47ca285c4..628c14b011c5 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+4-323", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+2-83", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+4", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+4-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+4-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+3", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 3d3ca5d567fa..a8af38d28ef3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+4", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+4", 1))); + "Oracle Corporation", createLabsJDKVersion("26+3", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+3", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index d684caf4233e..0a3dc1ea60c8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -1800,18 +1800,6 @@ protected boolean useExplicitReachabilityFence(GraphBuilderContext b) { return Options.ForceExplicitReachabilityFence.getValue(b.getOptions()); } }); - r.register(new InlineOnlyInvocationPlugin("get0", Receiver.class) { - @Override - public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { - ValueNode offset = b.add(ConstantNode.forLong(HotSpotReplacementsUtil.referentOffset(b.getMetaAccess()))); - AddressNode address = b.add(new OffsetAddressNode(receiver.get(true), offset)); - FieldLocationIdentity locationIdentity = new FieldLocationIdentity(HotSpotReplacementsUtil.referentField(b.getMetaAccess())); - JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.REFERENCE_GET, MemoryOrderMode.PLAIN, true)); - b.add(new MembarNode(MembarNode.FenceKind.NONE, locationIdentity)); - b.addPush(JavaKind.Object, read); - return true; - } - }); r.register(new InlineOnlyInvocationPlugin("refersTo0", Receiver.class, Object.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver, ValueNode o) { @@ -1819,7 +1807,6 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec AddressNode address = b.add(new OffsetAddressNode(receiver.get(true), offset)); FieldLocationIdentity locationIdentity = new FieldLocationIdentity(HotSpotReplacementsUtil.referentField(b.getMetaAccess())); JavaReadNode read = b.add(new JavaReadNode(StampFactory.object(), JavaKind.Object, address, locationIdentity, BarrierType.WEAK_REFERS_TO, MemoryOrderMode.PLAIN, true)); - b.add(new MembarNode(MembarNode.FenceKind.NONE, locationIdentity)); LogicNode objectEquals = b.add(ObjectEqualsNode.create(b.getConstantReflection(), b.getMetaAccess(), b.getOptions(), read, o, NodeView.DEFAULT)); b.addPush(JavaKind.Boolean, ConditionalNode.create(objectEquals, b.add(forBoolean(true)), b.add(forBoolean(false)), NodeView.DEFAULT)); return true; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index bf9e6698294e..9eb14fa71905 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -130,6 +130,8 @@ public UnimplementedGraalIntrinsics(Architecture arch) { // handled by an intrinsic for StringUTF16.indexOfLatin1Unsafe "java/lang/StringUTF16.indexOfLatin1([BI[BII)I", "java/lang/StringUTF16.indexOfLatin1([B[B)I", + // implemented through lowering + "java/lang/ref/Reference.get()Ljava/lang/Object;", // Relevant for Java flight recorder // [GR-10106] These JFR intrinsics are used for firing socket/file events // via Java instrumentation and are of low priority. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index de197ccd459d..20ba78cc90a6 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -50,17 +50,17 @@ // The following annotations are for files in `src/hotspot`, which are copied from the JDK @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/share/native/include/jni.h") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/java.base/unix/native/include/jni_md.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupSubsystem_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupSubsystem_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/os/linux/cgroupSubsystem_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupSubsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupUtil_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupUtil_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/osContainer_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/os/linux/os_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/osContainer_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/osContainer_linux.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/linux/os_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/posix/include/jvm_md.h") @@ -85,7 +85,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+4/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java index dd49aec700c3..d155b37f2c66 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Target_java_lang_ref_Reference.java @@ -123,12 +123,6 @@ public final class Target_java_lang_ref_Reference { @KeepOriginal native T get(); - @Substitute - @SuppressWarnings("unchecked") - private T get0() { - return (T) ReferenceInternals.getReferent(SubstrateUtil.cast(this, Reference.class)); - } - @KeepOriginal native void clear(); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_util_StaticProperty.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_util_StaticProperty.java index 4b3db5f051e5..bb72eee8511c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_util_StaticProperty.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_jdk_internal_util_StaticProperty.java @@ -96,18 +96,6 @@ final class Target_jdk_internal_util_StaticProperty { @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// private static String JAVA_PROPERTIES_DATE; - @Alias// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// - private static String STDIN_ENCODING; - - @Alias// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// - private static String STDERR_ENCODING; - - @Alias// - @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// - private static String STDOUT_ENCODING; - @Alias// @RecomputeFieldValue(kind = RecomputeFieldValue.Kind.Reset)// private static String SUN_JNU_ENCODING; @@ -205,10 +193,6 @@ final class Target_jdk_internal_util_StaticProperty { NATIVE_ENCODING = p.getInitialProperty("native.encoding"); FILE_ENCODING = p.getInitialProperty("file.encoding"); JAVA_PROPERTIES_DATE = p.getInitialProperty("java.properties.date"); - STDIN_ENCODING = p.getInitialProperty("stdin.encoding"); - STDERR_ENCODING = p.getInitialProperty("stderr.encoding"); - STDOUT_ENCODING = p.getInitialProperty("stdout.encoding"); - SUN_JNU_ENCODING = p.getInitialProperty("sun.jnu.encoding"); JAVA_LOCALE_USE_OLD_ISO_CODES = p.getInitialProperty("java.locale.useOldISOCodes", ""); @@ -313,24 +297,6 @@ public static String javaPropertiesDate() { return JAVA_PROPERTIES_DATE; } - @Substitute - public static String stdinEncoding() { - assert Objects.equals(STDIN_ENCODING, SystemPropertiesSupport.singleton().getInitialProperty("stdin.encoding")); - return STDIN_ENCODING; - } - - @Substitute - public static String stdoutEncoding() { - assert Objects.equals(STDOUT_ENCODING, SystemPropertiesSupport.singleton().getInitialProperty("stdout.encoding")); - return STDOUT_ENCODING; - } - - @Substitute - public static String stderrEncoding() { - assert Objects.equals(STDERR_ENCODING, SystemPropertiesSupport.singleton().getInitialProperty("stderr.encoding")); - return STDERR_ENCODING; - } - @Substitute public static String jnuEncoding() { assert Objects.equals(SUN_JNU_ENCODING, SystemPropertiesSupport.singleton().getInitialProperty("sun.jnu.encoding")); From 59f6ea8dac1ad24d7718f600e814fc85814d8ce2 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Tue, 16 Sep 2025 18:09:25 +0200 Subject: [PATCH 20/49] Revert "[GR-66295] Update labsjdk to 26+3-jvmci-b01." This reverts commit c28e6a53c088908c3e83cc789dddd1913409427d, reversing changes made to 5724d5d08547d5ba64ba31c09b03616bc2d276be. --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../svm/core/container/ContainerLibrary.java | 4 ++-- .../core/jdk/Target_java_nio_DirectByteBuffer.java | 2 +- .../oracle/svm/hosted/foreign/DowncallStub.java | 2 +- .../oracle/svm/hosted/SecurityServicesFeature.java | 8 -------- .../tck/resources/jdk_privileged_methods.json | 7 +++++++ 7 files changed, 20 insertions(+), 21 deletions(-) diff --git a/common.json b/common.json index 628c14b011c5..6ca082aba80c 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+3", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+3-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+3-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+2", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index a8af38d28ef3..0f0d6475435a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+3", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+3", 1))); + "Oracle Corporation", createLabsJDKVersion("26+2", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+2", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 20ba78cc90a6..5ec23ba56353 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -85,8 +85,8 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/runtime/globals.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/share/utilities/debug.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { static final int VERSION = 240100; 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 d9be85aedfc8..62efa2660aa9 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 @@ -34,7 +34,7 @@ import com.oracle.svm.core.util.VMError; @TargetClass(className = "java.nio.DirectByteBuffer") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+26/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template") public final class Target_java_nio_DirectByteBuffer { /** diff --git a/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/DowncallStub.java b/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/DowncallStub.java index 1a6fafecbf1d..84b5024c0da2 100644 --- a/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/DowncallStub.java +++ b/substratevm/src/com.oracle.svm.hosted.foreign/src/com/oracle/svm/hosted/foreign/DowncallStub.java @@ -87,7 +87,7 @@ @SuppressWarnings("javadoc") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+7/src/hotspot/share/prims/nativeEntryPoint.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+3/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+17/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp") class DowncallStub extends NonBytecodeMethod { public static Signature createSignature(MetaAccessProvider metaAccess) { return ResolvedSignature.fromKinds(new JavaKind[]{JavaKind.Object}, JavaKind.Object, metaAccess); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java index 4795070b4872..3ff424c9a901 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SecurityServicesFeature.java @@ -301,14 +301,6 @@ public void duringSetup(DuringSetupAccess a) { rci.initializeAtRunTime(NativePRNG.Blocking.class, "for substitutions"); rci.initializeAtRunTime(NativePRNG.NonBlocking.class, "for substitutions"); - /* - * The following classes will pull a SecureRandom instance into the image heap, so we need - * to explicitly move them to a run time. - */ - rci.initializeAtRunTime(clazz(access, "com.sun.security.sasl.CramMD5Server"), "for substitutions"); - rci.initializeAtRunTime(clazz(access, "com.sun.security.sasl.digest.DigestMD5Base"), "for substitutions"); - rci.initializeAtRunTime(clazz(access, "com.sun.security.sasl.digest.DigestMD5Client"), "for substitutions"); - rci.initializeAtRunTime(clazz(access, "sun.security.provider.SeedGenerator"), "for substitutions"); rci.initializeAtRunTime(clazz(access, "sun.security.provider.SecureRandom$SeederHolder"), "for substitutions"); diff --git a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json index dd990fc9e451..78332d3abd36 100644 --- a/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json +++ b/substratevm/src/com.oracle.svm.truffle.tck/src/com/oracle/svm/truffle/tck/resources/jdk_privileged_methods.json @@ -1072,6 +1072,13 @@ "parameterTypes": [ "java.net.DatagramPacket" ] + }, + { + "name": "send", + "parameterTypes": [ + "java.net.DatagramPacket", + "byte" + ] } ] }, From 09d26df3e7873c761faceaeab2fd5b7169f7ef12 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 10:04:54 +0200 Subject: [PATCH 21/49] Revert "[GR-65949] Update labsjdk to 26+2-jvmci-b01" This reverts commit c56e44ba0512cfbfaf8779658a48ad510ca98173, reversing changes made to c8ea2a4dfffabe683a561b69417f511e5eb2572b. --- common.json | 16 ++--- .../compiler/hotspot/JVMCIVersionCheck.java | 4 +- .../genscavenge/AbstractCollectionPolicy.java | 2 +- .../linux/LinuxThreadCpuTimeSupport.java | 2 +- .../posix/thread/PosixPlatformThreads.java | 4 +- .../svm/core/container/ContainerLibrary.java | 4 +- .../svm/core/jdk/SunMiscSubstitutions.java | 9 +++ ...ContentSubstitutedLocalizationSupport.java | 5 +- .../utils/BundleSerializationUtils.java | 9 +-- ...stResourceBundle_SubstituteLoadLookup.java | 21 ++++-- ...stResourceBundle_SubstituteLoadLookup.java | 66 +++++++++++++++++++ .../core/jvmti/headers/JvmtiDirectives.java | 2 +- .../jdk/localization/LocalizationFeature.java | 34 ++++++++-- web-image/mx.web-image/suite.py | 6 +- .../ResetStableSupplierTransformer.java | 53 --------------- .../svm/hosted/webimage/WebImageFeature.java | 35 ++++++++-- 16 files changed, 168 insertions(+), 104 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_ParallelListResourceBundle_SubstituteLoadLookup.java delete mode 100644 web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/ResetStableSupplierTransformer.java diff --git a/common.json b/common.json index 6ca082aba80c..1db4ba3234c9 100644 --- a/common.json +++ b/common.json @@ -8,7 +8,7 @@ "COMMENT.jdks": "When adding or removing JDKs keep in sync with JDKs in ci/common.jsonnet", "jdks": { - "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+2-83", "platformspecific": true, "extrabundles": ["static-libs"]}, + "galahad-jdk": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+26-3319", "platformspecific": true, "extrabundles": ["static-libs"]}, "oraclejdk17": {"name": "jpg-jdk", "version": "17.0.7", "build_id": "jdk-17.0.7+8", "platformspecific": true, "extrabundles": ["static-libs"]}, "labsjdk-ce-17": {"name": "labsjdk", "version": "ce-17.0.7+4-jvmci-23.1-b02", "platformspecific": true }, @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "26", "build_id": "jdk-26+2", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+2-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+2-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+1", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 0f0d6475435a..5876dfdfc511 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -57,8 +57,8 @@ public final class JVMCIVersionCheck { // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+2", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+2", 1))); + "Oracle Corporation", createLabsJDKVersion("26+1", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+1", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index f9ed146f73f2..fd8670301112 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -338,7 +338,7 @@ public final UnsignedWord getMinimumHeapSize() { @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected abstract long gcCount(); - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/share/gc/shared/genArguments.cpp#L190-L305") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/gc/shared/genArguments.cpp#L195-L310") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/gc/parallel/psYoungGen.cpp#L146-L168") protected SizeParameters computeSizeParameters(SizeParameters existing) { UnsignedWord minYoungSpaces = minSpaceSize(); // eden diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxThreadCpuTimeSupport.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxThreadCpuTimeSupport.java index 61ae2862e5f4..57f89137b123 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxThreadCpuTimeSupport.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxThreadCpuTimeSupport.java @@ -66,7 +66,7 @@ public long getThreadCpuTime(IsolateThread isolateThread, boolean includeSystemT return fastCpuTime(pthread); } - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/linux/os_linux.cpp#L4939-L4951") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23+10/src/hotspot/os/linux/os_linux.cpp#L5113-L5125") @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static long fastCpuTime(pthread_t pthread) { CIntPointer threadsClockId = StackValue.get(Integer.BYTES); 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 f9aa6d29e1f7..80dca1fbd70f 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 @@ -354,7 +354,7 @@ protected void park(boolean isAbsolute, long time) { } } - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/posix/os_posix.cpp#L1830-L1906") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23+10/src/hotspot/os/posix/os_posix.cpp#L1662-L1738") private void park0(boolean isAbsolute, long time) { int status = Pthread.pthread_mutex_trylock_no_transition(mutex); if (status == Errno.EBUSY()) { @@ -393,7 +393,7 @@ private void park0(boolean isAbsolute, long time) { } @Override - @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/posix/os_posix.cpp#L1908-L1931") + @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23+10/src/hotspot/os/posix/os_posix.cpp#L1740-L1763") protected void unpark() { StackOverflowCheck.singleton().makeYellowZoneAvailable(); try { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index 5ec23ba56353..ed94d74945f2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -60,11 +60,11 @@ @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/osContainer_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/osContainer_linux.hpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/linux/os_linux.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/os/linux/os_linux.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/linux/os_linux.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/posix/include/jvm_md.h") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/os/posix/os_posix.cpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/os/posix/os_posix.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+25/src/hotspot/os/posix/os_posix.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/os/posix/os_posix.inline.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.hpp") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java index 709bebde4abf..9a2a6d699a6e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/SunMiscSubstitutions.java @@ -198,6 +198,11 @@ private Class defineClass0(String name, byte[] b, int off, int len, ClassLoad @TargetClass(jdk.internal.access.SharedSecrets.class) final class Target_jdk_internal_access_SharedSecrets { + @Substitute + private static Target_jdk_internal_access_JavaAWTAccess getJavaAWTAccess() { + return null; + } + /** * The JavaIOAccess implementation installed by the class initializer of java.io.Console * captures state like "is a tty". The only way to remove such state is by resetting the field. @@ -210,6 +215,10 @@ final class Target_jdk_internal_access_SharedSecrets { final class Target_jdk_internal_access_JavaIOAccess { } +@TargetClass(jdk.internal.access.JavaAWTAccess.class) +final class Target_jdk_internal_access_JavaAWTAccess { +} + @TargetClass(className = "sun.reflect.misc.MethodUtil") final class Target_sun_reflect_misc_MethodUtil { @Substitute diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java index 50771070fec5..42f2ed2c9dff 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/BundleContentSubstitutedLocalizationSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. * 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.debug.GraalError; import sun.util.resources.OpenListResourceBundle; +import sun.util.resources.ParallelListResourceBundle; /** * This version of LocalizationSupport stores the content of resource bundles in a map to make the @@ -150,7 +151,7 @@ private static boolean isBundleSupported(ResourceBundle bundle) { @Platforms(Platform.HOSTED_ONLY.class) public static boolean isBundleSupported(Class bundleClass) { - return ListResourceBundle.class.isAssignableFrom(bundleClass) || OpenListResourceBundle.class.isAssignableFrom(bundleClass); + return ListResourceBundle.class.isAssignableFrom(bundleClass) || OpenListResourceBundle.class.isAssignableFrom(bundleClass) || ParallelListResourceBundle.class.isAssignableFrom(bundleClass); } @Platforms(Platform.HOSTED_ONLY.class) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/compression/utils/BundleSerializationUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/compression/utils/BundleSerializationUtils.java index 1c2f90686167..17469fae477e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/compression/utils/BundleSerializationUtils.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/compression/utils/BundleSerializationUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.util.List; import java.util.Map; import java.util.ResourceBundle; -import java.util.function.Supplier; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -60,11 +59,7 @@ public static Map extractContent(ResourceBundle bundle) { Class clazz = bundle.getClass().getSuperclass(); while (clazz != null && ResourceBundle.class.isAssignableFrom(clazz)) { try { - Object lookup = ReflectionUtil.lookupField(clazz, "lookup").get(bundle); - if (lookup instanceof Supplier) { - return ((Supplier>) lookup).get(); - } - return (Map) lookup; + return (Map) ReflectionUtil.lookupField(clazz, "lookup").get(bundle); } catch (ReflectionUtil.ReflectionUtilError | ReflectiveOperationException e) { clazz = clazz.getSuperclass(); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_OpenListResourceBundle_SubstituteLoadLookup.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_OpenListResourceBundle_SubstituteLoadLookup.java index f6e1fefc0e06..7ca2a208241b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_OpenListResourceBundle_SubstituteLoadLookup.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_OpenListResourceBundle_SubstituteLoadLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,13 +38,20 @@ @SuppressWarnings({"static-method"}) final class Target_sun_util_resources_OpenListResourceBundle_SubstituteLoadLookup { + @Alias private volatile Map lookup; + @Substitute - private Map lookup0() { - Map preloadedContent = ImageSingletons.lookup(LocalizationSupport.class).getBundleContentOf(this); - /* Use the type of map provided by the subclass. */ - Map map = createMap(preloadedContent.size()); - map.putAll(preloadedContent); - return map; + private void loadLookup() { + LocalizationSupport support = ImageSingletons.lookup(LocalizationSupport.class); + Map content = support.getBundleContentOf(this); + // use the supplied map implementation specified by the factory method + Map tmp = createMap(content.size()); + tmp.putAll(content); + synchronized (this) { + if (lookup == null) { + lookup = content; + } + } } @Alias diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_ParallelListResourceBundle_SubstituteLoadLookup.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_ParallelListResourceBundle_SubstituteLoadLookup.java new file mode 100644 index 000000000000..ea49b2811ab9 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/localization/substitutions/Target_sun_util_resources_ParallelListResourceBundle_SubstituteLoadLookup.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, 2021, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.jdk.localization.substitutions; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import org.graalvm.nativeimage.ImageSingletons; + +import com.oracle.svm.core.annotate.Alias; +import com.oracle.svm.core.annotate.Substitute; +import com.oracle.svm.core.annotate.TargetClass; +import com.oracle.svm.core.jdk.localization.LocalizationSupport; +import com.oracle.svm.core.jdk.localization.substitutions.modes.SubstituteLoadLookup; +import com.oracle.svm.core.util.VMError; + +import sun.util.resources.OpenListResourceBundle; + +@TargetClass(value = sun.util.resources.ParallelListResourceBundle.class, onlyWith = SubstituteLoadLookup.class) +@SuppressWarnings({"unused", "static-method"}) +final class Target_sun_util_resources_ParallelListResourceBundle_SubstituteLoadLookup { + + @Alias private ConcurrentMap lookup; + + @Substitute + private void setParallelContents(OpenListResourceBundle rb) { + throw VMError.unsupportedFeature("Resource bundle lookup must be loaded during native image generation: " + getClass().getTypeName()); + } + + @Substitute + private boolean areParallelContentsComplete() { + return true; + } + + @Substitute + private void loadLookupTablesIfNecessary() { + LocalizationSupport support = ImageSingletons.lookup(LocalizationSupport.class); + synchronized (this) { + if (lookup == null) { + lookup = new ConcurrentHashMap<>(support.getBundleContentOf(this)); + } + } + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java index f494545fc624..59b62437b21a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jvmti/headers/JvmtiDirectives.java @@ -35,7 +35,7 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.util.BasedOnJDKFile; -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-26+2/src/hotspot/share/prims/jvmti.xml") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+23/src/hotspot/share/prims/jvmti.xml") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-24+11/src/hotspot/share/prims/jvmtiH.xsl") class JvmtiDirectives implements CContext.Directives { private final Path jdkIncludeDir = Paths.get(System.getProperty("java.home")).resolve("include"); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java index 504587e5a921..6f42f5ffac85 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/localization/LocalizationFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -103,6 +103,7 @@ import sun.util.locale.provider.LocaleProviderAdapter; import sun.util.locale.provider.ResourceBundleBasedAdapter; import sun.util.resources.LocaleData; +import sun.util.resources.ParallelListResourceBundle; import sun.util.spi.CalendarProvider; /** @@ -163,6 +164,7 @@ public class LocalizationFeature implements InternalFeature { private Field baseLocaleCacheField; private Field localeCacheField; private Field candidatesCacheField; + private Field localeObjectCacheMapField; private Field langAliasesCacheField; private Field parentLocalesMapField; @Platforms(Platform.HOSTED_ONLY.class) private ImageClassLoader imageClassLoader; @@ -292,9 +294,10 @@ public void duringSetup(DuringSetupAccess a) { } langAliasesCacheField = access.findField(CLDRLocaleProviderAdapter.class, "langAliasesCache"); parentLocalesMapField = access.findField(CLDRLocaleProviderAdapter.class, "parentLocalesMap"); + baseLocaleCacheField = access.findField("sun.util.locale.BaseLocale$1InterningCache", "CACHE"); + localeCacheField = access.findField("java.util.Locale$LocaleCache", "LOCALE_CACHE"); + localeObjectCacheMapField = null; candidatesCacheField = access.findField("java.util.ResourceBundle$Control", "CANDIDATES_CACHE"); - baseLocaleCacheField = access.findField("sun.util.locale.BaseLocale", "CACHE"); - localeCacheField = access.findField("java.util.Locale", "LOCALE_CACHE"); String reason = "All ResourceBundleControlProvider that are registered as services end up as objects in the image heap, and are therefore registered to be initialized at image build time"; ServiceLoader.load(ResourceBundleControlProvider.class).stream() @@ -345,14 +348,27 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { @Override public void duringAnalysis(DuringAnalysisAccess a) { DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a; - - access.rescanRoot(baseLocaleCacheField); - access.rescanRoot(localeCacheField); - access.rescanRoot(candidatesCacheField); + scanLocaleCache(access, baseLocaleCacheField); + scanLocaleCache(access, localeCacheField); + scanLocaleCache(access, candidatesCacheField); access.rescanRoot(langAliasesCacheField); access.rescanRoot(parentLocalesMapField); } + private void scanLocaleCache(DuringAnalysisAccessImpl access, Field cacheFieldField) { + access.rescanRoot(cacheFieldField); + + Object localeCache; + try { + localeCache = cacheFieldField.get(null); + } catch (ReflectiveOperationException ex) { + throw VMError.shouldNotReachHere(ex); + } + if (localeCache != null && localeObjectCacheMapField != null) { + access.rescanField(localeCache, localeObjectCacheMapField); + } + } + @Platforms(Platform.HOSTED_ONLY.class) private static Set processLocalesOption() { Set locales = new HashSet<>(); @@ -494,6 +510,10 @@ protected void addResourceBundles() { prepareNegativeBundle(ConfigurationCondition.alwaysTrue(), baseName, locale, true); continue; /* No bundle for this `locale`. */ } + if (bundle instanceof ParallelListResourceBundle) { + /* Make sure the `bundle` content is complete. */ + localeData.setSupplementary((ParallelListResourceBundle) bundle); + } prepareJDKBundle(bundle, locale); } } diff --git a/web-image/mx.web-image/suite.py b/web-image/mx.web-image/suite.py index e6d4dd6e5ef3..f8baadbc0029 100644 --- a/web-image/mx.web-image/suite.py +++ b/web-image/mx.web-image/suite.py @@ -186,11 +186,7 @@ "java.compiler", ], "requiresConcealed": { - "java.base": [ - "sun.nio.ch", - "sun.security.provider", - "jdk.internal.reflect", - ], + "java.base": ["sun.nio.ch", "sun.security.provider", "jdk.internal.reflect"], "jdk.internal.vm.ci": ["jdk.vm.ci.code.site", "jdk.vm.ci.code", "jdk.vm.ci.common", "jdk.vm.ci.meta"], }, "javaCompliance": "21+", diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/ResetStableSupplierTransformer.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/ResetStableSupplierTransformer.java deleted file mode 100644 index 71c027d459cc..000000000000 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/ResetStableSupplierTransformer.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.oracle.svm.hosted.webimage; - -import java.lang.reflect.Method; -import java.util.function.Supplier; - -import org.graalvm.nativeimage.hosted.FieldValueTransformer; - -import com.oracle.svm.util.ReflectionUtil; - -/** - * Field value transformer that creates a new StableSupplier with the same {@link Supplier} as the - * original that was not initialized yet. - *

- * This can be used to reset caches that are based on stable value suppliers. - *

- * Uses reflection because StableSupplier is from JDK25 and proguard does not yet support class - * files from that version. - */ -public final class ResetStableSupplierTransformer implements FieldValueTransformer { - @Override - public Object transform(Object receiver, Object originalValue) { - Class stableSupplierClass = ReflectionUtil.lookupClass("jdk.internal.lang.stable.StableSupplier"); - Method stableSupplierOf = ReflectionUtil.lookupMethod(stableSupplierClass, "of", Supplier.class); - Method stableSupplierOriginal = ReflectionUtil.lookupMethod(stableSupplierClass, "original"); - Object originalSupplier = ReflectionUtil.invokeMethod(stableSupplierOriginal, originalValue); - return ReflectionUtil.invokeMethod(stableSupplierOf, null, originalSupplier); - } -} diff --git a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java index 2e68e92a761e..b3d6b0fe820a 100644 --- a/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java +++ b/web-image/src/com.oracle.svm.hosted.webimage/src/com/oracle/svm/hosted/webimage/WebImageFeature.java @@ -35,6 +35,7 @@ import java.util.List; import java.util.Map; import java.util.function.Predicate; +import java.util.function.Supplier; import org.graalvm.nativeimage.AnnotationAccess; import org.graalvm.nativeimage.ImageSingletons; @@ -189,12 +190,35 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { * * These caches can contribute ~1MB to the image size, clearing them avoids this overhead at * the cost of having to recreate the Locale and BaseLocale objects once when they're - * requested at run-time. + * requested. + * + * On JDK21, ReferencedKeySet and ReferencedKeyMap don't exist. We have to go through + * reflection to access them because analysis tools like spotbugs still run on JDK21 */ - Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale", "CACHE"); - Field localeCacheField = accessImpl.findField("java.util.Locale", "LOCALE_CACHE"); - access.registerFieldValueTransformer(baseLocaleCacheField, new ResetStableSupplierTransformer()); - access.registerFieldValueTransformer(localeCacheField, new ResetStableSupplierTransformer()); + Field baseLocaleCacheField = accessImpl.findField("sun.util.locale.BaseLocale$1InterningCache", "CACHE"); + Field localeCacheField = accessImpl.findField("java.util.Locale$LocaleCache", "LOCALE_CACHE"); + + access.registerFieldValueTransformer(baseLocaleCacheField, (receiver, originalValue) -> { + /* + * Executes `ReferencedKeySet.create(true, + * ReferencedKeySet.concurrentHashMapSupplier())` with reflection. + */ + Class referencedKeySetClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeySet"); + Method createMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "create", boolean.class, Supplier.class); + Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeySetClazz, "concurrentHashMapSupplier"); + return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); + }); + + access.registerFieldValueTransformer(localeCacheField, (receiver, originalValue) -> { + /* + * Executes `ReferencedKeyMap.create(true, + * ReferencedKeyMap.concurrentHashMapSupplier())` with reflection. + */ + Class referencedKeyMapClazz = ReflectionUtil.lookupClass("jdk.internal.util.ReferencedKeyMap"); + Method createMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "create", boolean.class, Supplier.class); + Method concurrentHashMapSupplierMethod = ReflectionUtil.lookupMethod(referencedKeyMapClazz, "concurrentHashMapSupplier"); + return ReflectionUtil.invokeMethod(createMethod, null, true, ReflectionUtil.invokeMethod(concurrentHashMapSupplierMethod, null)); + }); } @Override @@ -319,5 +343,4 @@ private boolean neverInlineTrivial(@SuppressWarnings("unused") AnalysisMethod ca */ return AnnotationAccess.isAnnotationPresent(callee, JS.class); } - } From b96f038057bd4fe52200ba2b77bcaa6bab132054 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 10:46:41 +0200 Subject: [PATCH 22/49] Revert "[GR-65668] Update labsjdk to 26+1-jvmci-b01" This reverts commit afeb9001e485779697122adbddbce521732d9140, reversing changes made to 80dfcb873900c30878d49c247c37d9f98e153282. --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/common.json b/common.json index 1db4ba3234c9..bd90e0e617cf 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-26+1", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-26+1-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-26+1-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+26", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 5876dfdfc511..cb50f8c7daf3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,16 +56,16 @@ public final class JVMCIVersionCheck { */ // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( - "26", Map.of( - "Oracle Corporation", createLabsJDKVersion("26+1", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("26+1", 1))); + "25", Map.of( + "Oracle Corporation", createLabsJDKVersion("25+26", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+26", 1))); // Checkstyle: resume stable iteration order check private static final int NA = 0; /** * Minimum Java release supported by Graal. */ - private static final int JAVA_MIN_RELEASE = 26; + private static final int JAVA_MIN_RELEASE = 25; /** * Convenience factory for the current version scheme that only uses the JDK version and the From 85f17041927fb1c414846ab05a4ebfc1b05ce649 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 11:28:15 +0200 Subject: [PATCH 23/49] Temporarily avoid JVMCIVersionCheck merge conflicts --- .../jdk.graal.compiler/.checkstyle_checks.xml | 54 ------------------- .../compiler/hotspot/JVMCIVersionCheck.java | 3 -- 2 files changed, 57 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml b/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml index 7e2167d31d1f..debd56a1ed03 100644 --- a/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml +++ b/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml @@ -141,24 +141,6 @@ - - - - - - - - - - - - - - - - - - @@ -195,42 +177,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index cb50f8c7daf3..cbcb489413fe 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -54,13 +54,10 @@ public final class JVMCIVersionCheck { * to {@code java.vm.vendor} to {@link Version}. {@link #DEFAULT_VENDOR_ENTRY} can be used as a * default/fallback entry. */ - // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( "Oracle Corporation", createLabsJDKVersion("25+26", 1), DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+26", 1))); - // Checkstyle: resume stable iteration order check - private static final int NA = 0; /** * Minimum Java release supported by Graal. From 3e6315fba95370a995fa805ece819053500a997d Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Fri, 4 Jul 2025 16:52:59 +0000 Subject: [PATCH 24/49] [GR-65959] Update labsjdk to 25+27-jvmci-b01. PullRequest: graal/21151 (cherry picked from commit d5d32c3256dfaa701dfde2160a2538639aca75e4) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index bd90e0e617cf..b030404e216b 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+26", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+26-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+26-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+27", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index cbcb489413fe..f1d734379bd5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+26", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+26", 1))); + "Oracle Corporation", createLabsJDKVersion("25+27", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+27", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From afb8e3c2396f3ba8d35bfc2db4820954aac51b84 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Wed, 16 Jul 2025 18:01:07 +0000 Subject: [PATCH 25/49] [GR-67254] Update labsjdk to 25+30-jvmci-b01 PullRequest: graal/21393 (cherry picked from commit a6efb7840ebcf6772899b6c3e835055e8acbae6f) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../svm/core/container/ContainerLibrary.java | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/common.json b/common.json index b030404e216b..f9c169e6ad00 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+27", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+27-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+27-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+30", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index f1d734379bd5..44810429c4ae 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+27", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+27", 1))); + "Oracle Corporation", createLabsJDKVersion("25+30", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+30", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java index ed94d74945f2..a05f1b4ebded 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/container/ContainerLibrary.java @@ -85,7 +85,7 @@ // The following annotations are for files in `src/svm`, which are completely customized for SVM @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/logging/log.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/memory/allocation.cpp") -@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+26/src/hotspot/share/runtime/globals.hpp") +@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+30/src/hotspot/share/runtime/globals.hpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+21/src/hotspot/share/utilities/debug.cpp") @BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-25+18/src/hotspot/share/utilities/debug.hpp") public class ContainerLibrary { From 1eb9715618f9b54039b7e8900e24f60a92807cfc Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 12:48:36 +0200 Subject: [PATCH 26/49] Temporarily disable HostInliningTest#testInliningRoot --- .../src/jdk/graal/compiler/truffle/test/HostInliningTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 291d23c22667..7412f023738b 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 @@ -151,7 +151,8 @@ public void test() { runTest("testImplicitCast"); runTest("testNativeCall"); runTest("testBCDSLPrologIfVersion"); - runTest("testInliningRoot"); + // temporarily disabled + // runTest("testInliningRoot"); } /* From 3f1fea1ad32547b55ad3bd1618d02a4f69939aca Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Tue, 22 Jul 2025 17:20:43 +0000 Subject: [PATCH 27/49] [GR-67650] [GR-67735] [GR-67811] Update labsjdk to 25+32-jvmci-b01 PullRequest: graal/21514 (cherry picked from commit 408894052866a9ae495e0a7de491c719232998a7) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- .../com/oracle/truffle/espresso/impl/Method.java | 4 ++-- .../svm/core/jfr/Target_jdk_jfr_internal_JVM.java | 10 ++++++++-- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/common.json b/common.json index f9c169e6ad00..0b37fbbd8380 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+30", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+30-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+32", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 44810429c4ae..8a592dc3c4b6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+30", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+30", 1))); + "Oracle Corporation", createLabsJDKVersion("25+32", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+32", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. diff --git a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java index 3091c81ac2a9..d48f20790087 100644 --- a/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java +++ b/espresso/src/com.oracle.truffle.espresso/src/com/oracle/truffle/espresso/impl/Method.java @@ -1961,10 +1961,10 @@ private EspressoException unsatisfiedLinkError() { private void checkPoisonPill(Meta meta) { if (poisonPill) { // Conflicting Maximally-specific non-abstract interface methods. - if (getJavaVersion().java9OrLater() && getSpecComplianceMode() == EspressoOptions.SpecComplianceMode.HOTSPOT) { + if (getJavaVersion().inRange(9, 24) && getSpecComplianceMode() == EspressoOptions.SpecComplianceMode.HOTSPOT) { /* * Supposed to be IncompatibleClassChangeError (see jvms-6.5.invokeinterface), - * but HotSpot throws AbstractMethodError. + * but HotSpot throws AbstractMethodError. See JDK-8356942. */ throw meta.throwExceptionWithMessage(meta.java_lang_AbstractMethodError, "Conflicting default methods: " + getName()); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java index 3b4d065267f9..2f66a5ed11f1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/Target_jdk_jfr_internal_JVM.java @@ -296,9 +296,15 @@ public static void setMethodSamplingPeriod(long type, long intervalMillis) { SubstrateJVM.get().setMethodSamplingInterval(type, intervalMillis); } - /** See {@code JVM#setCPUThrottle}. */ + /** See {@code JVM#setCPURate}. */ @Substitute - public static void setCPUThrottle(double rate, boolean autoAdapt) { + public static void setCPURate(double rate) { + // JFR CPUTimeSample is not supported. + } + + /** See {@code JVM#setCPUPeriod}. */ + @Substitute + public static void setCPUPeriod(long periodNanos) { // JFR CPUTimeSample is not supported. } From 7adf2a88e4ba22eb53a9d3f2f11ae578478bb1e2 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Wed, 30 Jul 2025 13:58:16 +0000 Subject: [PATCH 28/49] [GR-68054] Update labsjdk to 25+33-jvmci-b01 PullRequest: graal/21669 (cherry picked from commit d3c1067279727863f357154a4e8a98fb0fea4ac1) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index 0b37fbbd8380..9d2dbaaba9be 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+32", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+32-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+32-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+33", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 8a592dc3c4b6..e9f4be3e633f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+32", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+32", 1))); + "Oracle Corporation", createLabsJDKVersion("25+33", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+33", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From 4514108e5d47c1a10664076f111e35a214fc61a0 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Wed, 6 Aug 2025 16:40:01 +0000 Subject: [PATCH 29/49] [GR-68381] Update labsjdk to 25+34-jvmci-b01 PullRequest: graal/21755 (cherry picked from commit a35cb697a98edd3baef7be928e06630deb152c50) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index 9d2dbaaba9be..1410694ca703 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+33", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+33-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+33-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+34", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index e9f4be3e633f..408a5f7abe3d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+33", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+33", 1))); + "Oracle Corporation", createLabsJDKVersion("25+34", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+34", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From c7ac9162bf3d71c24db230da7b8a34755300f3f5 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Wed, 13 Aug 2025 18:10:19 +0000 Subject: [PATCH 30/49] [GR-68674] Update labsjdk to 25+35-jvmci-b01 PullRequest: graal/21822 (cherry picked from commit e66918b3ee1bb4a08b061b89368df056544a0ba0) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index 1410694ca703..ae0f4f126527 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+34", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+34-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+34-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+35", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 408a5f7abe3d..160097636543 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+34", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+34", 1))); + "Oracle Corporation", createLabsJDKVersion("25+35", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+35", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From 7b50348f4a9c2e25943d0617407b329b54e468c6 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Tue, 19 Aug 2025 15:14:31 +0000 Subject: [PATCH 31/49] [GR-68869] Update labsjdk to 25+36-jvmci-b01 PullRequest: graal/21899 (cherry picked from commit 004a60a914a300195ac9959b07afc87bb7629685) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index ae0f4f126527..99a1032f592c 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+35", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+35-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+35-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+36", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 160097636543..0c8d07cef1a9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+35", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+35", 1))); + "Oracle Corporation", createLabsJDKVersion("25+36", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+36", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From ed6e1a70a163eff8cd38f9fa4df3bec6f09845a3 Mon Sep 17 00:00:00 2001 From: ol-automation_ww Date: Mon, 1 Sep 2025 18:52:07 +0000 Subject: [PATCH 32/49] [GR-69263] Update labsjdk to 25+37-jvmci-b01 PullRequest: graal/22019 (cherry picked from commit cb9d29e7774666c950ffd7da85faaeb23fc3558c) --- common.json | 14 +++++++------- .../graal/compiler/hotspot/JVMCIVersionCheck.java | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/common.json b/common.json index 99a1032f592c..2cb80913430f 100644 --- a/common.json +++ b/common.json @@ -54,13 +54,13 @@ "labsjdk-ee-25-llvm": {"name": "labsjdk", "version": "ee-25+30-jvmci-b01-sulong", "platformspecific": true }, "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, - "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+36", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+36-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+36-jvmci-b01-sulong", "platformspecific": true } + "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+37", "platformspecific": true, "extrabundles": ["static-libs"]}, + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01-sulong", "platformspecific": true } }, "eclipse": { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index 0c8d07cef1a9..d1166bc51d02 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -56,8 +56,8 @@ public final class JVMCIVersionCheck { */ private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( - "Oracle Corporation", createLabsJDKVersion("25+36", 1), - DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+36", 1))); + "Oracle Corporation", createLabsJDKVersion("25+37", 1), + DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+37", 1))); private static final int NA = 0; /** * Minimum Java release supported by Graal. From 1606ea892222b35a343cd1287d32c35a7eaac556 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 13:10:22 +0200 Subject: [PATCH 33/49] Revert "Temporarily avoid JVMCIVersionCheck merge conflicts" This reverts commit 85f17041927fb1c414846ab05a4ebfc1b05ce649. --- .../jdk.graal.compiler/.checkstyle_checks.xml | 54 +++++++++++++++++++ .../compiler/hotspot/JVMCIVersionCheck.java | 3 ++ 2 files changed, 57 insertions(+) diff --git a/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml b/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml index debd56a1ed03..7e2167d31d1f 100644 --- a/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml +++ b/compiler/src/jdk.graal.compiler/.checkstyle_checks.xml @@ -141,6 +141,24 @@ + + + + + + + + + + + + + + + + + + @@ -177,6 +195,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java index d1166bc51d02..b23b591a3273 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/JVMCIVersionCheck.java @@ -54,10 +54,13 @@ public final class JVMCIVersionCheck { * to {@code java.vm.vendor} to {@link Version}. {@link #DEFAULT_VENDOR_ENTRY} can be used as a * default/fallback entry. */ + // Checkstyle: stop stable iteration order check private static final Map> JVMCI_MIN_VERSIONS = Map.of( "25", Map.of( "Oracle Corporation", createLabsJDKVersion("25+37", 1), DEFAULT_VENDOR_ENTRY, createLabsJDKVersion("25+37", 1))); + // Checkstyle: resume stable iteration order check + private static final int NA = 0; /** * Minimum Java release supported by Graal. From ba2e1eadd4397d643e76a8b7f4eb045f9ef292db Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:12:45 +0200 Subject: [PATCH 34/49] Temporarily disable strict JVMCI version check in the CI --- compiler/ci/ci_common/gate.jsonnet | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/ci/ci_common/gate.jsonnet b/compiler/ci/ci_common/gate.jsonnet index 5e6d6b03561c..63ada50c1f9a 100644 --- a/compiler/ci/ci_common/gate.jsonnet +++ b/compiler/ci/ci_common/gate.jsonnet @@ -550,7 +550,8 @@ local style_builds = [self.make_build(self.jdk_latest, "linux-amd64", "style").build + { environment+: { # Run the strict JVMCI version check, i.e., that JVMCIVersionCheck.JVMCI_MIN_VERSION matches the versions in common.json. - JVMCI_VERSION_CHECK: "strict", + # temporarily disable until labsjdk-ce|ee-25 is gone from common.json + # JVMCI_VERSION_CHECK: "strict", }, }], From 45b6ad4c6d2aad4cc1898f4e855859f4927b5265 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:25:18 +0200 Subject: [PATCH 35/49] update labsjdk to 25+37-jvmci-b02 --- common.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common.json b/common.json index 2cb80913430f..9d8b15342877 100644 --- a/common.json +++ b/common.json @@ -55,12 +55,12 @@ "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+37", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+37-jvmci-b01-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+37-jvmci-b01-sulong", "platformspecific": true } + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970-sulong", "platformspecific": true } }, "eclipse": { From 2ed2a1bfc4c0b3bda5dad8ec46810e1f2eb765bf Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:28:08 +0200 Subject: [PATCH 36/49] Revert "Workaround for missing JDK-8361355" This reverts commit 106619b97c4ed1dc18ddfadb4be8cd0ff5d40e59. --- .../graal/pointsto/infrastructure/WrappedJavaType.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java index 02f4d5f7c502..7bad26395435 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedJavaType.java @@ -30,13 +30,4 @@ public interface WrappedJavaType extends WrappedElement, ResolvedJavaType { @Override ResolvedJavaType getWrapped(); - - /** - * Returns true if this type represents an annotation interface. - * - * @return {@code true} if this type represents an annotation interface - */ - default boolean isAnnotation() { - return (getModifiers() & java.lang.reflect.AccessFlag.ANNOTATION.mask()) != 0; - } } From f5cf1b7fe0f2915c556481a775e949ec5cd8c8d5 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:29:39 +0200 Subject: [PATCH 37/49] Reapply "[GR-58163] Replay compilation." This reverts commit e1a91db9e14ea9b7b6e7a4e35e8929aecbb20f1f. --- compiler/CHANGELOG.md | 4 + compiler/docs/ReplayCompilation.md | 100 + compiler/mx.compiler/mx_compiler.py | 36 + .../libgraal/LibGraalEntryPoints.java | 44 + .../compiler/libgraal/LibGraalFeature.java | 7 +- .../RecordedOperationPersistenceTest.java | 181 ++ .../test/ReplayCompilationLauncher.java | 81 + .../test/ReplayCompilationTest.java | 231 ++ .../test/LibGraalCompilationDriver.java | 24 + .../util/json/test/JsonParserTest.java | 25 + .../bytecode/BytecodeDisassembler.java | 12 +- .../compiler/core/CompilationWrapper.java | 2 + .../compiler/core/common/LibGraalSupport.java | 6 + .../graal/compiler/debug/DebugOptions.java | 3 + .../compiler/hotspot/CompilationTask.java | 141 +- .../compiler/hotspot/EncodedSnippets.java | 61 +- .../hotspot/GraalHotSpotVMConfig.java | 6 +- .../hotspot/GraalHotSpotVMConfigAccess.java | 45 +- .../hotspot/HotSpotBackendFactory.java | 54 +- .../HotSpotBackendFactoryDecorators.java | 81 + .../HotSpotDecoratedBackendFactory.java | 212 ++ .../hotspot/HotSpotForeignCallLinkage.java | 5 + .../HotSpotForeignCallLinkageImpl.java | 19 + .../hotspot/HotSpotGraalCompilerFactory.java | 12 +- .../compiler/hotspot/HotSpotGraalRuntime.java | 46 +- .../hotspot/HotSpotGraalRuntimeProvider.java | 6 + .../compiler/hotspot/HotSpotHostBackend.java | 6 +- .../hotspot/HotSpotReplacementsImpl.java | 67 +- .../HotSpotSnippetMetaAccessProvider.java | 21 +- .../jdk/graal/compiler/hotspot/Platform.java | 94 + .../hotspot/SymbolicSnippetEncoder.java | 8 +- .../meta/HotSpotForeignCallsProviderImpl.java | 14 +- .../meta/HotSpotGraphBuilderPlugins.java | 9 +- .../meta/HotSpotHostForeignCallsProvider.java | 4 +- .../meta/HotSpotInvocationPlugins.java | 8 +- .../hotspot/meta/HotSpotProviders.java | 25 +- .../HotSpotSnippetReflectionProvider.java | 5 +- .../replaycomp/CompilationProxies.java | 76 + .../replaycomp/CompilationProxyMapper.java | 298 +++ .../CompilerInterfaceDeclarations.java | 949 ++++++++ .../DelayedDeserializationObject.java | 120 + .../HotSpotProxyBackendFactory.java | 195 ++ .../hotspot/replaycomp/OperationRecorder.java | 290 +++ .../RecordedForeignCallLinkages.java | 88 + .../RecordedOperationPersistence.java | 1986 +++++++++++++++++ .../RecordingCompilationProxies.java | 241 ++ .../replaycomp/ReplayCompilationProxies.java | 618 +++++ .../replaycomp/ReplayCompilationRunner.java | 495 ++++ .../replaycomp/ReplayCompilationSupport.java | 502 +++++ .../replaycomp/SpecialResultMarker.java | 120 + .../replaycomp/proxy/CompilationProxy.java | 297 +++ .../proxy/CompilationProxyBase.java | 112 + .../proxy/CompilerProfilerProxy.java | 71 + .../replaycomp/proxy/ConstantPoolProxy.java | 155 ++ .../proxy/HotSpotCodeCacheProviderProxy.java | 178 ++ ...otSpotConstantReflectionProviderProxy.java | 186 ++ .../HotSpotMemoryAccessProviderProxy.java | 93 + .../proxy/HotSpotMetaspaceConstantProxy.java | 106 + .../proxy/HotSpotObjectConstantProxy.java | 206 ++ .../proxy/HotSpotProfilingInfoProxy.java | 63 + .../proxy/HotSpotResolvedJavaFieldProxy.java | 122 + .../proxy/HotSpotResolvedJavaMethodProxy.java | 449 ++++ .../proxy/HotSpotResolvedJavaTypeProxy.java | 482 ++++ .../proxy/HotSpotResolvedObjectTypeProxy.java | 123 + .../proxy/HotSpotVMConfigAccessProxy.java | 120 + .../proxy/MetaAccessProviderProxy.java | 164 ++ .../MethodHandleAccessProviderProxy.java | 66 + .../replaycomp/proxy/PredicateProxy.java | 48 + .../replaycomp/proxy/ProfilingInfoProxy.java | 150 ++ .../replaycomp/proxy/SignatureProxy.java | 65 + .../replaycomp/proxy/SpeculationLogProxy.java | 83 + .../nodes/spi/StableProfileProvider.java | 29 +- .../replacements/SnippetTemplate.java | 23 +- .../SpeculationReasonGroup.java | 29 +- .../hotspot/HotSpotTruffleCompilerImpl.java | 2 +- .../graal/compiler/util/json/JsonParser.java | 7 +- .../util/json/JsonParserException.java | 35 + 77 files changed, 10991 insertions(+), 156 deletions(-) create mode 100644 compiler/docs/ReplayCompilation.md create mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java create mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java create mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java diff --git a/compiler/CHANGELOG.md b/compiler/CHANGELOG.md index 6a96191f05fa..9b995317b436 100644 --- a/compiler/CHANGELOG.md +++ b/compiler/CHANGELOG.md @@ -4,6 +4,10 @@ This changelog summarizes newly introduced optimizations and other compiler rela ## GraalVM for JDK 26 (Internal Version 26.0.0) * (GR-69280): Allow use of the `graal.` prefix for Graal compiler options without issuing a warning. +* (GR-58163): Added support for recording and replaying JIT compilations. The `-Djdk.graal.RecordForReplay=*` option + serializes all compilations matching the pattern to JSON files, which contain the results of JVMCI calls. The + recorded compilations can be replayed with the `mx replaycomp` command. Truffle compilations are currently not + supported. See `docs/ReplayCompilation.md` for details. ## GraalVM 25 (Internal Version 25.0.0) * (GR-60088): This PR adds the `org.graalvm.nativeimage.libgraal` SDK module. With this module, all logic for building diff --git a/compiler/docs/ReplayCompilation.md b/compiler/docs/ReplayCompilation.md new file mode 100644 index 000000000000..cafbf5a9e5bc --- /dev/null +++ b/compiler/docs/ReplayCompilation.md @@ -0,0 +1,100 @@ +# Replay Compilation + +The GraalVM compiler can record the inputs to a compilation task, serialize these inputs into a JSON file, and reproduce +the compilation using the same inputs. Replay compilation is based on instrumenting the JVM Compiler Interface (JVMCI). +Truffle compilations are currently not supported. It is not a goal to execute the replayed code. + +This file is a manual from the user's perspective. To learn how replay compilation is implemented, start by reading +`ReplayCompilationSupport.java` and `CompilerInterfaceDeclarations.java`. + +## Example + +Recording is enabled with the option `-Djdk.graal.RecordForReplay=*`. The value is a method filter selecting the methods +to be recorded. The syntax of method filters is explained `MethodFilter.java`. + +The below command records and serializes every compilation into `./replay-files/replaycomp/.json`. +The directories are created if they do not exist. + +```shell +mx benchmark renaissance:scrabble -- -Djdk.graal.RecordForReplay='*' -Djdk.graal.DumpPath=$PWD/replay-files -- -r 1 +``` + +It is recommended to select specific methods rather than `*` to avoid slowing the compiler down and producing gigabytes +of data. The compile speed overhead for recorded methods can be on the order of 10x. The size of a typical compilation +unit is between 1 and 10 MB but compression saves 95% of space. Note that if the VM exits during an ongoing compilation, +some of the JSON files may be incomplete. + +The `mx replaycomp` command finds all JSON replay files found in a given directory (and subdirectories) and invokes +the replay compiler on each. The command also accepts a path to a single file. + +```shell +mx replaycomp ./replay-files +``` + +## Debugging + +A replayed compilation can be debugged using a standard Java debugger (see `Debugging.md`). + +```shell +mx -d replaycomp ./replay-files +``` + +## Record Crashed Compilations + +Using the `-Djdk.graal.CompilationFailureAction=Diagnose` option, the compiler retries and records crashed compilations. +The command below exercises this behavior by forcing a crash. The JSON replay file can then be found in the `replaycomp` +directory inside the diagnostic zip archive. + +```shell +mx benchmark renaissance:scrabble -- -Djdk.graal.CompilationFailureAction=Diagnose -Djdk.graal.CrashAt=hashCode -- -r 1 +``` + +It is possible to **not** record retried compilations with the option `-Djdk.graal.DiagnoseOptions=RecordForReplay=`. + +## Replay with JVM Arguments + +JVM arguments, including compiler options, can be passed directly to the `replaycomp` command. + +```shell +mx replaycomp -Djdk.graal.Dump=:1 ./replay-files +``` + +Any `-ea`, `-esa`, and `-X` arguments from the command line are passed to the JVM as well. + +## Jargraal vs. Libgraal + +Both jargraal and libgraal compilations can be replayed on jargraal. When jargraal replays a libgraal compilation, +it uses encoded snippets to match the behavior and compilations results of libgraal. It is also possible to replay +libgraal compilations on libgraal. Replaying jargraal compilations on libgraal is not supported. + +It is necessary to explicitly enable the replay launcher entry point when building libgraal using the VM argument +`-Ddebug.jdk.graal.enableReplayLauncher=true`. + +```shell +EXTRA_IMAGE_BUILDER_ARGUMENTS=-Ddebug.jdk.graal.enableReplayLauncher=true mx --env libgraal build +``` + +When the `--libgraal` argument is passed to `mx replaycomp`, the previously built libgraal native library is loaded, and +the native launcher is invoked instead of the Java launcher. With the below command, all replay related processing +(including JSON parsing) is performed by libgraal code. + +```shell +mx replaycomp --libgraal ./replay-files +``` + +## Replay Options + +`--compare-graphs=true` compares the final canonical graph of the replayed compilation to the recorded one, which is +included in the JSON replay file. If there is a mismatch, the command exits with a non-zero status. + +```shell +mx replaycomp --compare-graphs=true ./replay-files +``` + +If the replayed compilation diverges from the recorded one, the compiler may query JVMCI information that is not +recorded in the JSON file. The default behavior is to return default values, which may not cause a compiler crash. +The `-Djdk.graal.ReplayDivergenceIsFailure=true` argument prevents using default values and instead causes a crash. + +```shell +mx replaycomp -Djdk.graal.ReplayDivergenceIsFailure=true ./replay-files +``` diff --git a/compiler/mx.compiler/mx_compiler.py b/compiler/mx.compiler/mx_compiler.py index 6047b0e56565..39d7fff61ebd 100644 --- a/compiler/mx.compiler/mx_compiler.py +++ b/compiler/mx.compiler/mx_compiler.py @@ -1571,6 +1571,41 @@ def profdiff(args): vm_args = ['-cp', cp, 'org.graalvm.profdiff.Profdiff'] + args return jdk.run_java(args=vm_args) +def replaycomp_vm_args(): + """Returns the VM arguments required to run the replay compilation launcher.""" + vm_args = [ + '-XX:-UseJVMCICompiler', + '--enable-native-access=org.graalvm.truffle', + '--add-exports=java.base/jdk.internal.module=ALL-UNNAMED', + '-Djdk.graal.CompilationFailureAction=Print' + ] + _, dists = mx.defaultDependencies(opt_limit_to_suite=True) + dists = [d for d in dists if d.isJARDistribution() and os.path.exists(d.classpath_repr(resolve=False))] + return mx.get_runtime_jvm_args(dists) + vm_args + +def replaycomp_main_class(): + """Returns the main class name for the replay compilation launcher.""" + return 'jdk.graal.compiler.hotspot.replaycomp.test.ReplayCompilationLauncher' + +def replaycomp(args): + """Runs the replay compilation launcher with the provided launcher and VM arguments.""" + extra_vm_args = [] + launcher_args = [] + for arg in args: + vm_arg_prefixes = ['-X', '-D', '-ea', '-enableassertions', '-esa', '-enablesystemassertions'] + if any(map(arg.startswith, vm_arg_prefixes)): + extra_vm_args.append(arg) + elif arg == '--libgraal': + jvmci_lib_path = os.path.join(mx.suite('sdk').get_output_root(platformDependent=True, jdkDependent=False), + mx.add_lib_suffix(mx.add_lib_prefix('jvmcicompiler')) + '.image') + extra_vm_args.extend([ + '-XX:+UseJVMCINativeLibrary', + f'-XX:JVMCILibPath={jvmci_lib_path}' + ]) + else: + launcher_args.append(arg) + return run_vm([*replaycomp_vm_args(), *extra_vm_args, replaycomp_main_class(), *launcher_args], nonZeroIsFatal=False) + def igvutil(args): """various utilities to inspect and modify IGV graphs""" cp = mx.classpath('GRAAL_IGVUTIL', jdk=jdk) @@ -1589,6 +1624,7 @@ def igvutil(args): 'graaljdk-show': [print_graaljdk_config, '[options]'], 'phaseplan-fuzz-jtt-tests': [phaseplan_fuzz_jtt_tests, "Runs JTT's unit tests with fuzzed phase plans."], 'profdiff': [profdiff, '[options] proftool_output1 optimization_log1 proftool_output2 optimization_log2'], + 'replaycomp': [replaycomp, ''], 'igvutil': [igvutil, '[subcommand] [options]'], }) diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java index eee479e027c6..30680f01da9f 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalEntryPoints.java @@ -31,6 +31,7 @@ import java.io.PrintStream; import java.util.Arrays; import java.util.Map; +import java.util.function.BooleanSupplier; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.JNI.JNIEnv; @@ -45,12 +46,15 @@ import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.hotspot.CompilationContext; import jdk.graal.compiler.hotspot.CompilationTask; 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.replaycomp.ReplayCompilationRunner; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionDescriptors; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionValues; @@ -288,4 +292,44 @@ private static long hashConstantOopFields(JNIEnv jniEnv, return 0; } } + + /** + * Runs the replay compilation launcher in libgraal with the provided command-line arguments. + * + * @param argBuffer a native buffer containing a zero-terminated UTF-8 string of + * {@code '\n'}-separated arguments for the replay compilation launcher + * @return the exit status of the replay compilation launcher + */ + @SuppressWarnings({"unused", "try"}) + @CEntryPoint(name = "Java_jdk_graal_compiler_hotspot_replaycomp_test_ReplayCompilationLauncher_runInLibgraal", include = LibGraalReplayLauncherEnabled.class) + private static int replayCompilation(JNIEnv jniEnv, + PointerBase jclass, + @IsolateThreadContext long isolateThread, + long argBuffer) { + try (JNIMethodScope scope = new JNIMethodScope("replayCompilation", jniEnv)) { + String argString = CTypeConversion.utf8ToJavaString(Word.pointer(argBuffer)); + String[] args; + if (argString.isEmpty()) { + args = new String[0]; + } else { + args = argString.split("\n"); + } + return ReplayCompilationRunner.run(args, TTY.out().out()).getStatus(); + } catch (Throwable t) { + JNIExceptionWrapper.throwInHotSpot(jniEnv, t); + return ReplayCompilationRunner.ExitStatus.Failure.getStatus(); + } finally { + LibGraalSupportImpl.doReferenceHandling(); + } + } + + /** + * Controls whether the replay launcher entry point should be included in libgraal. + */ + private static final class LibGraalReplayLauncherEnabled implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return new LibGraalFeature.IsEnabled().getAsBoolean() && ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER; + } + } } diff --git a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java index 3a078f678880..d8c1300f8d37 100644 --- a/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java +++ b/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/LibGraalFeature.java @@ -44,6 +44,7 @@ import java.util.function.Consumer; import java.util.stream.Collectors; +import jdk.graal.compiler.serviceprovider.GraalServices; import org.graalvm.collections.EconomicMap; import org.graalvm.jniutils.NativeBridgeSupport; import org.graalvm.nativeimage.ImageInfo; @@ -315,7 +316,11 @@ public void accept(DuringAnalysisAccess duringAnalysisAccess) { private void registerHostedOnlyElements(BeforeAnalysisAccess access, AnnotatedElement... elements) { for (AnnotatedElement element : elements) { - if (element.getAnnotation(HostedOnly.class) != null) { + HostedOnly annotation = element.getAnnotation(HostedOnly.class); + if (annotation == null) { + continue; + } + if (annotation.unlessTrue().isEmpty() || !Boolean.parseBoolean(GraalServices.getSavedProperty(annotation.unlessTrue()))) { access.registerReachabilityHandler(new HostedOnlyElementCallback(element, reachedHostedOnlyElements), element); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java new file mode 100644 index 000000000000..2c4ae5c65394 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/RecordedOperationPersistenceTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.test; + +import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.BitSet; +import java.util.List; +import java.util.Objects; + +import org.graalvm.collections.EconomicMap; +import org.junit.Assert; +import org.junit.Test; + +import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.replaycomp.CompilationProxyMapper; +import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; +import jdk.graal.compiler.hotspot.replaycomp.OperationRecorder; +import jdk.graal.compiler.hotspot.replaycomp.RecordedForeignCallLinkages; +import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; +import jdk.graal.compiler.hotspot.replaycomp.SpecialResultMarker; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; +import jdk.graal.compiler.util.CollectionsUtil; +import jdk.graal.compiler.util.json.JsonWriter; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; + +/** + * Tests the JSON serialization and deserialization performed by + * {@link RecordedOperationPersistence}. + */ +public class RecordedOperationPersistenceTest extends GraalCompilerTest { + @Test + public void dumpsAndLoads() throws IOException, RecordedOperationPersistence.DeserializationException { + CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); + RecordedOperationPersistence persistence = new RecordedOperationPersistence(declarations, Platform.ofCurrentHost(), + HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); + var compilationUnit = createRecordedCompilationUnit(); + ProxyFactory proxyFactory = new ProxyFactory(declarations); + CompilationProxyMapper proxyMapper = new CompilationProxyMapper(declarations, proxyFactory::proxify); + List proxifiedOperations = compilationUnit.operations().stream().map( + (operation) -> new OperationRecorder.RecordedOperation(proxyMapper.proxifyRecursive(operation.receiver()), operation.method(), + (Object[]) proxyMapper.proxifyRecursive(operation.args()), proxyMapper.proxifyRecursive(operation.resultOrMarker()))).toList(); + String json; + try (StringWriter stringWriter = new StringWriter(); JsonWriter jsonWriter = new JsonWriter(stringWriter)) { + persistence.dump(compilationUnit, jsonWriter); + json = stringWriter.toString(); + } + RecordedOperationPersistence.RecordedCompilationUnit parsedCompilationUnit; + try (StringReader reader = new StringReader(json)) { + parsedCompilationUnit = persistence.load(reader, proxyFactory); + } + for (var pair : CollectionsUtil.zipLongest(proxifiedOperations, parsedCompilationUnit.operations())) { + Assert.assertEquals(pair.getLeft().receiver(), pair.getRight().receiver()); + Assert.assertTrue(Objects.deepEquals(pair.getLeft().args(), pair.getRight().args())); + Object expectedResult = pair.getLeft().resultOrMarker(); + Object actualResult = pair.getRight().resultOrMarker(); + if (expectedResult instanceof SpecialResultMarker.ExceptionThrownMarker) { + Assert.assertTrue(actualResult instanceof SpecialResultMarker.ExceptionThrownMarker); + } else if (expectedResult instanceof Assumptions.AssumptionResult expectedAssumptionResult) { + if (actualResult instanceof Assumptions.AssumptionResult actualAssumptionResult) { + Assert.assertEquals(expectedAssumptionResult.getResult(), actualAssumptionResult.getResult()); + Assumptions expectedAssumptions = new Assumptions(); + expectedAssumptionResult.recordTo(expectedAssumptions); + Assumptions actualAssumptions = new Assumptions(); + actualAssumptionResult.recordTo(actualAssumptions); + Assert.assertEquals(expectedAssumptions, actualAssumptions); + } else { + Assert.fail(); + } + } else { + Assert.assertTrue(Objects.deepEquals(expectedResult, actualResult)); + } + } + } + + public static Object dummyMethod() { + try { + throw new Exception(); + } catch (Exception e) { + return null; + } + } + + private RecordedOperationPersistence.RecordedCompilationUnit createRecordedCompilationUnit() { + HotSpotResolvedJavaMethod dummyMethod = (HotSpotResolvedJavaMethod) getResolvedJavaMethod("dummyMethod"); + + CompilationProxy.SymbolicMethod constantGetCallSiteTarget = new CompilationProxy.SymbolicMethod(HotSpotObjectConstant.class, "getCallSiteTarget"); + CompilationProxy.SymbolicMethod symbolicReadArrayLength = new CompilationProxy.SymbolicMethod(ConstantReflectionProvider.class, "readArrayLength", JavaConstant.class); + CompilationProxy.SymbolicMethod symbolicGetHandlers = new CompilationProxy.SymbolicMethod(HotSpotResolvedJavaMethod.class, "getExceptionHandlers"); + CompilationProxy.SymbolicMethod symbolicGetOopMap = new CompilationProxy.SymbolicMethod(HotSpotResolvedJavaMethod.class, "getOopMapAt", int.class); + + JavaConstant constant = getSnippetReflection().forObject(new Object()); + JavaConstant otherConstant = getSnippetReflection().forObject(new Object()); + SpecialResultMarker exceptionMarker = new SpecialResultMarker.ExceptionThrownMarker(new IllegalArgumentException("test exception")); + BitSet bitSet = new BitSet(8); + bitSet.set(4); + bitSet.set(6); + + List operations = List.of( + new OperationRecorder.RecordedOperation(constant, constantGetCallSiteTarget, null, + new Assumptions.AssumptionResult<>(otherConstant, new Assumptions.CallSiteTargetValue(constant, otherConstant))), + new OperationRecorder.RecordedOperation(getConstantReflection(), symbolicReadArrayLength, new Object[]{constant}, exceptionMarker), + new OperationRecorder.RecordedOperation(dummyMethod, symbolicGetHandlers, null, dummyMethod.getExceptionHandlers()), + new OperationRecorder.RecordedOperation(dummyMethod, symbolicGetOopMap, new Object[]{0}, bitSet)); + + return new RecordedOperationPersistence.RecordedCompilationUnit( + new HotSpotCompilationRequest(dummyMethod, INVOCATION_ENTRY_BCI, 0L, 1), + "test configuration", + false, + Platform.ofCurrentHost(), + new RecordedForeignCallLinkages(EconomicMap.create()), + "test graph", + operations); + } + + private static final class ProxyFactory implements RecordedOperationPersistence.ProxyFactory { + private final CompilerInterfaceDeclarations declarations; + + private ProxyFactory(CompilerInterfaceDeclarations declarations) { + this.declarations = declarations; + } + + public CompilationProxy proxify(Object input) { + return createProxy(declarations.findRegistrationForInstance(input)); + } + + @Override + public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration) { + return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, invokableMethod, args) -> { + if (method.equals(CompilationProxyBase.unproxifyMethod)) { + return registration; + } else if (method.equals(CompilationProxyBase.equalsMethod)) { + if (args[0] instanceof CompilationProxy other) { + return registration == other.unproxify(); + } else { + return false; + } + } else if (method.equals(CompilationProxyBase.hashCodeMethod)) { + return registration.hashCode(); + } else if (method.equals(CompilationProxyBase.toStringMethod)) { + return registration.clazz().getSimpleName(); + } else { + return null; + } + }); + } + } +} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java new file mode 100644 index 000000000000..42680566b949 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationLauncher.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.test; + +import java.io.PrintStream; + +import com.oracle.truffle.runtime.hotspot.libgraal.LibGraal; +import com.oracle.truffle.runtime.hotspot.libgraal.LibGraalScope; + +import jdk.graal.compiler.api.test.ModuleSupport; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; +import jdk.graal.compiler.hotspot.test.LibGraalCompilationDriver; + +/** + * The first entry point for the replay compilation launcher. This class determines whether libgraal + * is available and tries to invoke the launcher in libgraal. Otherwise, it invokes the launcher in + * jargraal. + */ +public class ReplayCompilationLauncher { + static { + ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.graal.compiler"); + ModuleSupport.exportAndOpenAllPackagesToUnnamed("jdk.internal.vm.ci"); + ModuleSupport.exportAndOpenAllPackagesToUnnamed("org.graalvm.truffle.runtime"); + } + + /** + * Calls libgraal C entry point + * {@code jdk.graal.compiler.libgraal.LibGraalEntryPoints#replayCompilation}, which in turn + * calls {@link ReplayCompilationRunner#run(String[], PrintStream)}. + */ + public static native int runInLibgraal(long isolateThread, long argBuffer); + + public static void main(String[] args) { + if (LibGraal.isAvailable()) { + try { + LibGraal.registerNativeMethods(ReplayCompilationLauncher.class); + } catch (Error error) { + System.err.printf("The replay launcher entry point could not be linked. Build libgraal with -D%s=true as an extra image builder option to enable the launcher.%n", + ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP); + throw error; + } + StringBuilder argString = new StringBuilder(); + for (String arg : args) { + if (!argString.isEmpty()) { + argString.append('\n'); + } + argString.append(arg); + } + try (var stringBuffer = new LibGraalCompilationDriver.LibGraalParams.UTF8CStringBuffer(argString.toString()); + LibGraalScope scope = new LibGraalScope()) { + int status = runInLibgraal(scope.getIsolateThreadAddress(), stringBuffer.getAddress()); + System.exit(status); + } + } else { + ReplayCompilationRunner.run(args, System.out).exitVM(); + } + } +} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java new file mode 100644 index 000000000000..95beb5cbf83b --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp.test; + +import java.io.ByteArrayOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.EconomicSet; +import org.junit.Test; + +import com.oracle.truffle.api.Truffle; + +import jdk.graal.compiler.api.test.Graal; +import jdk.graal.compiler.core.CompilationWrapper; +import jdk.graal.compiler.core.GraalCompilerOptions; +import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.debug.DebugOptions; +import jdk.graal.compiler.debug.GlobalMetrics; +import jdk.graal.compiler.debug.LogStream; +import jdk.graal.compiler.debug.TTY; +import jdk.graal.compiler.hotspot.CompilationTask; +import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; +import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; +import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; +import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; +import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.runtime.RuntimeProvider; +import jdk.graal.compiler.util.json.JsonParser; +import jdk.graal.compiler.util.json.JsonWriter; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.runtime.JVMCICompiler; + +/** + * Tests for compilation recording and replay. + */ +public class ReplayCompilationTest extends GraalCompilerTest { + private static int[] lengthsSquared(List strings) { + return strings.stream().mapToInt(String::length).map(i -> i * i).toArray(); + } + + private static Map wordCount(List sentences) { + return sentences.stream().flatMap(sentence -> Arrays.stream(sentence.split("\\s+"))).collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); + } + + @Test + public void recordsOnRetryAndReplays() throws Throwable { + lengthsSquared(List.of("foo", "bar", "baz")); + runTest((temp) -> { + String methodName = "lengthsSquared"; + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + OptionValues initialOptions = getInitialOptions(); + String diagnoseOptionValue = DebugOptions.RecordForReplay.getName() + "=" + methodName; + OptionValues crashAndDiagnoseOptions = new OptionValues(initialOptions, DebugOptions.DumpPath, temp.toString(), + GraalCompilerOptions.CompilationFailureAction, CompilationWrapper.ExceptionAction.Diagnose, + DebugOptions.DiagnoseOptions, diagnoseOptionValue, GraalCompilerOptions.CrashAt, methodName); + /* + * Run a regular compilation with a forced crash, then retry and record the compilation. + * We need to run in a new compiler instance to override the dump path for diagnostics, + * where the recorded compilation unit is saved. + */ + HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, crashAndDiagnoseOptions); + assertTrue(regularResult.getFailure() != null); + + // Replay the compilation without forcing a crash and enable diagnostic options. + EconomicSet logTargets = EconomicSet.create(); + logTargets.add(DebugOptions.OptimizationLogTarget.Stdout); + OptionValues replayOptions = new OptionValues(initialOptions, DebugOptions.DumpPath, temp.toString(), + DebugOptions.PrintGraph, DebugOptions.PrintGraphTarget.File, DebugOptions.Dump, ":1", + DebugOptions.OptimizationLog, logTargets, DebugOptions.Log, "", DebugOptions.PrintBackendCFG, true); + replayCompilation(findReplayCompFile(temp.path), replayOptions); + }); + } + + @Test + public void recordAndExecuteReplayRunner() throws Throwable { + wordCount(List.of("first test sentence", "second test sentence")); + runTest((temp) -> { + String methodName = "wordCount"; + ResolvedJavaMethod method = getResolvedJavaMethod(methodName); + OptionValues initialOptions = getInitialOptions(); + OptionValues recordOptions = new OptionValues(initialOptions, DebugOptions.RecordForReplay, "*", + DebugOptions.DumpPath, temp.toString()); + HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, recordOptions); + assertTrue(regularResult.getFailure() == null); + Path replayFile = findReplayCompFile(temp.path); + Path replayFileLibgraal = Path.of(temp.path.toString(), "libgraal.json"); + copyReplayFileAsLibgraalCompilation(replayFile, replayFileLibgraal); + String[][] argumentLists = new String[][]{ + new String[]{"--compare-graphs=true", replayFile.toString()}, + new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", replayFileLibgraal.toString()} + }; + for (String[] arguments : argumentLists) { + ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(arguments, TTY.out().out()); + assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); + } + assertTrue(HotSpotReplacementsImpl.snippetsAreEncoded()); + }); + } + + /** + * Creates a copy of the source replay file that acts as if it was compiled with libgraal. This + * way, we test replaying libgraal compilations on jargraal (without access to libgraal). + * + * @param replayFile the source replay file + * @param destFile the created replay file that acts as a libgraal compilation + * ({@link jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence.RecordedCompilationUnit#isLibgraal()}) + */ + private static void copyReplayFileAsLibgraalCompilation(Path replayFile, Path destFile) throws Throwable { + try (FileReader reader = new FileReader(replayFile.toFile()); JsonWriter writer = new JsonWriter(destFile)) { + EconomicMap json = JsonParser.parseDict(reader); + json.put(RecordedOperationPersistence.RecordedCompilationUnitSerializer.IS_LIBGRAAL_PROPERTY, true); + writer.print(json); + } + } + + @Test + public void unparsableReplayFileSucceeds() throws Throwable { + runTest((temp) -> { + /* + * A replay file may not be parsable when the compiler thread exits during writing - + * this is not an error. + */ + assertTrue(Path.of(temp.path.toString(), "empty.json").toFile().createNewFile()); + ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(new String[]{temp.path.toString()}, TTY.out().out()); + assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); + }); + } + + @Test + public void emptyLauncherInputFails() throws Throwable { + runTest((temp) -> { + ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(new String[]{temp.path.toString()}, TTY.out().out()); + assertTrue(status == ReplayCompilationRunner.ExitStatus.Failure); + }); + } + + @FunctionalInterface + interface TestRunner { + void run(TemporaryDirectory temp) throws Throwable; + } + + @SuppressWarnings("try") + private static void runTest(TestRunner test) throws Throwable { + Truffle.getRuntime(); // Initialize the Truffle runtime and enable the HostInliningPhase. + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); TTY.Filter filter = new TTY.Filter(new LogStream(outputStream))) { + try (TemporaryDirectory temp = new TemporaryDirectory("ReplayCompilationTest")) { + test.run(temp); + } catch (Throwable throwable) { + System.err.println(outputStream.toString(Charset.defaultCharset())); + throw throwable; + } + } finally { + HotSpotReplacementsImpl.setEncodedSnippets(null); + HotSpotReplacementsImpl.clearSnippetEncoder(); + ReplayCompilationSupport.setReplayingLibgraalInJargraal(false); + } + } + + private static HotSpotCompilationRequestResult runRegularCompilation(ResolvedJavaMethod method, OptionValues options) { + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); + CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(runtimeProvider.getCompilerConfigurationName(), options, jvmciRuntime); + HotSpotGraalCompiler compiler = HotSpotGraalCompilerFactory.createCompiler("VM-test", jvmciRuntime, options, configFactory, null); + HotSpotCompilationRequest request = new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) method, JVMCICompiler.INVOCATION_ENTRY_BCI, 0L); + CompilationTask task = new CompilationTask(jvmciRuntime, compiler, request, true, false, false, false); + return task.runCompilation(options); + } + + private static void replayCompilation(Path replayCompFile, OptionValues options) throws ReplayCompilationRunner.ReplayLauncherFailure { + CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); + HotSpotJVMCIRuntime jvmciRuntime = HotSpotJVMCIRuntime.runtime(); + RuntimeProvider runtimeProvider = Graal.getRequiredCapability(RuntimeProvider.class); + CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(runtimeProvider.getCompilerConfigurationName(), options, jvmciRuntime); + try (ReplayCompilationRunner.Reproducer reproducer = ReplayCompilationRunner.Reproducer.initializeFromFile(replayCompFile.toString(), + declarations, jvmciRuntime, options, configFactory, new GlobalMetrics(), TTY.out().out(), EconomicMap.create())) { + reproducer.compile().verify(false); + } + } + + private static Path findReplayCompFile(Path dumpPath) throws IOException { + Path replayCompDirectory; + try (Stream replayCompDirectoryStream = Files.find(dumpPath, 8, + (path, attributes) -> attributes.isDirectory() && path.toFile().getName().equals("replaycomp"))) { + replayCompDirectory = replayCompDirectoryStream.findAny().orElseThrow(); + } + try (Stream replayCompFileStream = Files.list(replayCompDirectory)) { + return replayCompFileStream.findAny().orElseThrow(); + } + } +} diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java index 21ef8073fc7c..145d5d180004 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/LibGraalCompilationDriver.java @@ -28,6 +28,7 @@ import static jdk.internal.misc.Unsafe.ARRAY_BYTE_BASE_OFFSET; import java.io.ByteArrayOutputStream; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -235,6 +236,29 @@ public void close() { } } + /** + * A buffer holding a zero-terminated UTF-8 string. + */ + public static class UTF8CStringBuffer extends NativeBuffer { + private final byte[] encoded; + + public UTF8CStringBuffer(String string) { + byte[] utf8Bytes = string.getBytes(StandardCharsets.UTF_8); + encoded = new byte[utf8Bytes.length + 1]; + System.arraycopy(utf8Bytes, 0, encoded, 0, utf8Bytes.length); + } + + @Override + public void initialize(long address) { + UNSAFE.copyMemory(encoded, ARRAY_BYTE_BASE_OFFSET, null, address, encoded.length); + } + + @Override + public int length() { + return encoded.length; + } + } + /** * Native memory containing {@linkplain OptionsEncoder encoded} {@link OptionValues}. */ diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java index 3b54f81d76ed..35587d41f14f 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/util/json/test/JsonParserTest.java @@ -35,6 +35,7 @@ import jdk.graal.compiler.util.json.JsonFormatter; import jdk.graal.compiler.util.json.JsonParser; import jdk.graal.compiler.util.json.JsonParserException; +import jdk.vm.ci.meta.TriState; public class JsonParserTest { @@ -189,6 +190,30 @@ public void parseAllowedKeysErrors() throws IOException { } } + @Test + public void parserExceptionsAtEOF() throws IOException { + for (String input : List.of("", "[", "{", "{\"", "{\"a", "{\"a\"", "{\"a\":", "[\"a\",", "tru", "nul", "fals")) { + try { + new JsonParser(input).parse(); + Assert.fail("The input string is not a valid JSON."); + } catch (JsonParserException exception) { + Assert.assertEquals(TriState.TRUE, exception.isAtEOF()); + } + } + } + + @Test + public void parserExceptionsBeforeEOF() throws IOException { + for (String input : List.of("true??", "[?,", "{\"a\",\"b\"}")) { + try { + new JsonParser(input).parse(); + Assert.fail("The input string is not a valid JSON."); + } catch (JsonParserException exception) { + Assert.assertEquals(TriState.FALSE, exception.isAtEOF()); + } + } + } + private static void testErrorIntl(String json, String expectedMessage) throws IOException { JsonParser parser = new JsonParser(json); try { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java index e5adffecec85..102d3951f6f0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/bytecode/BytecodeDisassembler.java @@ -298,7 +298,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo case INVOKESPECIAL : case INVOKESTATIC : { int cpi = stream.readCPI(); - JavaMethod callee = cp.lookupMethod(cpi, opcode); + JavaMethod callee = cp.lookupMethod(cpi, opcode, method); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -315,7 +315,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo } case INVOKEINTERFACE: { int cpi = stream.readCPI(); - JavaMethod callee = cp.lookupMethod(cpi, opcode); + JavaMethod callee = cp.lookupMethod(cpi, opcode, method); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -334,7 +334,7 @@ private void decodeOperand(StringBuilder buf, BytecodeStream stream, ConstantPoo } case INVOKEDYNAMIC: { int cpi = stream.readCPI4(); - JavaMethod callee = cp.lookupMethod(cpi, opcode); + JavaMethod callee = cp.lookupMethod(cpi, opcode, method); cpi = cpiFunction.apply(opcode, cpi); if (format) { String calleeDesc = callee.getDeclaringClass().getName().equals(method.getDeclaringClass().getName()) ? callee.format("%n:(%P)%R") : callee.format("%H.%n:(%P)%R"); @@ -497,13 +497,11 @@ public static JavaMethod getInvokedMethodAt(ResolvedJavaMethod method, int invok case INVOKESTATIC: case INVOKEINTERFACE: { int cpi = stream.readCPI(); - JavaMethod callee = cp.lookupMethod(cpi, opcode); - return callee; + return cp.lookupMethod(cpi, opcode, method); } case INVOKEDYNAMIC: { int cpi = stream.readCPI4(); - JavaMethod callee = cp.lookupMethod(cpi, opcode); - return callee; + return cp.lookupMethod(cpi, opcode, method); } default: throw new InternalError(BytecodeDisassembler.disassembleOne(method, invokeBci)); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java index 8dfa836187d0..e2641c7057e6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/CompilationWrapper.java @@ -33,6 +33,7 @@ import static jdk.graal.compiler.debug.DebugOptions.Counters; import static jdk.graal.compiler.debug.DebugOptions.Timers; import static jdk.graal.compiler.debug.PathUtilities.getPath; +import static jdk.graal.compiler.debug.DebugOptions.RecordForReplay; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -397,6 +398,7 @@ private OptionValues getRetryOptions(OptionValues initialOptions, String dumpPat values.put(DumpPath, dumpPath); values.put(PrintBackendCFG, true); values.put(TrackNodeSourcePosition, true); + values.put(RecordForReplay, "*"); String diagnoseOptions = DebugOptions.DiagnoseOptions.getValue(initialOptions); parseRetryOptions(OptionsParser.splitOptions(diagnoseOptions), values); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java index fa36e8acba76..00826e59b1d6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/LibGraalSupport.java @@ -55,6 +55,12 @@ public interface LibGraalSupport { @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD}) @interface HostedOnly { + /** + * The name of a libgraal build-time system property that allows the annotated element to be + * used at libgraal run time. The value of the property is parsed using + * {@link Boolean#parseBoolean}. + */ + String unlessTrue() default ""; } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java index 63784ab3300f..8e7372082ebd 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/debug/DebugOptions.java @@ -286,6 +286,9 @@ public enum OptimizationLogTarget { @Option(help = "Path to the directory where the optimization log is saved if OptimizationLog is set to Directory. " + "Directories are created if they do no exist.", type = OptionType.Debug) public static final OptionKey OptimizationLogPath = new OptionKey<>(null); + + @Option(help = "Record the compilations matching the method filter for replay compilation.", type = OptionType.Debug) + public static final OptionKey RecordForReplay = new OptionKey<>(null); // @formatter:on /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index 9d9554d49b28..ced10d5179f4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -34,6 +34,7 @@ import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsing; import java.io.PrintStream; +import java.util.List; import java.util.ListIterator; import org.graalvm.collections.EconomicMap; @@ -57,7 +58,9 @@ import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.debug.TimerKey; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.nodes.StructuredGraph; +import jdk.graal.compiler.nodes.spi.ProfileProvider; import jdk.graal.compiler.nodes.spi.StableProfileProvider; import jdk.graal.compiler.nodes.spi.StableProfileProvider.TypeFilter; import jdk.graal.compiler.options.Option; @@ -75,7 +78,6 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.serviceprovider.GraalServices; import jdk.vm.ci.code.BailoutException; -import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotInstalledCode; @@ -290,6 +292,10 @@ private static boolean isNotCausedByOOME(Throwable throwable) { @Override protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) { HotSpotResolvedJavaMethod method = getMethod(); + if (ReplayCompilationSupport.matchesRecordCompilationFilter(debug.getOptions(), method) || compiler.getGraalRuntime().getReplayCompilationSupport() != null) { + return performCompilationWithReplaySupport(debug); + } + int entryBCI = getEntryBCI(); final boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; CompilationStatistics stats = CompilationStatistics.create(debug.getOptions(), method, isOSR); @@ -299,32 +305,15 @@ protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) try (DebugContext.Scope s = debug.scope("Compiling", new DebugDumpScope(getIdString(), true))) { graph = compiler.createGraph(method, entryBCI, profileProvider, compilationId, debug.getOptions(), debug); Suites suites = compiler.getSuites(compiler.getGraalRuntime().getHostProviders(), debug.getOptions()); - if (checkRecompileCycle && (MethodRecompilationLimit.getValue(debug.getOptions()) < 0 || decompileCount < MethodRecompilationLimit.getValue(debug.getOptions()))) { - /* - * Disable DeoptimizationGroupingPhase to simplify the creation of the - * speculations for each deopt. - */ - ListIterator> phase = suites.getMidTier().findPhase(DeoptimizationGroupingPhase.class); - if (phase != null) { - phase.remove(); - } - ListIterator> lowTierPhasesIterator = suites.getLowTier().findPhase(SchedulePhase.FinalSchedulePhase.class); - if (lowTierPhasesIterator != null) { - lowTierPhasesIterator.previous(); - lowTierPhasesIterator.add(new ForceDeoptSpeculationPhase(decompileCount)); - } - } + adjustSuitesForRecompilation(debug.getOptions(), suites); result = compiler.compile(graph, shouldRetainLocalVariables, shouldUsePreciseUnresolvedDeopts, eagerResolving, compilationId, debug, suites); - if (checkRecompileCycle && (MethodRecompilationLimit.getValue(debug.getOptions()) >= 0 && decompileCount >= MethodRecompilationLimit.getValue(debug.getOptions()))) { - ProfilingInfo info = profileProvider.getProfilingInfo(method); - throw new ForceDeoptSpeculationPhase.TooManyDeoptimizationsError("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase.getDeoptSummary(info)); - } + performRecompilationCheck(debug.getOptions(), method); } catch (Throwable e) { throw debug.handle(e); } try (DebugCloseable b = CodeInstallationTime.start(debug)) { - installMethod(debug, graph, result); + installMethod(compiler.getGraalRuntime().getHostBackend(), debug, graph, result); } // Installation is included in compilation time and memory usage reported by printer printer.finish(result, installedCode); @@ -334,6 +323,110 @@ protected HotSpotCompilationRequestResult performCompilation(DebugContext debug) return buildCompilationRequestResult(method); } + /** + * Modifies the provided suites to prevent excessive recompilation if necessary. + * + * @param options the option values + * @param suites the suites to modify + */ + private void adjustSuitesForRecompilation(OptionValues options, Suites suites) { + if (checkRecompileCycle && (MethodRecompilationLimit.getValue(options) < 0 || decompileCount < MethodRecompilationLimit.getValue(options))) { + /* + * Disable DeoptimizationGroupingPhase to simplify the creation of the speculations + * for each deopt. + */ + ListIterator> phase = suites.getMidTier().findPhase(DeoptimizationGroupingPhase.class); + if (phase != null) { + phase.remove(); + } + ListIterator> lowTierPhasesIterator = suites.getLowTier().findPhase(SchedulePhase.FinalSchedulePhase.class); + if (lowTierPhasesIterator != null) { + lowTierPhasesIterator.previous(); + lowTierPhasesIterator.add(new ForceDeoptSpeculationPhase(decompileCount)); + } + } + } + + /** + * Checks whether the recompilation limit is exceeded, and if so, throws an exception. + * + * @param options the option values + * @param method the compiled method + */ + private void performRecompilationCheck(OptionValues options, HotSpotResolvedJavaMethod method) { + if (checkRecompileCycle && (MethodRecompilationLimit.getValue(options) >= 0 && decompileCount >= MethodRecompilationLimit.getValue(options))) { + ProfilingInfo info = profileProvider.getProfilingInfo(method); + throw new ForceDeoptSpeculationPhase.TooManyDeoptimizationsError("too many decompiles: " + decompileCount + " " + ForceDeoptSpeculationPhase.getDeoptSummary(info)); + } + } + + private static final TimerKey CompilationReplayTime = DebugContext.timer("CompilationReplayTime").doc("The time spent in recorded/replayed compilations."); + + private static final CounterKey CompilationReplayBytecodes = DebugContext.counter("CompilationReplayBytecodes").doc("The size of bytecodes compiled in recorded/replayed compilations."); + + /** + * Performs a recorded or replayed compilation. + * + * @param initialDebug the initial debug context + * @return the compilation result + */ + @SuppressWarnings("try") + private HotSpotCompilationRequestResult performCompilationWithReplaySupport(DebugContext initialDebug) { + OptionValues options = initialDebug.getOptions(); + HotSpotGraalCompiler selectedCompiler; + if (compiler.getGraalRuntime().getReplayCompilationSupport() != null) { + selectedCompiler = compiler; + } else { + CompilerConfigurationFactory configFactory = CompilerConfigurationFactory.selectFactory(compiler.getGraalRuntime().getCompilerConfigurationName(), options, jvmciRuntime); + selectedCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-record", jvmciRuntime, options, configFactory, ReplayCompilationSupport.createRecording(configFactory.getName())); + } + ReplayCompilationSupport replaySupport = selectedCompiler.getGraalRuntime().getReplayCompilationSupport(); + HotSpotCompilationRequest request = getRequest(); + try (DebugCloseable closeable = replaySupport.enterCompilationContext(request, options)) { + request = replaySupport.decorateCompilationRequest(request); + HotSpotResolvedJavaMethod method = request.getMethod(); + /* + * Passing a snippet reflection instance to the debug handlers would cause replay + * failures. + */ + List debugHandlersFactories = List.of(new GraalDebugHandlersFactory(null)); + PrintStream selectedPrintStream = initialDebug.getConfig() == null ? DebugContext.getDefaultLogStream() : initialDebug.getConfig().output(); + try (DebugContext debug = selectedCompiler.getGraalRuntime().openDebugContext(options, compilationId, method, debugHandlersFactories, selectedPrintStream); + DebugContext.Activation a = debug.activate(); + DebugCloseable d = replaySupport.withDebugContext(debug); + DebugCloseable c = initialDebug.inRetryCompilation() ? debug.openRetryCompilation() : null; + DebugCloseable t = CompilationReplayTime.start(debug)) { + int entryBCI = getEntryBCI(); + boolean isOSR = entryBCI != JVMCICompiler.INVOCATION_ENTRY_BCI; + CompilationStatistics stats = CompilationStatistics.create(options, method, isOSR); + CompilationPrinter printer = CompilationPrinter.begin(options, compilationId, method, entryBCI); + if (initialDebug.inRetryCompilation()) { + profileProvider.forQueriedProfiles((profileKey, profilingInfo) -> { + replaySupport.injectProfiles(profileKey.method(), profileKey.includeNormal(), profileKey.includeOSR(), profilingInfo); + }); + } + ProfileProvider selectedProfileProvider = new StableProfileProvider(); + try (DebugContext.Scope s = debug.scope("Compiling with replay support", new DebugDumpScope(getIdString(), true))) { + graph = selectedCompiler.createGraph(method, entryBCI, selectedProfileProvider, compilationId, options, debug); + Suites suites = compiler.getSuites(compiler.getGraalRuntime().getHostProviders(), debug.getOptions()); + adjustSuitesForRecompilation(options, suites); + result = selectedCompiler.compile(graph, shouldRetainLocalVariables, shouldUsePreciseUnresolvedDeopts, eagerResolving, compilationId, debug, suites); + performRecompilationCheck(options, method); + CompilationReplayBytecodes.add(debug, result.getBytecodeSize()); + } catch (Throwable e) { + throw debug.handle(e); + } + try (DebugCloseable b = CodeInstallationTime.start(debug)) { + installMethod(selectedCompiler.getGraalRuntime().getHostBackend(), debug, graph, result); + } + printer.finish(result, installedCode); + stats.finish(method, installedCode); + replaySupport.recordCompilationArtifacts(graph, result); + return buildCompilationRequestResult(method); + } + } + } + protected HotSpotCompilationRequestResult buildCompilationRequestResult(HotSpotResolvedJavaMethod method) { // For compilation of substitutions the method in the compilation request might be // different than the actual method parsed. The root of the compilation will always @@ -599,11 +692,9 @@ protected HotSpotCompilationRequestResult runCompilation(DebugContext debug, Hot } @SuppressWarnings("try") - protected void installMethod(DebugContext debug, StructuredGraph graph, final CompilationResult compResult) { - final CodeCacheProvider codeCache = jvmciRuntime.getHostJVMCIBackend().getCodeCache(); - HotSpotBackend backend = compiler.getGraalRuntime().getHostBackend(); + protected void installMethod(HotSpotBackend backend, DebugContext debug, StructuredGraph graph, final CompilationResult compResult) { installedCode = null; - Object[] context = {new DebugDumpScope(getIdString(), true), codeCache, getMethod(), compResult}; + Object[] context = {new DebugDumpScope(getIdString(), true), backend.getProviders().getCodeCache(), getMethod(), compResult}; try (DebugContext.Scope s = debug.scope("CodeInstall", context, graph)) { HotSpotCompilationRequest request = getRequest(); installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index f6f1862f75b2..c09b8a98ad6a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -24,20 +24,24 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; +import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.snippetsAreEncoded; +import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.util.concurrent.ConcurrentHashMap; -import jdk.graal.compiler.core.common.LibGraalSupport; -import jdk.graal.compiler.nodes.NodeClassMap; import org.graalvm.collections.UnmodifiableEconomicMap; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; +import jdk.graal.compiler.core.CompilationWrapper; +import jdk.graal.compiler.core.GraalCompilerOptions; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; @@ -47,6 +51,7 @@ import jdk.graal.compiler.nodes.ConstantNode; import jdk.graal.compiler.nodes.EncodedGraph; import jdk.graal.compiler.nodes.FieldLocationIdentity; +import jdk.graal.compiler.nodes.NodeClassMap; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin; @@ -70,6 +75,29 @@ import jdk.vm.ci.meta.UnresolvedJavaType; public class EncodedSnippets { + /** + * Returns true if the current runtime or current compilation thread uses encoded snippets + * rather than parsing them directly. This is always true when executing in libgraal, and it is + * also true when the current thread is replaying a libgraal compilation in jargraal. + * + * @return true if encoded snippets are currently in use + */ + public static boolean isUsingEncodedSnippets() { + return inRuntimeCode() || isReplayingLibgraalInJargraal(); + } + + /** + * Returns true if the current runtime or current compilation thread uses encoded snippets and + * the snippets are already encoded. This is always true when executing in libgraal. If the + * current thread is replaying a libgraal compilation in jargraal, the method returns true after + * the snippets are encoded. + * + * @return true if encoded snippets are in use and already encoded + */ + public static boolean isAfterSnippetEncoding() { + return inRuntimeCode() || (isReplayingLibgraalInJargraal() && snippetsAreEncoded()); + } + /** * Metadata about a graph encoded in {@link EncodedSnippets#snippetEncoding}. */ @@ -212,7 +240,7 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod data = graphDatas.get(methodKey(method)); } if (data == null) { - if (LibGraalSupport.inLibGraalRuntime()) { + if (isUsingEncodedSnippets()) { throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport } else { return null; @@ -229,8 +257,16 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod if (declaringClass instanceof SnippetResolvedJavaType) { declaringClass = replacements.getProviders().getMetaAccess().lookupJavaType(Object.class); } - SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, snippetNodeClasses, data.originalMethod, declaringClass); - return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, LibGraalSupport.inLibGraalRuntime()); + /* + * If this is a recorded/replayed compilation, we must not mutate the snippet objects. This + * ensures we record all relevant operations during recording and no proxies are stored in + * the snippet objects during replay. + */ + boolean allowCacheReplacements = LibGraalSupport.inLibGraalRuntime() && replacements.getProviders().getReplayCompilationSupport() == null && + GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; + SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, + snippetNodeClasses, data.originalMethod, declaringClass); + return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, isUsingEncodedSnippets()); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @@ -306,7 +342,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.getProviders().getSnippetReflection(); - if (LibGraalSupport.inLibGraalRuntime()) { + if (isUsingEncodedSnippets()) { snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); } parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); @@ -397,15 +433,17 @@ static class SymbolicEncodedGraph extends EncodedGraph { private final ResolvedJavaType[] accessingClasses; private final String originalMethod; + private final boolean allowCacheReplacements; - SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { + SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowObjectsMutations, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { super(encoding, startOffset, objects, nodeClasses, null, null, false, false); this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; + this.allowCacheReplacements = allowObjectsMutations; } - SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod) { - this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), encodedGraph.getNodeClasses(), + SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod, boolean allowCacheReplacements) { + this(encodedGraph.getEncoding(), encodedGraph.getStartOffset(), encodedGraph.getObjects(), allowCacheReplacements, encodedGraph.getNodeClasses(), originalMethod, declaringClass); } @@ -453,7 +491,10 @@ public Object getObject(int i) { return o; } if (replacement != null) { - objects[i] = o = replacement; + o = replacement; + if (allowCacheReplacements) { + objects[i] = replacement; + } } else { throw new GraalError(error, "Can't resolve %s", o); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java index 2cb1aa6bde4c..9be0df530ead 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfig.java @@ -36,7 +36,7 @@ import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; -import jdk.vm.ci.hotspot.HotSpotVMConfigStore; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -63,8 +63,8 @@ public class GraalHotSpotVMConfig extends GraalHotSpotVMConfigAccess { */ public static final OptionValues INJECTED_OPTIONVALUES = null; - GraalHotSpotVMConfig(HotSpotVMConfigStore store) { - super(store); + GraalHotSpotVMConfig(HotSpotVMConfigAccess access, Platform platform) { + super(access, platform); int logMinObjAlignment = logMinObjAlignment(); assert narrowOopShift <= logMinObjAlignment : Assertions.errorMessageContext("narrowOopShift", narrowOopShift, "logMinObjAlignment", logMinObjAlignment); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java index 0664afc3c9bd..cfef20e412f8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/GraalHotSpotVMConfigAccess.java @@ -30,11 +30,9 @@ import java.util.Formatter; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import jdk.graal.compiler.debug.Assertions; -import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; @@ -51,56 +49,27 @@ public class GraalHotSpotVMConfigAccess { private final Map vmConstants; private final Map vmFields; - GraalHotSpotVMConfigAccess(HotSpotVMConfigStore store) { - this.access = new HotSpotVMConfigAccess(store); + GraalHotSpotVMConfigAccess(HotSpotVMConfigAccess access, Platform platform) { + this.access = access; + HotSpotVMConfigStore store = access.getStore(); this.vmAddresses = store.getAddresses(); this.vmConstants = store.getConstants(); this.vmFields = store.getFields(); - - String value = getSavedProperty("os.name"); - switch (value) { - case "Linux": - value = "linux"; - break; - case "SunOS": - value = "solaris"; - break; - case "Mac OS X": - value = "darwin"; - break; - default: - // Of course Windows is different... - if (value.startsWith("Windows")) { - value = "windows"; - } else { - throw new JVMCIError("Unexpected OS name: " + value); - } - } - assert KNOWN_OS_NAMES.contains(value); - this.osName = value; - - String arch = getSavedProperty("os.arch"); - if (arch.equals("x86_64")) { - arch = "amd64"; - } - osArch = arch; - assert KNOWN_ARCHITECTURES.contains(arch) : arch; + this.osName = platform.osName(); + this.osArch = platform.archName(); } public HotSpotVMConfigStore getStore() { return access.getStore(); } - public static final Set KNOWN_ARCHITECTURES = CollectionsUtil.setOf("amd64", "aarch64", "riscv64"); - public static final Set KNOWN_OS_NAMES = CollectionsUtil.setOf("windows", "linux", "darwin"); - /** - * Name for current OS. Will be a value in {@link #KNOWN_OS_NAMES}. + * Name for current OS. Will be a value in {@link Platform#KNOWN_OS_NAMES}. */ public final String osName; /** - * Name for current CPU architecture. Will be a value in {@link #KNOWN_ARCHITECTURES}. + * Name for current CPU architecture. Will be a value in {@link Platform#KNOWN_ARCHITECTURES}. */ public final String osArch; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index 933532b4feae..5895c1acfdd1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -26,6 +26,7 @@ import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.vm.ci.common.InitTimer.timer; import jdk.graal.compiler.bytecode.BytecodeProvider; @@ -85,6 +86,35 @@ @LibGraalService public abstract class HotSpotBackendFactory implements ArchitectureSpecific { + /** + * Creates a meta access provider based on a JVMCI backend. + * + * @param jvmci the JVMCI backend + * @return a meta access provider + */ + protected MetaAccessProvider createMetaAccessProvider(JVMCIBackend jvmci) { + return new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); + } + + /** + * Creates a constant reflection provider based on a JVMCI backend. + * + * @param jvmci the JVMCI backend + * @return a constant reflection provider + */ + protected HotSpotConstantReflectionProvider createConstantReflectionProvider(JVMCIBackend jvmci) { + return (HotSpotConstantReflectionProvider) jvmci.getConstantReflection(); + } + + /** + * Creates a code cache provider based on a JVMCI backend. + * + * @param jvmci the JVMCI backend + * @return a code cache provider. + */ + protected HotSpotCodeCacheProvider createCodeCacheProvider(JVMCIBackend jvmci) { + return (HotSpotCodeCacheProvider) jvmci.getCodeCache(); + } protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { return new HotSpotGraalConstantFieldProvider(config, metaAccess); @@ -129,6 +159,13 @@ protected LoopsDataProvider createLoopsDataProvider() { return new LoopsDataProviderImpl(); } + /** + * Hook method called after all JVMCI providers have been created (meta access, code cache, + * constant reflection). + */ + protected void afterJVMCIProvidersCreated() { + } + @SuppressWarnings("try") public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, HotSpotJVMCIRuntime jvmciRuntime, HotSpotBackend host) { assert host == null; @@ -136,14 +173,14 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti OptionValues options = graalRuntime.getOptions(); JVMCIBackend jvmci = jvmciRuntime.getHostJVMCIBackend(); GraalHotSpotVMConfig config = graalRuntime.getVMConfig(); - if (inBuildtimeCode() || inRuntimeCode()) { - SnippetSignature.initPrimitiveKindCache(jvmci.getMetaAccess()); - } - - HotSpotCodeCacheProvider codeCache = (HotSpotCodeCacheProvider) jvmci.getCodeCache(); + MetaAccessProvider metaAccess = createMetaAccessProvider(jvmci); + HotSpotCodeCacheProvider codeCache = createCodeCacheProvider(jvmci); + HotSpotConstantReflectionProvider constantReflection = createConstantReflectionProvider(jvmci); + afterJVMCIProvidersCreated(); TargetDescription target = codeCache.getTarget(); - MetaAccessProvider metaAccess = new HotSpotSnippetMetaAccessProvider(jvmci.getMetaAccess()); - HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) jvmci.getConstantReflection(); + if (inBuildtimeCode() || isUsingEncodedSnippets()) { + SnippetSignature.initPrimitiveKindCache(metaAccess); + } ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess); HotSpotProviders providers; HotSpotReplacementsImpl replacements; @@ -199,7 +236,8 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti identityHashCodeProvider = createIdentityHashCodeProvider(); } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, null, registers, - snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config, identityHashCodeProvider); + snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config, identityHashCodeProvider, + graalRuntime.getReplayCompilationSupport()); try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, bytecodeProvider); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java new file mode 100644 index 000000000000..b4a4c9361c2b --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactoryDecorators.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 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.hotspot; + +import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; + +/** + * Decorators for the providers created by a backend factory. + */ +public interface HotSpotBackendFactoryDecorators { + /** + * Decorates the given MetaAccessProvider. + * + * @param metaAccess the MetaAccessProvider to decorate + * @return the decorated MetaAccessProvider + */ + default MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { + return metaAccess; + } + + /** + * Decorates the given constant reflection provider. + * + * @param constantReflection the constant reflection provider to decorate + * @return the decorated constant reflection provider + */ + default HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotSpotConstantReflectionProvider constantReflection) { + return constantReflection; + } + + /** + * Decorates the given code cache provider. + * + * @param codeCacheProvider the code cache provider to decorate + * @return the decorated code cache provider + */ + default HotSpotCodeCacheProvider decorateCodeCacheProvider(HotSpotCodeCacheProvider codeCacheProvider) { + return codeCacheProvider; + } + + /** + * Decorates the given foreign calls provider. + * + * @param foreignCalls the foreign calls provider to decorate + * @return the decorated foreign calls provider + */ + default HotSpotHostForeignCallsProvider decorateForeignCallsProvider(HotSpotHostForeignCallsProvider foreignCalls) { + return foreignCalls; + } + + /** + * Called after JVMCI providers have been created. + */ + default void afterJVMCIProvidersCreated() { + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java new file mode 100644 index 000000000000..ff6db885e18a --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotDecoratedBackendFactory.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 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.hotspot; + +import jdk.graal.compiler.bytecode.BytecodeProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotMetaAccessExtensionProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotPlatformConfigurationProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.meta.HotSpotRegistersProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotSnippetReflectionProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotStampProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotSuitesProvider; +import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; +import jdk.graal.compiler.nodes.FixedWithNextNode; +import jdk.graal.compiler.nodes.ValueNode; +import jdk.graal.compiler.nodes.gc.BarrierSet; +import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import jdk.graal.compiler.nodes.memory.FixedAccessNode; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; +import jdk.graal.compiler.nodes.spi.LoopsDataProvider; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.tiers.CompilerConfiguration; +import jdk.graal.compiler.replacements.classfile.ClassfileBytecodeProvider; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.Value; +import jdk.vm.ci.runtime.JVMCIBackend; + +/** + * A backend factory that creates providers via a delegate factory and decorates them. + */ +public class HotSpotDecoratedBackendFactory extends HotSpotBackendFactory { + /** + * The delegate backend factory. + */ + private final HotSpotBackendFactory delegate; + + /** + * The decorators to apply to the providers created by the delegate factory. + */ + private final HotSpotBackendFactoryDecorators decorators; + + /** + * Constructs a new instance of a decorated backend factory. + * + * @param delegate the delegate backend factory + * @param decorators the decorators to apply to the providers created by the delegate factory + */ + public HotSpotDecoratedBackendFactory(HotSpotBackendFactory delegate, HotSpotBackendFactoryDecorators decorators) { + this.delegate = delegate; + this.decorators = decorators; + } + + @Override + protected void afterJVMCIProvidersCreated() { + decorators.afterJVMCIProvidersCreated(); + delegate.afterJVMCIProvidersCreated(); + } + + @Override + protected HotSpotGraalConstantFieldProvider createConstantFieldProvider(GraalHotSpotVMConfig config, MetaAccessProvider metaAccess) { + return delegate.createConstantFieldProvider(config, metaAccess); + } + + @Override + protected HotSpotWordTypes createWordTypes(MetaAccessProvider metaAccess, TargetDescription target) { + return delegate.createWordTypes(metaAccess, target); + } + + @Override + protected HotSpotStampProvider createStampProvider() { + return delegate.createStampProvider(); + } + + @Override + protected HotSpotPlatformConfigurationProvider createConfigInfoProvider(GraalHotSpotVMConfig config, BarrierSet barrierSet) { + return delegate.createConfigInfoProvider(config, barrierSet); + } + + @Override + protected HotSpotReplacementsImpl createReplacements(TargetDescription target, HotSpotProviders p, BytecodeProvider bytecodeProvider) { + return delegate.createReplacements(target, p, bytecodeProvider); + } + + @Override + protected ClassfileBytecodeProvider createBytecodeProvider(MetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection) { + return delegate.createBytecodeProvider(metaAccess, snippetReflection); + } + + @Override + protected HotSpotSnippetReflectionProvider createSnippetReflection(HotSpotGraalRuntimeProvider runtime, HotSpotConstantReflectionProvider constantReflection, HotSpotWordTypes wordTypes) { + return delegate.createSnippetReflection(runtime, constantReflection, wordTypes); + } + + @Override + protected IdentityHashCodeProvider createIdentityHashCodeProvider() { + return delegate.createIdentityHashCodeProvider(); + } + + @Override + protected boolean isWriteToNewObject(FixedAccessNode node) { + return delegate.isWriteToNewObject(node); + } + + @Override + protected boolean isWriteToNewObject(FixedWithNextNode node, ValueNode base) { + return delegate.isWriteToNewObject(node, base); + } + + @Override + protected LoopsDataProvider createLoopsDataProvider() { + return delegate.createLoopsDataProvider(); + } + + @Override + protected MetaAccessProvider createMetaAccessProvider(JVMCIBackend jvmci) { + return decorators.decorateMetaAccessProvider(jvmci.getMetaAccess()); + } + + @Override + protected HotSpotConstantReflectionProvider createConstantReflectionProvider(JVMCIBackend jvmci) { + return decorators.decorateConstantReflectionProvider(delegate.createConstantReflectionProvider(jvmci)); + } + + @Override + protected HotSpotCodeCacheProvider createCodeCacheProvider(JVMCIBackend jvmci) { + return decorators.decorateCodeCacheProvider(delegate.createCodeCacheProvider(jvmci)); + } + + @Override + public String getName() { + return delegate.getName(); + } + + @Override + protected HotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider graalRuntime, HotSpotProviders providers) { + return delegate.createBackend(config, graalRuntime, providers); + } + + @Override + protected Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig registerConfig) { + return delegate.createNativeABICallerSaveRegisters(config, registerConfig); + } + + @Override + protected GraphBuilderConfiguration.Plugins createGraphBuilderPlugins(HotSpotGraalRuntimeProvider graalRuntime, + CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, TargetDescription target, HotSpotConstantReflectionProvider constantReflection, + HotSpotHostForeignCallsProvider foreignCalls, MetaAccessProvider metaAccess, HotSpotSnippetReflectionProvider snippetReflection, HotSpotReplacementsImpl replacements, + HotSpotWordTypes wordTypes, OptionValues options, BarrierSet barrierSet) { + return delegate.createGraphBuilderPlugins(graalRuntime, compilerConfiguration, config, target, constantReflection, + foreignCalls, metaAccess, snippetReflection, replacements, wordTypes, options, barrierSet); + } + + @Override + protected HotSpotSuitesProvider createSuites(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, CompilerConfiguration compilerConfiguration, + GraphBuilderConfiguration.Plugins plugins, HotSpotRegistersProvider registers, OptionValues options) { + return delegate.createSuites(config, runtime, compilerConfiguration, plugins, registers, options); + } + + @Override + protected HotSpotRegistersProvider createRegisters() { + return delegate.createRegisters(); + } + + @Override + protected HotSpotLoweringProvider createLowerer(HotSpotGraalRuntimeProvider graalRuntime, MetaAccessProvider metaAccess, HotSpotHostForeignCallsProvider foreignCalls, + HotSpotRegistersProvider registers, HotSpotConstantReflectionProvider constantReflection, HotSpotPlatformConfigurationProvider platformConfig, + HotSpotMetaAccessExtensionProvider metaAccessExtensionProvider, TargetDescription target) { + return delegate.createLowerer(graalRuntime, metaAccess, foreignCalls, registers, constantReflection, platformConfig, + metaAccessExtensionProvider, target); + } + + @Override + protected HotSpotHostForeignCallsProvider createForeignCalls(HotSpotJVMCIRuntime jvmciRuntime, HotSpotGraalRuntimeProvider graalRuntime, MetaAccessProvider metaAccess, + HotSpotCodeCacheProvider codeCache, HotSpotWordTypes wordTypes, Value[] nativeABICallerSaveRegisters) { + return decorators.decorateForeignCallsProvider(delegate.createForeignCalls(jvmciRuntime, graalRuntime, metaAccess, codeCache, wordTypes, nativeABICallerSaveRegisters)); + } + + @Override + public String getArchitecture() { + return delegate.getArchitecture(); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java index 7ab569bf3561..5114de56f07c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkage.java @@ -266,6 +266,11 @@ enum RegisterEffect { long getAddress(); + /** + * Returns {@code true} if this linkage has a finalized address. + */ + boolean hasAddress(); + /** * Determines if the runtime function or stub might use floating point registers. If the answer * is no, then no FPU state management prologue or epilogue needs to be emitted around the call. diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java index dbeeb30c7f89..df1aef148d26 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotForeignCallLinkageImpl.java @@ -319,12 +319,31 @@ public void finalizeAddress(Backend backend) { } } + /** + * Sets the address and killed slots/registers of this foreign call linkage. This linkage should + * not have an address yet, and the new address must not be {@code 0L}. + * + * @param newAddress the new address of the linkage + * @param newTemporaries the new killed slots and registers + */ + public void finalizeExternally(long newAddress, Value[] newTemporaries) { + GraalError.guarantee(!hasAddress(), "the linkage should not be finalized yet"); + GraalError.guarantee(newAddress != 0L, "the updated linkage must have an address"); + address = newAddress; + temporaries = newTemporaries.clone(); + } + @Override public long getAddress() { assert address != 0L : "address not yet finalized: " + this; return address; } + @Override + public boolean hasAddress() { + return address != 0L; + } + @Override public boolean destroysRegisters() { return effect == RegisterEffect.DESTROYS_ALL_CALLER_SAVE_REGISTERS; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java index 6bb24817b00c..bf7baa99a0e1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalCompilerFactory.java @@ -28,11 +28,11 @@ import java.io.PrintStream; -import jdk.graal.compiler.core.common.LibGraalSupport; - import jdk.graal.compiler.api.runtime.GraalRuntime; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.TTY; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.Option; import jdk.graal.compiler.options.OptionKey; import jdk.graal.compiler.options.OptionType; @@ -183,7 +183,7 @@ public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) { if (isGraalPredicate != null) { isGraalPredicate.onCompilerConfigurationFactorySelection(hsRuntime, factory); } - HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory); + HotSpotGraalCompiler compiler = createCompiler("VM", runtime, options, factory, null); // Only the HotSpotGraalRuntime associated with the compiler created via // jdk.vm.ci.runtime.JVMCIRuntime.getCompiler() is registered for receiving // VM events. @@ -222,12 +222,14 @@ private void checkUnsafeAccess(HotSpotJVMCIRuntime hsRuntime) { * by this method * @param runtime the JVMCI runtime on which the {@link HotSpotGraalRuntime} is built * @param compilerConfigurationFactory factory for the {@link CompilerConfiguration} + * @param replaySupport replay compilation support if this is a recording or replaying compiler */ @SuppressWarnings("try") - public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory) { + public static HotSpotGraalCompiler createCompiler(String runtimeNameQualifier, JVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory compilerConfigurationFactory, + ReplayCompilationSupport replaySupport) { HotSpotJVMCIRuntime jvmciRuntime = (HotSpotJVMCIRuntime) runtime; try (InitTimer t = timer("HotSpotGraalRuntime.")) { - HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options); + HotSpotGraalRuntime graalRuntime = new HotSpotGraalRuntime(runtimeNameQualifier, jvmciRuntime, compilerConfigurationFactory, options, replaySupport); return new HotSpotGraalCompiler(jvmciRuntime, graalRuntime, graalRuntime.getOptions()); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java index 54bc15d5e8a3..103d8ad3249e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java @@ -59,6 +59,7 @@ import jdk.graal.compiler.debug.TTY; import jdk.graal.compiler.hotspot.debug.BenchmarkCounters; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.nodes.spi.StampProvider; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.tiers.CompilerConfiguration; @@ -70,6 +71,7 @@ import jdk.vm.ci.code.stack.StackIntrospection; import jdk.vm.ci.common.InitTimer; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.hotspot.HotSpotVMConfigStore; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -118,24 +120,40 @@ public GlobalMetrics getMetricValues() { private final CompilerProfiler compilerProfiler; + /** + * The interface for recording/replaying compilations or {@code null} if disabled. + */ + private final ReplayCompilationSupport replayCompilationSupport; + /** * @param nameQualifier a qualifier to be added to this runtime's {@linkplain #getName() name} * @param compilerConfigurationFactory factory for the compiler configuration * {@link CompilerConfigurationFactory#selectFactory} + * @param replaySupport replay compilation support if this is a runtime for a recording or + * replaying compiler */ @SuppressWarnings("try") - HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions) { + HotSpotGraalRuntime(String nameQualifier, HotSpotJVMCIRuntime jvmciRuntime, CompilerConfigurationFactory compilerConfigurationFactory, OptionValues initialOptions, + ReplayCompilationSupport replaySupport) { this.runtimeName = getClass().getSimpleName() + ":" + nameQualifier; HotSpotVMConfigStore store = jvmciRuntime.getConfigStore(); - config = new GraalHotSpotVMConfig(store); + HotSpotVMConfigAccess access = new HotSpotVMConfigAccess(store); + GraalHotSpotVMConfig selectedConfig = new GraalHotSpotVMConfig(access, Platform.ofCurrentHost()); // Only set HotSpotPrintInlining if it still has its default value (false). - if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && config.printInlining) { - options = new OptionValues(initialOptions, HotSpotPrintInlining, true); - } else { - options = initialOptions; + OptionValues selectedOptions = initialOptions; + if (GraalOptions.HotSpotPrintInlining.getValue(initialOptions) == false && selectedConfig.printInlining) { + selectedOptions = new OptionValues(selectedOptions, HotSpotPrintInlining, true); } + replayCompilationSupport = replaySupport; + if (replayCompilationSupport != null) { + access = replayCompilationSupport.decorateVMConfigAccess(access); + selectedConfig = new GraalHotSpotVMConfig(access, replayCompilationSupport.targetPlatform()); + selectedOptions = replayCompilationSupport.filterOptions(selectedOptions); + } + options = selectedOptions; + config = selectedConfig; outputDirectory = new DiagnosticsOutputDirectory(options); compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class); snippetCounterGroups = GraalOptions.SnippetCounters.getValue(options) ? new ArrayList<>() : null; @@ -153,6 +171,9 @@ public GlobalMetrics getMetricValues() { if (factory == null) { throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture); } + if (replayCompilationSupport != null) { + factory = replayCompilationSupport.decorateBackendFactory(factory); + } hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null)); } @@ -190,7 +211,11 @@ public GlobalMetrics getMetricValues() { runtimeStartTime = System.nanoTime(); bootstrapJVMCI = config.getFlag("BootstrapJVMCI", Boolean.class); - this.compilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); + CompilerProfiler selectedCompilerProfiler = GraalServices.loadSingle(CompilerProfiler.class, false); + if (replayCompilationSupport != null) { + selectedCompilerProfiler = replayCompilationSupport.decorateCompilerProfiler(selectedCompilerProfiler); + } + this.compilerProfiler = selectedCompilerProfiler; LibGraalSupport libgraal = LibGraalSupport.INSTANCE; if (libgraal != null) { @@ -410,7 +435,7 @@ public synchronized void addShutdownHook(Runnable hook) { } } - synchronized void shutdown() { + public synchronized void shutdown() { shutdown = true; for (Runnable r : shutdownHooks) { @@ -481,4 +506,9 @@ public DiagnosticsOutputDirectory getOutputDirectory() { public Map getCompilationProblemsPerAction() { return compilationProblemsPerAction; } + + @Override + public ReplayCompilationSupport getReplayCompilationSupport() { + return replayCompilationSupport; + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java index 323b7bfdc56c..9bf9fcde651f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntimeProvider.java @@ -35,6 +35,7 @@ import jdk.graal.compiler.debug.DebugDumpHandlersFactory; import jdk.graal.compiler.debug.DiagnosticsOutputDirectory; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.replacements.SnippetCounter.Group; import jdk.graal.compiler.runtime.RuntimeProvider; @@ -107,4 +108,9 @@ default String getName() { * Returns the instance holding the instrumentation data structures. */ Instrumentation getInstrumentation(); + + /** + * Returns the interface for recording/replaying compilations or {@code null} if disabled. + */ + ReplayCompilationSupport getReplayCompilationSupport(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java index 9a6f5803423c..0fc684bd8b75 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java @@ -37,11 +37,13 @@ import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.graal.compiler.core.gen.LIRGenerationProvider; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugDumpHandlersFactory; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.Stub; import jdk.graal.compiler.lir.LIR; import jdk.graal.compiler.lir.asm.CompilationResultBuilder; @@ -109,10 +111,10 @@ public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValue HotSpotHostForeignCallsProvider foreignCalls = providers.getForeignCalls(); final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer(); - try (InitTimer st = timer("foreignCalls.initialize")) { + try (InitTimer st = timer("foreignCalls.initialize"); DebugCloseable c = ReplayCompilationSupport.enterSnippetContext(providers)) { foreignCalls.initialize(providers, options); } - try (InitTimer st = timer("lowerer.initialize")) { + try (InitTimer st = timer("lowerer.initialize"); DebugCloseable c = ReplayCompilationSupport.enterSnippetContext(providers)) { Iterable factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection())); lowerer.initialize(options, factories, providers, config); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 81a73c8343f7..80c59b7b0e43 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -24,8 +24,11 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.LibGraalSupport.inLibGraalRuntime; import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; +import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import java.util.BitSet; @@ -35,11 +38,13 @@ import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; import jdk.graal.compiler.hotspot.meta.HotSpotWordOperationPlugin; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotOperation; import jdk.graal.compiler.java.GraphBuilderPhase.Instance; import jdk.graal.compiler.nodes.Invoke; @@ -60,6 +65,7 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.replacements.IntrinsicGraphBuilder; import jdk.graal.compiler.replacements.ReplacementsImpl; +import jdk.graal.compiler.replacements.SnippetTemplate; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -72,7 +78,7 @@ public class HotSpotReplacementsImpl extends ReplacementsImpl { public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider bytecodeProvider, TargetDescription target) { super(new GraalDebugHandlersFactory(providers.getSnippetReflection()), providers, bytecodeProvider, target); - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -80,7 +86,7 @@ public HotSpotReplacementsImpl(HotSpotProviders providers, BytecodeProvider byte HotSpotReplacementsImpl(HotSpotReplacementsImpl replacements, HotSpotProviders providers) { super(new GraalDebugHandlersFactory(replacements.getProviders().getSnippetReflection()), providers, replacements.getDefaultReplacementBytecodeProvider(), replacements.target); - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!inLibGraalRuntime()) { registeredSnippets = EconomicSet.create(); } } @@ -90,6 +96,13 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } + @LibGraalSupport.HostedOnly + public static void clearSnippetEncoder() { + synchronized (HotSpotReplacementsImpl.class) { + snippetEncoder = null; + } + } + @LibGraalSupport.HostedOnly public SymbolicSnippetEncoder maybeInitializeEncoder() { synchronized (HotSpotReplacementsImpl.class) { @@ -102,7 +115,7 @@ public SymbolicSnippetEncoder maybeInitializeEncoder() { @Override public Class getIntrinsifyingPlugin(ResolvedJavaMethod method) { - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!inLibGraalRuntime()) { if (method.getAnnotation(HotSpotOperation.class) != null) { return HotSpotWordOperationPlugin.class; } @@ -112,7 +125,7 @@ public Class getIntrinsifyingPlugin(ResolvedJavaMe @Override public void notifyNotInlined(GraphBuilderContext b, ResolvedJavaMethod method, Invoke invoke) { - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!inLibGraalRuntime()) { if (b.parsingIntrinsic() && snippetEncoder != null) { if (getIntrinsifyingPlugin(method) != null) { snippetEncoder.addDelayedInvocationPluginMethod(method); @@ -183,20 +196,35 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo @LibGraalSupport.HostedOnly// private boolean snippetRegistrationClosed; + @SuppressWarnings("try") @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (inBuildtimeCode()) { + if (isRegisteringSnippetMethods()) { assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { + snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); + } } } } + /** + * Returns true if the current runtime or current compilation thread registers snippet methods + * to be encoded. This is true when building libgraal or when replaying a libgraal compilation + * in jargraal. + * + * @return true if snippets methods should be registered + */ + private static boolean isRegisteringSnippetMethods() { + return !inLibGraalRuntime() && (inBuildtimeCode() || isReplayingLibgraalInJargraal()); + } + @Override public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { - if (inRuntimeCode()) { + if (isAfterSnippetEncoding()) { return getEncodedSnippets().getSnippetParameterInfo(method); } return super.getSnippetParameterInfo(method); @@ -204,7 +232,7 @@ public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @Override public boolean isSnippet(ResolvedJavaMethod method) { - if (inRuntimeCode()) { + if (isAfterSnippetEncoding()) { return getEncodedSnippets().isSnippet(method); } return super.isSnippet(method); @@ -232,6 +260,19 @@ public static boolean snippetsAreEncoded() { @LibGraalSupport.HostedOnly// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; + SnippetTemplate.setHostedEncodedSnippets(snippetsAreEncoded()); + } + + @LibGraalSupport.HostedOnly// + @SuppressWarnings("try") + public boolean encode(OptionValues options) { + SymbolicSnippetEncoder encoder = snippetEncoder; + if (encoder != null) { + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { + return encoder.encode(options); + } + } + return false; } private static volatile EncodedSnippets encodedSnippets; @@ -243,7 +284,7 @@ public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (LibGraalSupport.inLibGraalRuntime()) { + if (isUsingEncodedSnippets()) { // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { @@ -256,7 +297,9 @@ public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod } assert !inBuildtimeCode() || registeredSnippets == null || registeredSnippets.contains(method) : "Asking for snippet method that was never registered: " + method.format("%H.%n(%p)"); - return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { + return super.getSnippet(method, original, args, nonNullParameters, trackNodeSourcePosition, replaceePosition, options); + } } @SuppressWarnings("unchecked") @@ -269,13 +312,13 @@ public T getInjectedArgument(Class capability) { } public static MetaAccessProvider noticeTypes(MetaAccessProvider metaAccess) { - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!inLibGraalRuntime()) { return SymbolicSnippetEncoder.noticeTypes(metaAccess); } return metaAccess; } - static boolean isGraalClass(ResolvedJavaType type) { + public static boolean isGraalClass(ResolvedJavaType type) { return isGraalClass(type.toClassName()); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index 4373fd196925..2c714cada6ac 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -27,7 +27,6 @@ import java.lang.reflect.Executable; import java.lang.reflect.Field; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; @@ -41,16 +40,28 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; + public class HotSpotSnippetMetaAccessProvider implements MetaAccessProvider { private final MetaAccessProvider delegate; - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { + /** + * {@code true} if the compiler is recording/replaying a compilation. + */ + private final boolean replayCompilationEnabled; + + public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate, boolean replayCompilationEnabled) { this.delegate = delegate; + this.replayCompilationEnabled = replayCompilationEnabled; + } + + public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { + this(delegate, false); } @Override public ResolvedJavaType lookupJavaType(Class clazz) { - if (LibGraalSupport.inLibGraalRuntime()) { + if (isAfterSnippetEncoding()) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); if (type != null) { return type; @@ -73,14 +84,14 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - if (LibGraalSupport.inLibGraalRuntime() && HotSpotReplacementsImpl.isGraalClass(clazz)) { + if (isAfterSnippetEncoding() && HotSpotReplacementsImpl.isGraalClass(clazz)) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); return type; } return delegate.lookupJavaType(clazz); } - if (constant instanceof HotSpotObjectConstant hsConstant) { + if (constant instanceof HotSpotObjectConstant hsConstant && !replayCompilationEnabled) { Object object = hsConstant.asObject(Object.class); if (object != null) { Class clazz = object.getClass(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java new file mode 100644 index 000000000000..7020c628a468 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/Platform.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot; + +import static jdk.graal.compiler.serviceprovider.GraalServices.getSavedProperty; + +import java.util.Set; + +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.util.CollectionsUtil; +import jdk.vm.ci.common.JVMCIError; + +/** + * The name of a known OS and architecture. + * + * @param osName the name of a known OS (one of {@link #KNOWN_OS_NAMES}) + * @param archName the name of a known architecture (one of {@link #KNOWN_ARCHITECTURES}) + */ +public record Platform(String osName, String archName) { + public Platform { + GraalError.guarantee(KNOWN_OS_NAMES.contains(osName), "unknown OS name"); + GraalError.guarantee(KNOWN_ARCHITECTURES.contains(archName), "unknown architecture"); + } + + /** + * Returns the platform of the current host based on system properties. + */ + public static Platform ofCurrentHost() { + return new Platform(getCurrentOSName(), getCurrentArchName()); + } + + public static final Set KNOWN_ARCHITECTURES = CollectionsUtil.setOf("amd64", "aarch64", "riscv64"); + + public static final Set KNOWN_OS_NAMES = CollectionsUtil.setOf("windows", "linux", "darwin"); + + /** + * Returns the name of the host OS. + */ + private static String getCurrentOSName() { + String value = getSavedProperty("os.name"); + switch (value) { + case "Linux": + value = "linux"; + break; + case "SunOS": + value = "solaris"; + break; + case "Mac OS X": + value = "darwin"; + break; + default: + // Windows names contain the OS version. + if (value.startsWith("Windows")) { + value = "windows"; + } else { + throw new JVMCIError("Unexpected OS name: " + value); + } + } + return value; + } + + /** + * Returns the name of the host architecture. + */ + private static String getCurrentArchName() { + String arch = getSavedProperty("os.arch"); + if (arch.equals("x86_64")) { + arch = "amd64"; + } + return arch; + } +} 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 36c94930b3ed..15658006810c 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 @@ -60,6 +60,7 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -356,7 +357,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), originalProvider.getRegisters(), originalProvider.getSnippetReflection(), originalProvider.getWordTypes(), originalProvider.getStampProvider(), originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getLoopsDataProvider(), originalProvider.getConfig(), - originalProvider.getIdentityHashCodeProvider()); + originalProvider.getIdentityHashCodeProvider(), originalProvider.getReplayCompilationSupport()); HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); @@ -367,7 +368,7 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod } StructuredGraph snippet = filteringReplacements.makeGraph(debug, filteringReplacements.getDefaultReplacementBytecodeProvider(), method, args, null, original, trackNodeSourcePosition, null); - EncodedSnippets.SymbolicEncodedGraph symbolicGraph = new EncodedSnippets.SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), null); + EncodedSnippets.SymbolicEncodedGraph symbolicGraph = new EncodedSnippets.SymbolicEncodedGraph(encodedGraph, method.getDeclaringClass(), null, false); StructuredGraph decodedSnippet = EncodedSnippets.decodeSnippetGraph(symbolicGraph, original != null ? original : method, original, originalReplacements, null, StructuredGraph.AllowAssumptions.ifNonNull(graph.getAssumptions()), graph.getOptions(), false); String snippetString = getCanonicalGraphString(snippet, true, false); @@ -424,6 +425,9 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { if (HotSpotReplacementsImpl.snippetsAreEncoded()) { + if (ReplayCompilationSupport.isReplayingLibgraalInJargraal()) { + return; + } throw new GraalError("Snippet encoding has already been done"); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java index 9d469c91bae5..64479a1f99b0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotForeignCallsProviderImpl.java @@ -46,12 +46,14 @@ import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage.RegisterEffect; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkageImpl; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.stubs.InvokeJavaMethodStub; import jdk.graal.compiler.hotspot.stubs.Stub; @@ -264,13 +266,23 @@ public void invokeJavaMethodStub(OptionValues options, public static final boolean DONT_PREPEND_THREAD = !PREPEND_THREAD; @Override + @SuppressWarnings("try") public HotSpotForeignCallLinkage lookupForeignCall(ForeignCallSignature signature) { GraalError.guarantee(foreignCalls != null, "%s", signature); HotSpotForeignCallLinkage callTarget = foreignCalls.get(signature); if (callTarget == null) { throw GraalError.shouldNotReachHere("Missing implementation for runtime call: " + signature); // ExcludeFromJacocoGeneratedReport } - callTarget.finalizeAddress(runtime.getHostBackend()); + if (callTarget.hasAddress()) { + return callTarget; + } + ReplayCompilationSupport support = getRuntime().getReplayCompilationSupport(); + if (support != null && support.finalizeForeignCallLinkage(signature, callTarget)) { + return callTarget; + } + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(support)) { + callTarget.finalizeAddress(runtime.getHostBackend()); + } return callTarget; } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java index 0a3dc1ea60c8..edf17c13eb2f 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotGraphBuilderPlugins.java @@ -96,6 +96,7 @@ import jdk.graal.compiler.core.common.type.ObjectStamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.common.type.TypeReference; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotBackend; @@ -116,6 +117,7 @@ import jdk.graal.compiler.hotspot.replacements.ObjectCloneNode; import jdk.graal.compiler.hotspot.replacements.UnsafeCopyMemoryNode; import jdk.graal.compiler.hotspot.replacements.UnsafeSetMemoryNode; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; import jdk.graal.compiler.java.BytecodeParser; import jdk.graal.compiler.lir.SyncPort; @@ -236,6 +238,7 @@ public static class Options { /** * Creates a {@link Plugins} object that should be used when running on HotSpot. */ + @SuppressWarnings("try") public static Plugins create(HotSpotGraalRuntimeProvider graalRuntime, CompilerConfiguration compilerConfiguration, GraalHotSpotVMConfig config, @@ -320,8 +323,10 @@ public void run() { // In libgraal, all NodeIntrinsics have already been converted into nodes. NodeIntrinsificationProvider nodeIntrinsificationProvider = new NodeIntrinsificationProvider(metaAccess, snippetReflection, foreignCalls, wordTypes, target); invocationPlugins.defer(() -> { - for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) { - factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); + try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(graalRuntime.getReplayCompilationSupport())) { + for (GeneratedPluginFactory factory : GraalServices.load(GeneratedPluginFactory.class)) { + factory.registerPlugins(invocationPlugins, nodeIntrinsificationProvider); + } } }); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 74e721af3e9f..65ea199b8596 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -28,6 +28,7 @@ import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_DREM; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_FREM; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_PARTITION; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_SORT; import static jdk.graal.compiler.hotspot.HotSpotBackend.BASE64_DECODE_BLOCK; @@ -120,7 +121,6 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.word.LocationIdentity; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; @@ -379,7 +379,7 @@ private void registerStubCallFunctions(OptionValues options, HotSpotProviders pr } registerForeignCall(INVOKE_STATIC_METHOD_ONE_ARG, invokeJavaMethodAddress, NativeCall); - if (!LibGraalSupport.inLibGraalRuntime()) { + if (!isUsingEncodedSnippets()) { /* * These functions are only used for testing purposes but their registration also * ensures that libgraal has support for InvokeJavaMethodStub built into the image, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java index 7e1f42cb720a..1e6f1dd314b7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotInvocationPlugins.java @@ -32,6 +32,7 @@ import java.util.List; import java.util.function.Predicate; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; import org.graalvm.collections.MapCursor; @@ -94,7 +95,12 @@ record MethodKey(String name, String descriptor) { } } - registerIntrinsificationPredicate(runtime().getIntrinsificationTrustPredicate(compilerConfiguration.getClass())); + Predicate predicate = runtime().getIntrinsificationTrustPredicate(compilerConfiguration.getClass()); + ReplayCompilationSupport replayCompilationSupport = graalRuntime.getReplayCompilationSupport(); + if (replayCompilationSupport != null) { + predicate = replayCompilationSupport.decorateIntrinsificationTrustPredicate(predicate); + } + registerIntrinsificationPredicate(predicate); } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java index dff5d5f9c340..874f9c0dbcbb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java @@ -28,6 +28,7 @@ import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; +import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; @@ -52,6 +53,11 @@ public class HotSpotProviders extends Providers { private final HotSpotRegistersProvider registers; private final GraalHotSpotVMConfig config; + /** + * The interface for recording and replaying compilations or {@code null} if disabled. + */ + private final ReplayCompilationSupport replayCompilationSupport; + public HotSpotProviders(MetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, @@ -68,12 +74,14 @@ public HotSpotProviders(MetaAccessProvider metaAccess, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider, GraalHotSpotVMConfig config, - IdentityHashCodeProvider identityHashCodeProvider) { + IdentityHashCodeProvider identityHashCodeProvider, + ReplayCompilationSupport replayCompilationSupport) { super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); this.suites = suites; this.registers = registers; this.config = config; + this.replayCompilationSupport = replayCompilationSupport; } @Override @@ -117,7 +125,7 @@ public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider()); + config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); } @Override @@ -126,7 +134,7 @@ public HotSpotProviders copyWith(ConstantFieldProvider substitution) { getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider()); + config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); } @Override @@ -134,17 +142,24 @@ public HotSpotProviders copyWith(Replacements substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), - getLoopsDataProvider(), config, getIdentityHashCodeProvider()); + getLoopsDataProvider(), config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); } public HotSpotProviders copyWith() { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config, getIdentityHashCodeProvider()); + config, getIdentityHashCodeProvider(), getReplayCompilationSupport()); } public void setSuites(HotSpotSuitesProvider suites) { this.suites = suites; } + + /** + * Returns the interface for recording and replaying compilations or {@code null} if disabled. + */ + public ReplayCompilationSupport getReplayCompilationSupport() { + return replayCompilationSupport; + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index 14649c1fa292..975975f3087a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.hotspot.meta; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import java.lang.reflect.Executable; @@ -31,14 +32,12 @@ import java.util.Objects; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.SnippetObjectConstant; import jdk.graal.compiler.word.WordTypes; - import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; @@ -63,7 +62,7 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { - if (LibGraalSupport.inLibGraalRuntime()) { + if (isAfterSnippetEncoding()) { HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); // This can only be a compiler object when in libgraal. return new SnippetObjectConstant(object); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java new file mode 100644 index 000000000000..e419bc98e993 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; + +/** + * A holder and factory for compiler-interface proxies during a recorded/replayed compilation. + */ +public interface CompilationProxies { + /** + * Proxifies an instance of a registered compiler-interface class. In general, the returned + * proxy either records or replays the results of method invocations based on the argument + * values. The registered classes are declared by {@link CompilerInterfaceDeclarations} + * ({@link #getDeclarations()}). The behavior of the proxy is also defined by + * {@link CompilerInterfaceDeclarations}. + * + * @param input the instance for which a proxy should be created + * @return the proxy object + */ + CompilationProxy proxify(Object input); + + /** + * Gets the compiler interface declarations. This class defines for which classes proxies should + * be created and the method invocation behavior of these proxies. + * + * @return compiler interface declarations + */ + CompilerInterfaceDeclarations getDeclarations(); + + /** + * Enters the context of a snippet compilation. + * + * @return a debug closeable object representing the snippet context + */ + DebugCloseable enterSnippetContext(); + + /** + * Gets the target platform (the host platform during recording and the compilation target + * during replay). + */ + Platform targetPlatform(); + + /** + * Temporarily sets a debug context. + * + * @param debugContext the debug context to enter + * @return a debug closeable object representing the debug context + */ + DebugCloseable withDebugContext(DebugContext debugContext); +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java new file mode 100644 index 000000000000..2a1f69d04b86 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxyMapper.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.lang.reflect.Array; +import java.util.Map; +import java.util.WeakHashMap; +import java.util.function.Function; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; + +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.code.DebugInfo; +import jdk.vm.ci.code.StackLockValue; +import jdk.vm.ci.code.VirtualObject; +import jdk.vm.ci.code.site.Call; +import jdk.vm.ci.code.site.ConstantReference; +import jdk.vm.ci.code.site.DataPatch; +import jdk.vm.ci.code.site.ImplicitExceptionDispatch; +import jdk.vm.ci.code.site.Infopoint; +import jdk.vm.ci.code.site.Reference; +import jdk.vm.ci.code.site.Site; +import jdk.vm.ci.hotspot.HotSpotCompiledNmethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotSpeculationLog; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.EncodedSpeculationReason; +import jdk.vm.ci.meta.InvokeTarget; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaMethodProfile; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.JavaValue; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.UnresolvedJavaField; +import jdk.vm.ci.meta.UnresolvedJavaMethod; +import jdk.vm.ci.meta.VMConstant; + +/** + * Recursively proxifies or unproxifies instances of registered classes in composite objects. + *

+ * {@link CompilerInterfaceDeclarations} declares for which JVMCI objects proxies should be created. + * When these objects are stored inside composite objects (e.g., inside arrays or + * {@link DebugInfo}), this class can create deep copies of such composite objects, replacing the + * registered instances with proxies. This mapping is performed by the {@link #proxifyRecursive} + * method. + *

+ * This class can also perform the reverse mapping, i.e., create a deep copy of an object and + * replace the proxy with a local JVMCI object (by calling {@link CompilationProxy#unproxify()} on + * the proxies). This is performed by the {@link #unproxifyRecursive}. + */ +public class CompilationProxyMapper { + /** + * Declares the registered classes, indicating which objects should be proxified. + */ + private final CompilerInterfaceDeclarations declarations; + + /** + * Function that proxifies instances of registered classes. + */ + private final Function proxify; + + /** + * Maps instances of proxified arrays to the component types of the original arrays. + */ + private final Map> originalComponentType; + + /** + * Constructs a new proxy mapper. + * + * @param declarations the compiler interface declarations + * @param proxify the function used to proxify a single registered instance + */ + public CompilationProxyMapper(CompilerInterfaceDeclarations declarations, Function proxify) { + this.declarations = declarations; + this.proxify = proxify; + this.originalComponentType = new WeakHashMap<>(); + } + + /** + * Proxifies the given object, i.e., creates proxies for the instances of registered types and + * replaces them with proxies. + * + * @param input the input object + * @return an object where the registered instances are replaced with proxies + */ + public Object proxifyRecursive(Object input) { + return proxifyInternal(input, null); + } + + /** + * Unproxifies the given object, i.e., removes proxies from the instances of registered types. + * + * @param input the input object + * @return an object where the proxies are replaced with the original objects/local mirrors + */ + public Object unproxifyRecursive(Object input) { + return unproxifyInternal(input, null); + } + + @FunctionalInterface + private interface Mapper { + Object apply(Object input, EconomicMap cache); + } + + private Object proxifyInternal(Object input, EconomicMap cache) { + if (input instanceof Object[] array) { + Class originalClazz = input.getClass().componentType(); + Class adjustedClazz = declarations.findRegisteredSupertype(originalClazz); + if (adjustedClazz == null) { + adjustedClazz = originalClazz; + } + Object[] result = (Object[]) Array.newInstance(adjustedClazz, array.length); + for (int i = 0; i < array.length; i++) { + result[i] = proxifyInternal(array[i], null); + } + if (!adjustedClazz.equals(originalClazz)) { + originalComponentType.put(result, originalClazz); + } + return result; + } else if (declarations.isRegisteredClassInstance(input)) { + return proxify.apply(input); + } else { + return map(input, this::proxifyInternal, cache); + } + } + + private Object unproxifyInternal(Object input, EconomicMap cache) { + if (input instanceof Object[] array) { + Class clazz = originalComponentType.get(input); + if (clazz == null) { + clazz = input.getClass().componentType(); + } + Object[] result = (Object[]) Array.newInstance(clazz, array.length); + for (int i = 0; i < array.length; i++) { + result[i] = unproxifyInternal(array[i], cache); + } + return result; + } else if (input instanceof CompilationProxy compilationProxy) { + return compilationProxy.unproxify(); + } else { + return map(input, this::unproxifyInternal, cache); + } + } + + private static Object map(Object input, Mapper mapper, EconomicMap cache) { + switch (input) { + case SpecialResultMarker.ExceptionThrownMarker marker -> { + return new SpecialResultMarker.ExceptionThrownMarker((Throwable) mapper.apply(marker.getThrown(), cache)); + } + case HotSpotCompiledNmethod nmethod -> { + return new HotSpotCompiledNmethod(nmethod.getName(), nmethod.getTargetCode(), nmethod.getTargetCodeSize(), + (Site[]) mapper.apply(nmethod.getSites(), cache), (Assumptions.Assumption[]) mapper.apply(nmethod.getAssumptions(), cache), + (ResolvedJavaMethod[]) mapper.apply(nmethod.getMethods(), cache), nmethod.getComments(), + nmethod.getDataSection(), nmethod.getDataSectionAlignment(), (DataPatch[]) mapper.apply(nmethod.getDataSectionPatches(), cache), nmethod.isImmutablePIC(), + nmethod.getTotalFrameSize(), nmethod.getDeoptRescueSlot(), (HotSpotResolvedJavaMethod) mapper.apply(nmethod.getMethod(), cache), nmethod.getEntryBCI(), + nmethod.getId(), nmethod.getCompileState(), nmethod.hasUnsafeAccess()); + } + case Call call -> { + return new Call((InvokeTarget) mapper.apply(call.target, cache), call.pcOffset, call.size, call.direct, (DebugInfo) mapper.apply(call.debugInfo, cache)); + } + case ImplicitExceptionDispatch dispatch -> { + return new ImplicitExceptionDispatch(dispatch.pcOffset, dispatch.dispatchOffset, (DebugInfo) mapper.apply(dispatch.debugInfo, cache)); + } + case Infopoint infopoint -> { + return new Infopoint(infopoint.pcOffset, (DebugInfo) mapper.apply(infopoint.debugInfo, cache), infopoint.reason); + } + case DataPatch dataPatch -> { + return new DataPatch(dataPatch.pcOffset, (Reference) mapper.apply(dataPatch.reference, cache), mapper.apply(dataPatch.note, cache)); + } + case ConstantReference constantReference -> { + return new ConstantReference((VMConstant) mapper.apply(constantReference.getConstant(), cache)); + } + case HotSpotSpeculationLog.HotSpotSpeculation speculation -> { + return new HotSpotSpeculationLog.HotSpotSpeculation((SpeculationLog.SpeculationReason) mapper.apply(speculation.getReason(), cache), + (JavaConstant) mapper.apply(speculation.getEncoding(), cache), speculation.getReasonEncoding()); + } + case SpeculationLog.Speculation speculation -> { + return new SpeculationLog.Speculation((SpeculationLog.SpeculationReason) mapper.apply(speculation.getReason(), cache)); + } + case EncodedSpeculationReason speculationReason -> { + return new EncodedSpeculationReason(speculationReason.getGroupId(), speculationReason.getGroupName(), (Object[]) mapper.apply(speculationReason.getContext(), cache)); + } + case BytecodeFrame bytecodeFrame -> { + return new BytecodeFrame((BytecodeFrame) mapper.apply(bytecodeFrame.caller(), cache), (ResolvedJavaMethod) mapper.apply(bytecodeFrame.getMethod(), cache), + bytecodeFrame.getBCI(), bytecodeFrame.rethrowException, bytecodeFrame.duringCall, (JavaValue[]) mapper.apply(bytecodeFrame.values, cache), + bytecodeFrame.getSlotKinds(), bytecodeFrame.numLocals, bytecodeFrame.numStack, bytecodeFrame.numLocks); + } + case BytecodePosition bytecodePosition -> { + return new BytecodePosition((BytecodePosition) mapper.apply(bytecodePosition.getCaller(), cache), (ResolvedJavaMethod) mapper.apply(bytecodePosition.getMethod(), cache), + bytecodePosition.getBCI()); + } + case StackLockValue value -> { + return new StackLockValue((JavaValue) mapper.apply(value.getOwner(), cache), value.getSlot(), value.isEliminated()); + } + case JavaTypeProfile typeProfile -> { + return new JavaTypeProfile(typeProfile.getNullSeen(), typeProfile.getNotRecordedProbability(), (JavaTypeProfile.ProfiledType[]) mapper.apply(typeProfile.getTypes(), cache)); + } + case JavaTypeProfile.ProfiledType profiledType -> { + return new JavaTypeProfile.ProfiledType((ResolvedJavaType) mapper.apply(profiledType.getType(), cache), profiledType.getProbability()); + } + case JavaMethodProfile methodProfile -> { + return new JavaMethodProfile(methodProfile.getNotRecordedProbability(), (JavaMethodProfile.ProfiledMethod[]) mapper.apply(methodProfile.getMethods(), cache)); + } + case JavaMethodProfile.ProfiledMethod profiledMethod -> { + return new JavaMethodProfile.ProfiledMethod((ResolvedJavaMethod) mapper.apply(profiledMethod.getMethod(), cache), profiledMethod.getProbability()); + } + case DebugInfo debugInfo -> { + DebugInfo newDebugInfo = new DebugInfo((BytecodePosition) mapper.apply(debugInfo.frame(), cache), (VirtualObject[]) mapper.apply(debugInfo.getVirtualObjectMapping(), cache)); + newDebugInfo.setCalleeSaveInfo(debugInfo.getCalleeSaveInfo()); + newDebugInfo.setReferenceMap(debugInfo.getReferenceMap()); + return newDebugInfo; + } + case VirtualObject virtualObject -> { + VirtualObject newVirtualObject = VirtualObject.get((ResolvedJavaType) mapper.apply(virtualObject.getType(), cache), virtualObject.getId(), virtualObject.isAutoBox()); + EconomicMap selectedCache = cache; + if (selectedCache == null) { + selectedCache = EconomicMap.create(Equivalence.IDENTITY); + } else { + Object found = selectedCache.get(virtualObject); + if (found != null) { + return found; + } + } + selectedCache.put(virtualObject, newVirtualObject); + if (virtualObject.getValues() != null) { + newVirtualObject.setValues((JavaValue[]) mapper.apply(virtualObject.getValues(), selectedCache), virtualObject.getSlotKinds()); + } + return newVirtualObject; + } + case Assumptions.AssumptionResult result -> { + Assumptions assumptions = new Assumptions(); + result.recordTo(assumptions); + return new Assumptions.AssumptionResult<>(mapper.apply(result.getResult(), cache), (Assumptions.Assumption[]) mapper.apply(assumptions.toArray(), cache)); + } + case Assumptions.NoFinalizableSubclass assumption -> { + return new Assumptions.NoFinalizableSubclass((ResolvedJavaType) mapper.apply(assumption.receiverType, cache)); + } + case Assumptions.ConcreteSubtype assumption -> { + return new Assumptions.ConcreteSubtype((ResolvedJavaType) mapper.apply(assumption.context, cache), (ResolvedJavaType) mapper.apply(assumption.subtype, cache)); + } + case Assumptions.LeafType assumption -> { + return new Assumptions.LeafType((ResolvedJavaType) mapper.apply(assumption.context, cache)); + } + case Assumptions.ConcreteMethod assumption -> { + return new Assumptions.ConcreteMethod((ResolvedJavaMethod) mapper.apply(assumption.method, cache), (ResolvedJavaType) mapper.apply(assumption.context, cache), + (ResolvedJavaMethod) mapper.apply(assumption.impl, cache)); + } + case Assumptions.CallSiteTargetValue assumption -> { + return new Assumptions.CallSiteTargetValue((JavaConstant) mapper.apply(assumption.callSite, cache), (JavaConstant) mapper.apply(assumption.methodHandle, cache)); + } + case jdk.vm.ci.meta.ExceptionHandler exceptionHandler -> { + return new jdk.vm.ci.meta.ExceptionHandler(exceptionHandler.getStartBCI(), exceptionHandler.getEndBCI(), + exceptionHandler.getHandlerBCI(), exceptionHandler.catchTypeCPI(), (JavaType) mapper.apply(exceptionHandler.getCatchType(), cache)); + } + case UnresolvedJavaMethod method -> { + return new UnresolvedJavaMethod(method.getName(), (Signature) mapper.apply(method.getSignature(), cache), (JavaType) mapper.apply(method.getDeclaringClass(), cache)); + } + case UnresolvedJavaField field -> { + return new UnresolvedJavaField((JavaType) mapper.apply(field.getDeclaringClass(), cache), field.getName(), (JavaType) mapper.apply(field.getType(), cache)); + } + case DelayedDeserializationObject delayedDeserialization -> { + return mapper.apply(delayedDeserialization.deserialize(), cache); + } + case null, default -> { + return input; + } + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java new file mode 100644 index 000000000000..1da729880499 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import static java.util.FormattableFlags.ALTERNATE; +import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEDYNAMIC; +import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEINTERFACE; +import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; +import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; +import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; +import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; + +import java.lang.reflect.Proxy; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Formattable; +import java.util.Formatter; +import java.util.List; +import java.util.function.Predicate; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; +import org.graalvm.collections.UnmodifiableEconomicMap; + +import jdk.graal.compiler.bytecode.BytecodeStream; +import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.graph.NodeClass; +import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.ConstantPoolProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotCodeCacheProviderProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantReflectionProviderProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotMetaspaceConstantProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotObjectConstantProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotProfilingInfoProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaFieldProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaMethodProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedJavaTypeProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedObjectTypeProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.MetaAccessProviderProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.ProfilingInfoProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; +import jdk.graal.compiler.java.LambdaUtils; +import jdk.graal.compiler.replacements.SnippetCounter; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotProfilingInfo; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.hotspot.HotSpotResolvedPrimitiveType; +import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; + +/** + * Defines how the VM's interface to the compiler should be recorded and replayed. + * + *

+ * Recording and replaying is implemented by instrumenting JVMCI. For relevant JVMCI objects and + * service providers ({@link HotSpotResolvedJavaMethod}, {@link MetaAccessProvider}...), we create + * proxy implementations ({@link HotSpotResolvedJavaMethodProxy}, {@link MetaAccessProvider}...). + * These proxies do not implement any specific behavior; {@link CompilerInterfaceDeclarations} + * declares this behavior. {@link RecordingCompilationProxies} and {@link ReplayCompilationProxies} + * then provide proxy instance with the declared behavior during recording and replay, respectively. + * + *

+ * Registered Classes. This class defines for which JVMCI object we must create proxies + * during recording and replay. Whether an object is an instance of such a class can be queried + * using {@link #isRegisteredClassInstance} and the registration can be obtained with + * {@link #findRegistrationForInstance}. The {@link Registration} describes the behavior of the + * individual methods during replay and recording, how local mirrors are located, and other + * information. + * + *

+ * Method Registrations. A {@link MethodRegistration} describes the behavior of a proxy + * method invocation during recording and replay and also provides the arguments of method calls + * whose results should always be recorded even if the compiler does not invoke the method during + * the recorded compilation. The results of these operations may be needed during replay, e.g., to + * produce some diagnostic output. A default registration + * ({@link MethodRegistrationBuilder#createDefault}) is used if this class does not explicitly + * override it. {@link MethodStrategy} defines the behavior of a method during recording and replay. + * + *

+ * Recording. During recording, the proxies ({@link RecordingCompilationProxies}) either save + * the result of a method invocation or not. The result of a method invocation (an operation) is + * either a return value or an exception. The result is saved iff the strategy is + * {@link MethodStrategy#RecordReplay}. The recording proxies also ensure the result of an operation + * is stable during a single compilation by caching the result when the operation is performed for + * the first time. Subsequent proxy method invocations reuse the recorded result. + *

+ * At the end of a compilation, we also perform and record additional calls whose results could be + * needed during replay. These calls are declared in this class using {@link MethodCallToRecord} + * instances or a {@link MethodCallsToRecordProvider}. + * + *

+ * Replay. During a replayed compilation, there are multiple ways how to obtain a result for + * an operation invoked on a proxy object. The options are the following: + *

    + *
  • Look up a result in the recorded JSON file using the values of the argument and the + * receiver.
  • + *
  • Invoke the same method on a local mirror (may also replace the arguments with local + * mirrors).
  • + *
  • Return a predefined default value (e.g., {@code null}, {@code 0}, {@code false}) or a default + * value computed by an instance of {@link OperationResultSupplier}.
  • + *
  • Delegate to a fallback handler, which is also an instance of + * {@link OperationResultSupplier}.
  • + *
  • Ad-hoc special handling (for {@link Object#equals}, {@link Object#hashCode}).
  • + *
+ * In many conditions, only some of these options are available (there may be no recorded result, no + * local mirror, no fallback handler...). A {@link MethodStrategy} defines which of these options + * should be tried in what order and also which conditions are considered errors. + */ +public final class CompilerInterfaceDeclarations { + /** + * The strategy for replaying/recording a method. These strategies are implemented in + * {@link RecordingCompilationProxies} and {@link ReplayCompilationProxies} for recording and + * replay, respectively. + */ + public enum MethodStrategy { + /** + * A strategy that records the method's results and replays them. This is the default + * strategy for most methods. + *

+ * During recording, the strategy records the result of a method the first time it is + * invoked. If the compiler invokes the method with the same arguments again, the recorded + * result is returned instead of re-executing the method. This ensures a set of arguments + * can be unambiguously mapped to a result. + *

+ * During replay, the strategy looks up and returns the result from the recorded JSON file. + *

    + *
  • If no appropriate recorded result is found, falls back to invoking the same method on + * local mirrors (replacing both the receiver and arguments with local mirrors).
  • + *
  • If a local mirror cannot be identified, invokes the fallback handler.
  • + *
  • If there is no fallback handler, returns the default value. This is considered an + * error if {@link ReplayCompilationProxies.Options#ReplayDivergenceIsFailure} is set.
  • + *
+ */ + RecordReplay, + + /** + * A strategy that does not record the method's results and invokes the local mirror instead + * (without unproxifying the arguments). + *

+ * During recording, the results of method calls are not recorded since they will not be + * needed during replay. + *

+ * During replay, the strategy invokes the same method on the local mirror without + * unproxifying the arguments. Invokes the fallback handler if there is no local mirror. + */ + Passthrough, + + /** + * A strategy that does not record the method's results and returns a pre-defined or + * computed value during replay. + *

+ * During recording, the results of method calls are not recorded since they will not be + * needed during replay. + *

+ * During replay, the strategy returns the value computed by + * {@link Registration#findDefaultValue}. + */ + DefaultValue, + + /** + * A strategy that does not record the method's results and is handled specially during + * replay. + */ + Special + } + + /** + * Supplies the result of an operation during replay. + */ + @FunctionalInterface + public interface OperationResultSupplier { + /** + * Computes the result of the invoked method. + * + * @param proxy the proxy receiver + * @param method the invoked method + * @param args the arguments to the method + * @param singletonObjects a map of provider classes to instances + * @return the result of the operation + */ + Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects); + } + + /** + * Finds the local mirror of a proxy object during replay. + */ + @FunctionalInterface + public interface LocalMirrorLocator { + /** + * Finds and returns the local mirror of the given proxy object or {@code null} if not + * found. + * + * @param proxy the proxy object + * @param singletonObjects a map of provider classes to instances + * @return the local mirror or {@code null} + */ + Object findLocalMirror(Object proxy, EconomicMap, Object> singletonObjects); + } + + /** + * Provides a list of method calls that should be recorded for a given receiver object. + */ + @FunctionalInterface + public interface MethodCallsToRecordProvider { + /** + * Returns a list of method calls that should be recorded in the serialized compilation unit + * for the given receiver object. Every such call should be performed and recorded at the + * end of the compilation unless it was already recorded during the compilation. + * + * @param receiver the receiver object + * @return a list of method calls that should be recorded + */ + List getMethodCallsToRecord(Object receiver); + } + + /** + * Describes the recording and replay behavior for a method of one of the registered classes. + * + * @param methodStrategy the strategy to record/replay the method's results + * @param defaultValueSupplier a supplier for a default result value or {@code null} + * @param defaultValue the default result value + * @param callsToRecordArguments a list of argument arrays for which the method results should + * be recorded in the serialized compilation unit + * @param fallbackInvocationHandler a handler to use as a fallback when there is no recorded + * result or {@code null} + * @param invokableMethod a lambda to invoke the method (needed if there are calls to record) or + * {@code null} + */ + public record MethodRegistration(MethodStrategy methodStrategy, OperationResultSupplier defaultValueSupplier, Object defaultValue, + List callsToRecordArguments, OperationResultSupplier fallbackInvocationHandler, CompilationProxy.InvokableMethod invokableMethod) { + public MethodRegistration { + if (!callsToRecordArguments.isEmpty()) { + GraalError.guarantee(invokableMethod != null, "invokable method needed because there are calls that must be recorded"); + } + } + } + + /** + * Describes a method call that should be recorded in the serialized compilation unit. + * + * @param receiver the receiver object of the call + * @param symbolicMethod the method to invoke + * @param invokableMethod a lambda to invoke the method + * @param args the arguments to use for the method call (can be {@code null} for methods without + * parameters) + */ + public record MethodCallToRecord(Object receiver, CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object[] args) { + public MethodCallToRecord { + int argsLength = (args == null) ? 0 : args.length; + GraalError.guarantee(argsLength == symbolicMethod.paramCount(), "the provided number of arguments does not match the method signature"); + } + } + + /** + * Describes the recording and replay behavior of a compiler-interface class. + * + * @param clazz the class + * @param singleton {@code true} iff the class should be treated as a singleton (e.g., a + * provider) + * @param mirrorLocator a method that can find the local mirror of a proxy during replay or + * {@code null} + * @param methods the recording/replay behavior the methods - only needed for non-default + * behavior + * @param extraInterfaces additional interfaces the proxy should implement + * @param methodCallsToRecordProvider provides the methods calls that should be recorded in the + * serialized compilation unit + */ + public record Registration(Class clazz, boolean singleton, LocalMirrorLocator mirrorLocator, + UnmodifiableEconomicMap methods, Class[] extraInterfaces, + MethodCallsToRecordProvider methodCallsToRecordProvider) { + /** + * Finds the recording/replay strategy for a method of this class. + * + * @param method the method + * @return the strategy + */ + public MethodStrategy findStrategy(CompilationProxy.SymbolicMethod method) { + MethodRegistration found = methods.get(method); + if (found == null) { + return MethodRegistrationBuilder.defaultStrategy(method); + } else { + return found.methodStrategy; + } + } + + /** + * Finds the default value to return for a given call. + * + * @param proxy the proxy receiver object + * @param method the invoked method + * @param args the arguments passed to the invocation + * @param singletonObjects a map of provider classes to instances + * @return the default value + */ + public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + MethodRegistration found = methods.get(method); + if (found == null) { + return null; + } else if (found.defaultValueSupplier != null) { + return found.defaultValueSupplier.apply(proxy, method, args, singletonObjects); + } else { + return found.defaultValue; + } + } + + /** + * Finds a fallbacks handler for an invoked method. + * + * @param method the invoked method + * @return a handler or {@code null} + */ + public OperationResultSupplier findFallbackHandler(CompilationProxy.SymbolicMethod method) { + MethodRegistration found = methods.get(method); + if (found == null) { + return null; + } else { + return found.fallbackInvocationHandler; + } + } + + /** + * Gets a list of method calls that should be recorded in the serialized compilation unit. + * + * @param receiver the receiver object + * @return a list of method calls that should be recorded + */ + public List getMethodCallsToRecord(Object receiver) { + List calls = new ArrayList<>(); + var cursor = methods.getEntries(); + while (cursor.advance()) { + for (Object[] arguments : cursor.getValue().callsToRecordArguments()) { + calls.add(new MethodCallToRecord(receiver, cursor.getKey(), cursor.getValue().invokableMethod(), arguments)); + } + } + if (methodCallsToRecordProvider != null) { + calls.addAll(methodCallsToRecordProvider.getMethodCallsToRecord(receiver)); + } + return calls; + } + + /** + * Finds an invokable method for the given symbolic method. + * + * @param method the symbolic method + * @return the invokable method or {@code null} if not found + */ + public CompilationProxy.InvokableMethod findInvokableMethod(CompilationProxy.SymbolicMethod method) { + MethodRegistration found = methods.get(method); + if (found == null) { + return null; + } + return found.invokableMethod; + } + } + + private static final class MethodRegistrationBuilder { + private MethodStrategy methodStrategy; + private OperationResultSupplier defaultValueSupplier; + private Object defaultValue; + private final List callsToRecordArguments; + private OperationResultSupplier fallbackInvocationHandler; + private CompilationProxy.InvokableMethod invokableMethod; + + private MethodRegistrationBuilder(MethodStrategy methodStrategy, CompilationProxy.InvokableMethod invokableMethod, List callsToRecordArguments) { + this.methodStrategy = methodStrategy; + this.invokableMethod = invokableMethod; + this.callsToRecordArguments = callsToRecordArguments; + } + + public static MethodRegistrationBuilder createDefault(CompilationProxy.SymbolicMethod method) { + CompilationProxy.InvokableMethod invokableMethod = null; + List callsToRecordArguments = new ArrayList<>(); + if (CompilationProxyBase.toStringMethod.equals(method)) { + invokableMethod = (receiver, args) -> receiver.toString(); + callsToRecordArguments.add(null); + } + return new MethodRegistrationBuilder(defaultStrategy(method), invokableMethod, callsToRecordArguments); + } + + public static MethodStrategy defaultStrategy(CompilationProxy.SymbolicMethod method) { + if (CompilationProxyBase.hashCodeMethod.equals(method) || CompilationProxyBase.equalsMethod.equals(method) || CompilationProxyBase.toStringMethod.equals(method)) { + return MethodStrategy.Special; + } else { + return MethodStrategy.RecordReplay; + } + } + + private MethodRegistration build() { + return new MethodRegistration(methodStrategy, defaultValueSupplier, defaultValue, Collections.unmodifiableList(callsToRecordArguments), + fallbackInvocationHandler, invokableMethod); + } + } + + private static class RegistrationBuilder { + private final Class clazz; + + private boolean singleton; + + private LocalMirrorLocator mirrorLocator; + + private final EconomicMap methods; + + private final Class[] extraInterfaces; + + private MethodCallsToRecordProvider methodCallsToRecordProvider; + + RegistrationBuilder(Class clazz, Class... extraInterfaces) { + this.clazz = clazz; + this.methods = EconomicMap.create(); + this.extraInterfaces = extraInterfaces; + this.methods.put(CompilationProxyBase.toStringMethod, MethodRegistrationBuilder.createDefault(CompilationProxyBase.toStringMethod)); + } + + public RegistrationBuilder setLocalMirrorLocator(LocalMirrorLocator newLocator) { + mirrorLocator = newLocator; + return this; + } + + public RegistrationBuilder setSingleton(boolean newSingleton) { + singleton = newSingleton; + return this; + } + + private MethodRegistrationBuilder findRegistrationBuilder(CompilationProxy.SymbolicMethod symbolicMethod) { + MethodRegistrationBuilder builder = methods.get(symbolicMethod); + if (builder == null) { + builder = MethodRegistrationBuilder.createDefault(symbolicMethod); + methods.put(symbolicMethod, builder); + } + return builder; + } + + public RegistrationBuilder setStrategy(CompilationProxy.SymbolicMethod method, MethodStrategy strategy) { + findRegistrationBuilder(method).methodStrategy = strategy; + return this; + } + + public RegistrationBuilder setFallbackInvocationHandler(CompilationProxy.SymbolicMethod method, OperationResultSupplier handler) { + findRegistrationBuilder(method).fallbackInvocationHandler = handler; + return this; + } + + public RegistrationBuilder setDefaultValueStrategy(CompilationProxy.SymbolicMethod symbolicMethod, Object defaultValue) { + MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); + builder.methodStrategy = MethodStrategy.DefaultValue; + builder.defaultValue = defaultValue; + return this; + } + + public RegistrationBuilder setDefaultValue(CompilationProxy.SymbolicMethod method, Object defaultValue) { + findRegistrationBuilder(method).defaultValue = defaultValue; + return this; + } + + public RegistrationBuilder setDefaultValueSupplier(CompilationProxy.SymbolicMethod symbolicMethod, OperationResultSupplier supplier) { + MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); + builder.defaultValue = null; + builder.defaultValueSupplier = supplier; + return this; + } + + public RegistrationBuilder ensureRecorded(CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object... arguments) { + MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); + builder.callsToRecordArguments.add(arguments); + builder.invokableMethod = invokableMethod; + return this; + } + + public RegistrationBuilder provideMethodCallsToRecord(MethodCallsToRecordProvider newProvider) { + methodCallsToRecordProvider = newProvider; + return this; + } + + private void register(CompilerInterfaceDeclarations declarations) { + EconomicMap registrations = EconomicMap.create(); + var cursor = methods.getEntries(); + while (cursor.advance()) { + registrations.put(cursor.getKey(), cursor.getValue().build()); + } + declarations.addRegistration(new Registration(clazz, singleton, mirrorLocator, registrations, extraInterfaces, methodCallsToRecordProvider)); + } + } + + /** + * The list of the registered compiler-interface classes whose methods are recorded/replayed. + */ + private final List> classes; + + /** + * Maps the registered classes to the appropriate registrations. + */ + private final EconomicMap, Registration> registrations; + + private final EconomicMap, Class> supertypeCache; + + private static final Class NOT_REGISTERED = Class.class; + + private CompilerInterfaceDeclarations() { + classes = new ArrayList<>(); + registrations = EconomicMap.create(); + supertypeCache = EconomicMap.create(Equivalence.IDENTITY); + } + + /** + * Gets an iterable of the registered compiler-interface classes. + */ + public Iterable getRegistrations() { + return registrations.getValues(); + } + + private void addRegistration(Registration registration) { + classes.add(registration.clazz); + registrations.put(registration.clazz, registration); + } + + /** + * Finds and returns the registered supertype of the given type if it has a registered + * supertype. + * + * @param type the given type + * @return a registered (super)type or {@code null} + */ + public Class findRegisteredSupertype(Class type) { + Class cached = supertypeCache.get(type); + if (cached != null) { + if (cached == NOT_REGISTERED) { + return null; + } + return cached; + } + for (Class declared : classes) { + if (declared.isAssignableFrom(type)) { + supertypeCache.put(type, declared); + return declared; + } + } + supertypeCache.put(type, NOT_REGISTERED); + return null; + } + + /** + * Returns {@code true} if the given object is an instance of a registered class. + * + * @param object the object + * @return {@code true} if the given object is an instance of a registered class + */ + public boolean isRegisteredClassInstance(Object object) { + if (object == null) { + return false; + } + return findRegisteredSupertype(object.getClass()) != null; + } + + /** + * Finds the registration for the type of the given object if it is an instance of a registered + * type. + * + * @param object the object + * @return the registration or {@code null} + */ + public Registration findRegistrationForInstance(Object object) { + if (object == null) { + return null; + } + return registrations.get(findRegisteredSupertype(object.getClass())); + } + + /** + * Creates and returns a description of how the compiler interface should be recorded and + * replayed. + * + * @implNote The {@link MethodRegistrationBuilder#defaultStrategy default strategy} is + * sufficient for most methods, and it does not require an explicit registration. + */ + public static CompilerInterfaceDeclarations build() { + // @formatter:off + CompilerInterfaceDeclarations declarations = new CompilerInterfaceDeclarations(); + new RegistrationBuilder<>(HotSpotVMConfigAccess.class).setSingleton(true) + .register(declarations); + new RegistrationBuilder<>(MetaAccessProvider.class).setSingleton(true) + .setStrategy(MetaAccessProviderProxy.encodeDeoptActionAndReasonMethod, MethodStrategy.Passthrough) + .setStrategy(MetaAccessProviderProxy.decodeDeoptReasonMethod, MethodStrategy.Passthrough) + .setStrategy(MetaAccessProviderProxy.decodeDeoptActionMethod, MethodStrategy.Passthrough) + .setStrategy(MetaAccessProviderProxy.decodeDebugIdMethod, MethodStrategy.Passthrough) + .setStrategy(MetaAccessProviderProxy.encodeSpeculationMethod, MethodStrategy.Passthrough) + .setDefaultValue(MetaAccessProviderProxy.decodeSpeculationMethod, SpeculationLog.NO_SPECULATION) + .setStrategy(MetaAccessProviderProxy.getArrayBaseOffsetMethod, MethodStrategy.Passthrough) + .setStrategy(MetaAccessProviderProxy.getArrayIndexScaleMethod, MethodStrategy.Passthrough) + .provideMethodCallsToRecord((input) -> { + List result = new ArrayList<>(); + if (!LibGraalSupport.inLibGraalRuntime()) { + // Record the calls needed for HotSpotGraalConstantFieldProvider in jargraal. + // Not needed in libgraal because the lookups are handled by HotSpotSnippetMetaAccessProvider. + for (Class clazz : List.of(GraalHotSpotVMConfig.class, SnippetCounter.class, NodeClass.class)) { + result.add(new MethodCallToRecord(input, MetaAccessProviderProxy.lookupJavaTypeClassMethod, MetaAccessProviderProxy.lookupJavaTypeClassInvokable, new Object[]{clazz})); + } + } + return result; + }) + .setFallbackInvocationHandler(MetaAccessProviderProxy.lookupJavaTypeClassMethod, (proxy, method, args, singletonObjects) -> { + // Needed for Word types when replaying libgraal compilations on jargraal. + Class clazz = (Class) args[0]; + MetaAccessProvider localMetaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType localMirror = localMetaAccess.lookupJavaType(clazz); + if (localMirror == null) { + throw new IllegalArgumentException(); + } + return localMirror; + }) + .register(declarations); + new RegistrationBuilder<>(HotSpotConstantReflectionProvider.class).setSingleton(true) + .ensureRecorded(HotSpotConstantReflectionProviderProxy.forObjectMethod, HotSpotConstantReflectionProviderProxy.forObjectInvokable,(Object) null) + .setStrategy(HotSpotConstantReflectionProviderProxy.asJavaClassMethod, MethodStrategy.Passthrough) + .setStrategy(HotSpotConstantReflectionProviderProxy.asObjectHubMethod, MethodStrategy.Passthrough) + .setDefaultValueSupplier(HotSpotConstantReflectionProviderProxy.asJavaTypeMethod, + (proxy, method, args, singletonObjects) -> { + if (args[0] instanceof HotSpotMetaspaceConstant constant) { + return constant.asResolvedJavaType(); + } + return null; + }) + .register(declarations); + new RegistrationBuilder<>(MethodHandleAccessProvider.class) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); + return provider.getMethodHandleAccess(); + }) + .register(declarations); + new RegistrationBuilder<>(HotSpotMemoryAccessProvider.class) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); + return provider.getMemoryAccessProvider(); + }) + .register(declarations); + new RegistrationBuilder<>(HotSpotCodeCacheProvider.class).setSingleton(true) + .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.installCodeMethod, null) + // Interpreter frame size is not tracked since the arguments are not serializable. + .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.interpreterFrameSizeMethod, 0) + .register(declarations); + new RegistrationBuilder<>(CompilerProfiler.class).setSingleton(true) + .setStrategy(CompilerProfilerProxy.getTicksMethod, MethodStrategy.Passthrough) + .setStrategy(CompilerProfilerProxy.notifyCompilerPhaseEventMethod, MethodStrategy.Passthrough) + .setDefaultValueStrategy(CompilerProfilerProxy.notifyCompilerInliningEventMethod, null) + .register(declarations); + new RegistrationBuilder<>(HotSpotResolvedObjectType.class, HotSpotResolvedJavaType.class) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getNameMethod, HotSpotResolvedObjectTypeProxy.getNameInvokable) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getModifiersMethod, HotSpotResolvedObjectTypeProxy.getModifiersInvokable) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; + Class clazz; + try { + clazz = Class.forName(type.toClassName()); + } catch (ClassNotFoundException e) { + return null; + } + if (Proxy.class.isAssignableFrom(clazz)) { + return null; + } + return metaAccess.lookupJavaType(clazz); + }) + // getComponentType() is used by the default implementation of isArray(). + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getInstanceFieldsMethod, + HotSpotResolvedObjectTypeProxy.getInstanceFieldsInvokable, new Object[]{true}) // For snippet decoding + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getStaticFieldsMethod, HotSpotResolvedObjectTypeProxy.getStaticFieldsInvokable) // For snippet decoding + .setDefaultValueStrategy(HotSpotResolvedObjectTypeProxy.getJavaKindMethod, JavaKind.Object) + .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, CompilerInterfaceDeclarations::javaLangObjectSupplier) + .setDefaultValue(HotSpotResolvedObjectTypeProxy.isAssignableFromMethod, false) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.isInterfaceMethod, HotSpotResolvedObjectTypeProxy.isInterfaceInvokable) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.klassMethod, HotSpotResolvedObjectTypeProxy.klassInvokable) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getJavaMirrorMethod, HotSpotResolvedObjectTypeProxy.getJavaMirrorInvokable) + .setDefaultValue(HotSpotResolvedObjectTypeProxy.isInitializedMethod, false) + .provideMethodCallsToRecord((input) -> { + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) input; + if (!type.isArray() && !type.isInterface()) { + return List.of(new MethodCallToRecord(input, HotSpotResolvedObjectTypeProxy.instanceSizeMethod, HotSpotResolvedObjectTypeProxy.instanceSizeInvokable, null)); + } + return List.of(); + }) + .register(declarations); + // Must come after HotSpotResolvedObjectType. Needed for HotSpotResolvedPrimitiveType. + new RegistrationBuilder<>(HotSpotResolvedJavaType.class) + .ensureRecorded(HotSpotResolvedJavaTypeProxy.getNameMethod, HotSpotResolvedJavaTypeProxy.getNameInvokable) + .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaKindMethod, HotSpotResolvedJavaTypeProxy.getJavaKindInvokable) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) proxy; + return HotSpotResolvedPrimitiveType.forKind(type.getJavaKind()); + }) + .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaMirrorMethod, HotSpotResolvedJavaTypeProxy.getJavaMirrorInvokable) + .register(declarations); + new RegistrationBuilder<>(ConstantPool.class).register(declarations); + new RegistrationBuilder<>(HotSpotResolvedJavaMethod.class, Formattable.class) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getNameMethod, HotSpotResolvedJavaMethodProxy.getNameInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getModifiersMethod, HotSpotResolvedJavaMethodProxy.getModifiersInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.isConstructorMethod, HotSpotResolvedJavaMethodProxy.isConstructorInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundMethod, HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getCodeMethod, HotSpotResolvedJavaMethodProxy.getCodeInvokable) + .setStrategy(HotSpotResolvedJavaMethodProxy.formatToMethod, MethodStrategy.DefaultValue) + .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, singletonObjects) -> { + ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; + Formatter formatter = (Formatter) args[0]; + int flags = (int) args[1]; + int width = (int) args[2]; + String base = (flags & ALTERNATE) == ALTERNATE ? receiver.getName() : receiver.toString(); + formatter.format(DebugContext.applyFormattingFlagsAndWidth(base, flags & ~ALTERNATE, width)); + return null; + }) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, HotSpotResolvedJavaMethodProxy.asStackTraceElementInvokable, -1) + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, singletonObjects) -> { + ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; + return receiver.asStackTraceElement(-1); + }) + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, singletonObjects) -> { + byte[] code = ((ResolvedJavaMethod) proxy).getCode(); + if (code == null) { + return 0; + } else { + return code.length; + } + }) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getDeclaringClassMethod, HotSpotResolvedJavaMethodProxy.getDeclaringClassInvokable) + .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + ResolvedJavaMethod method = (ResolvedJavaMethod) proxy; + String methodName = method.getName(); + String methodDescriptor = method.getSignature().toMethodDescriptor(); + ResolvedJavaType holder = method.getDeclaringClass(); + Class clazz; + try { + clazz = Class.forName(holder.toClassName()); + } catch (ClassNotFoundException e) { + return null; + } + if (Proxy.class.isAssignableFrom(clazz)) { + return null; + } + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType holderMirror = metaAccess.lookupJavaType(clazz); + if (method.isConstructor()) { + for (ResolvedJavaMethod candidate : holderMirror.getDeclaredConstructors()) { + if (candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { + return candidate; + } + } + } else { + for (ResolvedJavaMethod candidate : holderMirror.getDeclaredMethods()) { + if (candidate.getName().equals(methodName) && candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { + return candidate; + } + } + } + return null; + }) + .setStrategy(HotSpotResolvedJavaMethodProxy.getParametersMethod, MethodStrategy.Passthrough) + .setStrategy(HotSpotResolvedJavaMethodProxy.getParameterAnnotationsMethod, MethodStrategy.Passthrough) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) + .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) + .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, singletonObjects) -> { + // The HostInliningPhase can query Truffle-related annotations during replay on jargraal. It is safe to return null. + return null; + }) + .setStrategy(HotSpotResolvedJavaMethodProxy.getGenericParameterTypesMethod, MethodStrategy.Passthrough) + .setDefaultValueStrategy(HotSpotResolvedJavaMethodProxy.hasCodeAtLevelMethod, false) + .setDefaultValue(HotSpotResolvedJavaMethodProxy.isInVirtualMethodTableMethod, false) + .setDefaultValue(HotSpotResolvedJavaMethodProxy.intrinsicIdMethod, 0) + .setDefaultValue(HotSpotResolvedJavaMethodProxy.canBeInlinedMethod, false) + .provideMethodCallsToRecord((receiver) -> { + // Record calls to be able to format stable lambda names during replay (using StableMethodNameFormatter). + HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) receiver; + List calls = new ArrayList<>(); + if (LambdaUtils.isLambdaType(method.getDeclaringClass()) || isMethodHandle(method.getDeclaringClass())) { + ConstantPool constantPool = method.getConstantPool(); + calls.add(new MethodCallToRecord(method, HotSpotResolvedJavaMethodProxy.getConstantPoolMethod, HotSpotResolvedJavaMethodProxy.getConstantPoolInvokable, null)); + for (BytecodeStream stream = new BytecodeStream(method.getCode()); stream.currentBCI() < stream.endBCI(); stream.next()) { + int opcode = stream.currentBC(); + int cpi; + switch (opcode) { + case INVOKEVIRTUAL: // fall through + case INVOKESPECIAL: // fall through + case INVOKESTATIC: // fall through + case INVOKEINTERFACE: + cpi = stream.readCPI(); + calls.add(new MethodCallToRecord(constantPool, ConstantPoolProxy.lookupMethodMethod, ConstantPoolProxy.lookupMethodInvokable, new Object[]{cpi, opcode, method})); + break; + case INVOKEDYNAMIC: + cpi = stream.readCPI4(); + calls.add(new MethodCallToRecord(constantPool, ConstantPoolProxy.lookupMethodMethod, ConstantPoolProxy.lookupMethodInvokable, new Object[]{cpi, opcode, method})); + break; + default: + break; + } + } + } + return calls; + }) + .register(declarations); + + new RegistrationBuilder<>(Signature.class) + .ensureRecorded(SignatureProxy.getParameterCountMethod, SignatureProxy.getParameterCountInvokable, false) + .ensureRecorded(SignatureProxy.getParameterCountMethod, SignatureProxy.getParameterCountInvokable, true) + .ensureRecorded(SignatureProxy.getReturnTypeMethod, SignatureProxy.getReturnTypeInvokable, (Object) null) + .provideMethodCallsToRecord((input) -> { + Signature signature = (Signature) input; + int count = signature.getParameterCount(false); + List calls = new ArrayList<>(); + CompilationProxy.SymbolicMethod symbolicMethod = new CompilationProxy.SymbolicMethod(Signature.class, "getParameterType", int.class, ResolvedJavaType.class); + CompilationProxy.InvokableMethod invokableMethod = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); + for (int i = 0; i < count; i++) { + calls.add(new MethodCallToRecord(input, symbolicMethod, invokableMethod, new Object[]{i, null})); + } + return calls; + }) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + Signature signature = (Signature) proxy; + return new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature.toMethodDescriptor()); + }) + .register(declarations); + new RegistrationBuilder<>(HotSpotResolvedJavaField.class) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.isStableMethod, HotSpotResolvedJavaFieldProxy.isStableInvokable) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.isSyntheticMethod, HotSpotResolvedJavaFieldProxy.isSyntheticInvokable) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.getOffsetMethod, HotSpotResolvedJavaFieldProxy.getOffsetInvokable) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.getDeclaringClassMethod, HotSpotResolvedJavaFieldProxy.getDeclaringClassInvokable) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.getNameMethod, HotSpotResolvedJavaFieldProxy.getNameInvokable) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.getModifiersMethod, HotSpotResolvedJavaFieldProxy.getModifiersInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotResolvedJavaFieldProxy.getTypeMethod, HotSpotResolvedJavaFieldProxy.getTypeInvokable) // For graph dumps (BinaryGraphPrinter) + .setLocalMirrorLocator((proxy, singletonObjects) -> { + ResolvedJavaField field = (ResolvedJavaField) proxy; + ResolvedJavaType holderProxy = field.getDeclaringClass(); + Class holderClazz; + try { + holderClazz = Class.forName(holderProxy.toClassName()); + } catch (ClassNotFoundException e) { + return null; + } + if (Proxy.class.isAssignableFrom(holderClazz)) { + return null; + } + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + ResolvedJavaType holder = metaAccess.lookupJavaType(holderClazz); + String name = field.getName(); + boolean isStatic = field.isStatic(); + ResolvedJavaField[] fields = (isStatic) ? holder.getStaticFields() : holder.getInstanceFields(false); + for (ResolvedJavaField candidate : fields) { + if (name.equals(candidate.getName())) { + return candidate; + } + } + throw new IllegalStateException("Cannot find mirror for " + field + ": the local holder does not contain a matching field"); + }) + .register(declarations); + new RegistrationBuilder<>(HotSpotObjectConstant.class) + .ensureRecorded(HotSpotObjectConstantProxy.toValueStringMethod, HotSpotObjectConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotObjectConstantProxy.isCompressedMethod, HotSpotObjectConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotObjectConstantProxy.getTypeMethod, HotSpotObjectConstantProxy.getTypeInvokable) + .setDefaultValueStrategy(HotSpotObjectConstantProxy.isNullMethod, false) + .setDefaultValueStrategy(HotSpotObjectConstantProxy.getJavaKindMethod, JavaKind.Object) + .setDefaultValueSupplier(HotSpotObjectConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) + .setDefaultValueSupplier(HotSpotObjectConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) + .register(declarations); + new RegistrationBuilder<>(HotSpotMetaspaceConstant.class) + .ensureRecorded(HotSpotMetaspaceConstantProxy.toValueStringMethod, HotSpotMetaspaceConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotMetaspaceConstantProxy.isCompressedMethod, HotSpotMetaspaceConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaTypeMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaTypeInvokable) + .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaMethodMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaMethodInvokable) + .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) + .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) + .register(declarations); + new RegistrationBuilder<>(HotSpotProfilingInfo.class) + .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) + .setDefaultValue(ProfilingInfoProxy.isMatureMethod, false) + // For CompilationTask constructor. + .ensureRecorded(HotSpotProfilingInfoProxy.getDecompileCountMethod, HotSpotProfilingInfoProxy.getDecompileCountInvokable) + .setDefaultValue(HotSpotProfilingInfoProxy.getDeoptimizationCountMethod, -1) + .register(declarations); + new RegistrationBuilder<>(ProfilingInfo.class) // Needed for DefaultProfilingInfo, CachingProfilingInfo. + .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) + .setDefaultValue(ProfilingInfoProxy.isMatureMethod, false) + .setDefaultValue(HotSpotProfilingInfoProxy.getDeoptimizationCountMethod, -1) + .register(declarations); + new RegistrationBuilder<>(SpeculationLog.class) + .setDefaultValue(SpeculationLogProxy.maySpeculateMethod, true) + .setDefaultValue(SpeculationLogProxy.speculateMethod, SpeculationLog.NO_SPECULATION) + .register(declarations); + new RegistrationBuilder<>(Predicate.class).setSingleton(true) + .register(declarations); // Intrinsification trust predicate. + // @formatter:on + return declarations; + } + + @SuppressWarnings("unused") + private static ResolvedJavaType javaLangObjectSupplier(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); + return metaAccess.lookupJavaType(Object.class); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java new file mode 100644 index 000000000000..279bc5b543e3 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/DelayedDeserializationObject.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp; + +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.TriState; + +/** + * Object that cannot be directly deserialized because it invokes methods on the supplied arguments. + * These methods cannot be replayed at the time of deserialization. + */ +sealed interface DelayedDeserializationObject { + /** + * Deserializes the object, returning the deserialized instance. + * + * @return the deserialized object + */ + Object deserialize(); + + /** + * A {@link jdk.vm.ci.meta.Assumptions.LeafType} assumption that will be deserialized later. + */ + final class LeafTypeWithDelayedDeserialization extends Assumptions.Assumption implements DelayedDeserializationObject { + private final ResolvedJavaType context; + + LeafTypeWithDelayedDeserialization(ResolvedJavaType context) { + this.context = context; + } + + @Override + public Object deserialize() { + return new Assumptions.LeafType(context); + } + } + + /** + * A {@link jdk.vm.ci.meta.Assumptions.ConcreteSubtype} assumption that will be deserialized + * later. + */ + final class ConcreteSubtypeWithDelayedDeserialization extends Assumptions.Assumption implements DelayedDeserializationObject { + private final ResolvedJavaType context; + private final ResolvedJavaType subtype; + + ConcreteSubtypeWithDelayedDeserialization(ResolvedJavaType context, ResolvedJavaType subtype) { + this.context = context; + this.subtype = subtype; + } + + @Override + public Object deserialize() { + return new Assumptions.ConcreteSubtype(context, subtype); + } + } + + /** + * A {@link JavaTypeProfile} that will be deserialized later. + */ + final class JavaTypeProfileWithDelayedDeserialization implements DelayedDeserializationObject { + private final TriState nullSeen; + private final double notRecordedProbability; + private final ProfiledTypeWithDelayedDeserialization[] items; + + JavaTypeProfileWithDelayedDeserialization(TriState nullSeen, double notRecordedProbability, ProfiledTypeWithDelayedDeserialization[] items) { + this.nullSeen = nullSeen; + this.notRecordedProbability = notRecordedProbability; + this.items = items; + } + + @Override + public Object deserialize() { + JavaTypeProfile.ProfiledType[] profiledTypes = new JavaTypeProfile.ProfiledType[items.length]; + for (int i = 0; i < items.length; i++) { + profiledTypes[i] = items[i].deserialize(); + } + return new JavaTypeProfile(nullSeen, notRecordedProbability, profiledTypes); + } + } + + /** + * A {@link ProfiledTypeWithDelayedDeserialization} that will be deserialized later. + */ + final class ProfiledTypeWithDelayedDeserialization implements DelayedDeserializationObject { + private final ResolvedJavaType type; + private final double probability; + + ProfiledTypeWithDelayedDeserialization(ResolvedJavaType type, double probability) { + this.type = type; + this.probability = probability; + } + + @Override + public JavaTypeProfile.ProfiledType deserialize() { + return new JavaTypeProfile.ProfiledType(type, probability); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java new file mode 100644 index 000000000000..4b48176c6bfd --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; + +import java.util.List; +import java.util.Objects; + +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.hotspot.HotSpotBackendFactoryDecorators; +import jdk.graal.compiler.hotspot.HotSpotSnippetMetaAccessProvider; +import jdk.graal.compiler.hotspot.SnippetObjectConstant; +import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * A backend factory that decorates the providers during recording and replay. + */ +class HotSpotProxyBackendFactory implements HotSpotBackendFactoryDecorators { + private final CompilationProxies proxies; + + private final ReplayCompilationSupport replayCompilationSupport; + + private MetaAccessProvider metaAccessProviderProxy; + + HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport) { + this.proxies = proxies; + this.replayCompilationSupport = replayCompilationSupport; + } + + @Override + public void afterJVMCIProvidersCreated() { + /* + * We need the key JVMCI providers (such as meta access) available to be able to find local + * mirrors. We must identify the local mirrors before initialization continues to avoid + * creating duplicate proxies for equivalent local mirrors. + */ + replayCompilationSupport.findLocalMirrors(); + } + + @Override + public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { + // Do not record snippet types in libgraal - decorate the JVMCI meta access only. + metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); + return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy, true); + } + + @Override + public HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotSpotConstantReflectionProvider constantReflection) { + // Only the operations invoked on the delegate are recorded and replayed. + HotSpotConstantReflectionProvider delegate = (HotSpotConstantReflectionProvider) proxies.proxify(constantReflection); + return new DecoratedConstantReflectionProvider(delegate); + } + + private final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { + private final HotSpotConstantReflectionProvider delegate; + + private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider delegate) { + super(null); + this.delegate = delegate; + } + + private static final List allowedFields = List.of("TYPE", "COMPACT_STRINGS"); + + @Override + public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { + /* + * Prevents jargraal from encoding runtime constants in snippets (such as in boxing + * snippets). Follows the logic of HotSpotSubstrateConstantReflectionProvider. + */ + if (!LibGraalSupport.inLibGraalRuntime() && replayCompilationSupport.isInSnippetContext() && !isGraalClass(field.getDeclaringClass()) && !allowedFields.contains(field.getName())) { + return null; + } + return delegate.readFieldValue(field, receiver); + } + + @Override + public JavaConstant forObject(Object value) { + return delegate.forObject(value); + } + + @Override + public Boolean constantEquals(Constant x, Constant y) { + if (x instanceof SnippetObjectConstant || y instanceof SnippetObjectConstant) { + /* + * Equality checks for snippet constants are not recorded because snippet constants + * are not serializable. + */ + return Objects.equals(x, y); + } else { + return delegate.constantEquals(x, y); + } + } + + @Override + public Integer readArrayLength(JavaConstant array) { + return delegate.readArrayLength(array); + } + + @Override + public JavaConstant readArrayElement(JavaConstant array, int index) { + return delegate.readArrayElement(array, index); + } + + @Override + public JavaConstant boxPrimitive(JavaConstant source) { + return delegate.boxPrimitive(source); + } + + @Override + public JavaConstant unboxPrimitive(JavaConstant source) { + return delegate.unboxPrimitive(source); + } + + @Override + public JavaConstant forString(String value) { + return delegate.forString(value); + } + + @Override + public ResolvedJavaType asJavaType(Constant constant) { + if (constant instanceof SnippetObjectConstant objectConstant) { + /* + * Avoids recording an operation with the snippet constant, which is not + * serializable. + */ + return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); + } else { + return delegate.asJavaType(constant); + } + } + + @Override + public MethodHandleAccessProvider getMethodHandleAccess() { + return delegate.getMethodHandleAccess(); + } + + @Override + public MemoryAccessProvider getMemoryAccessProvider() { + return delegate.getMemoryAccessProvider(); + } + + @Override + public JavaConstant asJavaClass(ResolvedJavaType type) { + return delegate.asJavaClass(type); + } + + @Override + public Constant asObjectHub(ResolvedJavaType type) { + return delegate.asObjectHub(type); + } + } + + @Override + public HotSpotCodeCacheProvider decorateCodeCacheProvider(HotSpotCodeCacheProvider codeCacheProvider) { + return (HotSpotCodeCacheProvider) proxies.proxify(codeCacheProvider); + } + + @Override + public HotSpotHostForeignCallsProvider decorateForeignCallsProvider(HotSpotHostForeignCallsProvider foreignCalls) { + replayCompilationSupport.setForeignCallsProvider(foreignCalls); + return foreignCalls; + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java new file mode 100644 index 000000000000..38a4b2d077ab --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/OperationRecorder.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import org.graalvm.collections.EconomicMap; + +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.debug.GraalError; + +/** + * Records the results of operations during a recorded compilation. + *

+ * An operation is a method call with a JVMCI object proxy as a receiver. The JVMCI objects for + * which proxies are created are registered in {@link CompilerInterfaceDeclarations}. + * {@link CompilerInterfaceDeclarations} also declares the behavior of the proxies during recording, + * i.e., which operations should be recorded or prefetched. + *

+ * This class is also used to ensure that the results of operations return stable values during a + * recorded compilation. The first invocation of a method should record the result and all + * subsequent invocations with the same arguments should reuse the result obtained from + * {@link #getRecordedResultOrMarker}. + *

+ * The recorder tracks the context of the current compiler thread. There are the following contexts: + *

    + *
  • global context - the initial context in which all results are recorded (e.g., compiler + * initialization),
  • + *
  • compilation context ({@link #enterCompilationContext()}) - a recorded compilation of a + * method,
  • + *
  • ignored context ({@link #enterIgnoredContext()}) - in this context, the results of operations + * are not recorded and the results of previous operations are not returned (useful for snippet + * parsing).
  • + *
+ * A context is open until the respective is scope is closed. A compilation context also considers + * the operations recorded in the global context (i.e., {@link #getRecordedResultOrMarker} and + * {@link #getCurrentRecordedOperations()} also returns the operations from the global context). + * + * @see ReplayCompilationSupport + * @see RecordingCompilationProxies + */ +public class OperationRecorder { + /** + * A recorded operation. + *

+ * Represents the receiver object, arguments, and the result of a method call from a recorded + * compilation. The result of an operation is either a return value or a thrown exception. + * Results other that non-null return values are represented with {@link SpecialResultMarker}. + *

+ * During a recorded compilation, the instances of this class reference raw JVMCI objects + * (without proxies). During a replayed compilation, the instances reference proxy objects. + * + * @param receiver the receiver object of the operation + * @param method the invoked method + * @param args the arguments passed to the method + * @param resultOrMarker the return value or a marker for the result (e.g., a thrown exception) + */ + public record RecordedOperation(Object receiver, CompilationProxy.SymbolicMethod method, Object[] args, Object resultOrMarker) { + public RecordedOperation { + Objects.requireNonNull(receiver); + Objects.requireNonNull(method); + Objects.requireNonNull(resultOrMarker); + } + } + + /** + * The key of a recorded operation. + * + * @param receiver the receiver object of the operation + * @param method the invoked methods + * @param args the arguments passed to the method + */ + public record RecordedOperationKey(Object receiver, CompilationProxy.SymbolicMethod method, Object[] args) { + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + if (object == null || getClass() != object.getClass()) { + return false; + } + RecordedOperationKey that = (RecordedOperationKey) object; + return receiver.equals(that.receiver) && method.equals(that.method) && Arrays.equals(args, that.args); + } + + @Override + public int hashCode() { + return Objects.hash(receiver, method, Arrays.hashCode(args)); + } + } + + private sealed interface RecordingContext { + Object getRecordedResultOrMarker(RecordedOperationKey key); + + void recordReturnValue(RecordedOperationKey key, Object result); + + void recordExceptionThrown(RecordedOperationKey key, Throwable throwable); + + List getRecordedOperations(); + } + + private static final class IgnoredRecordingContext implements RecordingContext { + @Override + public Object getRecordedResultOrMarker(RecordedOperationKey key) { + return SpecialResultMarker.NO_RESULT_MARKER; + } + + @Override + public void recordReturnValue(RecordedOperationKey key, Object result) { + } + + @Override + public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { + + } + + @Override + public List getRecordedOperations() { + return List.of(); + } + } + + private static final class GlobalRecordingContext implements RecordingContext { + private final ConcurrentHashMap operationResults; + + private GlobalRecordingContext() { + operationResults = new ConcurrentHashMap<>(); + } + + @Override + public Object getRecordedResultOrMarker(RecordedOperationKey key) { + return operationResults.getOrDefault(key, SpecialResultMarker.NO_RESULT_MARKER); + } + + @Override + public void recordReturnValue(RecordedOperationKey key, Object result) { + operationResults.put(key, (result == null) ? SpecialResultMarker.NULL_RESULT_MARKER : result); + } + + @Override + public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { + Objects.requireNonNull(throwable); + operationResults.put(key, new SpecialResultMarker.ExceptionThrownMarker(throwable)); + } + + @Override + public List getRecordedOperations() { + List results = new ArrayList<>(); + for (var entry : operationResults.entrySet()) { + RecordedOperationKey key = entry.getKey(); + results.add(new RecordedOperation(key.receiver, key.method, key.args, entry.getValue())); + } + return results; + } + } + + private static final class CompilationRecordingContext implements RecordingContext { + private final EconomicMap operationResults; + + private CompilationRecordingContext() { + this.operationResults = EconomicMap.create(); + } + + @Override + public Object getRecordedResultOrMarker(RecordedOperationKey key) { + return operationResults.get(key, SpecialResultMarker.NO_RESULT_MARKER); + } + + @Override + public void recordReturnValue(RecordedOperationKey key, Object result) { + operationResults.put(key, (result == null) ? SpecialResultMarker.NULL_RESULT_MARKER : result); + } + + @Override + public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { + Objects.requireNonNull(throwable); + operationResults.put(key, new SpecialResultMarker.ExceptionThrownMarker(throwable)); + } + + @Override + public List getRecordedOperations() { + List results = new ArrayList<>(); + var cursor = operationResults.getEntries(); + while (cursor.advance()) { + RecordedOperationKey key = cursor.getKey(); + results.add(new RecordedOperation(key.receiver, key.method, key.args, cursor.getValue())); + } + return results; + } + } + + private final GlobalRecordingContext globalContext; + + private final ThreadLocal currentContext; + + OperationRecorder() { + this.globalContext = new GlobalRecordingContext(); + this.currentContext = ThreadLocal.withInitial(() -> globalContext); + } + + /** + * Gets the result for a given operation. + * + * @param key the keu of the operation + * @return the return value or a marker for the result of the operation + */ + public Object getRecordedResultOrMarker(RecordedOperationKey key) { + return currentContext.get().getRecordedResultOrMarker(key); + } + + /** + * Records the return value for a recorded operation. + * + * @param key the key of the operation + * @param result the return value of the operation + */ + public void recordReturnValue(RecordedOperationKey key, Object result) { + currentContext.get().recordReturnValue(key, result); + } + + /** + * Records the exception thrown for a given operation. + * + * @param key the key of the operation + * @param throwable the exception thrown by the operation + */ + public void recordExceptionThrown(RecordedOperationKey key, Throwable throwable) { + currentContext.get().recordExceptionThrown(key, throwable); + } + + /** + * Gets the recorded operations in the global and current compilation context. + */ + public List getCurrentRecordedOperations() { + RecordingContext context = currentContext.get(); + GraalError.guarantee(context instanceof CompilationRecordingContext, "recorded operations can be retrieved in compilation context only"); + List results = globalContext.getRecordedOperations(); + results.addAll(context.getRecordedOperations()); + return results; + } + + /** + * Enters the context of a method compilation for the current compilation thread. + * + * @return a scope for the context + */ + public DebugCloseable enterCompilationContext() { + RecordingContext previousContext = currentContext.get(); + currentContext.set(new CompilationRecordingContext()); + return () -> currentContext.set(previousContext); + } + + /** + * Enters a context where recording should be disabled for the current compilation thread. + * + * @return a scope for the context + */ + public DebugCloseable enterIgnoredContext() { + RecordingContext previousContext = currentContext.get(); + currentContext.set(new IgnoredRecordingContext()); + return () -> currentContext.set(previousContext); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java new file mode 100644 index 000000000000..510206482d5e --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedForeignCallLinkages.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import org.graalvm.collections.EconomicMap; + +import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; +import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkageImpl; +import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; +import jdk.vm.ci.meta.Value; + +/** + * Represents the finalized foreign call linkages from a recorded compilation. + * + * @param linkages a list of individual linkages mapped by {@link ForeignCallSignature#toString()} + */ +public record RecordedForeignCallLinkages(EconomicMap linkages) { + /** + * A finalized foreign call linkage from a recorded compilation. + * + * @param address the address of the callee + * @param temporaries the slots and registers killed by the callee + */ + record RecordedForeignCallLinkage(long address, Value[] temporaries) { + RecordedForeignCallLinkage { + GraalError.guarantee(address != 0L, "only finalized linkages should be recorded"); + } + } + + /** + * Creates an instance of {@link RecordedForeignCallLinkages} using the finalized linkages from + * the given foreign calls provider. + * + * @param provider foreign calls provider + * @return the recorded linkages + */ + public static RecordedForeignCallLinkages createFrom(HotSpotHostForeignCallsProvider provider) { + EconomicMap linkages = EconomicMap.create(); + provider.forEachForeignCall((signature, linkage) -> { + if (linkage == null || !linkage.hasAddress()) { + return; + } + linkages.put(signature.toString(), new RecordedForeignCallLinkage(linkage.getAddress(), linkage.getTemporaries())); + }); + return new RecordedForeignCallLinkages(linkages); + } + + /** + * Sets the address and temporaries of a foreign call linkage to the recorded address and + * temporaries. This is a no-op if there is no recorded linkage with a matching signature. + * + * @param signature the signature of the foreign call + * @param linkage the linkage to be updated + * @return true if the linkage was finalized + */ + boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpotForeignCallLinkage linkage) { + RecordedForeignCallLinkage recordedLinkage = linkages.get(signature.toString()); + if (recordedLinkage == null) { + return false; + } + ((HotSpotForeignCallLinkageImpl) linkage).finalizeExternally(recordedLinkage.address, recordedLinkage.temporaries); + return true; + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java new file mode 100644 index 000000000000..504c0a705500 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java @@ -0,0 +1,1986 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.io.IOException; +import java.io.Reader; +import java.io.Serial; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.BitSet; +import java.util.Collection; +import java.util.EnumSet; +import java.util.List; +import java.util.Optional; + +import org.graalvm.collections.EconomicMap; + +import jdk.graal.compiler.core.common.spi.ForeignCallDescriptor; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.graal.compiler.hotspot.stubs.IllegalArgumentExceptionArgumentIsNotAnArrayStub; +import jdk.graal.compiler.util.json.JsonBuilder; +import jdk.graal.compiler.util.json.JsonParser; +import jdk.graal.compiler.util.json.JsonWriter; +import jdk.vm.ci.aarch64.AArch64; +import jdk.vm.ci.amd64.AMD64; +import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.code.Register; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.RegisterValue; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotCompressedNullConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotSpeculationLog; +import jdk.vm.ci.hotspot.VMField; +import jdk.vm.ci.hotspot.aarch64.AArch64HotSpotRegisterConfig; +import jdk.vm.ci.hotspot.amd64.AMD64HotSpotRegisterConfig; +import jdk.vm.ci.hotspot.riscv64.RISCV64HotSpotRegisterConfig; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.EncodedSpeculationReason; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.PrimitiveConstant; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; +import jdk.vm.ci.meta.TriState; +import jdk.vm.ci.meta.UnresolvedJavaField; +import jdk.vm.ci.meta.UnresolvedJavaMethod; +import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.Value; +import jdk.vm.ci.meta.ValueKind; +import jdk.vm.ci.riscv64.RISCV64; + +/** + * Provides functionality for persisting and loading recorded compilation units. + *

+ * A {@link RecordedCompilationUnit} contains all data required to run a replay compilation. This + * class can serialize these records to and from JSON files. A recorded compilation unit contains a + * list of the recorded operations (method calls and their results during a recorded compilation), + * foreign call linkages, and other metadata. + *

+ * The operations are collected during a recorded compilation via an {@link OperationRecorder}. An + * operation comprises a symbolic name of a method, the receiver object, argument values, and the + * result of that operation (a return value or an exception). After a recorded compilation, this + * class expects the raw JVMCI objects (without any proxies). It deduplicates these JVMCI objects by + * assigning a single ID to all JVMCI objects that are {@link Object#equals equal}. + *

+ * When {@link #load loading} the recorded compilation unit from JSON, the class creates proxies in + * place of the JVMCI objects using the provided {@link ProxyFactory}. + * + * @see ReplayCompilationSupport + * @see CompilerInterfaceDeclarations + */ +public class RecordedOperationPersistence { + /** + * A recorded compilation unit. + * + * @param request the compilation request + * @param compilerConfiguration the name of the compiler configuration + * @param isLibgraal {@code true} if the recorded compilation executed on libgraal + * @param platform the platform of the system + * @param linkages the recorded foreign call linkages + * @param finalGraph the final canonical graph or {@code null} if not available + * @param operations the recorded operations and their results + */ + public record RecordedCompilationUnit(HotSpotCompilationRequest request, String compilerConfiguration, + boolean isLibgraal, Platform platform, RecordedForeignCallLinkages linkages, String finalGraph, + List operations) { + } + + /** + * Factory for creating generic proxy objects for register compiler-interface classes. + */ + @FunctionalInterface + public interface ProxyFactory { + /** + * Creates a proxy for the given registration. + * + * @param registration the registration + * @return the proxy + */ + CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration); + } + + private interface RecursiveSerializer { + void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder) throws IOException; + + void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder, String tag) throws IOException; + } + + private interface RecursiveDeserializer { + Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException; + + Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException; + } + + private sealed interface ObjectSerializer { + default boolean serializesSubclasses() { + return false; + } + + Class clazz(); + + String tag(); + + void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException; + + Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException; + } + + public static final class DeserializationException extends Exception { + @Serial private static final long serialVersionUID = -6470496032190913296L; + + private DeserializationException(ObjectSerializer serializer, EconomicMap json, Throwable cause) { + super("Serializer " + serializer + " failed to deserialize " + json, cause); + } + + private DeserializationException(ObjectSerializer serializer, EconomicMap json, String message) { + super("Serializer " + serializer + " failed to deserialize " + json + ": " + message); + } + } + + private static final class ClassSerializer implements ObjectSerializer { + private static final Class[] knownClasses = new Class[]{String.class, System.class, Object[].class, + ExceptionHandler.class, IllegalArgumentExceptionArgumentIsNotAnArrayStub.class}; + + @Override + public Class clazz() { + return Class.class; + } + + @Override + public String tag() { + return "class"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + objectBuilder.append("name", ((Class) instance).getName()); + } + + @Override + public Class deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + Class primitiveClass = Class.forPrimitiveName(name); + if (primitiveClass != null) { + return primitiveClass; + } + for (Class knownClass : knownClasses) { + if (knownClass.getName().equals(name)) { + return knownClass; + } + } + try { + return Class.forName(name); + } catch (ClassNotFoundException e) { + throw new DeserializationException(this, json, e); + } + } + } + + private static final class OperationSerializer implements ObjectSerializer { + private static final String TAG = "operation"; + + @Override + public Class clazz() { + return OperationRecorder.RecordedOperation.class; + } + + @Override + public String tag() { + return TAG; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + OperationRecorder.RecordedOperation op = (OperationRecorder.RecordedOperation) instance; + try { + serializer.serialize(op.receiver(), objectBuilder.append("recv")); + objectBuilder.append("method", Arrays.asList(op.method().methodAndParamNames())); + if (op.args() != null) { + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("args").array()) { + for (Object arg : op.args()) { + serializer.serialize(arg, arrayBuilder.nextEntry()); + } + } + } + serializer.serialize(op.resultOrMarker(), objectBuilder.append("res")); + } catch (IllegalArgumentException e) { + throw new IllegalArgumentException("Failed to serialize " + op + " due to: " + e.getMessage(), e); + } + } + + @SuppressWarnings("unchecked") + @Override + public OperationRecorder.RecordedOperation deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) + throws DeserializationException { + Object recv = deserializer.deserialize(json.get("recv"), proxyFactory); + List methodProp = (List) json.get("method"); + String[] methodArray = new String[methodProp.size()]; + for (int i = 0; i < methodArray.length; i++) { + methodArray[i] = (String) methodProp.get(i); + } + CompilationProxy.SymbolicMethod method = new CompilationProxy.SymbolicMethod(methodArray); + List list = (List) json.get("args"); + Object[] args; + if (list == null) { + args = null; + } else { + args = new Object[list.size()]; + for (int i = 0; i < args.length; i++) { + args[i] = deserializer.deserialize(list.get(i), proxyFactory); + } + } + Object res = deserializer.deserialize(json.get("res"), proxyFactory); + return new OperationRecorder.RecordedOperation(recv, method, args, res); + } + } + + private static final class RegisteredSingletonSerializer implements ObjectSerializer { + private final CompilerInterfaceDeclarations.Registration registration; + + private Object singletonProxy; + + private RegisteredSingletonSerializer(CompilerInterfaceDeclarations.Registration registration) { + this.registration = registration; + if (!registration.singleton()) { + throw new IllegalArgumentException(); + } + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return registration.clazz(); + } + + @Override + public String tag() { + return clazz().getName(); + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) { + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + if (singletonProxy == null) { + singletonProxy = proxyFactory.createProxy(registration); + } + if (singletonProxy == null) { + throw new IllegalStateException("No singleton found for " + registration); + } + return singletonProxy; + } + } + + private static final class RegisteredInstanceSerializer implements ObjectSerializer { + private final CompilerInterfaceDeclarations.Registration registration; + + private final EconomicMap instanceId; + + private final EconomicMap proxyById; + + private RegisteredInstanceSerializer(CompilerInterfaceDeclarations.Registration registration) { + this.registration = registration; + this.instanceId = EconomicMap.create(); + this.proxyById = EconomicMap.create(); + if (registration.singleton()) { + throw new IllegalArgumentException(); + } + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return registration.clazz(); + } + + @Override + public String tag() { + return clazz().getSimpleName(); + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Integer id = instanceId.get(instance); + if (id == null) { + id = instanceId.size(); + instanceId.put(instance, id); + } + objectBuilder.append("id", id); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + int id = ((Number) json.get("id")).intValue(); + Object proxyInstance = proxyById.get(id); + if (proxyInstance == null) { + proxyInstance = proxyFactory.createProxy(registration); + proxyById.put(id, proxyInstance); + } + return proxyInstance; + } + } + + private static final class StackTraceElementSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return StackTraceElement.class; + } + + @Override + public String tag() { + return "ste"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + StackTraceElement ste = (StackTraceElement) instance; + objectBuilder.append("loader", ste.getClassLoaderName()); + objectBuilder.append("module", ste.getModuleName()); + objectBuilder.append("moduleVer", ste.getModuleVersion()); + objectBuilder.append("holder", ste.getClassName()); + objectBuilder.append("method", ste.getMethodName()); + objectBuilder.append("file", ste.getFileName()); + objectBuilder.append("line", ste.getLineNumber()); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String loader = (String) json.get("loader"); + String module = (String) json.get("module"); + String moduleVer = (String) json.get("moduleVer"); + String holder = (String) json.get("holder"); + String method = (String) json.get("method"); + String file = (String) json.get("file"); + int line = (int) json.get("line"); + return new StackTraceElement(loader, module, moduleVer, holder, method, file, line); + } + } + + private static final class StringSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return String.class; + } + + @Override + public String tag() { + return "string"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + objectBuilder.append("content", instance); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + return json.get("content"); + } + } + + private static final class BooleanSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Boolean.class; + } + + @Override + public String tag() { + return "boolean"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + objectBuilder.append("value", instance); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + return json.get("value"); + } + } + + private static final int HEX_RADIX = 16; + + private static String floatToHex(float value) { + return Integer.toHexString(Float.floatToRawIntBits(value)); + } + + private static float hexToFloat(String value) { + return Float.intBitsToFloat(Integer.parseUnsignedInt(value, HEX_RADIX)); + } + + private static String doubleToHex(double value) { + return Long.toHexString(Double.doubleToRawLongBits(value)); + } + + private static double hexToDouble(String value) { + return Double.longBitsToDouble(Long.parseUnsignedLong(value, HEX_RADIX)); + } + + private static final class NumberSerializer implements ObjectSerializer { + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return Number.class; + } + + @Override + public String tag() { + return "number"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + objectBuilder.append("class", instance.getClass().getSimpleName()); + String value = switch (instance) { + case Integer n -> Integer.toHexString(n); + case Byte n -> Integer.toHexString(n); + case Short n -> Integer.toHexString(n); + case Long n -> Long.toHexString(n); + case Float n -> floatToHex(n); + case Double n -> doubleToHex(n); + default -> throw new IllegalArgumentException("Unexpected value: " + instance); + }; + objectBuilder.append("value", value); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String className = (String) json.get("class"); + String value = (String) json.get("value"); + switch (className) { + case "Integer" -> { + return Integer.parseUnsignedInt(value, HEX_RADIX); + } + case "Byte" -> { + return (byte) Integer.parseUnsignedInt(value, HEX_RADIX); + } + case "Short" -> { + return (short) Integer.parseUnsignedInt(value, HEX_RADIX); + } + case "Long" -> { + return Long.parseUnsignedLong(value, HEX_RADIX); + } + case "Float" -> { + return hexToFloat(value); + } + case "Double" -> { + return hexToDouble(value); + } + default -> throw new IllegalArgumentException("Unknown class " + className + " for constant" + value); + } + } + } + + private static final class ResultMarkerSerializer implements ObjectSerializer { + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return SpecialResultMarker.class; + } + + @Override + public String tag() { + return "marker"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + String type; + if (instance == SpecialResultMarker.NO_RESULT_MARKER) { + type = "noResult"; + } else if (instance == SpecialResultMarker.NULL_RESULT_MARKER) { + type = "null"; + } else if (instance instanceof SpecialResultMarker.ExceptionThrownMarker thrownMarker) { + type = "exception"; + serializer.serialize(thrownMarker.getThrown(), objectBuilder.append("throwable")); + } else { + throw new IllegalArgumentException("Cannot serialize result marker " + instance); + } + objectBuilder.append("type", type); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + switch ((String) json.get("type")) { + case "noResult" -> { + return SpecialResultMarker.NO_RESULT_MARKER; + } + case "null" -> { + return SpecialResultMarker.NULL_RESULT_MARKER; + } + case "exception" -> { + return new SpecialResultMarker.ExceptionThrownMarker((Throwable) deserializer.deserialize(json.get("throwable"), proxyFactory)); + } + case null, default -> throw new DeserializationException(this, json, "Invalid marker type."); + } + } + } + + private static final class EnumSerializer implements ObjectSerializer { + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return Enum.class; + } + + @Override + public String tag() { + return "enum"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Enum en = (Enum) instance; + objectBuilder.append("holder", en.getClass().getName()); + objectBuilder.append("constant", en.name()); + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String holderName = (String) json.get("holder"); + String constantName = (String) json.get("constant"); + Class> enumClass; + try { + enumClass = (Class>) Class.forName(holderName); + } catch (ClassNotFoundException e) { + throw new DeserializationException(this, json, e); + } + // TODO This could be more efficient. + for (Enum constant : enumClass.getEnumConstants()) { + if (constant.name().equals(constantName)) { + return constant; + } + } + throw new DeserializationException(this, json, "Invalid constant."); + } + } + + private static final class ArraySerializer implements ObjectSerializer { + + private final CompilerInterfaceDeclarations declarations; + + private ArraySerializer(CompilerInterfaceDeclarations declarations) { + this.declarations = declarations; + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return Object[].class; + } + + @Override + public String tag() { + return "array"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Object[] array = (Object[]) instance; + Class componentType = array.getClass().getComponentType(); + Class supertype = declarations.findRegisteredSupertype(componentType); + if (supertype != null) { + componentType = supertype; + } + serializer.serialize(componentType, objectBuilder.append("component")); + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("elements").array()) { + for (Object object : array) { + serializer.serialize(object, arrayBuilder.nextEntry()); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Class component = (Class) deserializer.deserialize(json.get("component"), proxyFactory); + List elements = (List) json.get("elements"); + Object[] array = (Object[]) Array.newInstance(component, elements.size()); + for (int i = 0; i < elements.size(); i++) { + array[i] = deserializer.deserialize(elements.get(i), proxyFactory); + } + return array; + } + } + + private static final class ListSerializer implements ObjectSerializer { + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return List.class; + } + + @Override + public String tag() { + return "list"; + } + + @Override + @SuppressWarnings("unchecked") + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + List list = (List) instance; + try (var array = objectBuilder.append("elements").array()) { + for (Object element : list) { + serializer.serialize(element, array.nextEntry()); + } + } + } + + @Override + @SuppressWarnings("unchecked") + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + List list = new ArrayList<>(); + for (Object element : (List) json.get("elements")) { + list.add(deserializer.deserialize(element, proxyFactory)); + } + return list; + } + } + + private static final class ByteArraySerializer implements ObjectSerializer { + @Override + public Class clazz() { + return byte[].class; + } + + @Override + public String tag() { + return "byteArray"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + byte[] bytes = (byte[]) instance; + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("bytes").array()) { + for (byte b : bytes) { + arrayBuilder.append(b); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + List byteList = (List) json.get("bytes"); + byte[] bytes = new byte[byteList.size()]; + for (int i = 0; i < bytes.length; i++) { + bytes[i] = ((Number) byteList.get(i)).byteValue(); + } + return bytes; + } + } + + private static final class DoubleArraySerializer implements ObjectSerializer { + @Override + public Class clazz() { + return double[].class; + } + + @Override + public String tag() { + return "doubleArray"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + double[] doubles = (double[]) instance; + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("doubles").array()) { + for (double i : doubles) { + arrayBuilder.append(doubleToHex(i)); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + List doubleList = (List) json.get("doubles"); + double[] doubles = new double[doubleList.size()]; + for (int i = 0; i < doubles.length; i++) { + doubles[i] = hexToDouble((String) doubleList.get(i)); + } + return doubles; + } + } + + private static final class SingletonSerializer implements ObjectSerializer { + private final Object singleton; + + private SingletonSerializer(Object singleton) { + this.singleton = singleton; + } + + @Override + public Class clazz() { + return singleton.getClass(); + } + + @Override + public String tag() { + return singleton.getClass().getName(); + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) { + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + return singleton; + } + } + + private static final class RegisterSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Register.class; + } + + @Override + public String tag() { + return "register"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Register register = (Register) instance; + objectBuilder.append("number", register.number); + objectBuilder.append("name", register.name); + objectBuilder.append("encoding", register.encoding); + objectBuilder.append("catName", register.getRegisterCategory().toString()); + objectBuilder.append("containsRef", register.mayContainReference()); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + int number = (int) json.get("number"); + String name = (String) json.get("name"); + int encoding = (int) json.get("encoding"); + String catName = (String) json.get("catName"); + boolean containsRef = (boolean) json.get("containsRef"); + return new Register(number, encoding, name, new Register.RegisterCategory(catName, containsRef)); + } + } + + private static final class FieldSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Field.class; + } + + @Override + public String tag() { + return "field"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Field field = (Field) instance; + serializer.serialize(field.getDeclaringClass(), objectBuilder.append("holder")); + objectBuilder.append("name", field.getName()); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Class holder = (Class) deserializer.deserialize(json.get("holder"), proxyFactory); + String name = (String) json.get("name"); + try { + if (holder == String.class) { + // Ensure the reflection metadata is included in the libgraal image. + if ("coder".equals(name)) { + return String.class.getDeclaredField("coder"); + } else if ("value".equals(name)) { + return String.class.getDeclaredField("value"); + } + } + return holder.getDeclaredField(name); + } catch (NoSuchFieldException e) { + throw new DeserializationException(this, json, e); + } + } + } + + private static final class AssumptionResultSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.AssumptionResult.class; + } + + @Override + public String tag() { + return "assumpRes"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.AssumptionResult result = (Assumptions.AssumptionResult) instance; + serializer.serialize(result.getResult(), objectBuilder.append("result")); + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("assumptions").array()) { + Assumptions assumptions = new Assumptions(); + result.recordTo(assumptions); + for (Assumptions.Assumption assumption : assumptions) { + serializer.serialize(assumption, arrayBuilder.nextEntry()); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Object result = deserializer.deserialize(json.get("result"), proxyFactory); + List assumptions = new ArrayList<>(); + for (Object assumption : (List) json.get("assumptions")) { + assumptions.add((Assumptions.Assumption) deserializer.deserialize(assumption, proxyFactory)); + } + return new Assumptions.AssumptionResult<>(result, assumptions.toArray(Assumptions.Assumption[]::new)); + } + } + + private static final class NoFinalizableSubclassAssumptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.NoFinalizableSubclass.class; + } + + @Override + public String tag() { + return "noFinSubclass"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.NoFinalizableSubclass assumption = (Assumptions.NoFinalizableSubclass) instance; + serializer.serialize(assumption.receiverType, objectBuilder.append("receiverType")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + ResolvedJavaType receiverType = (ResolvedJavaType) deserializer.deserialize(json.get("receiverType"), proxyFactory); + return new Assumptions.NoFinalizableSubclass(receiverType); + } + } + + private static final class ConcreteSubtypeAssumptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.ConcreteSubtype.class; + } + + @Override + public String tag() { + return "concreteSubtype"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.ConcreteSubtype assumption = (Assumptions.ConcreteSubtype) instance; + serializer.serialize(assumption.subtype, objectBuilder.append("subtype")); + serializer.serialize(assumption.context, objectBuilder.append("context")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + ResolvedJavaType subtype = (ResolvedJavaType) deserializer.deserialize(json.get("subtype"), proxyFactory); + ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); + return new DelayedDeserializationObject.ConcreteSubtypeWithDelayedDeserialization(context, subtype); + } + } + + private static final class LeafTypeAssumptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.LeafType.class; + } + + @Override + public String tag() { + return "leafType"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.LeafType assumption = (Assumptions.LeafType) instance; + serializer.serialize(assumption.context, objectBuilder.append("context")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); + return new DelayedDeserializationObject.LeafTypeWithDelayedDeserialization(context); + } + } + + private static final class ConcreteMethodAssumptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.ConcreteMethod.class; + } + + @Override + public String tag() { + return "concreteMethod"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.ConcreteMethod assumption = (Assumptions.ConcreteMethod) instance; + serializer.serialize(assumption.context, objectBuilder.append("context")); + serializer.serialize(assumption.method, objectBuilder.append("method")); + serializer.serialize(assumption.impl, objectBuilder.append("impl")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + ResolvedJavaType context = (ResolvedJavaType) deserializer.deserialize(json.get("context"), proxyFactory); + ResolvedJavaMethod method = (ResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); + ResolvedJavaMethod impl = (ResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); + return new Assumptions.ConcreteMethod(method, context, impl); + } + } + + private static final class CallSiteTargetValueAssumptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return Assumptions.CallSiteTargetValue.class; + } + + @Override + public String tag() { + return "callSiteTarget"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Assumptions.CallSiteTargetValue assumption = (Assumptions.CallSiteTargetValue) instance; + serializer.serialize(assumption.callSite, objectBuilder.append("callSite")); + serializer.serialize(assumption.methodHandle, objectBuilder.append("methodHandle")); + + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + JavaConstant callSite = (JavaConstant) deserializer.deserialize(json.get("callSite"), proxyFactory); + JavaConstant methodHandle = (JavaConstant) deserializer.deserialize(json.get("methodHandle"), proxyFactory); + return new Assumptions.CallSiteTargetValue(callSite, methodHandle); + } + } + + private static final class UnresolvedJavaTypeSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return UnresolvedJavaType.class; + } + + @Override + public String tag() { + return "unresType"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + UnresolvedJavaType type = (UnresolvedJavaType) instance; + objectBuilder.append("name", type.getName()); + + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + return UnresolvedJavaType.create(name); + } + } + + private static final class UnresolvedJavaMethodSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return UnresolvedJavaMethod.class; + } + + @Override + public String tag() { + return "unresMethod"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + UnresolvedJavaMethod method = (UnresolvedJavaMethod) instance; + objectBuilder.append("name", method.getName()); + serializer.serialize(method.getSignature(), objectBuilder.append("signature")); + serializer.serialize(method.getDeclaringClass(), objectBuilder.append("holder")); + + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + Signature signature = (Signature) deserializer.deserialize(json.get("signature"), proxyFactory); + JavaType holder = (JavaType) deserializer.deserialize(json.get("holder"), proxyFactory); + return new UnresolvedJavaMethod(name, signature, holder); + } + } + + private static final class UnresolvedJavaFieldSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return UnresolvedJavaField.class; + } + + @Override + public String tag() { + return "unresField"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + UnresolvedJavaField method = (UnresolvedJavaField) instance; + objectBuilder.append("name", method.getName()); + serializer.serialize(method.getType(), objectBuilder.append("type")); + serializer.serialize(method.getDeclaringClass(), objectBuilder.append("holder")); + + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + JavaType type = (JavaType) deserializer.deserialize(json.get("type"), proxyFactory); + JavaType holder = (JavaType) deserializer.deserialize(json.get("holder"), proxyFactory); + return new UnresolvedJavaField(holder, name, type); + } + } + + private static final class PrimitiveConstantSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return PrimitiveConstant.class; + } + + @Override + public String tag() { + return "primConst"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + PrimitiveConstant constant = (PrimitiveConstant) instance; + objectBuilder.append("raw", constant.getRawValue()); + serializer.serialize(constant.getJavaKind(), objectBuilder.append("kind")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Number raw = (Number) json.get("raw"); + JavaKind kind = (JavaKind) deserializer.deserialize(json.get("kind"), proxyFactory); + return JavaConstant.forPrimitive(kind, raw.longValue()); + } + } + + private static final class ForeignCallDescriptorSerializer implements ObjectSerializer { + private static final class ForeignCallDescriptorSurrogate { + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return ForeignCallDescriptor.class; + } + + @Override + public String tag() { + return "foreignCallDesc"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + return new ForeignCallDescriptorSurrogate(); + } + } + + private static final class EncodedSpeculationReasonSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return EncodedSpeculationReason.class; + } + + @Override + public String tag() { + return "encSpecReason"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + EncodedSpeculationReason reason = (EncodedSpeculationReason) instance; + objectBuilder.append("groupName", reason.getGroupName()); + objectBuilder.append("groupId", reason.getGroupId()); + serializer.serialize(reason.getContext(), objectBuilder.append("context")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("groupName"); + int groupId = (int) json.get("groupId"); + Object[] context = (Object[]) deserializer.deserialize(json.get("context"), proxyFactory); + return new EncodedSpeculationReason(groupId, name, context); + } + } + + private static final class HotSpotSpeculationSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return HotSpotSpeculationLog.HotSpotSpeculation.class; + } + + @Override + public String tag() { + return "hsSpec"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + HotSpotSpeculationLog.HotSpotSpeculation speculation = (HotSpotSpeculationLog.HotSpotSpeculation) instance; + serializer.serialize(speculation.getReason(), objectBuilder.append("reason")); + serializer.serialize(speculation.getReasonEncoding(), objectBuilder.append("bytes")); + serializer.serialize(speculation.getEncoding(), objectBuilder.append("encoding")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + JavaConstant encoding = (JavaConstant) deserializer.deserialize(json.get("encoding"), proxyFactory); + byte[] bytes = (byte[]) deserializer.deserialize(json.get("bytes"), proxyFactory); + SpeculationLog.SpeculationReason reason = (SpeculationLog.SpeculationReason) deserializer.deserialize(json.get("reason"), proxyFactory); + return new HotSpotSpeculationLog.HotSpotSpeculation(reason, encoding, bytes); + } + } + + private static final class JavaTypeProfileSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return JavaTypeProfile.class; + } + + @Override + public String tag() { + return "typeProf"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + JavaTypeProfile typeProfile = (JavaTypeProfile) instance; + serializer.serialize(typeProfile.getNullSeen(), objectBuilder.append("nullSeen")); + objectBuilder.append("notRecorded", doubleToHex(typeProfile.getNotRecordedProbability())); + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("types").array()) { + for (JavaTypeProfile.ProfiledType item : typeProfile.getTypes()) { + serializer.serialize(item, arrayBuilder.nextEntry()); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + TriState nullSeen = (TriState) deserializer.deserialize(json.get("nullSeen"), proxyFactory); + double notRecorded = hexToDouble((String) json.get("notRecorded")); + List types = new ArrayList<>(); + for (var type : (List) json.get("types")) { + types.add((DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization) deserializer.deserialize(type, proxyFactory)); + } + return new DelayedDeserializationObject.JavaTypeProfileWithDelayedDeserialization(nullSeen, notRecorded, + types.toArray(DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization[]::new)); + } + } + + private static final class ProfiledTypeSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return JavaTypeProfile.ProfiledType.class; + } + + @Override + public String tag() { + return "ptype"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + JavaTypeProfile.ProfiledType profiledType = (JavaTypeProfile.ProfiledType) instance; + serializer.serialize(profiledType.getType(), objectBuilder.append("type")); + objectBuilder.append("prob", doubleToHex(profiledType.getProbability())); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + double prob = hexToDouble((String) json.get("prob")); + ResolvedJavaType type = (ResolvedJavaType) deserializer.deserialize(json.get("type"), proxyFactory); + return new DelayedDeserializationObject.ProfiledTypeWithDelayedDeserialization(type, prob); + } + } + + private static final class BitSetSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return BitSet.class; + } + + @Override + public String tag() { + return "bitset"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + BitSet bitSet = (BitSet) instance; + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("words").array()) { + for (long word : bitSet.toLongArray()) { + arrayBuilder.append(word); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + List list = (List) json.get("words"); + long[] longArray = new long[list.size()]; + for (int i = 0; i < list.size(); i++) { + longArray[i] = ((Number) list.get(i)).longValue(); + } + return BitSet.valueOf(longArray); + } + } + + private static final class VMFieldSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return VMField.class; + } + + @Override + public String tag() { + return "vmField"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + VMField vmField = (VMField) instance; + objectBuilder.append("name", vmField.name); + objectBuilder.append("type", vmField.type); + objectBuilder.append("offset", vmField.offset); + objectBuilder.append("address", Long.toHexString(vmField.address)); + serializer.serialize(vmField.value, objectBuilder.append("value")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + String type = (String) json.get("type"); + long offset = ((Number) json.get("offset")).longValue(); + long address = Long.parseUnsignedLong((String) json.get("address"), HEX_RADIX); + Object value = deserializer.deserialize(json.get("value"), proxyFactory); + return new VMField(name, type, offset, address, value); + } + } + + public static final class RecordedCompilationUnitSerializer implements ObjectSerializer { + public static final String IS_LIBGRAAL_PROPERTY = "isLibgraal"; + + private static final String TAG = "recordedCompilationUnit"; + + @Override + public Class clazz() { + return RecordedCompilationUnit.class; + } + + @Override + public String tag() { + return TAG; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + RecordedCompilationUnit unit = (RecordedCompilationUnit) instance; + serializer.serialize(unit.request.getMethod(), objectBuilder.append("method")); + objectBuilder.append("osName", unit.platform.osName()); + objectBuilder.append("archName", unit.platform.archName()); + objectBuilder.append("compilerConfiguration", unit.compilerConfiguration); + objectBuilder.append(IS_LIBGRAAL_PROPERTY, unit.isLibgraal); + objectBuilder.append("entryBCI", unit.request.getEntryBCI()); + objectBuilder.append("compileId", unit.request.getId()); + try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("operations").array()) { + for (OperationRecorder.RecordedOperation operation : unit.operations) { + serializer.serialize(operation, arrayBuilder.nextEntry(), OperationSerializer.TAG); + } + } + serializer.serialize(unit.linkages, objectBuilder.append("linkages"), RecordedForeignCallLinkagesSerializer.TAG); + objectBuilder.append("finalGraph", unit.finalGraph); + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + HotSpotResolvedJavaMethod method = (HotSpotResolvedJavaMethod) deserializer.deserialize(json.get("method"), proxyFactory); + String osName = (String) json.get("osName"); + String archName = (String) json.get("archName"); + Platform platform = new Platform(osName, archName); + String compilerConfiguration = (String) json.get("compilerConfiguration"); + boolean isLibgraal = (boolean) json.get(IS_LIBGRAAL_PROPERTY); + int entryBCI = (int) json.get("entryBCI"); + int compileId = (int) json.get("compileId"); + List list = (List) json.get("operations"); + List operations = new ArrayList<>(list.size()); + for (Object object : list) { + operations.add((OperationRecorder.RecordedOperation) deserializer.deserialize(object, proxyFactory, OperationSerializer.TAG)); + } + RecordedForeignCallLinkages linkages = (RecordedForeignCallLinkages) deserializer.deserialize(json.get("linkages"), proxyFactory, RecordedForeignCallLinkagesSerializer.TAG); + String finalGraph = (String) json.get("finalGraph"); + return new RecordedCompilationUnit(new HotSpotCompilationRequest(method, entryBCI, 0, compileId), compilerConfiguration, isLibgraal, platform, linkages, finalGraph, operations); + } + } + + private static final class RecordedForeignCallLinkagesSerializer implements ObjectSerializer { + private static final String TAG = "linkages"; + + @Override + public Class clazz() { + return RecordedForeignCallLinkages.class; + } + + @Override + public String tag() { + return TAG; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + RecordedForeignCallLinkages linkages = (RecordedForeignCallLinkages) instance; + try (JsonBuilder.ObjectBuilder builder = objectBuilder.append("map").object()) { + var cursor = linkages.linkages().getEntries(); + while (cursor.advance()) { + serializer.serialize(cursor.getValue(), builder.append(cursor.getKey()), RecordedForeignCallLinkageSerializer.TAG); + } + } + } + + @SuppressWarnings("unchecked") + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + EconomicMap linkages = EconomicMap.create(); + EconomicMap map = (EconomicMap) json.get("map"); + var cursor = map.getEntries(); + while (cursor.advance()) { + String key = cursor.getKey(); + RecordedForeignCallLinkages.RecordedForeignCallLinkage linkage = (RecordedForeignCallLinkages.RecordedForeignCallLinkage) deserializer.deserialize(cursor.getValue(), proxyFactory, + RecordedForeignCallLinkageSerializer.TAG); + linkages.put(key, linkage); + } + return new RecordedForeignCallLinkages(linkages); + } + } + + private static final class RecordedForeignCallLinkageSerializer implements ObjectSerializer { + private static final String TAG = "linkage"; + + @Override + public Class clazz() { + return RecordedForeignCallLinkages.RecordedForeignCallLinkage.class; + } + + @Override + public String tag() { + return TAG; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + RecordedForeignCallLinkages.RecordedForeignCallLinkage linkage = (RecordedForeignCallLinkages.RecordedForeignCallLinkage) instance; + objectBuilder.append("address", linkage.address()); + serializer.serialize(linkage.temporaries(), objectBuilder.append("temporaries")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + long address = ((Number) json.get("address")).longValue(); + Value[] temporaries = (Value[]) deserializer.deserialize(json.get("temporaries"), proxyFactory); + return new RecordedForeignCallLinkages.RecordedForeignCallLinkage(address, temporaries); + } + } + + private static final class RegisterValueSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return RegisterValue.class; + } + + @Override + public String tag() { + return "regVal"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + RegisterValue registerValue = (RegisterValue) instance; + serializer.serialize(registerValue.getRegister(), objectBuilder.append("register")); + serializer.serialize(registerValue.getValueKind(), objectBuilder.append("valueKind")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Register register = (Register) deserializer.deserialize(json.get("register"), proxyFactory); + ValueKind valueKind = (ValueKind) deserializer.deserialize(json.get("valueKind"), proxyFactory); + return register.asValue(valueKind); + } + } + + private static final class ExceptionHandlerSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return ExceptionHandler.class; + } + + @Override + public String tag() { + return "exceptHandler"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + ExceptionHandler handler = (ExceptionHandler) instance; + objectBuilder.append("startBCI", handler.getStartBCI()); + objectBuilder.append("endBCI", handler.getEndBCI()); + objectBuilder.append("catchBCI", handler.getHandlerBCI()); + objectBuilder.append("catchTypeCPI", handler.catchTypeCPI()); + serializer.serialize(handler.getCatchType(), objectBuilder.append("catchType")); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + int startBCI = ((Number) json.get("startBCI")).intValue(); + int endBCI = ((Number) json.get("endBCI")).intValue(); + int catchBCI = ((Number) json.get("catchBCI")).intValue(); + int catchTypeCPI = ((Number) json.get("catchTypeCPI")).intValue(); + JavaType catchType = (JavaType) deserializer.deserialize(json.get("catchType"), proxyFactory); + return new ExceptionHandler(startBCI, endBCI, catchBCI, catchTypeCPI, catchType); + } + } + + private static final class EnumSetSerializer implements ObjectSerializer { + /** + * Represents an unknown {@link Enum} type. Since the type system does not allow creating an + * {@link EnumSet} without specifying the exact enum type, we can use this type as a generic + * type parameter (which is erased anyway). + */ + private enum UnknownEnum { + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return EnumSet.class; + } + + @Override + public String tag() { + return "enumSet"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + EnumSet enumSet = (EnumSet) instance; + Class elementType; + Optional maybeElementType = enumSet.stream().findAny(); + if (maybeElementType.isPresent()) { + elementType = maybeElementType.get().getClass(); + } else { + maybeElementType = EnumSet.complementOf(enumSet).stream().findAny(); + if (maybeElementType.isPresent()) { + elementType = maybeElementType.get().getClass(); + } else { + elementType = UnknownEnum.class; + } + } + serializer.serialize(elementType, objectBuilder.append("enum")); + try (var array = objectBuilder.append("ordinals").array()) { + for (Enum element : enumSet) { + array.append(element.ordinal()); + } + } + } + + @Override + @SuppressWarnings("unchecked") + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Class elementType = (Class) deserializer.deserialize(json.get("enum"), proxyFactory); + return asEnumSet(elementType, (List) json.get("ordinals")); + } + + private static > EnumSet asEnumSet(Class clazz, Collection ordinals) { + EnumSet enumSet = EnumSet.noneOf(clazz); + E[] enumConstants = clazz.getEnumConstants(); + for (Object ordinal : ordinals) { + enumSet.add(enumConstants[((Number) ordinal).intValue()]); + } + return enumSet; + } + } + + private static final class TargetDescriptionSerializer implements ObjectSerializer { + + @Override + public Class clazz() { + return TargetDescription.class; + } + + @Override + public String tag() { + return "targetDescription"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + TargetDescription targetDescription = (TargetDescription) instance; + serializer.serialize(targetDescription.arch, objectBuilder.append("architecture")); + objectBuilder.append("isMP", targetDescription.isMP); + objectBuilder.append("stackAlignment", targetDescription.stackAlignment); + objectBuilder.append("implicitNullCheckLimit", targetDescription.implicitNullCheckLimit); + objectBuilder.append("inlineObjects", targetDescription.inlineObjects); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Architecture arch = (Architecture) deserializer.deserialize(json.get("architecture"), proxyFactory); + boolean isMP = (boolean) json.get("isMP"); + int stackAlignment = ((Number) json.get("stackAlignment")).intValue(); + int implicitNullCheckLimit = ((Number) json.get("implicitNullCheckLimit")).intValue(); + boolean inlineObjects = (boolean) json.get("inlineObjects"); + return new TargetDescription(arch, isMP, stackAlignment, implicitNullCheckLimit, inlineObjects); + } + } + + private static final class ArchitectureSerializer implements ObjectSerializer { + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return Architecture.class; + } + + @Override + public String tag() { + return "architecture"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Architecture architecture = (Architecture) instance; + objectBuilder.append("name", architecture.getName()); + serializer.serialize(architecture.getFeatures(), objectBuilder.append("features")); + } + + @Override + @SuppressWarnings("unchecked") + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + EnumSet features = (EnumSet) deserializer.deserialize(json.get("features"), proxyFactory); + return switch (name) { + case "AMD64" -> new AMD64((EnumSet) features); + case "riscv64" -> new RISCV64((EnumSet) features); + case "aarch64" -> new AArch64((EnumSet) features); + default -> throw new IllegalStateException("Unexpected value: " + name); + }; + } + } + + private static final class RegisterConfigSerializer implements ObjectSerializer { + private final boolean isHostWindowsOS; + + private final TargetDescription hostTarget; + + private RegisterConfigSerializer(Platform platform, TargetDescription hostTarget) { + this.isHostWindowsOS = platform.osName().equals("windows"); + this.hostTarget = hostTarget; + } + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return RegisterConfig.class; + } + + @Override + public String tag() { + return "registerConfig"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + RegisterConfig registerConfig = (RegisterConfig) instance; + String name = switch (registerConfig) { + case AMD64HotSpotRegisterConfig ignored -> "AMD64"; + case RISCV64HotSpotRegisterConfig ignored -> "RISCV64"; + case AArch64HotSpotRegisterConfig ignored -> "AArch64"; + default -> throw new IllegalStateException("Unexpected value: " + registerConfig); + }; + objectBuilder.append("name", name); + serializer.serialize(hostTarget, objectBuilder.append("target")); + serializer.serialize(registerConfig.getAllocatableRegisters(), objectBuilder.append("allocatable")); + objectBuilder.append("windowsOS", isHostWindowsOS); + } + + @Override + @SuppressWarnings("unchecked") + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + String name = (String) json.get("name"); + TargetDescription targetDescription = (TargetDescription) deserializer.deserialize(json.get("target"), proxyFactory); + List allocatable = (List) deserializer.deserialize(json.get("allocatable"), proxyFactory); + switch (name) { + case "AMD64" -> { + boolean windowsOS = (boolean) json.get("windowsOS"); + return new AMD64HotSpotRegisterConfig(targetDescription, allocatable, windowsOS); + } + case "RISCV64" -> { + return new RISCV64HotSpotRegisterConfig(targetDescription, allocatable); + } + case "AArch64" -> { + return new AArch64HotSpotRegisterConfig(targetDescription, allocatable); + } + default -> throw new IllegalStateException("Unexpected kind of register config: " + name); + } + } + } + + private static final class ThrowableSerializer implements ObjectSerializer { + + @Override + public boolean serializesSubclasses() { + return true; + } + + @Override + public Class clazz() { + return Throwable.class; + } + + @Override + public String tag() { + return "throwable"; + } + + @Override + public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { + Throwable throwable = (Throwable) instance; + serializer.serialize(throwable.getClass(), objectBuilder.append("class")); + objectBuilder.append("message", throwable.getMessage()); + } + + @Override + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { + Class clazz = (Class) deserializer.deserialize(json.get("class"), proxyFactory); + String message = (String) json.get("message"); + if (clazz == JVMCIError.class) { + return new JVMCIError(message); + } else if (clazz == GraalError.class) { + return new GraalError(message); + } else if (clazz == IllegalArgumentException.class) { + return new IllegalArgumentException(message); + } else { + return new Throwable(message); + } + } + } + + private final EconomicMap tagSerializers; + + private final EconomicMap, ObjectSerializer> exactClassSerializers; + + private final EconomicMap, ObjectSerializer> interfaceSerializers; + + /** + * Constructs a serializer/deserializer for recorded compilation units. + * + * @param declarations the definitions of the compiler interface + * @param hostPlatform the platform of the current host (for serialization) + * @param hostTarget the target of the current host (for serialization) + */ + public RecordedOperationPersistence(CompilerInterfaceDeclarations declarations, Platform hostPlatform, TargetDescription hostTarget) { + this.tagSerializers = EconomicMap.create(); + this.exactClassSerializers = EconomicMap.create(); + this.interfaceSerializers = EconomicMap.create(); + for (CompilerInterfaceDeclarations.Registration registration : declarations.getRegistrations()) { + if (registration.singleton()) { + addSerializer(new RegisteredSingletonSerializer(registration)); + } else { + addSerializer(new RegisteredInstanceSerializer(registration)); + } + } + addSerializer(new ClassSerializer()); + addSerializer(new OperationSerializer()); + addSerializer(new StringSerializer()); + addSerializer(new BooleanSerializer()); + addSerializer(new NumberSerializer()); + addSerializer(new StackTraceElementSerializer()); + addSerializer(new ResultMarkerSerializer()); + addSerializer(new EnumSerializer()); + addSerializer(new DoubleArraySerializer()); + addSerializer(new ByteArraySerializer()); + addSerializer(new ArraySerializer(declarations)); + addSerializer(new ListSerializer()); + addSerializer(new SingletonSerializer(JavaConstant.NULL_POINTER)); + addSerializer(new SingletonSerializer(HotSpotCompressedNullConstant.COMPRESSED_NULL)); + addSerializer(new SingletonSerializer(SpeculationLog.NO_SPECULATION)); + addSerializer(new SingletonSerializer(ValueKind.Illegal)); + addSerializer(new RegisterSerializer()); + addSerializer(new FieldSerializer()); + addSerializer(new AssumptionResultSerializer()); + addSerializer(new NoFinalizableSubclassAssumptionSerializer()); + addSerializer(new ConcreteSubtypeAssumptionSerializer()); + addSerializer(new LeafTypeAssumptionSerializer()); + addSerializer(new ConcreteMethodAssumptionSerializer()); + addSerializer(new CallSiteTargetValueAssumptionSerializer()); + addSerializer(new UnresolvedJavaTypeSerializer()); + addSerializer(new UnresolvedJavaMethodSerializer()); + addSerializer(new UnresolvedJavaFieldSerializer()); + addSerializer(new PrimitiveConstantSerializer()); + addSerializer(new ForeignCallDescriptorSerializer()); + addSerializer(new EncodedSpeculationReasonSerializer()); + addSerializer(new HotSpotSpeculationSerializer()); + addSerializer(new JavaTypeProfileSerializer()); + addSerializer(new ProfiledTypeSerializer()); + addSerializer(new BitSetSerializer()); + addSerializer(new VMFieldSerializer()); + addSerializer(new RecordedCompilationUnitSerializer()); + addSerializer(new RecordedForeignCallLinkagesSerializer()); + addSerializer(new RecordedForeignCallLinkageSerializer()); + addSerializer(new RegisterValueSerializer()); + addSerializer(new EnumSetSerializer()); + addSerializer(new ArchitectureSerializer()); + addSerializer(new TargetDescriptionSerializer()); + addSerializer(new RegisterConfigSerializer(hostPlatform, hostTarget)); + addSerializer(new ExceptionHandlerSerializer()); + addSerializer(new ThrowableSerializer()); + } + + private void addSerializer(ObjectSerializer serializer) { + tagSerializers.put(serializer.tag(), serializer); + if (serializer.serializesSubclasses()) { + interfaceSerializers.put(serializer.clazz(), serializer); + } else { + exactClassSerializers.put(serializer.clazz(), serializer); + } + } + + private final RecursiveSerializer recursiveSerializer = new RecursiveSerializer() { + @Override + public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder) throws IOException { + if (instance == null) { + valueBuilder.value(null); + return; + } + ObjectSerializer serializer = exactClassSerializers.get(instance.getClass()); + if (serializer == null) { + var cursor = interfaceSerializers.getEntries(); + while (cursor.advance()) { + if (cursor.getKey().isInstance(instance)) { + serializer = cursor.getValue(); + exactClassSerializers.put(instance.getClass(), serializer); + break; + } + } + if (serializer == null) { + throw new IllegalArgumentException("No serializer for " + instance.getClass() + ": " + instance); + } + } + try (JsonBuilder.ObjectBuilder builder = valueBuilder.object()) { + builder.append("tag", serializer.tag()); + serializer.serialize(instance, builder, this); + } + } + + @Override + public void serialize(Object instance, JsonBuilder.ValueBuilder valueBuilder, String tag) throws IOException { + if (instance == null) { + valueBuilder.value(null); + return; + } + ObjectSerializer serializer = tagSerializers.get(tag); + if (serializer == null) { + throw new IllegalArgumentException("No serializer registered for the given tag " + tag); + } + try (JsonBuilder.ObjectBuilder builder = valueBuilder.object()) { + serializer.serialize(instance, builder, this); + } + } + }; + + /** + * Dumps the given compilation unit to the given writer. + * + * @param compilationUnit the compilation unit + * @param writer the writer + * @throws IOException if dumping fails + */ + public void dump(RecordedCompilationUnit compilationUnit, JsonWriter writer) throws IOException { + recursiveSerializer.serialize(compilationUnit, writer.valueBuilder(), RecordedCompilationUnitSerializer.TAG); + } + + private final RecursiveDeserializer recursiveDeserializer = new RecursiveDeserializer() { + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + String tag = (String) map.get("tag"); + if (tag == null) { + throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); + } + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); + } + return deserializer.deserialize(map, this, proxyFactory); + } else { + return json; + } + } + + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); + } + return deserializer.deserialize(map, this, proxyFactory); + } else { + throw new IllegalArgumentException("Expected a map."); + } + } + }; + + /** + * Loads a recorded compilation unit from the given reader. + * + * @param source the reader + * @param proxyFactory the proxy factory + * @return the loaded compilation unit + * @throws IOException if loading fails + * @throws DeserializationException if deserialization fails + */ + public RecordedCompilationUnit load(Reader source, ProxyFactory proxyFactory) throws IOException, DeserializationException { + JsonParser parser = new JsonParser(source); + return (RecordedCompilationUnit) recursiveDeserializer.deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java new file mode 100644 index 000000000000..d264db2bd57b --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; +import jdk.graal.compiler.util.EconomicHashSet; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * A holder and factory for compiler-interface proxies during a recorded compilation. + *

+ * A proxy created by this class delegates method invocation to an original object (one obtained + * from the host VM). The proxy may also record the result of the invocation, which can be later + * serialized into a JSON file ({@link RecordedOperationPersistence}). The behavior of the proxy for + * individual methods is configured in {@link CompilerInterfaceDeclarations}. All subsequent method + * invocations with equal arguments produce the result computed initially. + *

+ * The result of an operation is either a return value or a thrown exception. + * + * @see CompilerInterfaceDeclarations + * @see ReplayCompilationSupport + */ +class RecordingCompilationProxies implements CompilationProxies { + /** + * Records the results of method invocations and also ensures the methods return stable values. + */ + private final OperationRecorder recorder; + + /** + * Declares which objects require a proxy (registered objects) and defines the behavior of + * method invocation. + */ + private final CompilerInterfaceDeclarations declarations; + + /** + * Used to replace registered objects inside composite objects with proxies and vice versa. + */ + private final CompilationProxyMapper proxyMapper; + + RecordingCompilationProxies(CompilerInterfaceDeclarations declarations) { + this.recorder = new OperationRecorder(); + this.declarations = declarations; + this.proxyMapper = new CompilationProxyMapper(declarations, this::proxify); + } + + /** + * Collects and returns a list of operations that should be serialized for the current + * compilation unit. This list includes the global operations needed to initialize the compiler, + * the operations recorded in this compilation unit, and the operations that should be recorded + * because they could be needed during replay (e.g., to produce debug output). These operations + * are defined in {@link CompilerInterfaceDeclarations}. + *

+ * Since the method calls performed and recorded by this method can return newly discovered + * objects that have operations to record of their own, this method uses a worklist to compute a + * transitive closure. + * + * @return a list of recorded compilation + */ + public List collectOperationsForSerialization() { + List worklist = new ArrayList<>(); + Set visited = new EconomicHashSet<>(); + CompilationProxyMapper worklistAdder = new CompilationProxyMapper(declarations, (input) -> { + if (!visited.contains(input)) { + visited.add(input); + worklist.add(input); + } + return proxify(input); + }); + // Add all referenced proxies to the worklist. + for (OperationRecorder.RecordedOperation operation : recorder.getCurrentRecordedOperations()) { + worklistAdder.proxifyRecursive(operation.receiver()); + worklistAdder.proxifyRecursive(operation.args()); + Object result = operation.resultOrMarker(); + if (result instanceof SpecialResultMarker.ExceptionThrownMarker thrownMarker) { + worklistAdder.proxifyRecursive(thrownMarker.getThrown()); + } else if (!(result instanceof SpecialResultMarker)) { + worklistAdder.proxifyRecursive(result); + } + } + /* + * Perform and record the calls that could be needed during replay, except those that were + * already recorded during the compilation. + */ + while (!worklist.isEmpty()) { + Object receiver = worklist.removeLast(); + CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(receiver); + for (CompilerInterfaceDeclarations.MethodCallToRecord methodCall : registration.getMethodCallsToRecord(receiver)) { + OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(methodCall.receiver(), methodCall.symbolicMethod(), methodCall.args()); + if (recorder.getRecordedResultOrMarker(key) != SpecialResultMarker.NO_RESULT_MARKER) { + // The result of the call is already recorded. + continue; + } + try { + Object result = methodCall.invokableMethod().invoke(methodCall.receiver(), methodCall.args()); + recorder.recordReturnValue(key, result); + // Make sure to record the method calls for the results of this call as well. + worklistAdder.proxifyRecursive(result); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + recorder.recordExceptionThrown(key, cause); + worklistAdder.proxifyRecursive(cause); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Recording failed due to an exception", e); + } + } + } + return recorder.getCurrentRecordedOperations(); + } + + /** + * Enters the context of a method compilation for the current compilation thread. + * + * @return a scope for the context + */ + public DebugCloseable enterCompilationContext() { + return recorder.enterCompilationContext(); + } + + @Override + public DebugCloseable enterSnippetContext() { + return recorder.enterIgnoredContext(); + } + + @Override + public Platform targetPlatform() { + return Platform.ofCurrentHost(); + } + + @Override + public DebugCloseable withDebugContext(DebugContext debugContext) { + return DebugCloseable.VOID_CLOSEABLE; + } + + @Override + public CompilationProxy proxify(Object input) { + if (input instanceof CompilationProxy compilationProxy) { + return compilationProxy; + } + CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input); + if (registration == null) { + throw new IllegalArgumentException(input + " is not an instance of a registered class."); + } + return CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> { + if (method.equals(CompilationProxyBase.unproxifyMethod)) { + return input; + } + Object[] unproxifiedArgs = (Object[]) unproxifyRecursive(args); + CompilerInterfaceDeclarations.MethodStrategy methodStrategy = registration.findStrategy(method); + OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(input, method, unproxifiedArgs); + Object result; + if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { + Object resultOrMarker = recorder.getRecordedResultOrMarker(key); + if (resultOrMarker instanceof SpecialResultMarker.ExceptionThrownMarker exceptionThrownMarker) { + throw (Throwable) proxifyRecursive(exceptionThrownMarker.getThrown()); + } else if (resultOrMarker == SpecialResultMarker.NULL_RESULT_MARKER) { + return null; + } else if (resultOrMarker != SpecialResultMarker.NO_RESULT_MARKER) { + return proxifyRecursive(resultOrMarker); + } + } + try { + result = callback.invoke(input, unproxifiedArgs); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { + recorder.recordExceptionThrown(key, cause); + } + throw (Throwable) proxifyRecursive(cause); + } catch (IllegalAccessException e) { + throw new IllegalStateException("Recording failed due to an exception", e); + } + if (methodStrategy == CompilerInterfaceDeclarations.MethodStrategy.RecordReplay) { + recorder.recordReturnValue(key, result); + } + return proxifyRecursive(result); + }); + } + + @Override + public CompilerInterfaceDeclarations getDeclarations() { + return declarations; + } + + private Object proxifyRecursive(Object input) { + return proxyMapper.proxifyRecursive(input); + } + + private Object unproxifyRecursive(Object input) { + return proxyMapper.unproxifyRecursive(input); + } + + private static final CompilationProxy.SymbolicMethod getProfilingInfo = new CompilationProxy.SymbolicMethod(ResolvedJavaMethod.class, "getProfilingInfo", boolean.class, boolean.class); + + /** + * Injects profiling information for the given method. + *

+ * Profiles can be injected when recording a retried compilation. All subsequent calls to + * {@link ResolvedJavaMethod#getProfilingInfo()} when the receiver is a proxy representing the + * given method will return the specified profiles. + * + * @param method the method to inject profiles into + * @param includeNormal whether to include normal profiles + * @param includeOSR whether to include OSR profiles + * @param profilingInfo the profiling information to inject + */ + public void injectProfiles(ResolvedJavaMethod method, boolean includeNormal, boolean includeOSR, ProfilingInfo profilingInfo) { + recorder.recordReturnValue(new OperationRecorder.RecordedOperationKey(method, getProfilingInfo, new Object[]{includeNormal, includeOSR}), profilingInfo); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java new file mode 100644 index 000000000000..47b6fcc4d06b --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java @@ -0,0 +1,618 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.io.Serial; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +import org.graalvm.collections.EconomicMap; +import org.graalvm.collections.Equivalence; + +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.debug.GlobalMetrics; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.debug.TimerKey; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; +import jdk.graal.compiler.options.Option; +import jdk.graal.compiler.options.OptionKey; +import jdk.graal.compiler.options.OptionType; +import jdk.graal.compiler.options.OptionValues; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.meta.Constant; + +//JaCoCo Exclude + +/** + * A holder and factory for compiler-interface proxies during a replayed compilation. + *

+ * This class creates proxies for the classes registered in {@link CompilerInterfaceDeclarations}. + * The behavior of proxy method invocation is also specified in + * {@link CompilerInterfaceDeclarations}. In general, the proxies usually try to produce the same + * results as those from the recorded compilation. + *

+ * The recorded operations (from a JSON file produced during the recorded compilation) are loaded + * using {@link #loadOperationResults}. This class creates a flat representation of the data to keep + * memory usage low, which is important when replaying many compilations on libgraal and + * benchmarking compile time. + *

+ * It is necessary to call {@link #findLocalMirrors()} after the operations are loaded and JVMCI + * providers are created. The local mirrors may be required during a replayed compilation to query + * information from the local VM, which is needed for snippet parsing. + * + * @see ReplayCompilationSupport + */ +@LibGraalSupport.HostedOnly(unlessTrue = ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP) +public class ReplayCompilationProxies implements CompilationProxies { + public static class Options { + // @formatter:off + @Option(help = "Fail when there is no recorded result for a JVMCI operation during compilation replay.", type = OptionType.Debug) + public static final OptionKey ReplayDivergenceIsFailure = new OptionKey<>(false); + // @formatter:on + } + + /** + * Metadata for a proxy object. + */ + private static final class ProxyInfo { + /** + * The {@link #operationResults} index where the recorded operations for this proxy begin. + */ + private int resultsBegin; + + /** + * The {@link #operationResults} index where the recorded operations for this proxy end. + */ + private int resultsEnd; + + /** + * A local mirror identified for this proxy or {@code null}. + */ + private Object localMirror; + + private ProxyInfo() { + } + + public void setLocalMirror(Object newLocalMirror) { + localMirror = newLocalMirror; + } + } + + /** + * Declares which objects require a proxy (registered objects) and defines the behavior of + * method invocation. + */ + private final CompilerInterfaceDeclarations declarations; + + /** + * A flattened representation of the recorded operations and their results. This representation + * aims to save memory when replaying a large number of compilation units as a benchmark. + *

+ * The recorded operations for a given proxy are stored as a subarray from + * {@link ProxyInfo#resultsBegin} to {@link ProxyInfo#resultsEnd}. The subarray is formed by + * multiple runs, each run corresponding to a particular symbolic method. The first element in + * every run is the corresponding method. + *

    + *
  • If the method is parameterless, the next (and last element) of the run is the return + * value.
  • + *
  • If the method has {@code p > 0} parameters, the next element is the number of records + * {@code r > 0}. This is followed by {@code r} records. Every record contains {@code p} + * argument elements and a single return value.
  • + *
+ */ + private Object[] operationResults; + + /** + * A map of proxies created for singleton compiler-interface classes (as defined by + * {@link #declarations}). + */ + private final EconomicMap, CompilationProxy> singletonProxies; + + /** + * A map of compiler-interface singletons. + */ + private final EconomicMap, Object> singletonObjects; + + /** + * Proxifies and unproxifies composite objects. + */ + private final CompilationProxyMapper proxyMapper; + + /** + * Maps metadata to all created proxies. + */ + private final EconomicMap createdProxies; + + /** + * Maps local objects to created proxies. + */ + private final EconomicMap localMirrorToProxy; + + /** + * The platform of the target system. + */ + private Platform targetPlatform; + + /** + * The global metrics where the metrics from the current {@link #debug} context should be + * accumulated. + */ + private final GlobalMetrics globalMetrics; + + /** + * The debug information for the current context or {@code null}. + */ + private DebugContext debug; + + /** + * {@code true} if failing to find a recorded result should throw an exception. + */ + private final boolean divergenceIsFailure; + + @SuppressWarnings("this-escape") + public ReplayCompilationProxies(CompilerInterfaceDeclarations declarations, GlobalMetrics globalMetrics, OptionValues options) { + this.declarations = declarations; + this.singletonProxies = EconomicMap.create(); + this.singletonObjects = EconomicMap.create(); + this.proxyMapper = new CompilationProxyMapper(declarations, this::proxify); + this.createdProxies = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); + this.localMirrorToProxy = EconomicMap.create(); + this.globalMetrics = globalMetrics; + this.divergenceIsFailure = Options.ReplayDivergenceIsFailure.getValue(options); + } + + /** + * Sets the target platform for replay compilation. + * + * @param platform the target platform + */ + public void setTargetPlatform(Platform platform) { + targetPlatform = platform; + } + + @Override + public Platform targetPlatform() { + return targetPlatform; + } + + @Override + public DebugCloseable withDebugContext(DebugContext debugContext) { + debug = debugContext; + return () -> { + globalMetrics.add(debug); + debug = null; + }; + } + + /** + * Loads the recorded operations from a collection. + * + * @param operations the collection of recorded operations + * @param internPool the pool of interned objects + */ + public void loadOperationResults(Collection operations, EconomicMap internPool) { + /* + * Maps a proxy to another map, which will form the subarray of the recorded operations for + * the given proxy. + */ + EconomicMap>> results = EconomicMap.create(Equivalence.IDENTITY_WITH_SYSTEM_HASHCODE); + int length = 0; // the length of operationResults + for (OperationRecorder.RecordedOperation operation : operations) { + CompilationProxy proxy = (CompilationProxy) operation.receiver(); + /* + * Maps a method to the flattened records for the recorded invocations of the method + * using this proxy as a receiver. + */ + EconomicMap> proxyMap = results.get(proxy); + if (proxyMap == null) { + proxyMap = EconomicMap.create(); + results.put(proxy, proxyMap); + } + // The flattened records for this proxy. + List list = proxyMap.get(operation.method()); + if (list == null) { + list = new ArrayList<>(); + proxyMap.put(operation.method(), list); + ++length; + if (operation.method().hasParams()) { + ++length; + } + } + // Add a record for the given proxy and a method. + if (operation.method().hasParams()) { + // The record starts with the argument values. + for (Object arg : operation.args()) { + list.add(arg); + ++length; + } + } else if (!list.isEmpty()) { + // Redundant recorded operation, skipping. + continue; + } + // Finish the record by adding the return value. + list.add(operation.resultOrMarker()); + ++length; + } + operationResults = new Object[length]; + int index = 0; + var proxyCursor = createdProxies.getEntries(); + while (proxyCursor.advance()) { + // Begin the subarray with recorded operations for the given proxy. + CompilationProxy proxy = proxyCursor.getKey(); + ProxyInfo proxyInfo = proxyCursor.getValue(); + proxyInfo.resultsBegin = index; + var proxyMap = results.get(proxy); + if (proxyMap != null) { + var proxyMapCursor = proxyMap.getEntries(); + while (proxyMapCursor.advance()) { + CompilationProxy.SymbolicMethod method = proxyMapCursor.getKey(); + List list = proxyMapCursor.getValue(); + // Store the method at the beginning of a run. + operationResults[index++] = intern(method, internPool); + if (method.hasParams()) { + // For a method with parameters, store the number of records. + int recordCount = list.size() / (method.paramCount() + 1); + // Intern the boxed integer. + operationResults[index++] = intern(recordCount, internPool); + } else { + GraalError.guarantee(list.size() == 1, "records for parameterless methods contain only the return value"); + } + // Write the records (or just the return value if the method is parameterless). + for (Object object : list) { + operationResults[index++] = intern(object, internPool); + } + } + } + proxyInfo.resultsEnd = index; + } + } + + /** + * Interns the given object in the provided intern pool. + * + * @param object the object to be interned + * @param internPool the map used to store interned objects + * @return the interned object + */ + private static Object intern(Object object, EconomicMap internPool) { + if (object == null) { + return null; + } + if (object instanceof CompilationProxy || object instanceof Object[] || object instanceof TargetDescription) { + return object; + } + Object interned = internPool.get(object); + if (interned == null) { + interned = object; + internPool.put(interned, interned); + } + return interned; + } + + /** + * Finds local mirrors for all created proxies. + *

+ * A local mirror of a proxy is a JVMCI object obtained from the host VM that is logically + * equivalent to the proxy. For example, for a given type proxy, we can find the local type with + * the same name. Local mirrors can be used to query information about the object if the + * information was not recorded in the JSON file. This is particularly useful for snippet + * parsing, which is intentionally not recorded. + *

+ * During snippet parsing, the compiler may discover a JVMCI object which has no matching proxy. + * For such objects, local-only proxies are created using {@link #proxify(Object)}. + */ + public void findLocalMirrors() { + var cursor = createdProxies.getEntries(); + while (cursor.advance()) { + CompilationProxy proxy = cursor.getKey(); + CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(proxy); + if (registration.mirrorLocator() != null) { + Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, singletonObjects); + if (localMirror != null) { + Object previousProxy = localMirrorToProxy.put(localMirror, proxy); + GraalError.guarantee(previousProxy == null, "there must be at most one proxy instance for an object"); + ProxyInfo proxyInfo = cursor.getValue(); + proxyInfo.setLocalMirror(localMirror); + registerLocalMirrorsForConstantResults(proxyInfo); + } + } + } + } + + /** + * Registers the local mirrors for constant results of a given proxy object. + *

+ * This method finds whether the object has any getters that returns a proxy representing a + * constant. If so, it invokes the getters on the local mirror of the proxy object to obtain the + * local mirror of the constant proxy. + * + * @param proxyInfo metadata for the proxy object + */ + private void registerLocalMirrorsForConstantResults(ProxyInfo proxyInfo) { + for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { + CompilationProxy.SymbolicMethod method = (CompilationProxy.SymbolicMethod) operationResults[i++]; + if (method.hasParams()) { + int entries = (Integer) operationResults[i++]; + i += (method.paramCount() + 1) * entries; + } else { + Object result = operationResults[i++]; + if (!(result instanceof Constant)) { + continue; + } + Object receiver = proxyInfo.localMirror; + CompilationProxy.InvokableMethod invokable = declarations.findRegistrationForInstance(receiver).findInvokableMethod(method); + if (invokable == null) { + continue; + } + Object localMirror; + try { + localMirror = invokable.invoke(receiver, new Object[0]); + } catch (Exception ignored) { + continue; + } + createdProxies.get((CompilationProxy) result).setLocalMirror(localMirror); + } + } + } + + @Override + public CompilationProxy proxify(Object input) { + if (input instanceof CompilationProxy compilationProxy) { + return compilationProxy; + } + CompilationProxy proxy = localMirrorToProxy.get(input); + if (proxy != null) { + return proxy; + } + CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(input); + GraalError.guarantee(registration != null, "the input must be an instance of a registered class"); + proxy = createProxy(registration); + ProxyInfo proxyInfo = createdProxies.get(proxy); + proxyInfo.setLocalMirror(input); + localMirrorToProxy.put(input, proxy); + if (registration.singleton()) { + singletonObjects.put(registration.clazz(), input); + } + return proxy; + } + + @Override + public CompilerInterfaceDeclarations getDeclarations() { + return declarations; + } + + @Override + public DebugCloseable enterSnippetContext() { + return DebugCloseable.VOID_CLOSEABLE; + } + + private static final TimerKey JVMCIReplayTime = DebugContext.timer("JVMCIReplayTime"); + + private static final class NotUnproxifiableException extends RuntimeException { + @Serial private static final long serialVersionUID = -4899571461334839074L; + } + + /** + * Creates a new proxy object for a specific registered compiler-interface class. + * + * @param registration a registration for a compiler-interface class + * @return a new proxy object + */ + @SuppressWarnings("try") + public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration registration) { + if (registration.singleton()) { + CompilationProxy found = singletonProxies.get(registration.clazz()); + if (found != null) { + return found; + } + } + ProxyInfo proxyInfo = new ProxyInfo(); + CompilationProxy instance = CompilationProxy.newProxyInstance(registration.clazz(), (proxy, method, callback, args) -> { + try (DebugCloseable ignored = (debug == null) ? null : JVMCIReplayTime.start(debug)) { + if (method.equals(CompilationProxyBase.unproxifyMethod)) { + Object localMirror = proxyInfo.localMirror; + if (localMirror == null) { + throw new NotUnproxifiableException(); + } + return localMirror; + } else if (method.equals(CompilationProxyBase.equalsMethod)) { + return proxy == args[0]; + } else if (method.equals(CompilationProxyBase.hashCodeMethod)) { + return System.identityHashCode(proxy); + } + Object input; + if (registration.singleton()) { + input = singletonObjects.get(registration.clazz()); + } else { + input = null; + } + CompilerInterfaceDeclarations.MethodStrategy strategy = registration.findStrategy(method); + if (strategy == CompilerInterfaceDeclarations.MethodStrategy.Passthrough) { + if (proxyInfo.localMirror == null) { + CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); + if (handler != null) { + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); + } + } + GraalError.guarantee(proxyInfo.localMirror != null, "a proxy with passthrough strategy must have a local mirror or fallback handler"); + return callback.invoke(proxyInfo.localMirror, args); + } else if (strategy == CompilerInterfaceDeclarations.MethodStrategy.DefaultValue) { + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); + } + Object result = findResult(proxyInfo, method, args); + if (result != SpecialResultMarker.NO_RESULT_MARKER) { + if (result instanceof SpecialResultMarker marker) { + // We proxify the result due to objects with delayed deserialization. + return proxyMapper.proxifyRecursive(marker.materialize()); + } else { + return proxyMapper.proxifyRecursive(result); + } + } + try { + Object[] unproxifiedArgs = (Object[]) proxyMapper.unproxifyRecursive(args); + if (registration.singleton()) { + return proxyMapper.proxifyRecursive(callback.invoke(input, unproxifiedArgs)); + } + Object localMirror = proxyInfo.localMirror; + if (localMirror != null) { + return proxyMapper.proxifyRecursive(callback.invoke(localMirror, unproxifiedArgs)); + } + } catch (NotUnproxifiableException ignored2) { + // Cannot unproxify the arguments: continue. + } catch (InvocationTargetException exception) { + // The result of the invocation is a thrown exception. + throw exception.getTargetException(); + } + CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); + if (handler != null) { + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); + } + if (args != null) { + for (Object arg : args) { + if (arg instanceof CompilationProxy unproxifiable) { + GraalError.guarantee(createdProxies.containsKey(unproxifiable), "a proxy argument was not created by this instance"); + } + } + } + if (divergenceIsFailure) { + failOnDivergence(proxy, proxyInfo, method, args); + } + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); + } + }); + if (registration.singleton()) { + singletonProxies.put(registration.clazz(), instance); + } + createdProxies.put(instance, proxyInfo); + return instance; + } + + /** + * Finds the recorded result for a given method invocation on a proxy object. + *

+ * This method iterates over the recorded operations for the proxy object and checks if the + * method and arguments match the recorded operation. If a match is found, it returns the + * recorded result. If no match is found, it returns + * {@link SpecialResultMarker#NO_RESULT_MARKER}. + * + * @param proxyInfo metadata for the proxy object + * @param method the symbolic method being invoked + * @param args the arguments passed to the method invocation + * @return the recorded result or {@link SpecialResultMarker#NO_RESULT_MARKER} if not found + */ + private Object findResult(ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method, Object[] args) { + for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { + CompilationProxy.SymbolicMethod resultMethod = (CompilationProxy.SymbolicMethod) operationResults[i++]; + if (resultMethod.hasParams()) { + int entries = (Integer) operationResults[i++]; + if (!method.equals(resultMethod)) { + i += (resultMethod.paramCount() + 1) * entries; + continue; + } + entry: for (int j = 0; j < entries; j++) { + for (int k = 0; k < method.paramCount(); k++) { + Object arg = operationResults[i++]; + if (!Objects.equals(args[k], arg)) { + i += method.paramCount() - k; + continue entry; + } + } + return operationResults[i]; + } + } else { + if (!method.equals(resultMethod)) { + ++i; + continue; + } + return operationResults[i]; + } + return SpecialResultMarker.NO_RESULT_MARKER; + } + return SpecialResultMarker.NO_RESULT_MARKER; + } + + /** + * Throws an exception when a recorded result is not found for a given method invocation during + * replay compilation. + * + * @param proxy the proxy object on which the method was invoked + * @param proxyInfo metadata for the proxy object + * @param method the symbolic method being invoked + * @param args the arguments passed to the method invocation + * @throws GraalError always thrown to indicate the divergence + */ + private void failOnDivergence(Object proxy, ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method, Object[] args) { + StringBuilder sb = new StringBuilder(); + sb.append("No result for ").append(method).append('[').append(Arrays.toString(args)).append(']').append(System.lineSeparator()); + formatRecordedOperations(sb, proxyInfo, method); + if (!method.equals(CompilationProxyBase.toStringMethod)) { + sb.append("Receiver: ").append(proxy).append(System.lineSeparator()); + } + sb.append("Local mirror: ").append(proxyInfo.localMirror).append(System.lineSeparator()); + throw new GraalError(sb.toString()); + } + + /** + * Formats the recorded operations for a given proxy object and method into a string builder. + *

+ * This method iterates over the recorded operations for the proxy object and appends the + * available keys for the given method to the string builder. + * + * @param sb the string builder to append the formatted recorded operations to + * @param proxyInfo metadata for the proxy object + * @param method the symbolic method being invoked + */ + private void formatRecordedOperations(StringBuilder sb, ProxyInfo proxyInfo, CompilationProxy.SymbolicMethod method) { + for (int i = proxyInfo.resultsBegin; i < proxyInfo.resultsEnd;) { + CompilationProxy.SymbolicMethod resultMethod = (CompilationProxy.SymbolicMethod) operationResults[i++]; + if (resultMethod.hasParams()) { + int entries = (Integer) operationResults[i++]; + if (!method.equals(resultMethod)) { + i += (resultMethod.paramCount() + 1) * entries; + continue; + } + for (int j = 0; j < entries; j++) { + Object[] args = new Object[method.paramCount()]; + for (int k = 0; k < method.paramCount(); k++) { + args[k] = operationResults[i++]; + } + i++; + sb.append(" Available key: ").append(method).append('[').append(Arrays.toString(args)).append(']').append(System.lineSeparator()); + } + } else { + ++i; + } + return; + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java new file mode 100644 index 000000000000..025e14ab43d3 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java @@ -0,0 +1,495 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import java.io.Closeable; +import java.io.FileReader; +import java.io.IOException; +import java.io.PrintStream; +import java.io.Serial; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; + +import org.graalvm.collections.EconomicMap; + +import jdk.graal.compiler.core.GraalCompilerOptions; +import jdk.graal.compiler.core.common.GraalOptions; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.GlobalMetrics; +import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; +import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; +import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; +import jdk.graal.compiler.hotspot.HotSpotGraalOptionValues; +import jdk.graal.compiler.hotspot.HotSpotGraalRuntime; +import jdk.graal.compiler.hotspot.HotSpotGraalRuntimeProvider; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.util.args.BooleanValue; +import jdk.graal.compiler.util.args.IntegerValue; +import jdk.graal.compiler.util.args.OptionValue; +import jdk.graal.compiler.util.args.Program; +import jdk.graal.compiler.util.args.StringValue; +import jdk.graal.compiler.util.json.JsonParserException; +import jdk.vm.ci.code.CompilationRequest; +import jdk.vm.ci.code.CompilationRequestResult; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; + +//JaCoCo Exclude + +/** + * The entry point for running replay compilations in jargraal and libgraal. + * + * @see ReplayCompilationSupport + * @see CompilerInterfaceDeclarations + */ +@LibGraalSupport.HostedOnly(unlessTrue = ReplayCompilationSupport.ENABLE_REPLAY_LAUNCHER_PROP) +public class ReplayCompilationRunner { + /** + * The exit status of a replay compilation run. + */ + public enum ExitStatus { + /** + * Successful execution. + */ + Success(0), + + /** + * Failed execution. + */ + Failure(1); + + private final int status; + + ExitStatus(int status) { + this.status = status; + } + + /** + * Exits the virtual machine with the corresponding status code. + */ + public void exitVM() { + System.exit(status); + } + + /** + * Returns the exit status code. + */ + public int getStatus() { + return status; + } + } + + /** + * Runs the replay compilation launcher based on the provided command-line arguments. + * + * @param args command-line arguments + * @param out output stream for printing messages + * @return the exit status of the launcher + */ + @SuppressWarnings("try") + public static ExitStatus run(String[] args, PrintStream out) { + Program program = new Program("mx replaycomp", "Replay compilations from files."); + OptionValue benchmarkArg = program.addNamed("--benchmark", new BooleanValue("true|false", false, "Replay compilations as a benchmark.")); + OptionValue iterationsArg = program.addNamed("--iterations", new IntegerValue("n", 10, "The number of benchmark iterations.")); + OptionValue compareGraphsArg = program.addNamed("--compare-graphs", new BooleanValue("true|false", false, "Verify that the replayed graph equals the recorded one.")); + OptionValue inputPathArg = program.addPositional(new StringValue("TARGET", "Path to a directory with replay compilation files (or path to a single file).")); + program.parseAndValidate(args, true); + Path inputPath = Path.of(inputPathArg.getValue()); + List inputFiles; + try { + inputFiles = findJsonFiles(inputPath); + } catch (IOException e) { + out.println(e.getMessage()); + return ExitStatus.Failure; + } + if (inputFiles.isEmpty()) { + out.println("No replay files found in " + inputPath); + return ExitStatus.Failure; + } + + OptionValues systemOptions = new OptionValues(HotSpotGraalOptionValues.parseOptions()); + OptionValues options = new OptionValues(systemOptions, GraalCompilerOptions.SystemicCompilationFailureRate, 0); + CompilerInterfaceDeclarations declarations = CompilerInterfaceDeclarations.build(); + HotSpotJVMCIRuntime runtime = HotSpotJVMCIRuntime.runtime(); + CompilerConfigurationFactory factory = CompilerConfigurationFactory.selectFactory(null, options, runtime); + + LibGraalSupport libgraal = LibGraalSupport.INSTANCE; + GlobalMetrics globalMetrics = new GlobalMetrics(); + if (benchmarkArg.getValue()) { + List reproducers = new ArrayList<>(); + EconomicMap internPool = EconomicMap.create(); + for (Path file : inputFiles) { + try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { + try { + reproducers.add(Reproducer.initializeFromFile(file.toString(), declarations, runtime, options, + factory, globalMetrics, out, internPool)); + } catch (Exception e) { + out.println("Preparation failed for " + file + ": " + e); + } + } catch (Exception e) { + return ExitStatus.Failure; + } + } + internPool.clear(); + Runtime javaRuntime = Runtime.getRuntime(); + for (int i = 0; i < iterationsArg.getValue(); i++) { + out.printf("====== replaycomp iteration %d started ======%n", i); + double memBefore = (javaRuntime.totalMemory() - javaRuntime.freeMemory()) / 1_000_000d; + long before = System.nanoTime(); + System.gc(); + long afterGC = System.nanoTime(); + double memAfter = (javaRuntime.totalMemory() - javaRuntime.freeMemory()) / 1_000_000d; + double gcMillis = (afterGC - before) / 1_000_000d; + out.printf("GC before operation: completed in %.3f ms, heap usage %.3f MB -> %.3f MB.%n", gcMillis, memBefore, memAfter); + int codeHash = 0; + for (Reproducer reproducer : reproducers) { + try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null) { + ReplayResult replayResult = reproducer.compile(); + replayResult.verify(compareGraphsArg.getValue()); + codeHash = codeHash * 31 + Arrays.hashCode(replayResult.replayedArtifacts().result().getTargetCode()); + } catch (Exception e) { + out.println("Replay failed: " + e); + return ExitStatus.Failure; + } + } + out.printf("Compiled code hash: %d%n", codeHash); + long after = System.nanoTime(); + double iterMillis = (after - before) / 1_000_000d; + out.printf("====== replaycomp iteration %d completed (%.3f ms) ======%n", i, iterMillis); + } + for (Reproducer reproducer : reproducers) { + reproducer.close(); + } + } else { + ReplayCompilationStatistics statistics = new ReplayCompilationStatistics(); + for (Path file : inputFiles) { + ReplayCompilationTask task = statistics.startTask(file.toString()); + try (AutoCloseable ignored = libgraal != null ? libgraal.openCompilationRequestScope() : null; + Reproducer reproducer = Reproducer.initializeFromFile(file.toString(), declarations, runtime, + options, factory, globalMetrics, out, EconomicMap.create())) { + reproducer.compile().verify(compareGraphsArg.getValue()); + out.println("Successfully replayed " + reproducer.request); + } catch (ReplayParserFailure failure) { + out.println("Replay failed: " + failure.getMessage()); + task.setFailureReason(failure.getMessage()); + } catch (Exception e) { + out.println("Replay failed: " + e); + return ExitStatus.Failure; + } + } + out.println(); + statistics.printStatistics(out); + } + globalMetrics.print(options); + return ExitStatus.Success; + } + + /** + * Recursively searches for JSON files within the given root directory (or file) and its + * subdirectories. The returned list of paths is sorted lexicographically to ensure consistency + * between runs. + * + * @param root the root directory/file to start the search from + * @return a list of paths to JSON files found within the root directory/file and its + * subdirectories + * @throws IOException if an I/O error occurs while traversing the file tree + */ + private static List findJsonFiles(Path root) throws IOException { + List paths = new ArrayList<>(); + Files.walkFileTree(root, new FileVisitor<>() { + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) { + if (Files.isRegularFile(file) && file.toString().endsWith(".json")) { + paths.add(file); + } + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) { + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) { + return FileVisitResult.CONTINUE; + } + }); + paths.sort(Path::compareTo); + return paths; + } + + public static sealed class ReplayLauncherFailure extends Exception { + @Serial private static final long serialVersionUID = -1610853593485835928L; + + public ReplayLauncherFailure(String message) { + super(message); + } + } + + private static final class ReplayParserFailure extends ReplayLauncherFailure { + @Serial private static final long serialVersionUID = 6521004798119106469L; + + ReplayParserFailure(String message) { + super(message); + } + } + + /** + * The result of a single replay compilation. + * + * @param request the compilation request for the replay compilation + * @param result the result of the replayed compilation + * @param replayedArtifacts the artifacts produced by the replayed compilation + * @param originalGraph the canonical graph string of the final original graph (if available) + */ + public record ReplayResult(CompilationRequest request, CompilationRequestResult result, ReplayCompilationSupport.CompilationArtifacts replayedArtifacts, String originalGraph) { + public void verify(boolean verifyGraphs) throws ReplayLauncherFailure { + if (result.getFailure() == null) { + if (!verifyGraphs) { + return; + } + if (originalGraph == null) { + throw new ReplayLauncherFailure("Cannot verify the replayed graph for " + request); + } else if (!originalGraph.equals(replayedArtifacts.finalCanonicalGraph())) { + throw new ReplayLauncherFailure("Replay completed but final graphs differ"); + } + } else { + throw new ReplayLauncherFailure(Objects.toString(result.getFailure())); + } + } + } + + /** + * A recorded compilation that is ready to be compiled (potentially multiple times). + */ + public static final class Reproducer implements Closeable { + /** + * The compiler instance used for replaying the compilation. + */ + private final HotSpotGraalCompiler replayCompiler; + + /** + * The compilation request for the replayed compilation. + */ + private final HotSpotCompilationRequest request; + + /** + * The final graph of the recorded compilation. + */ + private final String finalGraph; + + /** + * The compiler options for replay. + */ + private final OptionValues options; + + /** + * Whether the recorded compilation was performed on libgraal. + */ + private final boolean isLibgraal; + + private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options, + boolean isLibgraal) { + this.replayCompiler = replayCompiler; + this.request = request; + this.finalGraph = finalGraph; + this.options = options; + this.isLibgraal = isLibgraal; + } + + /** + * Creates a new reproducer instance from a JSON file. + * + * @param fileName the name of the JSON file containing the recorded compilation + * @param declarations describes the compiler interface + * @param runtime the JVMCI runtime + * @param options the options for the replay compiler + * @param factory the factory used to create the compiler configuration + * @param globalMetrics the metrics object where metrics from the replayed compilations are + * accumulated + * @param out stream for debug output + * @param internPool the pool of interned objects + * @return a new reproducer instance + * @throws ReplayLauncherFailure if an error occurs during initialization + */ + @SuppressWarnings("try") + public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDeclarations declarations, HotSpotJVMCIRuntime runtime, + OptionValues options, CompilerConfigurationFactory factory, GlobalMetrics globalMetrics, PrintStream out, EconomicMap internPool) throws ReplayLauncherFailure { + ReplayCompilationProxies proxies = new ReplayCompilationProxies(declarations, globalMetrics, options); + out.println("Loading " + fileName); + RecordedOperationPersistence.RecordedCompilationUnit compilationUnit; + try (FileReader reader = new FileReader(fileName)) { + RecordedOperationPersistence persistence = new RecordedOperationPersistence(declarations, Platform.ofCurrentHost(), + HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); + compilationUnit = persistence.load(reader, proxies::createProxy); + proxies.setTargetPlatform(compilationUnit.platform()); + proxies.loadOperationResults(compilationUnit.operations(), internPool); + } catch (Exception exception) { + if (exception instanceof JsonParserException parserException && parserException.isAtEOF().isTrue()) { + throw new ReplayParserFailure("Failed to parse an incomplete JSON file (likely caused by VM shutdown during the recorded compilation)."); + } + throw new ReplayParserFailure("Parsing failed due to " + exception.getMessage()); + } + HotSpotCompilationRequest request = compilationUnit.request(); + boolean replayingLibgraalInJargraal = !LibGraalSupport.inLibGraalRuntime() && compilationUnit.isLibgraal(); + ReplayCompilationSupport.setReplayingLibgraalInJargraal(replayingLibgraalInJargraal); + if (LibGraalSupport.inLibGraalRuntime() && !compilationUnit.isLibgraal()) { + throw new ReplayLauncherFailure("Cannot replay jargraal compilation " + request + " in libgraal"); + } + boolean encodeSnippets = replayingLibgraalInJargraal && !HotSpotReplacementsImpl.snippetsAreEncoded(); + if (encodeSnippets) { + /* + * Ensure the snippet encoder will be created and linked to the decorated providers + * created below. + */ + HotSpotReplacementsImpl.clearSnippetEncoder(); + } + OptionValues selectedOptions = options; + if (replayingLibgraalInJargraal) { + selectedOptions = new OptionValues(options, GraalOptions.EagerSnippets, true); + } + out.println("Initializing the replay compiler for " + request); + HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, selectedOptions, factory, new ReplayCompilationSupport(proxies, factory.getName())); + HotSpotGraalRuntimeProvider graalRuntime = replayCompiler.getGraalRuntime(); + if (!graalRuntime.getCompilerConfigurationName().equals(compilationUnit.compilerConfiguration())) { + throw new ReplayLauncherFailure(("Compiler configuration mismatch: the task was compiled using " + compilationUnit.compilerConfiguration() + + " but the initialized compiler is " + graalRuntime.getCompilerConfigurationName())); + } + ReplayCompilationSupport support = graalRuntime.getReplayCompilationSupport(); + support.setRecordedForeignCallLinkages(compilationUnit.linkages()); + if (encodeSnippets) { + out.println("Encoding snippets"); + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) graalRuntime.getHostProviders().getReplacements(); + replacements.encode(graalRuntime.getOptions()); + } + return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), selectedOptions, compilationUnit.isLibgraal()); + } + + /** + * Compiles (or recompiles) the method using the recorded data. + * + * @return a replay result object containing the compilation result and the replayed graph + */ + @SuppressWarnings("try") + public ReplayResult compile() { + ReplayCompilationSupport.setReplayingLibgraalInJargraal(!LibGraalSupport.inLibGraalRuntime() && isLibgraal); + ReplayCompilationSupport support = replayCompiler.getGraalRuntime().getReplayCompilationSupport(); + CompilationRequestResult result = replayCompiler.compileMethod(request, true, options); + ReplayCompilationSupport.CompilationArtifacts replayedArtifacts = support.clearCompilationArtifacts(); + return new ReplayResult(request, result, replayedArtifacts, finalGraph); + } + + /** + * Shuts down the {@link HotSpotGraalRuntime} associated with this reproducer. + */ + @Override + public void close() { + ((HotSpotGraalRuntime) replayCompiler.getGraalRuntime()).shutdown(); + } + } + + /** + * Tracks the outcome of a single replayed compilation. + */ + private static class ReplayCompilationTask { + private final String fileName; + + private boolean success; + + private String failureReason; + + ReplayCompilationTask(String fileName) { + this.fileName = fileName; + this.success = true; + } + + public void setFailureReason(String newFailureReason) { + failureReason = newFailureReason; + success = false; + } + + public boolean isSuccess() { + return success; + } + + public boolean isFailure() { + return !success; + } + } + + /** + * Tracks the outcomes of all replayed compilations, which is used to print summary statistics + * at the end. + */ + private static class ReplayCompilationStatistics { + private final List tasks; + + ReplayCompilationStatistics() { + this.tasks = new ArrayList<>(); + } + + public ReplayCompilationTask startTask(String fileName) { + ReplayCompilationTask task = new ReplayCompilationTask(fileName); + tasks.add(task); + return task; + } + + public void printStatistics(PrintStream out) { + out.printf("Completed %d replay compilation task(s)%n", tasks.size()); + out.printf("%8d task(s) succeeded%n", successCount()); + out.printf("%8d task(s) failed%n", failureCount()); + for (ReplayCompilationTask task : failedTasks()) { + out.printf(" %s %s%n", task.fileName, task.failureReason); + } + } + + private long successCount() { + return tasks.stream().filter(ReplayCompilationTask::isSuccess).count(); + } + + private long failureCount() { + return tasks.stream().filter(ReplayCompilationTask::isFailure).count(); + } + + private List failedTasks() { + return tasks.stream().filter(ReplayCompilationTask::isFailure).toList(); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java new file mode 100644 index 000000000000..19b390fea953 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java @@ -0,0 +1,502 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; + +import java.nio.file.Path; +import java.util.function.Predicate; + +import jdk.graal.compiler.code.CompilationResult; +import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.core.common.spi.ForeignCallSignature; +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.debug.DebugOptions; +import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.debug.MethodFilter; +import jdk.graal.compiler.debug.PathUtilities; +import jdk.graal.compiler.debug.TTY; +import jdk.graal.compiler.hotspot.HotSpotBackendFactory; +import jdk.graal.compiler.hotspot.HotSpotDecoratedBackendFactory; +import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; +import jdk.graal.compiler.hotspot.Platform; +import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; +import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.nodes.StructuredGraph; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.printer.CanonicalStringGraphPrinter; +import jdk.graal.compiler.replacements.SnippetTemplate; +import jdk.graal.compiler.serviceprovider.GraalServices; +import jdk.graal.compiler.util.json.JsonWriter; +import jdk.vm.ci.hotspot.HotSpotCompilationRequest; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** + * Provides support for recording and replaying compilations, acting as an interface between the + * compiler and the internal implementation of replay compilation. + * + *

+ * Recording is enabled using {@link DebugOptions#RecordForReplay}. Replay compilations are executed + * by the {@link ReplayCompilationRunner}. It is not a goal to execute the replayed code. + * + *

+ * Proxies. Recording and replay require creating proxies for JVMCI objects. During + * recording, these proxies record the arguments and results of methods to serialize them into a + * JSON file ({@link RecordedOperationPersistence}). During replay, they look up and return the + * appropriate results. The behavior of every proxy and method is configured in + * {@link CompilerInterfaceDeclarations}. + * + *

+ * Decorators. To enable recording and replay, we create service providers that return the + * appropriate proxies. This is achieved by decorating the backend factory + * {@link #decorateBackendFactory}. Moreover, {@link #decorateCompilationRequest}, + * {@link #decorateCompilerProfiler}, {@link #decorateVMConfigAccess}, and + * {@link #decorateIntrinsificationTrustPredicate} return proxies for additional objects. + * + *

+ * Compiler Instances. Since we hijack the compiler's backend factory, a dedicated compiler + * instance must be created for recording and replay. To modify the compiler's behavior even from + * places where an instance of this class cannot be reasonably obtained, this class tracks whether + * the current compiler thread is performing a replay of a libgraal compilation in jargraal + * ({@link #isReplayingLibgraalInJargraal()}) and whether it is in a snippet context + * ({@link #isInSnippetContext()}). During recording, separate compiler instances should be used for + * the recorded methods ({@link #matchesRecordCompilationFilter}) and the methods that are not + * recorded. This ensures that the recording overhead is paid for the recorded methods only. + * + *

+ * Snippets. It is possible to record a libgraal compilation and replay it on jargraal. To + * ensure the replayed compilation matches the recorded one, we replay such compilations using + * encoded snippets ({@link #isReplayingLibgraalInJargraal()}). We must never mix raw JVMCI object + * and JVMCI proxies in a single graph, so we create proxies even during snippet parsing. Due to the + * need to replay libgraal compilations on jargraal and since snippets are compiler code rather than + * application code, the proxies do not record the operations during snippet parsing (i.e., inside + * snippet context {@link #enterSnippetContext}). When snippets are parsed during replay, the + * proxies may use local mirrors to query the information required for the snippets from the host VM + * instance. + * + *

+ * Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the + * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that + * was not recorded, including the information to parse snippets. There are also local-only proxies + * that do not originate from the recorded JSON but are instead created from local JVMCI objects + * (created using {@link CompilationProxies#proxify}). The exact rules when operations are delegated + * to local mirrors are dictated by the strategies defined in {@link CompilerInterfaceDeclarations}. + * + *

+ * Foreign Call Linkages. During recording, we capture the addresses and killed registers of + * finalized foreign calls ({@link RecordedForeignCallLinkages}). During replay, we restore these + * linkages ({@link #finalizeForeignCallLinkage}) to ensure that the machine code compiled during + * replay is close to the code compiled during recording. + */ +public final class ReplayCompilationSupport { + /** + * Libgraal build-time system property name for enabling the replay compilation launcher. + */ + public static final String ENABLE_REPLAY_LAUNCHER_PROP = "debug.jdk.graal.enableReplayLauncher"; + + /** + * Whether the replay compilation launcher is enabled in libgraal. + */ + public static final boolean ENABLE_REPLAY_LAUNCHER = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_REPLAY_LAUNCHER_PROP)); + + /** + * Returns whether this compiler thread is replaying a libgraal compilation in jargraal. + */ + public static boolean isReplayingLibgraalInJargraal() { + return !inRuntimeCode() && isReplayingLibgraalInJargraal.get(); + } + + /** + * Sets whether the current compiler thread is replaying a libgraal compilation in jargraal. + * + * @param replayingLibgraalInJargraal true if the current compiler thread is replaying a + * libgraal compilation in jargraal, false otherwise + */ + public static void setReplayingLibgraalInJargraal(boolean replayingLibgraalInJargraal) { + if (replayingLibgraalInJargraal) { + GraalError.guarantee(!inRuntimeCode(), "this option is only valid in jargraal"); + } + ReplayCompilationSupport.isReplayingLibgraalInJargraal.set(replayingLibgraalInJargraal); + } + + /** + * Checks whether the given method's compilation should be recorded according to the given + * options. + * + * @param options the option values + * @param method the method to check against the filter + * @return true if the method's compilation should be recorded + */ + public static boolean matchesRecordCompilationFilter(OptionValues options, ResolvedJavaMethod method) { + String filter = DebugOptions.RecordForReplay.getValue(options); + if (filter == null) { + return false; + } else { + return MethodFilter.parse(filter).matches(method); + } + } + + /** + * Whether the current compiler thread is replaying a libgraal compilation in jargraal. + */ + private static final ThreadLocal isReplayingLibgraalInJargraal = ThreadLocal.withInitial(() -> false); + + /** + * The proxies used for recording/replaying the compilations. + */ + private final CompilationProxies proxies; + + /** + * The compiler's foreign call provider. + */ + private HotSpotHostForeignCallsProvider foreignCallsProvider; + + /** + * Recorded foreign call linkages used to finalize foreign calls. + */ + private RecordedForeignCallLinkages recordedForeignCallLinkages; + + /** + * Whether the compiler thread is in a snippet context. + */ + private final ThreadLocal inSnippetContext = ThreadLocal.withInitial(() -> false); + + /** + * The compilation artifacts of the current compiler thread. + */ + private final ThreadLocal compilationArtifacts = ThreadLocal.withInitial(() -> null); + + /** + * The compiler's configuration name. + */ + private final String compilerConfigurationName; + + ReplayCompilationSupport(CompilationProxies proxies, String compilerConfigurationName) { + this.proxies = proxies; + this.compilerConfigurationName = compilerConfigurationName; + } + + /** + * Creates a replay compilation support for a recording compiler. + * + * @param compilerConfigurationName the name of the compiler's configuration + * @return the support for a recording compiler + */ + public static ReplayCompilationSupport createRecording(String compilerConfigurationName) { + return new ReplayCompilationSupport(new RecordingCompilationProxies(CompilerInterfaceDeclarations.build()), compilerConfigurationName); + } + + /** + * Sets the foreign calls provider of the compiler bound to this instance. + * + * @param newForeignCallsProvider the compiler's foreign calls provider + */ + public void setForeignCallsProvider(HotSpotHostForeignCallsProvider newForeignCallsProvider) { + foreignCallsProvider = newForeignCallsProvider; + } + + /** + * Sets the recorded foreign calls linkages to be used to finalize foreign calls. + * + * @param linkages recorded linkages + */ + public void setRecordedForeignCallLinkages(RecordedForeignCallLinkages linkages) { + recordedForeignCallLinkages = linkages; + } + + /** + * Filters the given options to remove any that are not allowed during recording. + * + * @param options the options to filter + * @return the filtered options + */ + public OptionValues filterOptions(OptionValues options) { + if (proxies instanceof RecordingCompilationProxies) { + // GraalOptions.UseSnippetGraphCache can remain enabled. + return new OptionValues(options, SnippetTemplate.Options.UseSnippetTemplateCache, false); + } else { + return options; + } + } + + /** + * Enters a snippet context for the current compiler thread. In a recorded compilation, the + * proxies should not record JVMCI calls and results related to snippet parsing and + * optimization. In a replayed compilation, the proxies can delegate to the local mirrors to + * handle JVMCI calls. + * + * @return a debug closeable that should be closed when exiting the context + */ + private DebugCloseable enterSnippetContext() { + boolean previous = inSnippetContext.get(); + inSnippetContext.set(true); + DebugCloseable closeable = proxies.enterSnippetContext(); + return () -> { + inSnippetContext.set(previous); + closeable.close(); + }; + } + + /** + * Enters a snippet context for the given providers. + *

+ * If the providers have a non-null {@link ReplayCompilationSupport} instance, this method + * enters a snippet context for the current compiler thread. Otherwise, it returns {@code null}. + * + * @param providers the providers to check for {@link ReplayCompilationSupport} + * @return a scope representing the snippet context, or {@code null} if not supported + */ + public static DebugCloseable enterSnippetContext(HotSpotProviders providers) { + return enterSnippetContext(providers.getReplayCompilationSupport()); + } + + /** + * Enters a snippet context for the given {@link ReplayCompilationSupport} instance. + *

+ * If the provided {@code support} is not {@code null}, this method enters a snippet context for + * the current compiler thread. Otherwise, it returns {@code null}. + * + * @param support the instance to check + * @return a scope representing the snippet context, or {@code null} if not supported + */ + public static DebugCloseable enterSnippetContext(ReplayCompilationSupport support) { + if (support == null) { + return null; + } else { + return support.enterSnippetContext(); + } + } + + /** + * Returns whether this compiler thread is in a snippet context. + */ + public boolean isInSnippetContext() { + return inSnippetContext.get(); + } + + /** + * Enters a scope with a given debug context. + * + * @param debug the debug context to use in the scope + * @return an object that closes the scope + */ + public DebugCloseable withDebugContext(DebugContext debug) { + return proxies.withDebugContext(debug); + } + + /** + * Enters a compilation context for the specified compilation request. + * + * @param originalRequest the original compilation request + * @param initialOptions the initial options for the compilation + * @return a debug closeable that should be closed after the compilation + */ + public DebugCloseable enterCompilationContext(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { + if (proxies instanceof RecordingCompilationProxies recordingCompilationProxies) { + DebugCloseable context = recordingCompilationProxies.enterCompilationContext(); + return () -> { + try { + serializeRecordedCompilation(originalRequest, initialOptions); + } finally { + context.close(); + } + }; + } else { + return DebugCloseable.VOID_CLOSEABLE; + } + } + + private void serializeRecordedCompilation(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { + RecordedForeignCallLinkages linkages = RecordedForeignCallLinkages.createFrom(foreignCallsProvider); + try { + String directory = PathUtilities.getPath(DebugOptions.getDumpDirectory(initialOptions), "replaycomp"); + PathUtilities.createDirectories(directory); + String requestId = Integer.toString(originalRequest.getId()); + String fileName = requestId + ".json"; + Path path = Path.of(directory, fileName); + RecordedOperationPersistence persistence = new RecordedOperationPersistence(proxies.getDeclarations(), Platform.ofCurrentHost(), + HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getTarget()); + RecordingCompilationProxies recordingCompilationProxies = (RecordingCompilationProxies) proxies; + CompilationArtifacts artifacts = clearCompilationArtifacts(); + String finalCanonicalGraph = (artifacts == null) ? null : artifacts.finalCanonicalGraph(); + RecordedOperationPersistence.RecordedCompilationUnit compilationUnit = new RecordedOperationPersistence.RecordedCompilationUnit(originalRequest, compilerConfigurationName, + LibGraalSupport.inLibGraalRuntime(), recordingCompilationProxies.targetPlatform(), linkages, finalCanonicalGraph, + recordingCompilationProxies.collectOperationsForSerialization()); + try (JsonWriter jsonWriter = new JsonWriter(path)) { + persistence.dump(compilationUnit, jsonWriter); + } + TTY.println("Serialized " + originalRequest + " to " + path); + } catch (Exception exception) { + TTY.println("Failed to serialize the recorded operations to a file."); + exception.printStackTrace(TTY.out().out()); + } + } + + /** + * Sets the address and temporaries of a foreign call linkage using the recorded linkages if + * they are available and contain the given foreign call signature. + * + * @param signature the foreign call signature + * @param callTarget the foreign call target to update + * @return true if the linkage was finalized + */ + public boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpotForeignCallLinkage callTarget) { + if (recordedForeignCallLinkages != null) { + return recordedForeignCallLinkages.finalizeForeignCallLinkage(signature, callTarget); + } + return false; + } + + /** + * Finds local mirrors for the parsed proxies during replay compilation. This should be invoked + * just after the core JVMCI providers are created because they are needed to look up the + * mirrors. + */ + public void findLocalMirrors() { + if (proxies instanceof ReplayCompilationProxies replayCompilationProxies) { + replayCompilationProxies.findLocalMirrors(); + } + } + + /** + * Decorates a backend factory. + * + * @param factory the backend factory to decorate + * @return the decorated backend factory + */ + public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory) { + return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this)); + } + + /** + * Decorates a compilation request. + * + * @param request the compilation request to decorate + * @return the decorated compilation request + */ + public HotSpotCompilationRequest decorateCompilationRequest(HotSpotCompilationRequest request) { + return new HotSpotCompilationRequest((HotSpotResolvedJavaMethod) proxies.proxify(request.getMethod()), request.getEntryBCI(), request.getJvmciEnv(), request.getId()); + } + + /** + * Decorates a compiler profiler. + * + * @param compilerProfiler the compiler profiler to decorate + * @return the decorated compiler profiler + */ + public CompilerProfiler decorateCompilerProfiler(CompilerProfiler compilerProfiler) { + return (CompilerProfiler) proxies.proxify(compilerProfiler); + } + + /** + * Decorates an intrinsification trust predicate. + * + * @param predicate the intrinsification trust predicate to decorate + * @return the decorated intrinsification trust predicate + */ + @SuppressWarnings("unchecked") + public Predicate decorateIntrinsificationTrustPredicate(Predicate predicate) { + return (Predicate) proxies.proxify(predicate); + } + + /** + * Decorates a VM config access. + * + * @param access the VM config access to decorate + * @return the decorated VM config access + */ + public HotSpotVMConfigAccess decorateVMConfigAccess(HotSpotVMConfigAccess access) { + return (HotSpotVMConfigAccess) proxies.proxify(access); + } + + /** + * Returns the target platform. + */ + public Platform targetPlatform() { + return proxies.targetPlatform(); + } + + /** + * The artifacts produced by a compilation. + * + * @param graph the final graph + * @param result the compilation result + */ + public record CompilationArtifacts(StructuredGraph graph, CompilationResult result) { + /** + * Returns the canonical graph string for the final graph. + */ + public String finalCanonicalGraph() { + return CanonicalStringGraphPrinter.getCanonicalGraphString(graph, false, true); + } + } + + /** + * Records the artifacts produced by the last compilation of the current compiler thread. + * + * @param graph the final graph + * @param result the compilation result + */ + public void recordCompilationArtifacts(StructuredGraph graph, CompilationResult result) { + compilationArtifacts.set(new CompilationArtifacts(graph, result)); + } + + /** + * Clears and returns the artifacts produced by the last successfully completed compilation of + * the current compiler thread. May return {@code null} if the last compilation did not complete + * successfully. + * + * @return the cleared compilation artifacts or {@code null} + */ + public CompilationArtifacts clearCompilationArtifacts() { + CompilationArtifacts result = compilationArtifacts.get(); + compilationArtifacts.remove(); + return result; + } + + /** + * Injects profiles for the given method during recording. + * + * @param method the method to inject profiles into + * @param includeNormal whether to include normal profiles + * @param includeOSR whether to include OSR profiles + * @param profilingInfo the profiling information to inject + * @throws UnsupportedOperationException if called during replay + */ + public void injectProfiles(ResolvedJavaMethod method, boolean includeNormal, boolean includeOSR, ProfilingInfo profilingInfo) { + if (proxies instanceof RecordingCompilationProxies recordingProxies) { + recordingProxies.injectProfiles(method, includeNormal, includeOSR, profilingInfo); + } else { + throw new UnsupportedOperationException("injectProfiles during replay"); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java new file mode 100644 index 000000000000..77f722b69059 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/SpecialResultMarker.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp; + +/** + * A marker representing the result of a recorded operation that did not produce a non-null value: + * it may have thrown an exception, returned null, or there is no recorded result. + */ +public sealed interface SpecialResultMarker { + /** + * Marker indicating that no result was recorded. + */ + NoResultMarker NO_RESULT_MARKER = new NoResultMarker(); + + /** + * Marker indicating that a null result was recorded. + */ + NullResultMarker NULL_RESULT_MARKER = new NullResultMarker(); + + /** + * Materializes the result represented by this marker. + * + * @return the materialized result, or {@code null} if the result is null + * @throws Throwable if the recorded operation threw an exception + */ + Object materialize() throws Throwable; + + /** + * A marker indicating that no result was recorded. + */ + final class NoResultMarker implements SpecialResultMarker { + private NoResultMarker() { + } + + @Override + public String toString() { + return "[no recorded result]"; + } + + @Override + public Object materialize() throws Throwable { + throw new IllegalStateException(); + } + } + + /** + * A marker indicating that a null result was recorded. + */ + final class NullResultMarker implements SpecialResultMarker { + private NullResultMarker() { + } + + @Override + public String toString() { + return "[null result]"; + } + + @Override + public Object materialize() throws Throwable { + return null; + } + } + + /** + * A marker indicating that an exception was thrown during the operation. + */ + final class ExceptionThrownMarker implements SpecialResultMarker { + private final Throwable thrown; + + /** + * Creates a new instance of this marker with the given thrown exception. + * + * @param thrown the exception that was thrown + */ + public ExceptionThrownMarker(Throwable thrown) { + this.thrown = thrown; + } + + /** + * Returns the exception that was thrown. + * + * @return the thrown exception + */ + public Throwable getThrown() { + return thrown; + } + + @Override + public String toString() { + return "[thrown: " + thrown + "]"; + } + + @Override + public Object materialize() throws Throwable { + throw thrown; + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java new file mode 100644 index 000000000000..35eb865bf83f --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; +import java.lang.reflect.UndeclaredThrowableException; +import java.util.Arrays; +import java.util.function.Predicate; + +import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.debug.GraalError; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotProfilingInfo; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; + +//JaCoCo Exclude + +/** + * A proxy object for a compiler-interface class. + *

+ * The implementations of this interface are static proxies for JVMCI objects. We use static proxies + * instead of {@link Proxy dynamic proxies} to minimize the amount of reachable methods in a + * libgraal image and for a finer control over which interface methods need to be overridden. + *

    + *
  • {@link SymbolicMethod} and {@link InvokableMethod} are replacements for {@link Method}. Using + * an {@link InvokableMethod} instead of an invokable {@link Method} avoids marking the methods as + * compilation roots, allowing the points-to analysis to keep the reachable methods only.
  • + *
  • The {@link SymbolicMethod} and {@link InvokableMethod} instances are stored in static final + * fields and initialized at image build time. This is preferred over allocation at run time.
  • + *
  • Interface methods with a default implementation (implemented by calling other interface + * methods) do not require an overriding implementation. Omitting the implementation can make + * recording and replay more efficient. For example, many methods of {@link ResolvedJavaMethod} are + * implemented by delegating to {@link ResolvedJavaMethod#getModifiers()}, so we override + * {@link ResolvedJavaMethod#getModifiers()} but do not override + * {@link ResolvedJavaMethod#isInterface()}.
  • + *
+ * + * @see jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport + * @see jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations + */ +public interface CompilationProxy { + /** + * Returns the underlying object being proxied or {@code null} if such an object was not + * identified in this VM. + * + * @return the underlying object + */ + Object unproxify(); + + /** + * Represents a compiler-interface method that can be invoked. + */ + @FunctionalInterface + interface InvokableMethod { + /** + * Invokes the method on the given receiver object with the provided arguments. + * + * @param receiver the object on which to invoke the method + * @param args the method arguments + * @return the result of the method invocation + * @throws InvocationTargetException if the method invocation fails + * @throws IllegalAccessException if access to the method is denied + */ + Object invoke(Object receiver, Object[] args) throws InvocationTargetException, IllegalAccessException; + } + + /** + * A symbolic non-invokable representation of a compiler-interface method. + * + * @param methodAndParamNames the method name and parameter class names + */ + record SymbolicMethod(String[] methodAndParamNames) { + public SymbolicMethod(String methodName, Class... params) { + this(toArray(methodName, params)); + } + + /** + * Returns {@code true} if the method has parameters. + */ + public boolean hasParams() { + return methodAndParamNames.length > 1; + } + + /** + * Returns the number of method parameters. + */ + public int paramCount() { + return methodAndParamNames.length - 1; + } + + private static String[] toArray(String methodName, Class[] params) { + String[] result = new String[params.length + 1]; + result[0] = methodName; + for (int i = 0; i < params.length; i++) { + result[i + 1] = params[i].getSimpleName(); + } + return result; + } + + /** + * Creates a new symbolic method instance from a list receiver classes, method name, and + * parameter types. At least one of the receiver classes must declare a method with the + * given signature. + * + * @param receiverClasses the receiver classes + * @param methodName the method name + * @param params the parameter types + */ + public SymbolicMethod(Class[] receiverClasses, String methodName, Class... params) { + this(methodName, params); + if (!LibGraalSupport.inLibGraalRuntime()) { + // Omit the check in the image to avoid increasing image size. + for (Class receiverClass : receiverClasses) { + try { + receiverClass.getDeclaredMethod(methodName, params); + return; + } catch (NoSuchMethodException ignored) { + } + try { + receiverClass.getMethod(methodName, params); + return; + } catch (NoSuchMethodException ignored) { + } + } + throw new GraalError("Method " + methodName + " not found"); + } + } + + /** + * Creates a new symbolic method from a receiver class, method name, and parameter types. + * The receiver class must declare a method with the given signature. + * + * @param receiverClass the receiver class + * @param methodName the method name + * @param params the parameter types + */ + public SymbolicMethod(Class receiverClass, String methodName, Class... params) { + this(new Class[]{receiverClass}, methodName, params); + } + + @Override + public boolean equals(Object o) { + if (o instanceof SymbolicMethod that) { + return Arrays.equals(methodAndParamNames, that.methodAndParamNames); + } + return false; + } + + @Override + public int hashCode() { + return Arrays.hashCode(methodAndParamNames); + } + + @Override + public String toString() { + return Arrays.toString(methodAndParamNames); + } + } + + /** + * An invocation handler for a proxy object. + */ + @FunctionalInterface + interface InvocationHandler { + /** + * Handles an invocation on the proxy object. + * + * @param proxy the proxy object + * @param method the symbolic method being invoked + * @param invokableMethod the underlying compiler-interface method + * @param args the invocation arguments + * @return the result of the invocation + * @throws Throwable thrown by the handler + */ + Object handle(Object proxy, SymbolicMethod method, InvokableMethod invokableMethod, Object[] args) throws Throwable; + } + + /** + * Handles an invocation on a proxy object using the provided invocation handler. This method + * should be invoked by the proxy implementations. + * + * @param handler the invocation handler + * @param proxy the proxy object + * @param method the symbolic method being invoked + * @param invokable the underlying compiler-interface method + * @param args the invocation arguments + * @return the result of the invocation + * @throws UndeclaredThrowableException if the handler throws a checked exception + */ + static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod method, InvokableMethod invokable, Object... args) { + try { + return handler.handle(proxy, method, (Object receiver, Object[] actualArgs) -> { + try { + return invokable.invoke(receiver, actualArgs); + } catch (Throwable e) { + throw new InvocationTargetException(e); + } + }, (args.length == 0) ? null : args); + } catch (RuntimeException | Error e) { + throw e; + } catch (Throwable e) { + throw new UndeclaredThrowableException(e); + } + } + + /** + * Creates a new compilation proxy instance for the specified class and invocation handler. + * + * @param clazz the class (interface) that the proxy must implement + * @param handler the invocation handler for the proxy + * @return a new compilation proxy instance + * @throws GraalError if no proxy class exists for the specified interfaces + */ + static CompilationProxy newProxyInstance(Class clazz, InvocationHandler handler) { + if (clazz == HotSpotResolvedObjectType.class) { + return new HotSpotResolvedObjectTypeProxy(handler); + } else if (clazz == HotSpotResolvedJavaType.class) { + return new HotSpotResolvedJavaTypeProxy(handler); + } else if (clazz == HotSpotResolvedJavaMethod.class) { + return new HotSpotResolvedJavaMethodProxy(handler); + } else if (clazz == HotSpotResolvedJavaField.class) { + return new HotSpotResolvedJavaFieldProxy(handler); + } else if (clazz == HotSpotVMConfigAccess.class) { + return new HotSpotVMConfigAccessProxy(handler); + } else if (clazz == MetaAccessProvider.class) { + return new MetaAccessProviderProxy(handler); + } else if (clazz == HotSpotConstantReflectionProvider.class) { + return new HotSpotConstantReflectionProviderProxy(handler); + } else if (clazz == MethodHandleAccessProvider.class) { + return new MethodHandleAccessProviderProxy(handler); + } else if (clazz == HotSpotMemoryAccessProvider.class) { + return new HotSpotMemoryAccessProviderProxy(handler); + } else if (clazz == HotSpotCodeCacheProvider.class) { + return new HotSpotCodeCacheProviderProxy(handler); + } else if (clazz == CompilerProfiler.class) { + return new CompilerProfilerProxy(handler); + } else if (clazz == ConstantPool.class) { + return new ConstantPoolProxy(handler); + } else if (clazz == Signature.class) { + return new SignatureProxy(handler); + } else if (clazz == HotSpotObjectConstant.class) { + return new HotSpotObjectConstantProxy(handler); + } else if (clazz == HotSpotMetaspaceConstant.class) { + return new HotSpotMetaspaceConstantProxy(handler); + } else if (clazz == HotSpotProfilingInfo.class) { + return new HotSpotProfilingInfoProxy(handler); + } else if (clazz == ProfilingInfo.class) { + return new ProfilingInfoProxy(handler); + } else if (clazz == SpeculationLog.class) { + return new SpeculationLogProxy(handler); + } else if (clazz == Predicate.class) { + return new PredicateProxy(handler); + } else { + throw new GraalError("No proxy class for " + clazz); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java new file mode 100644 index 000000000000..7676f906701d --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxyBase.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AnnotatedElement; + +//JaCoCo Exclude + +/** + * A base class for compilation proxies providing implementations of shared methods. + */ +public class CompilationProxyBase implements CompilationProxy { + public static final SymbolicMethod unproxifyMethod = new SymbolicMethod(CompilationProxy.class, "unproxify"); + public static final InvokableMethod unproxifyInvokable = (receiver, args) -> ((CompilationProxy) receiver).unproxify(); + + public static final SymbolicMethod hashCodeMethod = new SymbolicMethod(Object.class, "hashCode"); + public static final InvokableMethod hashCodeInvokable = (receiver, args) -> receiver.hashCode(); + + public static final SymbolicMethod equalsMethod = new SymbolicMethod(Object.class, "equals", Object.class); + public static final InvokableMethod equalsInvokable = (receiver, args) -> receiver.equals(args[0]); + + public static final SymbolicMethod toStringMethod = new SymbolicMethod(Object.class, "toString"); + public static final InvokableMethod toStringInvokable = (receiver, args) -> receiver.toString(); + + protected final InvocationHandler handler; + + CompilationProxyBase(InvocationHandler handler) { + this.handler = handler; + } + + protected final Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { + return CompilationProxy.handle(handler, this, method, invokable, args); + } + + @Override + public final Object unproxify() { + return handle(unproxifyMethod, unproxifyInvokable); + } + + @Override + public final int hashCode() { + return (int) handle(hashCodeMethod, hashCodeInvokable); + } + + @Override + public final boolean equals(Object obj) { + return (boolean) handle(equalsMethod, equalsInvokable, obj); + } + + @Override + public final String toString() { + return (String) handle(toStringMethod, toStringInvokable); + } + + /** + * Base class to share method implementations for proxies that implement + * {@link AnnotatedElement}. + */ + public abstract static class CompilationProxyAnnotatedBase extends CompilationProxyBase implements AnnotatedElement { + CompilationProxyAnnotatedBase(InvocationHandler handler) { + super(handler); + } + + public static final SymbolicMethod getAnnotationMethod = new SymbolicMethod(AnnotatedElement.class, "getAnnotation", Class.class); + @SuppressWarnings("unchecked") public static final InvokableMethod getAnnotationInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getAnnotation((Class) args[0]); + + @Override + @SuppressWarnings("unchecked") + public final T getAnnotation(Class annotationClass) { + return (T) handle(getAnnotationMethod, getAnnotationInvokable, annotationClass); + } + + public static final SymbolicMethod getAnnotationsMethod = new SymbolicMethod(AnnotatedElement.class, "getAnnotations"); + public static final InvokableMethod getAnnotationsInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getAnnotations(); + + @Override + public final Annotation[] getAnnotations() { + return (Annotation[]) handle(getAnnotationsMethod, getAnnotationsInvokable); + } + + public static final SymbolicMethod getDeclaredAnnotationsMethod = new SymbolicMethod(AnnotatedElement.class, "getDeclaredAnnotations"); + public static final InvokableMethod getDeclaredAnnotationsInvokable = (receiver, args) -> ((AnnotatedElement) receiver).getDeclaredAnnotations(); + + @Override + public final Annotation[] getDeclaredAnnotations() { + return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); + } + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java new file mode 100644 index 000000000000..c70d955d7d0b --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilerProfilerProxy.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp.proxy; + +import jdk.graal.compiler.core.common.CompilerProfiler; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +//JaCoCo Exclude + +public final class CompilerProfilerProxy extends CompilationProxyBase implements CompilerProfiler { + CompilerProfilerProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(CompilerProfiler.class, name, params); + } + + public static final SymbolicMethod getTicksMethod = method("getTicks"); + private static final InvokableMethod getTicksInvokable = (receiver, args) -> ((CompilerProfiler) receiver).getTicks(); + + @Override + public long getTicks() { + return (long) handle(getTicksMethod, getTicksInvokable); + } + + public static final SymbolicMethod notifyCompilerPhaseEventMethod = method("notifyCompilerPhaseEvent", int.class, long.class, String.class, int.class); + private static final InvokableMethod notifyCompilerPhaseEventInvokable = (receiver, args) -> { + ((CompilerProfiler) receiver).notifyCompilerPhaseEvent((int) args[0], (long) args[1], (String) args[2], (int) args[3]); + return null; + }; + + @Override + public void notifyCompilerPhaseEvent(int compileId, long startTime, String name, int nestingLevel) { + handle(notifyCompilerPhaseEventMethod, notifyCompilerPhaseEventInvokable, compileId, startTime, name, nestingLevel); + } + + public static final SymbolicMethod notifyCompilerInliningEventMethod = method("notifyCompilerInliningEvent", int.class, ResolvedJavaMethod.class, ResolvedJavaMethod.class, boolean.class, + String.class, int.class); + private static final InvokableMethod notifyCompilerInliningEventInvokable = (receiver, args) -> { + ((CompilerProfiler) receiver).notifyCompilerInliningEvent((int) args[0], (ResolvedJavaMethod) args[1], (ResolvedJavaMethod) args[2], (boolean) args[3], (String) args[4], (int) args[5]); + return null; + }; + + @Override + public void notifyCompilerInliningEvent(int compileId, ResolvedJavaMethod caller, ResolvedJavaMethod callee, boolean succeeded, String message, int bci) { + handle(notifyCompilerInliningEventMethod, notifyCompilerInliningEventInvokable, compileId, caller, callee, succeeded, message, bci); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java new file mode 100644 index 000000000000..6e50b2afea42 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ConstantPoolProxy.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaField; +import jdk.vm.ci.meta.JavaMethod; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.Signature; + +import java.util.List; + +//JaCoCo Exclude + +public final class ConstantPoolProxy extends CompilationProxyBase implements ConstantPool { + ConstantPoolProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(ConstantPool.class, name, params); + } + + private static final SymbolicMethod lengthMethod = method("length"); + private static final InvokableMethod lengthInvokable = (receiver, args) -> ((ConstantPool) receiver).length(); + + @Override + public int length() { + return (int) handle(lengthMethod, lengthInvokable); + } + + private static final SymbolicMethod loadReferencedTypeMethod = method("loadReferencedType", int.class, int.class); + private static final InvokableMethod loadReferencedTypeInvokable = (receiver, args) -> { + ((ConstantPool) receiver).loadReferencedType((int) args[0], (int) args[1]); + return null; + }; + + @Override + public void loadReferencedType(int rawIndex, int opcode) { + handle(loadReferencedTypeMethod, loadReferencedTypeInvokable, rawIndex, opcode); + } + + private static final SymbolicMethod lookupReferencedTypeMethod = method("lookupReferencedType", int.class, int.class); + private static final InvokableMethod lookupReferencedTypeInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupReferencedType((int) args[0], (int) args[1]); + + @Override + public JavaType lookupReferencedType(int rawIndex, int opcode) { + return (JavaType) handle(lookupReferencedTypeMethod, lookupReferencedTypeInvokable, rawIndex, opcode); + } + + private static final SymbolicMethod lookupFieldMethod = method("lookupField", int.class, ResolvedJavaMethod.class, int.class); + private static final InvokableMethod lookupFieldInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupField((int) args[0], (ResolvedJavaMethod) args[1], (int) args[2]); + + @Override + public JavaField lookupField(int rawIndex, ResolvedJavaMethod method, int opcode) { + return (JavaField) handle(lookupFieldMethod, lookupFieldInvokable, rawIndex, method, opcode); + } + + public static final SymbolicMethod lookupMethodMethod = method("lookupMethod", int.class, int.class, ResolvedJavaMethod.class); + public static final InvokableMethod lookupMethodInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupMethod((int) args[0], (int) args[1], (ResolvedJavaMethod) args[2]); + + @Override + public JavaMethod lookupMethod(int cpi, int opcode, ResolvedJavaMethod caller) { + return (JavaMethod) handle(lookupMethodMethod, lookupMethodInvokable, cpi, opcode, caller); + } + + private static final SymbolicMethod lookupBootstrapMethodInvocationMethod = method("lookupBootstrapMethodInvocation", int.class, int.class); + private static final InvokableMethod lookupBootstrapMethodInvocationInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupBootstrapMethodInvocation((int) args[0], (int) args[1]); + + @Override + public BootstrapMethodInvocation lookupBootstrapMethodInvocation(int index, int opcode) { + return (BootstrapMethodInvocation) handle(lookupBootstrapMethodInvocationMethod, lookupBootstrapMethodInvocationInvokable, index, opcode); + } + + private static final SymbolicMethod lookupBootstrapMethodInvocationsMethod = method("lookupBootstrapMethodInvocations", boolean.class); + private static final InvokableMethod lookupBootstrapMethodInvocationsInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupBootstrapMethodInvocations((boolean) args[0]); + + @Override + @SuppressWarnings("unchecked") + public List lookupBootstrapMethodInvocations(boolean invokeDynamic) { + return (List) handle(lookupBootstrapMethodInvocationsMethod, lookupBootstrapMethodInvocationsInvokable, invokeDynamic); + } + + private static final SymbolicMethod lookupTypeMethod = method("lookupType", int.class, int.class); + private static final InvokableMethod lookupTypeInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupType((int) args[0], (int) args[1]); + + @Override + public JavaType lookupType(int cpi, int opcode) { + return (JavaType) handle(lookupTypeMethod, lookupTypeInvokable, cpi, opcode); + } + + private static final SymbolicMethod lookupUtf8Method = method("lookupUtf8", int.class); + private static final InvokableMethod lookupUtf8Invokable = (receiver, args) -> ((ConstantPool) receiver).lookupUtf8((int) args[0]); + + @Override + public String lookupUtf8(int cpi) { + return (String) handle(lookupUtf8Method, lookupUtf8Invokable, cpi); + } + + private static final SymbolicMethod lookupSignatureMethod = method("lookupSignature", int.class); + private static final InvokableMethod lookupSignatureInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupSignature((int) args[0]); + + @Override + public Signature lookupSignature(int cpi) { + return (Signature) handle(lookupSignatureMethod, lookupSignatureInvokable, cpi); + } + + private static final SymbolicMethod lookupConstantMethod = method("lookupConstant", int.class); + private static final InvokableMethod lookupConstantInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupConstant((int) args[0]); + + @Override + public Object lookupConstant(int cpi) { + return handle(lookupConstantMethod, lookupConstantInvokable, cpi); + } + + private static final SymbolicMethod lookupConstantBooleanMethod = method("lookupConstant", int.class, boolean.class); + private static final InvokableMethod lookupConstantBooleanInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupConstant((int) args[0], (boolean) args[1]); + + @Override + public Object lookupConstant(int cpi, boolean resolve) { + return handle(lookupConstantBooleanMethod, lookupConstantBooleanInvokable, cpi, resolve); + } + + private static final SymbolicMethod lookupAppendixMethod = method("lookupAppendix", int.class, int.class); + private static final InvokableMethod lookupAppendixInvokable = (receiver, args) -> ((ConstantPool) receiver).lookupAppendix((int) args[0], (int) args[1]); + + @Override + public JavaConstant lookupAppendix(int rawIndex, int opcode) { + return (JavaConstant) handle(lookupAppendixMethod, lookupAppendixInvokable, rawIndex, opcode); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java new file mode 100644 index 000000000000..8117c1a6f3ae --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotCodeCacheProviderProxy.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; + +import jdk.vm.ci.code.BytecodeFrame; +import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.InstalledCode; +import jdk.vm.ci.code.RegisterConfig; +import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.SpeculationLog; + +//JaCoCo Exclude + +public final class HotSpotCodeCacheProviderProxy extends HotSpotCodeCacheProvider implements CompilationProxy { + private final InvocationHandler handler; + + HotSpotCodeCacheProviderProxy(InvocationHandler handler) { + super(HotSpotJVMCIRuntime.runtime(), null, null); + this.handler = handler; + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotCodeCacheProvider.class, name, params); + } + + private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { + return CompilationProxy.handle(handler, this, method, invokable, args); + } + + public static final SymbolicMethod installCodeMethod = method("installCode", ResolvedJavaMethod.class, CompiledCode.class, InstalledCode.class, SpeculationLog.class, boolean.class, boolean.class); + private static final InvokableMethod installCodeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).installCode( + (ResolvedJavaMethod) args[0], (CompiledCode) args[1], (InstalledCode) args[2], (SpeculationLog) args[3], (boolean) args[4], (boolean) args[5]); + + @Override + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { + return (InstalledCode) handle(installCodeMethod, installCodeInvokable, method, compiledCode, installedCode, log, isDefault, profileDeopt); + } + + private static final SymbolicMethod invalidateInstalledCodeMethod = method("invalidateInstalledCode", InstalledCode.class); + private static final InvokableMethod invalidateInstalledCodeInvokable = (receiver, args) -> { + ((HotSpotCodeCacheProvider) receiver).invalidateInstalledCode((InstalledCode) args[0]); + return null; + }; + + @Override + public void invalidateInstalledCode(InstalledCode installedCode) { + handle(invalidateInstalledCodeMethod, invalidateInstalledCodeInvokable, installedCode); + } + + private static final SymbolicMethod getRegisterConfigMethod = method("getRegisterConfig"); + private static final InvokableMethod getRegisterConfigInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getRegisterConfig(); + + @Override + public RegisterConfig getRegisterConfig() { + return (RegisterConfig) handle(getRegisterConfigMethod, getRegisterConfigInvokable); + } + + private static final SymbolicMethod getMinimumOutgoingSizeMethod = method("getMinimumOutgoingSize"); + private static final InvokableMethod getMinimumOutgoingSizeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getMinimumOutgoingSize(); + + @Override + public int getMinimumOutgoingSize() { + return (int) handle(getMinimumOutgoingSizeMethod, getMinimumOutgoingSizeInvokable); + } + + private static final SymbolicMethod getTargetMethod = method("getTarget"); + private static final InvokableMethod getTargetInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getTarget(); + + @Override + public TargetDescription getTarget() { + return (TargetDescription) handle(getTargetMethod, getTargetInvokable); + } + + private static final SymbolicMethod createSpeculationLogMethod = method("createSpeculationLog"); + private static final InvokableMethod createSpeculationLogInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).createSpeculationLog(); + + @Override + public SpeculationLog createSpeculationLog() { + return (SpeculationLog) handle(createSpeculationLogMethod, createSpeculationLogInvokable); + } + + private static final SymbolicMethod getMaxCallTargetOffsetMethod = method("getMaxCallTargetOffset", long.class); + private static final InvokableMethod getMaxCallTargetOffsetInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getMaxCallTargetOffset((long) args[0]); + + @Override + public long getMaxCallTargetOffset(long address) { + return (long) handle(getMaxCallTargetOffsetMethod, getMaxCallTargetOffsetInvokable, address); + } + + private static final SymbolicMethod shouldDebugNonSafepointsMethod = method("shouldDebugNonSafepoints"); + private static final InvokableMethod shouldDebugNonSafepointsInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).shouldDebugNonSafepoints(); + + @Override + public boolean shouldDebugNonSafepoints() { + return (boolean) handle(shouldDebugNonSafepointsMethod, shouldDebugNonSafepointsInvokable); + } + + private static final SymbolicMethod disassembleMethod = method("disassemble", InstalledCode.class); + private static final InvokableMethod disassembleInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).disassemble((InstalledCode) args[0]); + + @Override + public String disassemble(InstalledCode code) { + return (String) handle(disassembleMethod, disassembleInvokable, code); + } + + public static final SymbolicMethod interpreterFrameSizeMethod = method("interpreterFrameSize", BytecodeFrame.class); + private static final InvokableMethod interpreterFrameSizeInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).interpreterFrameSize((BytecodeFrame) args[0]); + + @Override + public int interpreterFrameSize(BytecodeFrame pos) { + return (int) handle(interpreterFrameSizeMethod, interpreterFrameSizeInvokable, pos); + } + + private static final SymbolicMethod resetCompilationStatisticsMethod = method("resetCompilationStatistics"); + private static final InvokableMethod resetCompilationStatisticsInvokable = (receiver, args) -> { + ((HotSpotCodeCacheProvider) receiver).resetCompilationStatistics(); + return null; + }; + + @Override + public void resetCompilationStatistics() { + handle(resetCompilationStatisticsMethod, resetCompilationStatisticsInvokable); + } + + @Override + public Object unproxify() { + return handle(unproxifyMethod, unproxifyInvokable); + } + + @Override + public int hashCode() { + return (int) handle(hashCodeMethod, hashCodeInvokable); + } + + @Override + public boolean equals(Object obj) { + return (boolean) handle(equalsMethod, equalsInvokable, obj); + } + + @Override + public String toString() { + return (String) handle(toStringMethod, toStringInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java new file mode 100644 index 000000000000..b3f8470506ee --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantReflectionProviderProxy.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; + +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MemoryAccessProvider; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaType; + +//JaCoCo Exclude + +public final class HotSpotConstantReflectionProviderProxy extends HotSpotConstantReflectionProvider implements CompilationProxy { + private final InvocationHandler handler; + + HotSpotConstantReflectionProviderProxy(InvocationHandler handler) { + super(null); + this.handler = handler; + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotConstantReflectionProvider.class, name, params); + } + + private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { + return CompilationProxy.handle(handler, this, method, invokable, args); + } + + private static final SymbolicMethod constantEqualsMethod = method("constantEquals", Constant.class, Constant.class); + private static final InvokableMethod constantEqualsInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).constantEquals((Constant) args[0], (Constant) args[1]); + + @Override + public Boolean constantEquals(Constant x, Constant y) { + return (Boolean) handle(constantEqualsMethod, constantEqualsInvokable, x, y); + } + + private static final SymbolicMethod readArrayLengthMethod = method("readArrayLength", JavaConstant.class); + private static final InvokableMethod readArrayLengthInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readArrayLength((JavaConstant) args[0]); + + @Override + public Integer readArrayLength(JavaConstant array) { + return (Integer) handle(readArrayLengthMethod, readArrayLengthInvokable, array); + } + + private static final SymbolicMethod readArrayElementMethod = method("readArrayElement", JavaConstant.class, int.class); + private static final InvokableMethod readArrayElementInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readArrayElement((JavaConstant) args[0], (int) args[1]); + + @Override + public JavaConstant readArrayElement(JavaConstant array, int index) { + return (JavaConstant) handle(readArrayElementMethod, readArrayElementInvokable, array, index); + } + + private static final SymbolicMethod readFieldValueMethod = method("readFieldValue", ResolvedJavaField.class, JavaConstant.class); + private static final InvokableMethod readFieldValueInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).readFieldValue((ResolvedJavaField) args[0], + (JavaConstant) args[1]); + + @Override + public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant rec) { + return (JavaConstant) handle(readFieldValueMethod, readFieldValueInvokable, field, rec); + } + + private static final SymbolicMethod boxPrimitiveMethod = method("boxPrimitive", JavaConstant.class); + private static final InvokableMethod boxPrimitiveInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).boxPrimitive((JavaConstant) args[0]); + + @Override + public JavaConstant boxPrimitive(JavaConstant source) { + return (JavaConstant) handle(boxPrimitiveMethod, boxPrimitiveInvokable, source); + } + + private static final SymbolicMethod unboxPrimitiveMethod = method("unboxPrimitive", JavaConstant.class); + private static final InvokableMethod unboxPrimitiveInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).unboxPrimitive((JavaConstant) args[0]); + + @Override + public JavaConstant unboxPrimitive(JavaConstant source) { + return (JavaConstant) handle(unboxPrimitiveMethod, unboxPrimitiveInvokable, source); + } + + private static final SymbolicMethod forStringMethod = method("forString", String.class); + private static final InvokableMethod forStringInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).forString((String) args[0]); + + @Override + public JavaConstant forString(String value) { + return (JavaConstant) handle(forStringMethod, forStringInvokable, value); + } + + public static final SymbolicMethod forObjectMethod = method("forObject", Object.class); + public static final InvokableMethod forObjectInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).forObject(args[0]); + + @Override + public JavaConstant forObject(Object value) { + return (JavaConstant) handle(forObjectMethod, forObjectInvokable, value); + } + + public static final SymbolicMethod asJavaTypeMethod = method("asJavaType", Constant.class); + private static final InvokableMethod asJavaTypeInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asJavaType((Constant) args[0]); + + @Override + public ResolvedJavaType asJavaType(Constant constant) { + return (ResolvedJavaType) handle(asJavaTypeMethod, asJavaTypeInvokable, constant); + } + + private static final SymbolicMethod getMethodHandleAccessMethod = method("getMethodHandleAccess"); + private static final InvokableMethod getMethodHandleAccessInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).getMethodHandleAccess(); + + @Override + public MethodHandleAccessProvider getMethodHandleAccess() { + return (MethodHandleAccessProvider) handle(getMethodHandleAccessMethod, getMethodHandleAccessInvokable); + } + + private static final SymbolicMethod getMemoryAccessProviderMethod = method("getMemoryAccessProvider"); + private static final InvokableMethod getMemoryAccessProviderInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).getMemoryAccessProvider(); + + @Override + public MemoryAccessProvider getMemoryAccessProvider() { + return (MemoryAccessProvider) handle(getMemoryAccessProviderMethod, getMemoryAccessProviderInvokable); + } + + public static final SymbolicMethod asJavaClassMethod = method("asJavaClass", ResolvedJavaType.class); + private static final InvokableMethod asJavaClassInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asJavaClass((ResolvedJavaType) args[0]); + + @Override + public JavaConstant asJavaClass(ResolvedJavaType type) { + return (JavaConstant) handle(asJavaClassMethod, asJavaClassInvokable, type); + } + + public static final SymbolicMethod asObjectHubMethod = method("asObjectHub", ResolvedJavaType.class); + private static final InvokableMethod asObjectHubInvokable = (receiver, args) -> ((HotSpotConstantReflectionProvider) receiver).asObjectHub((ResolvedJavaType) args[0]); + + @Override + public Constant asObjectHub(ResolvedJavaType type) { + return (Constant) handle(asObjectHubMethod, asObjectHubInvokable, type); + } + + @Override + public Object unproxify() { + return handle(unproxifyMethod, unproxifyInvokable); + } + + @Override + public int hashCode() { + return (int) handle(hashCodeMethod, hashCodeInvokable); + } + + @Override + public boolean equals(Object obj) { + return (boolean) handle(equalsMethod, equalsInvokable, obj); + } + + @Override + public String toString() { + return (String) handle(toStringMethod, toStringInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java new file mode 100644 index 000000000000..b6048659a320 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMemoryAccessProviderProxy.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotMemoryAccessProvider; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; + +//JaCoCo Exclude + +final class HotSpotMemoryAccessProviderProxy extends CompilationProxyBase implements HotSpotMemoryAccessProvider { + HotSpotMemoryAccessProviderProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotMemoryAccessProvider.class, name, params); + } + + private static final SymbolicMethod readNarrowOopConstantMethod = method("readNarrowOopConstant", Constant.class, long.class); + private static final InvokableMethod readNarrowOopConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readNarrowOopConstant((Constant) args[0], (long) args[1]); + + @Override + public JavaConstant readNarrowOopConstant(Constant base, long displacement) { + return (JavaConstant) handle(readNarrowOopConstantMethod, readNarrowOopConstantInvokable, base, displacement); + } + + private static final SymbolicMethod readKlassPointerConstantMethod = method("readKlassPointerConstant", Constant.class, long.class); + private static final InvokableMethod readKlassPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readKlassPointerConstant((Constant) args[0], (long) args[1]); + + @Override + public Constant readKlassPointerConstant(Constant base, long displacement) { + return (Constant) handle(readKlassPointerConstantMethod, readKlassPointerConstantInvokable, base, displacement); + } + + private static final SymbolicMethod readNarrowKlassPointerConstantMethod = method("readNarrowKlassPointerConstant", Constant.class, long.class); + private static final InvokableMethod readNarrowKlassPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readNarrowKlassPointerConstant((Constant) args[0], + (long) args[1]); + + @Override + public Constant readNarrowKlassPointerConstant(Constant base, long displacement) { + return (Constant) handle(readNarrowKlassPointerConstantMethod, readNarrowKlassPointerConstantInvokable, base, displacement); + } + + private static final SymbolicMethod readMethodPointerConstantMethod = method("readMethodPointerConstant", Constant.class, long.class); + private static final InvokableMethod readMethodPointerConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readMethodPointerConstant((Constant) args[0], + (long) args[1]); + + @Override + public Constant readMethodPointerConstant(Constant base, long displacement) { + return (Constant) handle(readMethodPointerConstantMethod, readMethodPointerConstantInvokable, base, displacement); + } + + private static final SymbolicMethod readPrimitiveConstantMethod = method("readPrimitiveConstant", JavaKind.class, Constant.class, long.class, int.class); + private static final InvokableMethod readPrimitiveConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readPrimitiveConstant((JavaKind) args[0], (Constant) args[1], + (long) args[2], (int) args[3]); + + @Override + public JavaConstant readPrimitiveConstant(JavaKind kind, Constant base, long displacement, int bits) { + return (JavaConstant) handle(readPrimitiveConstantMethod, readPrimitiveConstantInvokable, kind, base, displacement, bits); + } + + private static final SymbolicMethod readObjectConstantMethod = method("readObjectConstant", Constant.class, long.class); + private static final InvokableMethod readObjectConstantInvokable = (receiver, args) -> ((HotSpotMemoryAccessProvider) receiver).readObjectConstant((Constant) args[0], (long) args[1]); + + @Override + public JavaConstant readObjectConstant(Constant base, long displacement) { + return (JavaConstant) handle(readObjectConstantMethod, readObjectConstantInvokable, base, displacement); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java new file mode 100644 index 000000000000..52599c0f2c72 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Constant; + +//JaCoCo Exclude + +public final class HotSpotMetaspaceConstantProxy extends CompilationProxyBase implements HotSpotMetaspaceConstant { + HotSpotMetaspaceConstantProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotMetaspaceConstant.class, name, params); + } + + private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); + private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isDefaultForKind(); + + @Override + public boolean isDefaultForKind() { + return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + } + + public static final SymbolicMethod toValueStringMethod = method("toValueString"); + public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).toValueString(); + + @Override + public String toValueString() { + return (String) handle(toValueStringMethod, toValueStringInvokable); + } + + public static final SymbolicMethod isCompressedMethod = method("isCompressed"); + public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressed(); + + @Override + public boolean isCompressed() { + return (boolean) handle(isCompressedMethod, isCompressedInvokable); + } + + private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); + private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressible(); + + @Override + public boolean isCompressible() { + return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); + } + + public static final SymbolicMethod compressMethod = method("compress"); + private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).compress(); + + @Override + public Constant compress() { + return (Constant) handle(compressMethod, compressInvokable); + } + + public static final SymbolicMethod uncompressMethod = method("uncompress"); + private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).uncompress(); + + @Override + public Constant uncompress() { + return (Constant) handle(uncompressMethod, uncompressInvokable); + } + + public static final SymbolicMethod asResolvedJavaTypeMethod = method("asResolvedJavaType"); + public static final InvokableMethod asResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaType(); + + @Override + public HotSpotResolvedObjectType asResolvedJavaType() { + return (HotSpotResolvedObjectType) handle(asResolvedJavaTypeMethod, asResolvedJavaTypeInvokable); + } + + public static final SymbolicMethod asResolvedJavaMethodMethod = method("asResolvedJavaMethod"); + public static final InvokableMethod asResolvedJavaMethodInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaMethod(); + + @Override + public HotSpotResolvedJavaMethod asResolvedJavaMethod() { + return (HotSpotResolvedJavaMethod) handle(asResolvedJavaMethodMethod, asResolvedJavaMethodInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java new file mode 100644 index 000000000000..034db556df9d --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaType; + +//JaCoCo Exclude + +public final class HotSpotObjectConstantProxy extends CompilationProxyBase implements HotSpotObjectConstant { + HotSpotObjectConstantProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotObjectConstant.class, name, params); + } + + public static final SymbolicMethod compressMethod = method("compress"); + private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).compress(); + + @Override + public JavaConstant compress() { + return (JavaConstant) handle(compressMethod, compressInvokable); + } + + public static final SymbolicMethod uncompressMethod = method("uncompress"); + private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).uncompress(); + + @Override + public JavaConstant uncompress() { + return (JavaConstant) handle(uncompressMethod, uncompressInvokable); + } + + public static final SymbolicMethod getTypeMethod = method("getType"); + public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getType(); + + @Override + public HotSpotResolvedObjectType getType() { + return (HotSpotResolvedObjectType) handle(getTypeMethod, getTypeInvokable); + } + + private static final SymbolicMethod getIdentityHashCodeMethod = method("getIdentityHashCode"); + private static final InvokableMethod getIdentityHashCodeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getIdentityHashCode(); + + @Override + public int getIdentityHashCode() { + return (int) handle(getIdentityHashCodeMethod, getIdentityHashCodeInvokable); + } + + private static final SymbolicMethod getCallSiteTargetMethod = method("getCallSiteTarget"); + private static final InvokableMethod getCallSiteTargetInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getCallSiteTarget(); + + @Override + @SuppressWarnings("unchecked") + public Assumptions.AssumptionResult getCallSiteTarget() { + return (Assumptions.AssumptionResult) handle(getCallSiteTargetMethod, getCallSiteTargetInvokable); + } + + private static final SymbolicMethod isInternedStringMethod = method("isInternedString"); + private static final InvokableMethod isInternedStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isInternedString(); + + @Override + public boolean isInternedString() { + return (boolean) handle(isInternedStringMethod, isInternedStringInvokable); + } + + private static final SymbolicMethod asObjectClassMethod = method("asObject", Class.class); + private static final InvokableMethod asObjectClassInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asObject((Class) args[0]); + + @Override + @SuppressWarnings("unchecked") + public T asObject(Class type) { + return (T) handle(asObjectClassMethod, asObjectClassInvokable, type); + } + + private static final SymbolicMethod asObjectResolvedJavaTypeMethod = method("asObject", ResolvedJavaType.class); + private static final InvokableMethod asObjectResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asObject((ResolvedJavaType) args[0]); + + @Override + public Object asObject(ResolvedJavaType type) { + return handle(asObjectResolvedJavaTypeMethod, asObjectResolvedJavaTypeInvokable, type); + } + + public static final SymbolicMethod getJavaKindMethod = method("getJavaKind"); + private static final InvokableMethod getJavaKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getJavaKind(); + + @Override + public JavaKind getJavaKind() { + return (JavaKind) handle(getJavaKindMethod, getJavaKindInvokable); + } + + public static final SymbolicMethod isNullMethod = method("isNull"); + private static final InvokableMethod isNullInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isNull(); + + @Override + public boolean isNull() { + return (boolean) handle(isNullMethod, isNullInvokable); + } + + private static final SymbolicMethod asBoxedPrimitiveMethod = method("asBoxedPrimitive"); + private static final InvokableMethod asBoxedPrimitiveInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asBoxedPrimitive(); + + @Override + public Object asBoxedPrimitive() { + return handle(asBoxedPrimitiveMethod, asBoxedPrimitiveInvokable); + } + + private static final SymbolicMethod asIntMethod = method("asInt"); + private static final InvokableMethod asIntInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asInt(); + + @Override + public int asInt() { + return (int) handle(asIntMethod, asIntInvokable); + } + + private static final SymbolicMethod asBooleanMethod = method("asBoolean"); + private static final InvokableMethod asBooleanInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asBoolean(); + + @Override + public boolean asBoolean() { + return (boolean) handle(asBooleanMethod, asBooleanInvokable); + } + + private static final SymbolicMethod asLongMethod = method("asLong"); + private static final InvokableMethod asLongInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asLong(); + + @Override + public long asLong() { + return (long) handle(asLongMethod, asLongInvokable); + } + + private static final SymbolicMethod asFloatMethod = method("asFloat"); + private static final InvokableMethod asFloatInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asFloat(); + + @Override + public float asFloat() { + return (float) handle(asFloatMethod, asFloatInvokable); + } + + private static final SymbolicMethod asDoubleMethod = method("asDouble"); + private static final InvokableMethod asDoubleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).asDouble(); + + @Override + public double asDouble() { + return (double) handle(asDoubleMethod, asDoubleInvokable); + } + + public static final SymbolicMethod isCompressedMethod = method("isCompressed"); + public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressed(); + + @Override + public boolean isCompressed() { + return (boolean) handle(isCompressedMethod, isCompressedInvokable); + } + + private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); + private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressible(); + + @Override + public boolean isCompressible() { + return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); + } + + private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); + private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isDefaultForKind(); + + @Override + public boolean isDefaultForKind() { + return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + } + + public static final SymbolicMethod toValueStringMethod = method("toValueString"); + public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).toValueString(); + + @Override + public String toValueString() { + return (String) handle(toValueStringMethod, toValueStringInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java new file mode 100644 index 000000000000..0effa426d5da --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotProfilingInfoProxy.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotProfilingInfo; + +//JaCoCo Exclude + +public final class HotSpotProfilingInfoProxy extends ProfilingInfoProxy implements HotSpotProfilingInfo { + HotSpotProfilingInfoProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotProfilingInfo.class, name, params); + } + + public static final SymbolicMethod getDecompileCountMethod = method("getDecompileCount"); + public static final InvokableMethod getDecompileCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getDecompileCount(); + + @Override + public int getDecompileCount() { + return (int) handle(getDecompileCountMethod, getDecompileCountInvokable); + } + + private static final SymbolicMethod getOverflowRecompileCountMethod = method("getOverflowRecompileCount"); + private static final InvokableMethod getOverflowRecompileCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getOverflowRecompileCount(); + + @Override + public int getOverflowRecompileCount() { + return (int) handle(getOverflowRecompileCountMethod, getOverflowRecompileCountInvokable); + } + + private static final SymbolicMethod getOverflowTrapCountMethod = method("getOverflowTrapCount"); + private static final InvokableMethod getOverflowTrapCountInvokable = (receiver, args) -> ((HotSpotProfilingInfo) receiver).getOverflowTrapCount(); + + @Override + public int getOverflowTrapCount() { + return (int) handle(getOverflowTrapCountMethod, getOverflowTrapCountInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java new file mode 100644 index 000000000000..47e24ed98219 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaFieldProxy.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; + +//JaCoCo Exclude + +public final class HotSpotResolvedJavaFieldProxy extends CompilationProxyBase.CompilationProxyAnnotatedBase implements HotSpotResolvedJavaField { + HotSpotResolvedJavaFieldProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotResolvedJavaField.class, name, params); + } + + private static final SymbolicMethod isInObjectMethod = method("isInObject", JavaConstant.class); + private static final InvokableMethod isInObjectInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isInObject((JavaConstant) args[0]); + + @Override + public boolean isInObject(JavaConstant object) { + return (boolean) handle(isInObjectMethod, isInObjectInvokable, object); + } + + public static final SymbolicMethod isStableMethod = method("isStable"); + public static final InvokableMethod isStableInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isStable(); + + @Override + public boolean isStable() { + return (boolean) handle(isStableMethod, isStableInvokable); + } + + public static final SymbolicMethod getOffsetMethod = method("getOffset"); + public static final InvokableMethod getOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getOffset(); + + @Override + public int getOffset() { + return (int) handle(getOffsetMethod, getOffsetInvokable); + } + + private static final SymbolicMethod isInternalMethod = method("isInternal"); + private static final InvokableMethod isInternalInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isInternal(); + + @Override + public boolean isInternal() { + return (boolean) handle(isInternalMethod, isInternalInvokable); + } + + public static final SymbolicMethod isSyntheticMethod = method("isSynthetic"); + public static final InvokableMethod isSyntheticInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).isSynthetic(); + + @Override + public boolean isSynthetic() { + return (boolean) handle(isSyntheticMethod, isSyntheticInvokable); + } + + public static final SymbolicMethod getNameMethod = method("getName"); + public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getName(); + + @Override + public String getName() { + return (String) handle(getNameMethod, getNameInvokable); + } + + public static final SymbolicMethod getTypeMethod = method("getType"); + public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getType(); + + @Override + public JavaType getType() { + return (JavaType) handle(getTypeMethod, getTypeInvokable); + } + + public static final SymbolicMethod getDeclaringClassMethod = method("getDeclaringClass"); + public static final InvokableMethod getDeclaringClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getDeclaringClass(); + + @Override + public ResolvedJavaType getDeclaringClass() { + return (ResolvedJavaType) handle(getDeclaringClassMethod, getDeclaringClassInvokable); + } + + private static final SymbolicMethod getConstantValueMethod = method("getConstantValue"); + private static final InvokableMethod getConstantValueInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getConstantValue(); + + @Override + public JavaConstant getConstantValue() { + return (JavaConstant) handle(getConstantValueMethod, getConstantValueInvokable); + } + + public static final SymbolicMethod getModifiersMethod = method("getModifiers"); + public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaField) receiver).getModifiers(); + + @Override + public int getModifiers() { + return (int) handle(getModifiersMethod, getModifiersInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java new file mode 100644 index 000000000000..a81654130ee6 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.BitSet; +import java.util.Formattable; +import java.util.Formatter; + +import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ExceptionHandler; +import jdk.vm.ci.meta.LineNumberTable; +import jdk.vm.ci.meta.LocalVariableTable; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; + +//JaCoCo Exclude + +public final class HotSpotResolvedJavaMethodProxy extends CompilationProxyBase.CompilationProxyAnnotatedBase implements HotSpotResolvedJavaMethod, Formattable { + HotSpotResolvedJavaMethodProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotResolvedJavaMethod.class, name, params); + } + + private static final SymbolicMethod isCallerSensitiveMethod = method("isCallerSensitive"); + private static final InvokableMethod isCallerSensitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isCallerSensitive(); + + @Override + public boolean isCallerSensitive() { + return (boolean) handle(isCallerSensitiveMethod, isCallerSensitiveInvokable); + } + + public static final SymbolicMethod getCodeMethod = method("getCode"); + public static final InvokableMethod getCodeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getCode(); + + @Override + public byte[] getCode() { + return (byte[]) handle(getCodeMethod, getCodeInvokable); + } + + public static final SymbolicMethod getCodeSizeMethod = method("getCodeSize"); + private static final InvokableMethod getCodeSizeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getCodeSize(); + + @Override + public int getCodeSize() { + return (int) handle(getCodeSizeMethod, getCodeSizeInvokable); + } + + public static final SymbolicMethod getNameMethod = method("getName"); + public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getName(); + + @Override + public String getName() { + return (String) handle(getNameMethod, getNameInvokable); + } + + public static final SymbolicMethod getDeclaringClassMethod = method("getDeclaringClass"); + public static final InvokableMethod getDeclaringClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getDeclaringClass(); + + @Override + public HotSpotResolvedObjectType getDeclaringClass() { + return (HotSpotResolvedObjectType) handle(getDeclaringClassMethod, getDeclaringClassInvokable); + } + + public static final SymbolicMethod getSignatureMethod = method("getSignature"); + public static final InvokableMethod getSignatureInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getSignature(); + + @Override + public Signature getSignature() { + return (Signature) handle(getSignatureMethod, getSignatureInvokable); + } + + private static final SymbolicMethod getMaxLocalsMethod = method("getMaxLocals"); + private static final InvokableMethod getMaxLocalsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getMaxLocals(); + + @Override + public int getMaxLocals() { + return (int) handle(getMaxLocalsMethod, getMaxLocalsInvokable); + } + + private static final SymbolicMethod getMaxStackSizeMethod = method("getMaxStackSize"); + private static final InvokableMethod getMaxStackSizeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getMaxStackSize(); + + @Override + public int getMaxStackSize() { + return (int) handle(getMaxStackSizeMethod, getMaxStackSizeInvokable); + } + + private static final SymbolicMethod isSyntheticMethod = method("isSynthetic"); + private static final InvokableMethod isSyntheticInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isSynthetic(); + + @Override + public boolean isSynthetic() { + return (boolean) handle(isSyntheticMethod, isSyntheticInvokable); + } + + private static final SymbolicMethod isVarArgsMethod = method("isVarArgs"); + private static final InvokableMethod isVarArgsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isVarArgs(); + + @Override + public boolean isVarArgs() { + return (boolean) handle(isVarArgsMethod, isVarArgsInvokable); + } + + private static final SymbolicMethod isBridgeMethod = method("isBridge"); + private static final InvokableMethod isBridgeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isBridge(); + + @Override + public boolean isBridge() { + return (boolean) handle(isBridgeMethod, isBridgeInvokable); + } + + private static final SymbolicMethod isDeclaredMethod = method("isDeclared"); + private static final InvokableMethod isDeclaredInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isDeclared(); + + @Override + public boolean isDeclared() { + return (boolean) handle(isDeclaredMethod, isDeclaredInvokable); + } + + private static final SymbolicMethod isClassInitializerMethod = method("isClassInitializer"); + private static final InvokableMethod isClassInitializerInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isClassInitializer(); + + @Override + public boolean isClassInitializer() { + return (boolean) handle(isClassInitializerMethod, isClassInitializerInvokable); + } + + public static final SymbolicMethod isConstructorMethod = method("isConstructor"); + public static final InvokableMethod isConstructorInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isConstructor(); + + @Override + public boolean isConstructor() { + return (boolean) handle(isConstructorMethod, isConstructorInvokable); + } + + public static final SymbolicMethod canBeStaticallyBoundMethod = method("canBeStaticallyBound"); + public static final InvokableMethod canBeStaticallyBoundInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).canBeStaticallyBound(); + + @Override + public boolean canBeStaticallyBound() { + return (boolean) handle(canBeStaticallyBoundMethod, canBeStaticallyBoundInvokable); + } + + private static final SymbolicMethod getExceptionHandlersMethod = method("getExceptionHandlers"); + private static final InvokableMethod getExceptionHandlersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getExceptionHandlers(); + + @Override + public ExceptionHandler[] getExceptionHandlers() { + return (ExceptionHandler[]) handle(getExceptionHandlersMethod, getExceptionHandlersInvokable); + } + + public static final SymbolicMethod asStackTraceElementMethod = method("asStackTraceElement", int.class); + public static final InvokableMethod asStackTraceElementInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).asStackTraceElement((int) args[0]); + + @Override + public StackTraceElement asStackTraceElement(int bci) { + return (StackTraceElement) handle(asStackTraceElementMethod, asStackTraceElementInvokable, bci); + } + + private static final SymbolicMethod getProfilingInfoMethod = method("getProfilingInfo", boolean.class, boolean.class); + private static final InvokableMethod getProfilingInfoInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getProfilingInfo((boolean) args[0], (boolean) args[1]); + + @Override + public ProfilingInfo getProfilingInfo(boolean includeNormal, boolean includeOSR) { + return (ProfilingInfo) handle(getProfilingInfoMethod, getProfilingInfoInvokable, includeNormal, includeOSR); + } + + private static final SymbolicMethod reprofileMethod = method("reprofile"); + private static final InvokableMethod reprofileInvokable = (receiver, args) -> { + ((HotSpotResolvedJavaMethod) receiver).reprofile(); + return null; + }; + + @Override + public void reprofile() { + handle(reprofileMethod, reprofileInvokable); + } + + public static final SymbolicMethod getConstantPoolMethod = method("getConstantPool"); + public static final InvokableMethod getConstantPoolInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getConstantPool(); + + @Override + public ConstantPool getConstantPool() { + return (ConstantPool) handle(getConstantPoolMethod, getConstantPoolInvokable); + } + + public static final SymbolicMethod getParametersMethod = method("getParameters"); + private static final InvokableMethod getParametersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getParameters(); + + @Override + public Parameter[] getParameters() { + return (Parameter[]) handle(getParametersMethod, getParametersInvokable); + } + + public static final SymbolicMethod getParameterAnnotationsMethod = method("getParameterAnnotations"); + private static final InvokableMethod getParameterAnnotationsInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getParameterAnnotations(); + + @Override + public Annotation[][] getParameterAnnotations() { + return (Annotation[][]) handle(getParameterAnnotationsMethod, getParameterAnnotationsInvokable); + } + + public static final SymbolicMethod getGenericParameterTypesMethod = method("getGenericParameterTypes"); + private static final InvokableMethod getGenericParameterTypesInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getGenericParameterTypes(); + + @Override + public Type[] getGenericParameterTypes() { + return (Type[]) handle(getGenericParameterTypesMethod, getGenericParameterTypesInvokable); + } + + public static final SymbolicMethod canBeInlinedMethod = method("canBeInlined"); + private static final InvokableMethod canBeInlinedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).canBeInlined(); + + @Override + public boolean canBeInlined() { + return (boolean) handle(canBeInlinedMethod, canBeInlinedInvokable); + } + + private static final SymbolicMethod hasNeverInlineDirectiveMethod = method("hasNeverInlineDirective"); + private static final InvokableMethod hasNeverInlineDirectiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasNeverInlineDirective(); + + @Override + public boolean hasNeverInlineDirective() { + return (boolean) handle(hasNeverInlineDirectiveMethod, hasNeverInlineDirectiveInvokable); + } + + private static final SymbolicMethod shouldBeInlinedMethod = method("shouldBeInlined"); + private static final InvokableMethod shouldBeInlinedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).shouldBeInlined(); + + @Override + public boolean shouldBeInlined() { + return (boolean) handle(shouldBeInlinedMethod, shouldBeInlinedInvokable); + } + + private static final SymbolicMethod getLineNumberTableMethod = method("getLineNumberTable"); + private static final InvokableMethod getLineNumberTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getLineNumberTable(); + + @Override + public LineNumberTable getLineNumberTable() { + return (LineNumberTable) handle(getLineNumberTableMethod, getLineNumberTableInvokable); + } + + private static final SymbolicMethod getLocalVariableTableMethod = method("getLocalVariableTable"); + private static final InvokableMethod getLocalVariableTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getLocalVariableTable(); + + @Override + public LocalVariableTable getLocalVariableTable() { + return (LocalVariableTable) handle(getLocalVariableTableMethod, getLocalVariableTableInvokable); + } + + private static final SymbolicMethod getEncodingMethod = method("getEncoding"); + private static final InvokableMethod getEncodingInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getEncoding(); + + @Override + public Constant getEncoding() { + return (Constant) handle(getEncodingMethod, getEncodingInvokable); + } + + public static final SymbolicMethod isInVirtualMethodTableMethod = method("isInVirtualMethodTable", ResolvedJavaType.class); + private static final InvokableMethod isInVirtualMethodTableInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isInVirtualMethodTable((ResolvedJavaType) args[0]); + + @Override + public boolean isInVirtualMethodTable(ResolvedJavaType resolved) { + return (boolean) handle(isInVirtualMethodTableMethod, isInVirtualMethodTableInvokable, resolved); + } + + private static final SymbolicMethod isScopedMethod = method("isScoped"); + private static final InvokableMethod isScopedInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isScoped(); + + @Override + public boolean isScoped() { + return (boolean) handle(isScopedMethod, isScopedInvokable); + } + + private static final SymbolicMethod getSpeculationLogMethod = method("getSpeculationLog"); + private static final InvokableMethod getSpeculationLogInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getSpeculationLog(); + + @Override + public SpeculationLog getSpeculationLog() { + return (SpeculationLog) handle(getSpeculationLogMethod, getSpeculationLogInvokable); + } + + private static final SymbolicMethod isForceInlineMethod = method("isForceInline"); + private static final InvokableMethod isForceInlineInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isForceInline(); + + @Override + public boolean isForceInline() { + return (boolean) handle(isForceInlineMethod, isForceInlineInvokable); + } + + private static final SymbolicMethod hasReservedStackAccessMethod = method("hasReservedStackAccess"); + private static final InvokableMethod hasReservedStackAccessInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasReservedStackAccess(); + + @Override + public boolean hasReservedStackAccess() { + return (boolean) handle(hasReservedStackAccessMethod, hasReservedStackAccessInvokable); + } + + private static final SymbolicMethod setNotInlinableOrCompilableMethod = method("setNotInlinableOrCompilable"); + private static final InvokableMethod setNotInlinableOrCompilableInvokable = (receiver, args) -> { + ((HotSpotResolvedJavaMethod) receiver).setNotInlinableOrCompilable(); + return null; + }; + + @Override + public void setNotInlinableOrCompilable() { + handle(setNotInlinableOrCompilableMethod, setNotInlinableOrCompilableInvokable); + } + + private static final SymbolicMethod ignoredBySecurityStackWalkMethod = method("ignoredBySecurityStackWalk"); + private static final InvokableMethod ignoredBySecurityStackWalkInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).ignoredBySecurityStackWalk(); + + @Override + public boolean ignoredBySecurityStackWalk() { + return (boolean) handle(ignoredBySecurityStackWalkMethod, ignoredBySecurityStackWalkInvokable); + } + + private static final SymbolicMethod uniqueConcreteMethodMethod = method("uniqueConcreteMethod", HotSpotResolvedObjectType.class); + private static final InvokableMethod uniqueConcreteMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).uniqueConcreteMethod((HotSpotResolvedObjectType) args[0]); + + @Override + public ResolvedJavaMethod uniqueConcreteMethod(HotSpotResolvedObjectType rec) { + return (ResolvedJavaMethod) handle(uniqueConcreteMethodMethod, uniqueConcreteMethodInvokable, rec); + } + + private static final SymbolicMethod hasCompiledCodeMethod = method("hasCompiledCode"); + private static final InvokableMethod hasCompiledCodeInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCompiledCode(); + + @Override + public boolean hasCompiledCode() { + return (boolean) handle(hasCompiledCodeMethod, hasCompiledCodeInvokable); + } + + private static final SymbolicMethod hasCompiledCodeAtLevelMethod = method("hasCompiledCodeAtLevel", int.class); + private static final InvokableMethod hasCompiledCodeAtLevelInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCompiledCodeAtLevel((int) args[0]); + + @Override + public boolean hasCompiledCodeAtLevel(int level) { + return (boolean) handle(hasCompiledCodeAtLevelMethod, hasCompiledCodeAtLevelInvokable, level); + } + + private static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); + private static final InvokableMethod vtableEntryOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).vtableEntryOffset((ResolvedJavaType) args[0]); + + @Override + public int vtableEntryOffset(ResolvedJavaType resolved) { + return (int) handle(vtableEntryOffsetMethod, vtableEntryOffsetInvokable, resolved); + } + + public static final SymbolicMethod intrinsicIdMethod = method("intrinsicId"); + private static final InvokableMethod intrinsicIdInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).intrinsicId(); + + @Override + public int intrinsicId() { + return (int) handle(intrinsicIdMethod, intrinsicIdInvokable); + } + + private static final SymbolicMethod isIntrinsicCandidateMethod = method("isIntrinsicCandidate"); + private static final InvokableMethod isIntrinsicCandidateInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).isIntrinsicCandidate(); + + @Override + public boolean isIntrinsicCandidate() { + return (boolean) handle(isIntrinsicCandidateMethod, isIntrinsicCandidateInvokable); + } + + private static final SymbolicMethod allocateCompileIdMethod = method("allocateCompileId", int.class); + private static final InvokableMethod allocateCompileIdInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).allocateCompileId((int) args[0]); + + @Override + public int allocateCompileId(int entryBCI) { + return (int) handle(allocateCompileIdMethod, allocateCompileIdInvokable, entryBCI); + } + + public static final SymbolicMethod hasCodeAtLevelMethod = method("hasCodeAtLevel", int.class, int.class); + private static final InvokableMethod hasCodeAtLevelInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).hasCodeAtLevel((int) args[0], (int) args[1]); + + @Override + public boolean hasCodeAtLevel(int entryBCI, int level) { + return (boolean) handle(hasCodeAtLevelMethod, hasCodeAtLevelInvokable, entryBCI, level); + } + + private static final SymbolicMethod methodIdnumMethod = method("methodIdnum"); + private static final InvokableMethod methodIdnumInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).methodIdnum(); + + @Override + public int methodIdnum() { + return (int) handle(methodIdnumMethod, methodIdnumInvokable); + } + + private static final SymbolicMethod getOopMapAtMethod = method("getOopMapAt", int.class); + private static final InvokableMethod getOopMapAtInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getOopMapAt((int) args[0]); + + @Override + public BitSet getOopMapAt(int bci) { + return (BitSet) handle(getOopMapAtMethod, getOopMapAtInvokable, bci); + } + + public static final SymbolicMethod getModifiersMethod = method("getModifiers"); + public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).getModifiers(); + + @Override + public int getModifiers() { + return (int) handle(getModifiersMethod, getModifiersInvokable); + } + + public static final SymbolicMethod formatToMethod = new SymbolicMethod(Formattable.class, "formatTo", Formatter.class, int.class, int.class, int.class); + private static final InvokableMethod formatToInvokable = (receiver, args) -> { + ((Formattable) receiver).formatTo((Formatter) args[0], (int) args[1], (int) args[2], (int) args[3]); + return null; + }; + + @Override + public void formatTo(Formatter formatter, int flags, int width, int precision) { + handle(formatToMethod, formatToInvokable, formatter, flags, width, precision); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java new file mode 100644 index 000000000000..a9eaefc24157 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -0,0 +1,482 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod; + +import java.lang.annotation.Annotation; +import java.util.List; + +import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Assumptions; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.UnresolvedJavaField; +import jdk.vm.ci.meta.UnresolvedJavaType; + +//JaCoCo Exclude + +public sealed class HotSpotResolvedJavaTypeProxy extends HotSpotResolvedJavaType implements CompilationProxy permits HotSpotResolvedObjectTypeProxy { + private final InvocationHandler handler; + + protected HotSpotResolvedJavaTypeProxy(InvocationHandler handler) { + super("HotSpotResolvedJavaTypeProxy"); + this.handler = handler; + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotResolvedJavaType.class, name, params); + } + + protected final Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { + return CompilationProxy.handle(handler, this, method, invokable, args); + } + + @Override + protected final HotSpotResolvedObjectType getArrayType() { + throw new UnsupportedOperationException("getArrayType"); + } + + private static final SymbolicMethod getArrayClassMethod = method("getArrayClass"); + private static final InvokableMethod getArrayClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getArrayClass(); + + @Override + public final HotSpotResolvedObjectType getArrayClass() { + return (HotSpotResolvedObjectType) handle(getArrayClassMethod, getArrayClassInvokable); + } + + @Override + protected final boolean isBeingInitialized() { + throw new UnsupportedOperationException("isBeingInitialized"); + } + + private static final SymbolicMethod resolveMethod = method("resolve", ResolvedJavaType.class); + private static final InvokableMethod resolveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolve((ResolvedJavaType) args[0]); + + @Override + public final ResolvedJavaType resolve(ResolvedJavaType accessingClass) { + return (ResolvedJavaType) handle(resolveMethod, resolveInvokable, accessingClass); + } + + private static final SymbolicMethod resolveMethodMethod = method("resolveMethod", ResolvedJavaMethod.class, ResolvedJavaType.class); + private static final InvokableMethod resolveMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolveMethod((ResolvedJavaMethod) args[0], (ResolvedJavaType) args[1]); + + @Override + public final ResolvedJavaMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { + return (ResolvedJavaMethod) handle(resolveMethodMethod, resolveMethodInvokable, method, callerType); + } + + public static final SymbolicMethod getNameMethod = method("getName"); + public static final InvokableMethod getNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getName(); + + @Override + public final String getName() { + return (String) handle(getNameMethod, getNameInvokable); + } + + public static final SymbolicMethod getComponentTypeMethod = method("getComponentType"); + public static final InvokableMethod getComponentTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getComponentType(); + + @Override + public final ResolvedJavaType getComponentType() { + return (ResolvedJavaType) handle(getComponentTypeMethod, getComponentTypeInvokable); + } + + private static final SymbolicMethod findLeafConcreteSubtypeMethod = method("findLeafConcreteSubtype"); + private static final InvokableMethod findLeafConcreteSubtypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findLeafConcreteSubtype(); + + @Override + @SuppressWarnings("unchecked") + public final Assumptions.AssumptionResult findLeafConcreteSubtype() { + return (Assumptions.AssumptionResult) handle(findLeafConcreteSubtypeMethod, findLeafConcreteSubtypeInvokable); + } + + private static final SymbolicMethod hasFinalizerMethod = method("hasFinalizer"); + private static final InvokableMethod hasFinalizerInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasFinalizer(); + + @Override + public final boolean hasFinalizer() { + return (boolean) handle(hasFinalizerMethod, hasFinalizerInvokable); + } + + private static final SymbolicMethod hasFinalizableSubclassMethod = method("hasFinalizableSubclass"); + private static final InvokableMethod hasFinalizableSubclassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasFinalizableSubclass(); + + @Override + @SuppressWarnings("unchecked") + public final Assumptions.AssumptionResult hasFinalizableSubclass() { + return (Assumptions.AssumptionResult) handle(hasFinalizableSubclassMethod, hasFinalizableSubclassInvokable); + } + + public static final SymbolicMethod getModifiersMethod = method("getModifiers"); + public static final InvokableMethod getModifiersInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getModifiers(); + + @Override + public final int getModifiers() { + return (int) handle(getModifiersMethod, getModifiersInvokable); + } + + public static final SymbolicMethod isInterfaceMethod = method("isInterface"); + public static final InvokableMethod isInterfaceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInterface(); + + @Override + public final boolean isInterface() { + return (boolean) handle(isInterfaceMethod, isInterfaceInvokable); + } + + private static final SymbolicMethod isInstanceClassMethod = method("isInstanceClass"); + private static final InvokableMethod isInstanceClassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstanceClass(); + + @Override + public final boolean isInstanceClass() { + return (boolean) handle(isInstanceClassMethod, isInstanceClassInvokable); + } + + private static final SymbolicMethod isEnumMethod = method("isEnum"); + private static final InvokableMethod isEnumInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isEnum(); + + @Override + public final boolean isEnum() { + return (boolean) handle(isEnumMethod, isEnumInvokable); + } + + public static final SymbolicMethod isInitializedMethod = method("isInitialized"); + private static final InvokableMethod isInitializedInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInitialized(); + + @Override + public final boolean isInitialized() { + return (boolean) handle(isInitializedMethod, isInitializedInvokable); + } + + private static final SymbolicMethod initializeMethod = method("initialize"); + private static final InvokableMethod initializeInvokable = (receiver, args) -> { + ((HotSpotResolvedJavaType) receiver).initialize(); + return null; + }; + + @Override + public final void initialize() { + handle(initializeMethod, initializeInvokable); + } + + private static final SymbolicMethod isLinkedMethod = method("isLinked"); + private static final InvokableMethod isLinkedInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isLinked(); + + @Override + public final boolean isLinked() { + return (boolean) handle(isLinkedMethod, isLinkedInvokable); + } + + private static final SymbolicMethod linkMethod = method("link"); + private static final InvokableMethod linkInvokable = (receiver, args) -> { + ((HotSpotResolvedJavaType) receiver).link(); + return null; + }; + + @Override + public final void link() { + handle(linkMethod, linkInvokable); + } + + private static final SymbolicMethod hasDefaultMethodsMethod = method("hasDefaultMethods"); + private static final InvokableMethod hasDefaultMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).hasDefaultMethods(); + + @Override + public final boolean hasDefaultMethods() { + return (boolean) handle(hasDefaultMethodsMethod, hasDefaultMethodsInvokable); + } + + private static final SymbolicMethod declaresDefaultMethodsMethod = method("declaresDefaultMethods"); + private static final InvokableMethod declaresDefaultMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).declaresDefaultMethods(); + + @Override + public final boolean declaresDefaultMethods() { + return (boolean) handle(declaresDefaultMethodsMethod, declaresDefaultMethodsInvokable); + } + + public static final SymbolicMethod isAssignableFromMethod = method("isAssignableFrom", ResolvedJavaType.class); + private static final InvokableMethod isAssignableFromInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isAssignableFrom((ResolvedJavaType) args[0]); + + @Override + public final boolean isAssignableFrom(ResolvedJavaType other) { + return (boolean) handle(isAssignableFromMethod, isAssignableFromInvokable, other); + } + + private static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); + private static final InvokableMethod isInstanceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstance((JavaConstant) args[0]); + + @Override + public final boolean isInstance(JavaConstant obj) { + return (boolean) handle(isInstanceMethod, isInstanceInvokable, obj); + } + + private static final SymbolicMethod getSuperclassMethod = method("getSuperclass"); + private static final InvokableMethod getSuperclassInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSuperclass(); + + @Override + public final HotSpotResolvedObjectType getSuperclass() { + return (HotSpotResolvedObjectType) handle(getSuperclassMethod, getSuperclassInvokable); + } + + private static final SymbolicMethod getInterfacesMethod = method("getInterfaces"); + private static final InvokableMethod getInterfacesInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getInterfaces(); + + @Override + public final HotSpotResolvedObjectType[] getInterfaces() { + return (HotSpotResolvedObjectType[]) handle(getInterfacesMethod, getInterfacesInvokable); + } + + private static final SymbolicMethod getSingleImplementorMethod = method("getSingleImplementor"); + private static final InvokableMethod getSingleImplementorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSingleImplementor(); + + @Override + public final ResolvedJavaType getSingleImplementor() { + return (ResolvedJavaType) handle(getSingleImplementorMethod, getSingleImplementorInvokable); + } + + public static final SymbolicMethod findLeastCommonAncestorMethod = method("findLeastCommonAncestor", ResolvedJavaType.class); + private static final InvokableMethod findLeastCommonAncestorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findLeastCommonAncestor((ResolvedJavaType) args[0]); + + @Override + public final HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType otherType) { + return (HotSpotResolvedObjectType) handle(findLeastCommonAncestorMethod, findLeastCommonAncestorInvokable, otherType); + } + + private static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); + private static final InvokableMethod isPrimitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isPrimitive(); + + @Override + public final boolean isPrimitive() { + return (boolean) handle(isPrimitiveMethod, isPrimitiveInvokable); + } + + public static final SymbolicMethod getJavaKindMethod = method("getJavaKind"); + public static final InvokableMethod getJavaKindInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getJavaKind(); + + @Override + public final JavaKind getJavaKind() { + return (JavaKind) handle(getJavaKindMethod, getJavaKindInvokable); + } + + private static final SymbolicMethod findUniqueConcreteMethodMethod = method("findUniqueConcreteMethod", ResolvedJavaMethod.class); + private static final InvokableMethod findUniqueConcreteMethodInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findUniqueConcreteMethod((ResolvedJavaMethod) args[0]); + + @Override + @SuppressWarnings("unchecked") + public final Assumptions.AssumptionResult findUniqueConcreteMethod(ResolvedJavaMethod method) { + return (Assumptions.AssumptionResult) handle(findUniqueConcreteMethodMethod, findUniqueConcreteMethodInvokable, method); + } + + public static final SymbolicMethod getInstanceFieldsMethod = method("getInstanceFields", boolean.class); + public static final InvokableMethod getInstanceFieldsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getInstanceFields((boolean) args[0]); + + @Override + public final ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { + return (ResolvedJavaField[]) handle(getInstanceFieldsMethod, getInstanceFieldsInvokable, includeSuperclasses); + } + + public static final SymbolicMethod getStaticFieldsMethod = method("getStaticFields"); + public static final InvokableMethod getStaticFieldsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getStaticFields(); + + @Override + public final ResolvedJavaField[] getStaticFields() { + return (ResolvedJavaField[]) handle(getStaticFieldsMethod, getStaticFieldsInvokable); + } + + private static final SymbolicMethod findInstanceFieldWithOffsetMethod = method("findInstanceFieldWithOffset", long.class, JavaKind.class); + private static final InvokableMethod findInstanceFieldWithOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).findInstanceFieldWithOffset((long) args[0], + (JavaKind) args[1]); + + @Override + public final ResolvedJavaField findInstanceFieldWithOffset(long offset, JavaKind expectedKind) { + return (ResolvedJavaField) handle(findInstanceFieldWithOffsetMethod, findInstanceFieldWithOffsetInvokable, offset, expectedKind); + } + + private static final SymbolicMethod getSourceFileNameMethod = method("getSourceFileName"); + private static final InvokableMethod getSourceFileNameInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getSourceFileName(); + + @Override + public final String getSourceFileName() { + return (String) handle(getSourceFileNameMethod, getSourceFileNameInvokable); + } + + private static final SymbolicMethod isLocalMethod = method("isLocal"); + private static final InvokableMethod isLocalInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isLocal(); + + @Override + public final boolean isLocal() { + return (boolean) handle(isLocalMethod, isLocalInvokable); + } + + private static final SymbolicMethod isMemberMethod = method("isMember"); + private static final InvokableMethod isMemberInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isMember(); + + @Override + public final boolean isMember() { + return (boolean) handle(isMemberMethod, isMemberInvokable); + } + + private static final SymbolicMethod getEnclosingTypeMethod = method("getEnclosingType"); + private static final InvokableMethod getEnclosingTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getEnclosingType(); + + @Override + public final HotSpotResolvedObjectType getEnclosingType() { + return (HotSpotResolvedObjectType) handle(getEnclosingTypeMethod, getEnclosingTypeInvokable); + } + + private static final SymbolicMethod getDeclaredConstructorsMethod = method("getDeclaredConstructors"); + private static final InvokableMethod getDeclaredConstructorsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredConstructors(); + + @Override + public final ResolvedJavaMethod[] getDeclaredConstructors() { + return (ResolvedJavaMethod[]) handle(getDeclaredConstructorsMethod, getDeclaredConstructorsInvokable); + } + + private static final SymbolicMethod getDeclaredConstructorsBooleanMethod = method("getDeclaredConstructors", boolean.class); + private static final InvokableMethod getDeclaredConstructorsBooleanInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredConstructors((Boolean) args[0]); + + @Override + public final ResolvedJavaMethod[] getDeclaredConstructors(boolean forceLink) { + return (ResolvedJavaMethod[]) handle(getDeclaredConstructorsBooleanMethod, getDeclaredConstructorsBooleanInvokable, forceLink); + } + + private static final SymbolicMethod getDeclaredMethodsMethod = method("getDeclaredMethods"); + private static final InvokableMethod getDeclaredMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredMethods(); + + @Override + public final ResolvedJavaMethod[] getDeclaredMethods() { + return (ResolvedJavaMethod[]) handle(getDeclaredMethodsMethod, getDeclaredMethodsInvokable); + } + + private static final SymbolicMethod getAllMethodsMethod = method("getAllMethods", boolean.class); + private static final InvokableMethod getAllMethodsInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getAllMethods((boolean) args[0]); + + @Override + @SuppressWarnings("unchecked") + public List getAllMethods(boolean forceLink) { + return (List) handle(getAllMethodsMethod, getAllMethodsInvokable); + } + + private static final SymbolicMethod getDeclaredMethodsBooleanMethod = method("getDeclaredMethods", boolean.class); + private static final InvokableMethod getDeclaredMethodsBooleanInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getDeclaredMethods((boolean) args[0]); + + @Override + public final ResolvedJavaMethod[] getDeclaredMethods(boolean forceLink) { + return (ResolvedJavaMethod[]) handle(getDeclaredMethodsBooleanMethod, getDeclaredMethodsBooleanInvokable, forceLink); + } + + private static final SymbolicMethod getClassInitializerMethod = method("getClassInitializer"); + private static final InvokableMethod getClassInitializerInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getClassInitializer(); + + @Override + public final ResolvedJavaMethod getClassInitializer() { + return (ResolvedJavaMethod) handle(getClassInitializerMethod, getClassInitializerInvokable); + } + + private static final SymbolicMethod isCloneableWithAllocationMethod = method("isCloneableWithAllocation"); + private static final InvokableMethod isCloneableWithAllocationInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isCloneableWithAllocation(); + + @Override + public final boolean isCloneableWithAllocation() { + return (boolean) handle(isCloneableWithAllocationMethod, isCloneableWithAllocationInvokable); + } + + private static final SymbolicMethod lookupTypeMethod = method("lookupType", UnresolvedJavaType.class, boolean.class); + private static final InvokableMethod lookupTypeInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).lookupType((UnresolvedJavaType) args[0], (Boolean) args[1]); + + @Override + public final ResolvedJavaType lookupType(UnresolvedJavaType unresolvedJavaType, boolean resolve) { + return (ResolvedJavaType) handle(lookupTypeMethod, lookupTypeInvokable, unresolvedJavaType, resolve); + } + + private static final SymbolicMethod resolveFieldMethod = method("resolveField", UnresolvedJavaField.class, ResolvedJavaType.class); + private static final InvokableMethod resolveFieldInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).resolveField((UnresolvedJavaField) args[0], (ResolvedJavaType) args[1]); + + @Override + public final ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, ResolvedJavaType accessingClass) { + return (ResolvedJavaField) handle(resolveFieldMethod, resolveFieldInvokable, unresolvedJavaField, accessingClass); + } + + @Override + @SuppressWarnings("unchecked") + public final T getAnnotation(Class annotationClass) { + return (T) handle(getAnnotationMethod, getAnnotationInvokable, annotationClass); + } + + @Override + public final Annotation[] getAnnotations() { + return (Annotation[]) handle(getAnnotationsMethod, getAnnotationsInvokable); + } + + @Override + public final Annotation[] getDeclaredAnnotations() { + return (Annotation[]) handle(getDeclaredAnnotationsMethod, getDeclaredAnnotationsInvokable); + } + + @Override + public final Object unproxify() { + return handle(unproxifyMethod, unproxifyInvokable); + } + + @Override + public final int hashCode() { + return (int) handle(hashCodeMethod, hashCodeInvokable); + } + + public static final SymbolicMethod getJavaMirrorMethod = method("getJavaMirror"); + public static final InvokableMethod getJavaMirrorInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).getJavaMirror(); + + @Override + public final JavaConstant getJavaMirror() { + return (JavaConstant) handle(getJavaMirrorMethod, getJavaMirrorInvokable); + } + + @Override + public final boolean equals(Object obj) { + return (boolean) handle(equalsMethod, equalsInvokable, obj); + } + + @Override + public final String toString() { + return (String) handle(toStringMethod, toStringInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java new file mode 100644 index 000000000000..7e1d52812e29 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; +import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.ResolvedJavaType; + +//JaCoCo Exclude + +public final class HotSpotResolvedObjectTypeProxy extends HotSpotResolvedJavaTypeProxy implements HotSpotResolvedObjectType { + HotSpotResolvedObjectTypeProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotResolvedObjectType.class, name, params); + } + + private static final SymbolicMethod getSupertypeMethod = method("getSupertype"); + private static final InvokableMethod getSupertypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getSupertype(); + + @Override + public HotSpotResolvedObjectType getSupertype() { + return (HotSpotResolvedObjectType) handle(getSupertypeMethod, getSupertypeInvokable); + } + + private static final SymbolicMethod getConstantPoolMethod = method("getConstantPool"); + private static final InvokableMethod getConstantPoolInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getConstantPool(); + + @Override + public ConstantPool getConstantPool() { + return (ConstantPool) handle(getConstantPoolMethod, getConstantPoolInvokable); + } + + public static final SymbolicMethod instanceSizeMethod = method("instanceSize"); + public static final InvokableMethod instanceSizeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).instanceSize(); + + @Override + public int instanceSize() { + return (int) handle(instanceSizeMethod, instanceSizeInvokable); + } + + private static final SymbolicMethod getVtableLengthMethod = method("getVtableLength"); + private static final InvokableMethod getVtableLengthInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).getVtableLength(); + + @Override + public int getVtableLength() { + return (int) handle(getVtableLengthMethod, getVtableLengthInvokable); + } + + private static final SymbolicMethod isDefinitelyResolvedWithRespectToMethod = method("isDefinitelyResolvedWithRespectTo", ResolvedJavaType.class); + private static final InvokableMethod isDefinitelyResolvedWithRespectToInvokable = (receiver, + args) -> ((HotSpotResolvedObjectType) receiver).isDefinitelyResolvedWithRespectTo((ResolvedJavaType) args[0]); + + @Override + public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass) { + return (boolean) handle(isDefinitelyResolvedWithRespectToMethod, isDefinitelyResolvedWithRespectToInvokable, accessingClass); + } + + public static final SymbolicMethod klassMethod = method("klass"); + public static final InvokableMethod klassInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).klass(); + + @Override + public Constant klass() { + return (Constant) handle(klassMethod, klassInvokable); + } + + private static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); + private static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); + + @Override + public boolean isPrimaryType() { + return (boolean) handle(isPrimaryTypeMethod, isPrimaryTypeInvokable); + } + + private static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); + private static final InvokableMethod superCheckOffsetInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).superCheckOffset(); + + @Override + public int superCheckOffset() { + return (int) handle(superCheckOffsetMethod, superCheckOffsetInvokable); + } + + private static final SymbolicMethod prototypeMarkWordMethod = method("prototypeMarkWord"); + private static final InvokableMethod prototypeMarkWordInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).prototypeMarkWord(); + + @Override + public long prototypeMarkWord() { + return (long) handle(prototypeMarkWordMethod, prototypeMarkWordInvokable); + } + + private static final SymbolicMethod layoutHelperMethod = method("layoutHelper"); + private static final InvokableMethod layoutHelperInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).layoutHelper(); + + @Override + public int layoutHelper() { + return (int) handle(layoutHelperMethod, layoutHelperInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java new file mode 100644 index 000000000000..08ae243616bf --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotVMConfigAccessProxy.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.equalsMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.hashCodeMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.toStringMethod; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyInvokable; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase.unproxifyMethod; + +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; +import jdk.vm.ci.hotspot.HotSpotVMConfigStore; +import jdk.vm.ci.hotspot.VMField; + +//JaCoCo Exclude + +final class HotSpotVMConfigAccessProxy extends HotSpotVMConfigAccess implements CompilationProxy { + private final InvocationHandler handler; + + HotSpotVMConfigAccessProxy(InvocationHandler handler) { + super(null); + this.handler = handler; + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotVMConfigAccess.class, name, params); + } + + private Object handle(SymbolicMethod method, InvokableMethod invokable, Object... args) { + return CompilationProxy.handle(handler, this, method, invokable, args); + } + + @Override + public HotSpotVMConfigStore getStore() { + // Config store serialization is not implemented. + return HotSpotJVMCIRuntime.runtime().getConfigStore(); + } + + private static final SymbolicMethod getAddressMethod = method("getAddress", String.class, Long.class); + private static final InvokableMethod getAddressInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getAddress((String) args[0], (Long) args[1]); + + @Override + public long getAddress(String name, Long notPresent) { + return (long) handle(getAddressMethod, getAddressInvokable, name, notPresent); + } + + private static final SymbolicMethod getConstantMethod = method("getConstant", String.class, Class.class, Object.class); + @SuppressWarnings("unchecked") private static final InvokableMethod getConstantInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getConstant((String) args[0], + (Class) args[1], args[2]); + + @Override + @SuppressWarnings("unchecked") + public T getConstant(String name, Class type, T notPresent) { + return (T) handle(getConstantMethod, getConstantInvokable, name, type, notPresent); + } + + private static final SymbolicMethod getFieldMethod = method("getField", String.class, String.class, boolean.class); + private static final InvokableMethod getFieldInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getField((String) args[0], (String) args[1], (boolean) args[2]); + + @Override + public VMField getField(String name, String cppType, boolean required) { + return (VMField) handle(getFieldMethod, getFieldInvokable, name, cppType, required); + } + + private static final SymbolicMethod getFlagMethod = method("getFlag", String.class, Class.class, Object.class); + @SuppressWarnings("unchecked") private static final InvokableMethod getFlagInvokable = (receiver, args) -> ((HotSpotVMConfigAccess) receiver).getFlag((String) args[0], (Class) args[1], + args[2]); + + @Override + @SuppressWarnings("unchecked") + public T getFlag(String name, Class type, T notPresent) { + return (T) handle(getFlagMethod, getFlagInvokable, name, type, notPresent); + } + + @Override + public Object unproxify() { + return handle(unproxifyMethod, unproxifyInvokable); + } + + @Override + public int hashCode() { + return (int) handle(hashCodeMethod, hashCodeInvokable); + } + + @Override + public boolean equals(Object obj) { + return (boolean) handle(equalsMethod, equalsInvokable, obj); + } + + @Override + public String toString() { + return (String) handle(toStringMethod, toStringInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java new file mode 100644 index 000000000000..99e5368e338c --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MetaAccessProviderProxy.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import java.lang.reflect.Executable; +import java.lang.reflect.Field; + +import jdk.vm.ci.meta.DeoptimizationAction; +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; +import jdk.vm.ci.meta.SpeculationLog; + +//JaCoCo Exclude + +public final class MetaAccessProviderProxy extends CompilationProxyBase implements MetaAccessProvider { + MetaAccessProviderProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(MetaAccessProvider.class, name, params); + } + + public static final SymbolicMethod lookupJavaTypeClassMethod = method("lookupJavaType", Class.class); + public static final InvokableMethod lookupJavaTypeClassInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaType((Class) args[0]); + + @Override + public ResolvedJavaType lookupJavaType(Class clazz) { + return (ResolvedJavaType) handle(lookupJavaTypeClassMethod, lookupJavaTypeClassInvokable, clazz); + } + + private static final SymbolicMethod lookupJavaMethodMethod = method("lookupJavaMethod", Executable.class); + private static final InvokableMethod lookupJavaMethodInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaMethod((Executable) args[0]); + + @Override + public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { + return (ResolvedJavaMethod) handle(lookupJavaMethodMethod, lookupJavaMethodInvokable, reflectionMethod); + } + + private static final SymbolicMethod lookupJavaFieldMethod = method("lookupJavaField", Field.class); + private static final InvokableMethod lookupJavaFieldInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaField((Field) args[0]); + + @Override + public ResolvedJavaField lookupJavaField(Field reflectionField) { + return (ResolvedJavaField) handle(lookupJavaFieldMethod, lookupJavaFieldInvokable, reflectionField); + } + + private static final SymbolicMethod lookupJavaTypeConstantMethod = method("lookupJavaType", JavaConstant.class); + private static final InvokableMethod lookupJavaTypeConstantInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).lookupJavaType((JavaConstant) args[0]); + + @Override + public ResolvedJavaType lookupJavaType(JavaConstant constant) { + return (ResolvedJavaType) handle(lookupJavaTypeConstantMethod, lookupJavaTypeConstantInvokable, constant); + } + + private static final SymbolicMethod getMemorySizeMethod = method("getMemorySize", JavaConstant.class); + private static final InvokableMethod getMemorySizeInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getMemorySize((JavaConstant) args[0]); + + @Override + public long getMemorySize(JavaConstant constant) { + return (long) handle(getMemorySizeMethod, getMemorySizeInvokable, constant); + } + + private static final SymbolicMethod parseMethodDescriptorMethod = method("parseMethodDescriptor", String.class); + private static final InvokableMethod parseMethodDescriptorInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).parseMethodDescriptor((String) args[0]); + + @Override + public Signature parseMethodDescriptor(String methodDescriptor) { + return (Signature) handle(parseMethodDescriptorMethod, parseMethodDescriptorInvokable, methodDescriptor); + } + + public static final SymbolicMethod encodeDeoptActionAndReasonMethod = method("encodeDeoptActionAndReason", DeoptimizationAction.class, DeoptimizationReason.class, int.class); + private static final InvokableMethod encodeDeoptActionAndReasonInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).encodeDeoptActionAndReason((DeoptimizationAction) args[0], + (DeoptimizationReason) args[1], (int) args[2]); + + @Override + public JavaConstant encodeDeoptActionAndReason(DeoptimizationAction action, DeoptimizationReason reason, int debugId) { + return (JavaConstant) handle(encodeDeoptActionAndReasonMethod, encodeDeoptActionAndReasonInvokable, action, reason, debugId); + } + + public static final SymbolicMethod encodeSpeculationMethod = method("encodeSpeculation", SpeculationLog.Speculation.class); + private static final InvokableMethod encodeSpeculationInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).encodeSpeculation((SpeculationLog.Speculation) args[0]); + + @Override + public JavaConstant encodeSpeculation(SpeculationLog.Speculation speculation) { + return (JavaConstant) handle(encodeSpeculationMethod, encodeSpeculationInvokable, speculation); + } + + public static final SymbolicMethod decodeSpeculationMethod = method("decodeSpeculation", JavaConstant.class, SpeculationLog.class); + private static final InvokableMethod decodeSpeculationInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeSpeculation((JavaConstant) args[0], (SpeculationLog) args[1]); + + @Override + public SpeculationLog.Speculation decodeSpeculation(JavaConstant constant, SpeculationLog speculationLog) { + return (SpeculationLog.Speculation) handle(decodeSpeculationMethod, decodeSpeculationInvokable, constant, speculationLog); + } + + public static final SymbolicMethod decodeDeoptReasonMethod = method("decodeDeoptReason", JavaConstant.class); + private static final InvokableMethod decodeDeoptReasonInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDeoptReason((JavaConstant) args[0]); + + @Override + public DeoptimizationReason decodeDeoptReason(JavaConstant constant) { + return (DeoptimizationReason) handle(decodeDeoptReasonMethod, decodeDeoptReasonInvokable, constant); + } + + public static final SymbolicMethod decodeDeoptActionMethod = method("decodeDeoptAction", JavaConstant.class); + private static final InvokableMethod decodeDeoptActionInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDeoptAction((JavaConstant) args[0]); + + @Override + public DeoptimizationAction decodeDeoptAction(JavaConstant constant) { + return (DeoptimizationAction) handle(decodeDeoptActionMethod, decodeDeoptActionInvokable, constant); + } + + public static final SymbolicMethod decodeDebugIdMethod = method("decodeDebugId", JavaConstant.class); + private static final InvokableMethod decodeDebugIdInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).decodeDebugId((JavaConstant) args[0]); + + @Override + public int decodeDebugId(JavaConstant constant) { + return (int) handle(decodeDebugIdMethod, decodeDebugIdInvokable, constant); + } + + public static final SymbolicMethod getArrayBaseOffsetMethod = method("getArrayBaseOffset", JavaKind.class); + private static final InvokableMethod getArrayBaseOffsetInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getArrayBaseOffset((JavaKind) args[0]); + + @Override + public int getArrayBaseOffset(JavaKind elementKind) { + return (int) handle(getArrayBaseOffsetMethod, getArrayBaseOffsetInvokable, elementKind); + } + + public static final SymbolicMethod getArrayIndexScaleMethod = method("getArrayIndexScale", JavaKind.class); + private static final InvokableMethod getArrayIndexScaleInvokable = (receiver, args) -> ((MetaAccessProvider) receiver).getArrayIndexScale((JavaKind) args[0]); + + @Override + public int getArrayIndexScale(JavaKind elementKind) { + return (int) handle(getArrayIndexScaleMethod, getArrayIndexScaleInvokable, elementKind); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java new file mode 100644 index 000000000000..f4cf9270d93d --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/MethodHandleAccessProviderProxy.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +//JaCoCo Exclude + +final class MethodHandleAccessProviderProxy extends CompilationProxyBase implements MethodHandleAccessProvider { + MethodHandleAccessProviderProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(MethodHandleAccessProvider.class, name, params); + } + + private static final SymbolicMethod lookupMethodHandleIntrinsicMethod = method("lookupMethodHandleIntrinsic", ResolvedJavaMethod.class); + private static final InvokableMethod lookupMethodHandleIntrinsicInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).lookupMethodHandleIntrinsic((ResolvedJavaMethod) args[0]); + + @Override + public IntrinsicMethod lookupMethodHandleIntrinsic(ResolvedJavaMethod method) { + return (IntrinsicMethod) handle(lookupMethodHandleIntrinsicMethod, lookupMethodHandleIntrinsicInvokable, method); + } + + private static final SymbolicMethod resolveInvokeBasicTargetMethod = method("resolveInvokeBasicTarget", JavaConstant.class, boolean.class); + private static final InvokableMethod resolveInvokeBasicTargetInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).resolveInvokeBasicTarget((JavaConstant) args[0], + (boolean) args[1]); + + @Override + public ResolvedJavaMethod resolveInvokeBasicTarget(JavaConstant methodHandle, boolean forceBytecodeGeneration) { + return (ResolvedJavaMethod) handle(resolveInvokeBasicTargetMethod, resolveInvokeBasicTargetInvokable, methodHandle, forceBytecodeGeneration); + } + + private static final SymbolicMethod resolveLinkToTargetMethod = method("resolveLinkToTarget", JavaConstant.class); + private static final InvokableMethod resolveLinkToTargetInvokable = (receiver, args) -> ((MethodHandleAccessProvider) receiver).resolveLinkToTarget((JavaConstant) args[0]); + + @Override + public ResolvedJavaMethod resolveLinkToTarget(JavaConstant memberName) { + return (ResolvedJavaMethod) handle(resolveLinkToTargetMethod, resolveLinkToTargetInvokable, memberName); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java new file mode 100644 index 000000000000..eac5dc9bcb65 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/PredicateProxy.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import java.util.function.Predicate; + +//JaCoCo Exclude + +final class PredicateProxy extends CompilationProxyBase implements Predicate { + PredicateProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(Predicate.class, name, params); + } + + private static final SymbolicMethod testMethod = method("test", Object.class); + @SuppressWarnings("unchecked") private static final InvokableMethod testInvokable = (receiver, args) -> ((Predicate) receiver).test(args[0]); + + @Override + @SuppressWarnings("unchecked") + public boolean test(Object t) { + return (boolean) handle(testMethod, testInvokable, t); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java new file mode 100644 index 000000000000..81daccca5ad5 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/ProfilingInfoProxy.java @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.meta.DeoptimizationReason; +import jdk.vm.ci.meta.JavaMethodProfile; +import jdk.vm.ci.meta.JavaTypeProfile; +import jdk.vm.ci.meta.ProfilingInfo; +import jdk.vm.ci.meta.TriState; + +//JaCoCo Exclude + +public sealed class ProfilingInfoProxy extends CompilationProxyBase implements ProfilingInfo permits HotSpotProfilingInfoProxy { + ProfilingInfoProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(ProfilingInfo.class, name, params); + } + + private static final SymbolicMethod getCodeSizeMethod = method("getCodeSize"); + private static final InvokableMethod getCodeSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getCodeSize(); + + @Override + public int getCodeSize() { + return (int) handle(getCodeSizeMethod, getCodeSizeInvokable); + } + + private static final SymbolicMethod getBranchTakenProbabilityMethod = method("getBranchTakenProbability", int.class); + private static final InvokableMethod getBranchTakenProbabilityInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getBranchTakenProbability((int) args[0]); + + @Override + public double getBranchTakenProbability(int bci) { + return (double) handle(getBranchTakenProbabilityMethod, getBranchTakenProbabilityInvokable, bci); + } + + private static final SymbolicMethod getSwitchProbabilitiesMethod = method("getSwitchProbabilities", int.class); + private static final InvokableMethod getSwitchProbabilitiesInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getSwitchProbabilities((int) args[0]); + + @Override + public double[] getSwitchProbabilities(int bci) { + return (double[]) handle(getSwitchProbabilitiesMethod, getSwitchProbabilitiesInvokable, bci); + } + + private static final SymbolicMethod getTypeProfileMethod = method("getTypeProfile", int.class); + private static final InvokableMethod getTypeProfileInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getTypeProfile((int) args[0]); + + @Override + public JavaTypeProfile getTypeProfile(int bci) { + return (JavaTypeProfile) handle(getTypeProfileMethod, getTypeProfileInvokable, bci); + } + + private static final SymbolicMethod getMethodProfileMethod = method("getMethodProfile", int.class); + private static final InvokableMethod getMethodProfileInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getMethodProfile((int) args[0]); + + @Override + public JavaMethodProfile getMethodProfile(int bci) { + return (JavaMethodProfile) handle(getMethodProfileMethod, getMethodProfileInvokable, bci); + } + + private static final SymbolicMethod getExceptionSeenMethod = method("getExceptionSeen", int.class); + private static final InvokableMethod getExceptionSeenInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getExceptionSeen((int) args[0]); + + @Override + public TriState getExceptionSeen(int bci) { + return (TriState) handle(getExceptionSeenMethod, getExceptionSeenInvokable, bci); + } + + private static final SymbolicMethod getNullSeenMethod = method("getNullSeen", int.class); + private static final InvokableMethod getNullSeenInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getNullSeen((int) args[0]); + + @Override + public TriState getNullSeen(int bci) { + return (TriState) handle(getNullSeenMethod, getNullSeenInvokable, bci); + } + + private static final SymbolicMethod getExecutionCountMethod = method("getExecutionCount", int.class); + private static final InvokableMethod getExecutionCountInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getExecutionCount((int) args[0]); + + @Override + public int getExecutionCount(int bci) { + return (int) handle(getExecutionCountMethod, getExecutionCountInvokable, bci); + } + + public static final SymbolicMethod getDeoptimizationCountMethod = method("getDeoptimizationCount", DeoptimizationReason.class); + private static final InvokableMethod getDeoptimizationCountInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getDeoptimizationCount((DeoptimizationReason) args[0]); + + @Override + public int getDeoptimizationCount(DeoptimizationReason reason) { + return (int) handle(getDeoptimizationCountMethod, getDeoptimizationCountInvokable, reason); + } + + public static final SymbolicMethod setCompilerIRSizeMethod = method("setCompilerIRSize", Class.class, int.class); + private static final InvokableMethod setCompilerIRSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).setCompilerIRSize((Class) args[0], (int) args[1]); + + @Override + public boolean setCompilerIRSize(Class irType, int irSize) { + return (boolean) handle(setCompilerIRSizeMethod, setCompilerIRSizeInvokable, irType, irSize); + } + + private static final SymbolicMethod getCompilerIRSizeMethod = method("getCompilerIRSize", Class.class); + private static final InvokableMethod getCompilerIRSizeInvokable = (receiver, args) -> ((ProfilingInfo) receiver).getCompilerIRSize((Class) args[0]); + + @Override + public int getCompilerIRSize(Class irType) { + return (int) handle(getCompilerIRSizeMethod, getCompilerIRSizeInvokable, irType); + } + + public static final SymbolicMethod isMatureMethod = method("isMature"); + private static final InvokableMethod isMatureInvokable = (receiver, args) -> ((ProfilingInfo) receiver).isMature(); + + @Override + public boolean isMature() { + return (boolean) handle(isMatureMethod, isMatureInvokable); + } + + private static final SymbolicMethod setMatureMethod = method("setMature"); + private static final InvokableMethod setMatureInvokable = (receiver, args) -> { + ((ProfilingInfo) receiver).setMature(); + return null; + }; + + @Override + public void setMature() { + handle(setMatureMethod, setMatureInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java new file mode 100644 index 000000000000..935e03bf1934 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.ResolvedJavaType; +import jdk.vm.ci.meta.Signature; + +//JaCoCo Exclude + +public final class SignatureProxy extends CompilationProxyBase implements Signature { + SignatureProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(Signature.class, name, params); + } + + public static final SymbolicMethod getParameterCountMethod = method("getParameterCount", boolean.class); + public static final InvokableMethod getParameterCountInvokable = (receiver, args) -> ((Signature) receiver).getParameterCount((boolean) args[0]); + + @Override + public int getParameterCount(boolean rec) { + return (int) handle(getParameterCountMethod, getParameterCountInvokable, rec); + } + + private static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); + private static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); + + @Override + public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { + return (JavaType) handle(getParameterTypeMethod, getParameterTypeInvokable, index, accessingClass); + } + + public static final SymbolicMethod getReturnTypeMethod = method("getReturnType", ResolvedJavaType.class); + public static final InvokableMethod getReturnTypeInvokable = (receiver, args) -> ((Signature) receiver).getReturnType((ResolvedJavaType) args[0]); + + @Override + public JavaType getReturnType(ResolvedJavaType accessingClass) { + return (JavaType) handle(getReturnTypeMethod, getReturnTypeInvokable, accessingClass); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java new file mode 100644 index 000000000000..d688787e35ee --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SpeculationLogProxy.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.SpeculationLog; + +//JaCoCo Exclude + +public final class SpeculationLogProxy extends CompilationProxyBase implements SpeculationLog { + SpeculationLogProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(SpeculationLog.class, name, params); + } + + private static final SymbolicMethod collectFailedSpeculationsMethod = method("collectFailedSpeculations"); + private static final InvokableMethod collectFailedSpeculationsInvokable = (receiver, args) -> { + ((SpeculationLog) receiver).collectFailedSpeculations(); + return null; + }; + + @Override + public void collectFailedSpeculations() { + handle(collectFailedSpeculationsMethod, collectFailedSpeculationsInvokable); + } + + public static final SymbolicMethod maySpeculateMethod = method("maySpeculate", SpeculationReason.class); + private static final InvokableMethod maySpeculateInvokable = (receiver, args) -> ((SpeculationLog) receiver).maySpeculate((SpeculationReason) args[0]); + + @Override + public boolean maySpeculate(SpeculationReason reason) { + return (boolean) handle(maySpeculateMethod, maySpeculateInvokable, reason); + } + + public static final SymbolicMethod speculateMethod = method("speculate", SpeculationReason.class); + private static final InvokableMethod speculateInvokable = (receiver, args) -> ((SpeculationLog) receiver).speculate((SpeculationReason) args[0]); + + @Override + public Speculation speculate(SpeculationReason reason) { + return (Speculation) handle(speculateMethod, speculateInvokable, reason); + } + + private static final SymbolicMethod hasSpeculationsMethod = method("hasSpeculations"); + private static final InvokableMethod hasSpeculationsInvokable = (receiver, args) -> ((SpeculationLog) receiver).hasSpeculations(); + + @Override + public boolean hasSpeculations() { + return (boolean) handle(hasSpeculationsMethod, hasSpeculationsInvokable); + } + + private static final SymbolicMethod lookupSpeculationMethod = method("lookupSpeculation", JavaConstant.class); + private static final InvokableMethod lookupSpeculationInvokable = (receiver, args) -> ((SpeculationLog) receiver).lookupSpeculation((JavaConstant) args[0]); + + @Override + public Speculation lookupSpeculation(JavaConstant constant) { + return (Speculation) handle(lookupSpeculationMethod, lookupSpeculationInvokable, constant); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java index fabfcbff2f2e..8769854534e2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/StableProfileProvider.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import java.util.function.BiConsumer; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.MapCursor; @@ -195,7 +196,7 @@ public ProfilingInfo getProfilingInfo(ResolvedJavaMethod method) { return getProfilingInfo(method, true, true); } - static class ProfileKey { + public static class ProfileKey { final ResolvedJavaMethod method; final boolean includeNormal; final boolean includeOSR; @@ -206,6 +207,18 @@ static class ProfileKey { this.includeOSR = includeOSR; } + public ResolvedJavaMethod method() { + return method; + } + + public boolean includeNormal() { + return includeNormal; + } + + public boolean includeOSR() { + return includeOSR; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -680,4 +693,18 @@ public EconomicMap recordProfiles(EconomicMap ma } return map; } + + /** + * Iterates over all queried profiles and invokes the provided consumer for each pair of + * {@link ProfileKey} and corresponding {@link ProfilingInfo}. + * + * @param consumer a callback function that accepts a {@link ProfileKey} and a + * {@link ProfilingInfo} as input parameters + */ + public void forQueriedProfiles(BiConsumer consumer) { + var cursor = profiles.getEntries(); + while (cursor.advance()) { + consumer.accept(cursor.getKey(), cursor.getValue()); + } + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java index 81d39255ff60..240d54a188b9 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java @@ -2929,19 +2929,34 @@ public String toString() { return buf.append(')').toString(); } + /** + * {@code true} if encoded snippets are in use in a hosted context. This is needed to disable + * assertions that are not supported with encoded snippets. {@code EncodedSnippets} is not + * referencable from this context, so this is the only way to check this fact. + */ + private static volatile boolean hostedEncodedSnippets = false; + + /** + * Notifies snippet templates whether snippets are encoded in a hosted context. If {@code true}, + * this call disables assertions that are not supported with encoded snippets. + * + * @param value whether snippets are encoded in a hosted context + */ + public static void setHostedEncodedSnippets(boolean value) { + hostedEncodedSnippets = value; + } + private static boolean checkTemplate(MetaAccessProvider metaAccess, Arguments args, ResolvedJavaMethod method) { Signature signature = method.getSignature(); int offset = args.info.hasReceiver() ? 1 : 0; for (int i = offset; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { JavaKind kind = signature.getParameterKind(i - offset); - assert inRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); - + assert inRuntimeCode() || hostedEncodedSnippets || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); } else if (args.info.isVarargsParameter(i)) { assert args.values[i] instanceof Varargs : Assertions.errorMessage(args.values[i], args, method); Varargs varargs = (Varargs) args.values[i]; - assert inRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); - + assert inRuntimeCode() || hostedEncodedSnippets || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); } else if (args.info.isNonNullParameter(i)) { assert checkNonNull(method, args.info.getParameterName(i), args.values[i]); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java index 790ec771a34a..9e659a32e1a4 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/serviceprovider/SpeculationReasonGroup.java @@ -26,7 +26,8 @@ import java.util.Arrays; import java.util.Set; -import java.util.concurrent.atomic.AtomicInteger; + +import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.code.BytecodePosition; @@ -43,18 +44,14 @@ public final class SpeculationReasonGroup { private final String name; private final Class[] signature; - private static final AtomicInteger nextId = new AtomicInteger(1); - /** * Creates a speculation group whose context will always match {@code signature}. - * - * This constructor is deleted in libgraal to ensure group ids are allocated during build time. - * Without this invariant, it would possible for 2 different groups to have the same id if the - * groups are allocated in different libgraal isolates (since static variables are - * isolate-local). + *

+ * The group ID is {@code name.hashCode()}, which ensures the IDs are stable regardless the + * order in which these objects are constructed. */ public SpeculationReasonGroup(String name, Class... signature) { - this.id = nextId.getAndIncrement(); + this.id = name.hashCode(); this.name = name; this.signature = signature; for (Class c : signature) { @@ -62,6 +59,20 @@ public SpeculationReasonGroup(String name, Class... signature) { throw new IllegalArgumentException("Unsupported speculation context type: " + c.getName()); } } + assert UniqueGroupIDVerification.checkUniqueGroupID(this.id, name) : "each created group must have a unique ID"; + } + + private static final class UniqueGroupIDVerification { + private static final EconomicMap groupNamesByID = EconomicMap.create(); + + private static synchronized boolean checkUniqueGroupID(int groupID, String groupName) { + String previousName = groupNamesByID.put(groupID, groupName); + if (previousName != null) { + throw new AssertionError("The speculation reason groups " + groupName + " and " + previousName + + " have the exact same hash of group names, which is used as the group ID. Changing either name should resolve the collision."); + } + return true; + } } @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java index 3f06b88485c2..38cb88f0eeb2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java @@ -240,7 +240,7 @@ static GraalJVMCICompiler getCompiler(OptionValues options) { } } CompilerConfigurationFactory compilerConfigurationFactory = CompilerConfigurationFactory.selectFactory(Options.TruffleCompilerConfiguration.getValue(options), options, runtime); - return HotSpotGraalCompilerFactory.createCompiler("Truffle", runtime, options, compilerConfigurationFactory); + return HotSpotGraalCompilerFactory.createCompiler("Truffle", runtime, options, compilerConfigurationFactory, null); } public HotSpotTruffleCompilerImpl(HotSpotGraalRuntimeProvider hotspotGraalRuntime, TruffleCompilerConfiguration config) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java index c5fe5645a893..5d34107e99ac 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParser.java @@ -498,6 +498,11 @@ private int next() throws IOException { if (buffer.isEmpty()) { buffer.clear(); // resets position and limit if (source.read(buffer) == -1) { // eof + /* + * Set the limit to 0 to ensure that subsequent next() calls do not start re-reading + * the cleared buffer. + */ + buffer.limit(0); next = -1; return cur; } @@ -537,7 +542,7 @@ private static String toString(final int c) { private JsonParserException error(final String message, final int position) { final int columnNum = position - beginningOfLine; final String formatted = format(message, line, columnNum); - return new JsonParserException(formatted); + return new JsonParserException(formatted, peek() == EOF); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java index e9df2d25a84b..9a058a275f67 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/util/json/JsonParserException.java @@ -24,12 +24,47 @@ */ package jdk.graal.compiler.util.json; +import jdk.vm.ci.meta.TriState; + /** * Thrown by {@link JsonParser} if an error is encountered during parsing. */ @SuppressWarnings("serial") public final class JsonParserException extends RuntimeException { + /** + * Whether the parser was at the end of the input when the exception occurred. This may be + * {@link TriState#UNKNOWN} for exceptions that were not thrown by {@link JsonParser}. + */ + private final TriState isAtEOF; + + /** + * Constructs a new JSON parser exception with the specified detail message. The state of + * whether the parser was at the end of the input when the exception occurred is unknown. + * + * @param msg the detail message + */ public JsonParserException(final String msg) { super(msg); + this.isAtEOF = TriState.UNKNOWN; + } + + /** + * Constructs a new JSON parser exception with the specified detail message and information + * about whether the parser was at the end of the input when the exception occurred. + * + * @param msg the detail message + * @param isAtEOF whether the parser was at the end of the input when the exception occurred + */ + public JsonParserException(String msg, boolean isAtEOF) { + super(msg); + this.isAtEOF = TriState.get(isAtEOF); + } + + /** + * Returns whether the parser was at the end of the input when the exception occurred. This may + * be {@link TriState#UNKNOWN} for exceptions that were not thrown by {@link JsonParser}. + */ + public TriState isAtEOF() { + return isAtEOF; } } From 4390ce9c6e5ea322dc1d1e820e2994f9173b8efc Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:30:03 +0200 Subject: [PATCH 38/49] Reapply "[GR-68037] Use encoded snippets in jargraal." This reverts commit a8c8c7401923367cbf29bb8c0886911bf198c829. --- compiler/docs/ReplayCompilation.md | 4 +- .../test/TransplantLowLevelGraphTest.java | 30 ++- .../hotspot/amd64/test/StubAVXTest.java | 11 +- .../test/ReplayCompilationTest.java | 31 +--- .../test/TestNewInstanceWithException.java | 19 +- ...estNewInstanceWithExceptionRegression.java | 4 +- .../test/SnippetCountersTest.java | 87 +++++++++ .../compiler/core/common/GraalOptions.java | 3 - .../compiler/hotspot/CompilerConfig.java | 9 +- .../compiler/hotspot/EncodedSnippets.java | 171 ++++++++++++++---- .../hotspot/HotSpotBackendFactory.java | 6 +- .../compiler/hotspot/HotSpotHostBackend.java | 50 +++++ .../hotspot/HotSpotReplacementsImpl.java | 98 +++++----- .../HotSpotSnippetMetaAccessProvider.java | 28 +-- .../hotspot/SymbolicSnippetEncoder.java | 38 ++-- .../meta/HotSpotHostForeignCallsProvider.java | 4 +- .../HotSpotSnippetReflectionProvider.java | 4 +- .../CompilerInterfaceDeclarations.java | 25 --- .../HotSpotProxyBackendFactory.java | 17 +- .../RecordedOperationPersistence.java | 8 +- .../replaycomp/ReplayCompilationRunner.java | 43 +---- .../replaycomp/ReplayCompilationSupport.java | 96 ++-------- .../hotspot/stubs/HotSpotGraphKit.java | 19 +- .../replacements/SnippetTemplate.java | 105 +++-------- .../compiler/replacements/TestSnippets.java | 30 +++ .../hotspot/HotSpotTruffleCompilerImpl.java | 22 +++ .../IntentionallyUnsupportedOptions.java | 2 - .../svm/hosted/NativeImageGenerator.java | 6 - .../AnalysisToHostedGraphTransplanter.java | 4 +- .../NativeImageWasmGeneratorRunner.java | 5 - 30 files changed, 508 insertions(+), 471 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java diff --git a/compiler/docs/ReplayCompilation.md b/compiler/docs/ReplayCompilation.md index cafbf5a9e5bc..66ad033ad9d7 100644 --- a/compiler/docs/ReplayCompilation.md +++ b/compiler/docs/ReplayCompilation.md @@ -63,9 +63,7 @@ Any `-ea`, `-esa`, and `-X` arguments from the command line are passed to the JV ## Jargraal vs. Libgraal -Both jargraal and libgraal compilations can be replayed on jargraal. When jargraal replays a libgraal compilation, -it uses encoded snippets to match the behavior and compilations results of libgraal. It is also possible to replay -libgraal compilations on libgraal. Replaying jargraal compilations on libgraal is not supported. +Jargraal can replay both jargraal and libgraal compilations. Libgraal can replay only libgraal compilations. It is necessary to explicitly enable the replay launcher entry point when building libgraal using the VM argument `-Ddebug.jdk.graal.enableReplayLauncher=true`. diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java index 22301acd9cbd..6564eff47c6b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/TransplantLowLevelGraphTest.java @@ -31,9 +31,12 @@ import org.junit.Test; import jdk.graal.compiler.api.directives.GraalDirectives; +import jdk.graal.compiler.api.test.Graal; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampFactory; import jdk.graal.compiler.core.phases.HighTier; +import jdk.graal.compiler.debug.DebugCloseable; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.nodes.GraphState.GuardsStage; import jdk.graal.compiler.nodes.ValueNode; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; @@ -48,35 +51,30 @@ import jdk.graal.compiler.replacements.TestSnippets; import jdk.graal.compiler.replacements.TestSnippets.TransplantTestSnippets; import jdk.graal.compiler.replacements.nodes.LateLoweredNode; +import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; public class TransplantLowLevelGraphTest extends GraalCompilerTest { + private static DebugCloseable snippetScope; + + private static TestSnippets.TransplantTestSnippets.Templates transplantTestSnippets; @BeforeClass public static void setup() { - /** - * Ensure snippets can be registered in a test setup running jargraal only. - */ - System.setProperty("GraalUnitTest", "true"); + Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); + OptionValues options = getInitialOptions(); + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); + snippetScope = replacements.suppressEncodedSnippets(); + transplantTestSnippets = new TestSnippets.TransplantTestSnippets.Templates(options, providers); + replacements.encode(options); } @AfterClass public static void teardown() { - System.clearProperty("GraalUnitTest"); - } - - TestSnippets.TransplantTestSnippets.Templates transplantTestSnippets; - - @SuppressWarnings("this-escape") - public TransplantLowLevelGraphTest() { - Providers p = getProviders(); - OptionValues opt = getInitialOptions(); - - // ensure that the snippets are registered - transplantTestSnippets = new TestSnippets.TransplantTestSnippets.Templates(opt, p); + snippetScope.close(); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java index 5662e05d71f9..8abab2966bd6 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/amd64/test/StubAVXTest.java @@ -44,9 +44,11 @@ import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.type.DataPointerConstant; import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.hotspot.HotSpotBackend; import jdk.graal.compiler.hotspot.HotSpotForeignCallLinkage; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; @@ -240,8 +242,11 @@ public static int testStub() { public void test() { HotSpotProviders providers = (HotSpotProviders) getProviders(); HotSpotForeignCallsProviderImpl foreignCalls = providers.getForeignCalls(); - HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED); - linkage.setCompiledStub(new TestStub(GraalCompilerTest.getInitialOptions(), providers, linkage)); - runTest("testStub"); + OptionValues options = GraalCompilerTest.getInitialOptions(); + try (DebugCloseable _ = ((HotSpotReplacementsImpl) providers.getReplacements()).suppressEncodedSnippets()) { + HotSpotForeignCallLinkage linkage = foreignCalls.registerStubCall(TEST_STUB, HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO, NO_SIDE_EFFECT, COMPUTES_REGISTERS_KILLED); + linkage.setCompiledStub(new TestStub(options, providers, linkage)); + runTest("testStub"); + } } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java index 95beb5cbf83b..60eb1efb8085 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java @@ -25,7 +25,6 @@ package jdk.graal.compiler.hotspot.replaycomp.test; import java.io.ByteArrayOutputStream; -import java.io.FileReader; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; @@ -55,15 +54,10 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; -import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; -import jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence; import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.runtime.RuntimeProvider; -import jdk.graal.compiler.util.json.JsonParser; -import jdk.graal.compiler.util.json.JsonWriter; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -124,36 +118,17 @@ public void recordAndExecuteReplayRunner() throws Throwable { HotSpotCompilationRequestResult regularResult = runRegularCompilation(method, recordOptions); assertTrue(regularResult.getFailure() == null); Path replayFile = findReplayCompFile(temp.path); - Path replayFileLibgraal = Path.of(temp.path.toString(), "libgraal.json"); - copyReplayFileAsLibgraalCompilation(replayFile, replayFileLibgraal); String[][] argumentLists = new String[][]{ new String[]{"--compare-graphs=true", replayFile.toString()}, - new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", replayFileLibgraal.toString()} + new String[]{"--compare-graphs=false", "--benchmark=true", "--iterations=1", temp.path.toString()} }; for (String[] arguments : argumentLists) { ReplayCompilationRunner.ExitStatus status = ReplayCompilationRunner.run(arguments, TTY.out().out()); assertTrue(status == ReplayCompilationRunner.ExitStatus.Success); } - assertTrue(HotSpotReplacementsImpl.snippetsAreEncoded()); }); } - /** - * Creates a copy of the source replay file that acts as if it was compiled with libgraal. This - * way, we test replaying libgraal compilations on jargraal (without access to libgraal). - * - * @param replayFile the source replay file - * @param destFile the created replay file that acts as a libgraal compilation - * ({@link jdk.graal.compiler.hotspot.replaycomp.RecordedOperationPersistence.RecordedCompilationUnit#isLibgraal()}) - */ - private static void copyReplayFileAsLibgraalCompilation(Path replayFile, Path destFile) throws Throwable { - try (FileReader reader = new FileReader(replayFile.toFile()); JsonWriter writer = new JsonWriter(destFile)) { - EconomicMap json = JsonParser.parseDict(reader); - json.put(RecordedOperationPersistence.RecordedCompilationUnitSerializer.IS_LIBGRAAL_PROPERTY, true); - writer.print(json); - } - } - @Test public void unparsableReplayFileSucceeds() throws Throwable { runTest((temp) -> { @@ -190,10 +165,6 @@ private static void runTest(TestRunner test) throws Throwable { System.err.println(outputStream.toString(Charset.defaultCharset())); throw throwable; } - } finally { - HotSpotReplacementsImpl.setEncodedSnippets(null); - HotSpotReplacementsImpl.clearSnippetEncoder(); - ReplayCompilationSupport.setReplayingLibgraalInJargraal(false); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java index ed89537bd54f..ec22c1155ab4 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithException.java @@ -569,6 +569,11 @@ public void runSubprocessTest(Runnable r, String... args) throws IOException, In } } + /** + * The argument setting the maximum heap space of the subprocess. + */ + public static final String MAX_HEAP_SPACE_ARG = "-Xmx64m"; + public static class TestNewInstanceWithException1 extends TestNewInstanceWithException { @Test @@ -579,7 +584,7 @@ public void testNewArrayWithException() throws IOException, InterruptedException } catch (InvalidInstalledCodeException e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -592,7 +597,7 @@ public void testNewInstanceWithException() throws IOException, InterruptedExcept } catch (InvalidInstalledCodeException e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -605,7 +610,7 @@ public void testDynamicNewInstanceWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -618,7 +623,7 @@ public void testDynamicNewInstanceWithExceptionCanonToInstanceWithException() th } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -631,7 +636,7 @@ public void testDynamicNewArrayWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -644,7 +649,7 @@ public void testDynamicNewArrayWithExceptionCanonToArrayWithException() throws T } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } @@ -657,7 +662,7 @@ public void testNewMultiArrayWithException() throws Throwable { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java index fbac45013caa..52c94dce692d 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/TestNewInstanceWithExceptionRegression.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.hotspot.test; +import static jdk.graal.compiler.hotspot.test.TestNewInstanceWithException.MAX_HEAP_SPACE_ARG; + import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -70,7 +72,7 @@ public void test01() throws IOException, InterruptedException { } catch (Throwable e) { throw GraalError.shouldNotReachHere(e); } - }, "-Xmx32m"); + }, MAX_HEAP_SPACE_ARG); } } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java new file mode 100644 index 000000000000..a38cc64deb94 --- /dev/null +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/SnippetCountersTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.replacements.test; + +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.DebugCloseable; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; +import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; +import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.replacements.SnippetCounter; +import jdk.graal.compiler.replacements.SnippetSubstitutionInvocationPlugin; +import jdk.graal.compiler.replacements.SnippetTemplate; +import jdk.graal.compiler.replacements.TestSnippets; +import jdk.vm.ci.meta.ResolvedJavaMethod; + +/** + * Tests snippet counters with encoded snippets on jargraal. + */ +public class SnippetCountersTest extends GraalCompilerTest { + public static void testedMethod() { + substitutedInvoke(); + } + + public static void substitutedInvoke() { + } + + private TestSnippets.CounterTestSnippets.TestSnippetCounters counters; + + @Test + public void test() { + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) getReplacements(); + try (DebugCloseable _ = replacements.suppressEncodedSnippets()) { + OptionValues options = new OptionValues(getInitialOptions(), GraalOptions.SnippetCounters, true); + replacements.registerSnippetTemplateCache(new TestSnippets.CounterTestSnippets.Templates(options, getProviders())); + replacements.encode(options); + counters = new TestSnippets.CounterTestSnippets.TestSnippetCounters(SnippetCounter.Group::new); + executeActual(getResolvedJavaMethod("testedMethod"), null); + Assert.assertEquals(1L, counters.increments.value()); + Assert.assertEquals(2L, counters.doubleIncrements.value()); + } + } + + @Override + protected GraphBuilderConfiguration.Plugins getDefaultGraphBuilderPlugins() { + GraphBuilderConfiguration.Plugins p = super.getDefaultGraphBuilderPlugins(); + InvocationPlugins.Registration r = new InvocationPlugins.Registration(p.getInvocationPlugins(), SnippetCountersTest.class); + r.register(new SnippetSubstitutionInvocationPlugin<>(TestSnippets.CounterTestSnippets.Templates.class, "substitutedInvoke") { + @Override + public SnippetTemplate.SnippetInfo getSnippet(TestSnippets.CounterTestSnippets.Templates templates) { + return templates.increase; + } + + @Override + protected Object[] getConstantArguments(ResolvedJavaMethod targetMethod) { + return new Object[]{counters}; + } + }); + return p; + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java index 3731b473d95d..07a59d640c71 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/common/GraalOptions.java @@ -291,9 +291,6 @@ public final class GraalOptions { @Option(help = "Enable counters for various paths in snippets.", type = OptionType.Debug) public static final OptionKey SnippetCounters = new OptionKey<>(false); - @Option(help = "Eagerly construct extra snippet info.", type = OptionType.Debug) - public static final OptionKey EagerSnippets = new OptionKey<>(false); - @Option(help = "Use a cache for snippet graphs.", type = OptionType.Debug) public static final OptionKey UseSnippetGraphCache = new OptionKey<>(true); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java index ffef728cb93f..2fdeceb8a130 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilerConfig.java @@ -38,8 +38,8 @@ import org.graalvm.collections.MapCursor; import jdk.graal.compiler.core.common.Fields; -import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.core.common.spi.ForeignCallSignature; import jdk.graal.compiler.core.target.Backend; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.graph.NodeClass; @@ -104,6 +104,7 @@ protected ClassInfo makeClassInfo(Class declaringClass) { } private static EncodedSnippets getEncodedSnippets(HotSpotReplacementsImpl replacements, OptionValues options) { + GraalError.guarantee(!HotSpotReplacementsImpl.snippetsAreEncoded(), "snippets should not be encoded"); SymbolicSnippetEncoder snippetEncoder = replacements.maybeInitializeEncoder(); return snippetEncoder.encodeSnippets(options); } @@ -130,7 +131,11 @@ private static EconomicMap coll HotSpotProviders providers = replacements.getProviders(); collectForeignCalls(providers.getForeignCalls(), allForeignCalls); - // Instantiate the Truffle compiler to collect its foreign calls as well + /* + * Instantiate the Truffle compiler to collect its foreign calls as well. Ensure the + * snippets are registered using this encoder. + */ + replacements.shareSnippetEncoder(); for (Backend truffleBackend : HotSpotTruffleCompilerImpl.ensureBackendsInitialized(options)) { HotSpotProviders truffleProviders = (HotSpotProviders) truffleBackend.getProviders(); collectForeignCalls(truffleProviders.getForeignCalls(), allForeignCalls); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index c09b8a98ad6a..9acc8fffc452 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -27,7 +27,6 @@ import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.snippetsAreEncoded; -import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; import java.lang.reflect.Executable; @@ -41,7 +40,9 @@ import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; import jdk.graal.compiler.core.CompilationWrapper; import jdk.graal.compiler.core.GraalCompilerOptions; +import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; +import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.type.Stamp; import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; @@ -54,8 +55,10 @@ import jdk.graal.compiler.nodes.NodeClassMap; 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; import jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext; +import jdk.graal.compiler.nodes.graphbuilderconf.NodePlugin; import jdk.graal.compiler.nodes.graphbuilderconf.ParameterPlugin; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; import jdk.graal.compiler.nodes.spi.SnippetParameterInfo; @@ -64,6 +67,7 @@ import jdk.graal.compiler.replacements.ConstantBindingParameterPlugin; import jdk.graal.compiler.replacements.PEGraphDecoder; import jdk.graal.compiler.replacements.PartialIntrinsicCallTargetNode; +import jdk.graal.compiler.replacements.SnippetCounter; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -75,17 +79,6 @@ import jdk.vm.ci.meta.UnresolvedJavaType; public class EncodedSnippets { - /** - * Returns true if the current runtime or current compilation thread uses encoded snippets - * rather than parsing them directly. This is always true when executing in libgraal, and it is - * also true when the current thread is replaying a libgraal compilation in jargraal. - * - * @return true if encoded snippets are currently in use - */ - public static boolean isUsingEncodedSnippets() { - return inRuntimeCode() || isReplayingLibgraalInJargraal(); - } - /** * Returns true if the current runtime or current compilation thread uses encoded snippets and * the snippets are already encoded. This is always true when executing in libgraal. If the @@ -95,7 +88,7 @@ public static boolean isUsingEncodedSnippets() { * @return true if encoded snippets are in use and already encoded */ public static boolean isAfterSnippetEncoding() { - return inRuntimeCode() || (isReplayingLibgraalInJargraal() && snippetsAreEncoded()); + return inRuntimeCode() || snippetsAreEncoded(); } /** @@ -218,8 +211,11 @@ public NodeClassMap getSnippetNodeClasses() { public ResolvedJavaType lookupSnippetType(Class clazz) { SnippetResolvedJavaType type = snippetTypes.get(clazz); if (type == null && isGraalClass(clazz)) { - // During image building, references to Graal classes from snippets are tracked. - // If a class isn't found in this path at runtime it means something was missed. + /* + * During snippet encoding, references to Graal classes from snippets are tracked. If a + * class isn't found in this path at runtime it means something was missed. However, + * Truffle on jargraal can look up Graal classes that are not snippet types. + */ throw new GraalError("Missing Graal class " + clazz.getName()); } return type; @@ -240,11 +236,7 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod data = graphDatas.get(methodKey(method)); } if (data == null) { - if (isUsingEncodedSnippets()) { - throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport - } else { - return null; - } + throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport } Class receiverClass = null; @@ -262,11 +254,11 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod * ensures we record all relevant operations during recording and no proxies are stored in * the snippet objects during replay. */ - boolean allowCacheReplacements = LibGraalSupport.inLibGraalRuntime() && replacements.getProviders().getReplayCompilationSupport() == null && + boolean allowCacheReplacements = replacements.getProviders().getReplayCompilationSupport() == null && GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, snippetNodeClasses, data.originalMethod, declaringClass); - return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, isUsingEncodedSnippets()); + return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, true); } public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { @@ -342,11 +334,17 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res if (args != null) { MetaAccessProvider meta = HotSpotReplacementsImpl.noticeTypes(providers.getMetaAccess()); SnippetReflectionProvider snippetReflection = replacements.getProviders().getSnippetReflection(); - if (isUsingEncodedSnippets()) { - snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); - } + snippetReflection = new LibGraalSnippetReflectionProvider(snippetReflection); parameterPlugin = new ConstantBindingParameterPlugin(args, meta, snippetReflection); } + NodePlugin[] nodePlugins = null; + if (!inRuntimeCode() && GraalOptions.SnippetCounters.getValue(options)) { + /* + * SnippetCounters are supported on jargraal, but they require a plugin to fold the + * loads of SnippetCounter objects during decoding. + */ + nodePlugins = new NodePlugin[]{new SnippetCounterFoldingPlugin()}; + } try (DebugContext debug = replacements.openDebugContext("LibGraal", method, options)) { // @formatter:off @@ -358,10 +356,10 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res .build(); // @formatter:on try (DebugContext.Scope scope = debug.scope("LibGraal.DecodeSnippet", result)) { - PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, mustSucceed); + PEGraphDecoder graphDecoder = new SubstitutionGraphDecoder(providers, result, replacements, parameterPlugin, method, INLINE_AFTER_PARSING, encodedGraph, nodePlugins, mustSucceed); assert result.isSubstitution(); graphDecoder.decode(method); - postDecode(debug, result, original); + postDecode(debug, result, original, providers.getSnippetReflection(), providers.getMetaAccess()); assert result.verify(); return result; } catch (Throwable t) { @@ -370,7 +368,7 @@ static StructuredGraph decodeSnippetGraph(SymbolicEncodedGraph encodedGraph, Res } } - private static void postDecode(DebugContext debug, StructuredGraph result, ResolvedJavaMethod original) { + private static void postDecode(DebugContext debug, StructuredGraph result, ResolvedJavaMethod original, SnippetReflectionProvider snippetReflection, MetaAccessProvider metaAccess) { debug.dump(DebugContext.VERBOSE_LEVEL, result, "Before PartialIntrinsicCallTargetNode replacement"); for (PartialIntrinsicCallTargetNode partial : result.getNodes(PartialIntrinsicCallTargetNode.TYPE)) { // Ensure the original method matches @@ -381,11 +379,18 @@ private static void postDecode(DebugContext debug, StructuredGraph result, Resol partial.replaceAndDelete(target); } debug.dump(DebugContext.VERBOSE_LEVEL, result, "After decoding"); - for (ValueNode n : result.getNodes().filter(ValueNode.class)) { - if (n instanceof ConstantNode) { - ConstantNode constant = (ConstantNode) n; - if (constant.asConstant() instanceof SnippetObjectConstant) { - throw new InternalError(n.toString(Verbosity.Debugger)); + for (ConstantNode constant : result.getNodes().filter(ConstantNode.class).snapshot()) { + if (constant.asConstant() instanceof SnippetObjectConstant snippetConstant) { + if (!inRuntimeCode() && snippetConstant.asObject(SnippetCounter.class) != null) { + /* + * Convert SnippetCounter objects wrapped in SnippetObjectConstants to HotSpot + * constants (when snippet counters are enabled on jargraal). + */ + ConstantNode replacement = ConstantNode.forConstant(SnippetCounterFoldingPlugin.asHotSpotConstant(snippetConstant, snippetReflection), metaAccess); + replacement = result.unique(replacement); + constant.replace(result, replacement); + } else { + throw new InternalError(constant.toString(Verbosity.Debugger)); } } } @@ -398,10 +403,10 @@ static class SubstitutionGraphDecoder extends PEGraphDecoder { private final boolean mustSucceed; SubstitutionGraphDecoder(Providers providers, StructuredGraph result, HotSpotReplacementsImpl replacements, ParameterPlugin parameterPlugin, ResolvedJavaMethod method, - IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, boolean mustSucceed) { + IntrinsicContext.CompilationContext context, EncodedGraph encodedGraph, NodePlugin[] nodePlugins, boolean mustSucceed) { super(providers.getCodeCache().getTarget().arch, result, providers, null, replacements.getGraphBuilderPlugins().getInvocationPlugins(), new InlineInvokePlugin[0], parameterPlugin, - null, null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), false, false); + nodePlugins, null, null, new ConcurrentHashMap<>(), new ConcurrentHashMap<>(), false, false); this.method = method; this.encodedGraph = encodedGraph; this.mustSucceed = mustSucceed; @@ -429,17 +434,109 @@ protected boolean pluginReplacementMustSucceed() { } } + /** + * Performs constant folding of snippet counter code during snippet decoding on jargraal. + * Folding the loads allows the SnippetCounterNode_add plugin to succeed. + */ + @LibGraalSupport.HostedOnly + private static final class SnippetCounterFoldingPlugin implements NodePlugin { + @Override + public boolean handleLoadField(GraphBuilderContext b, ValueNode receiver, ResolvedJavaField field) { + if (receiver.isConstant()) { + JavaConstant asJavaConstant = receiver.asJavaConstant(); + return tryConstantFold(b, field, asJavaConstant); + } + return false; + } + + @Override + public boolean handleLoadStaticField(GraphBuilderContext b, ResolvedJavaField field) { + return tryConstantFold(b, field, null); + } + + /** + * Converts a snippet object constant to a HotSpot constant. + * + * @param snippetConstant the snippet constant + * @param snippetReflection snippet reflection + * @return the HotSpot constant + */ + private static JavaConstant asHotSpotConstant(SnippetObjectConstant snippetConstant, SnippetReflectionProvider snippetReflection) { + return snippetReflection.forObject(snippetConstant.asObject(Object.class)); + } + + private static boolean tryConstantFold(GraphBuilderContext b, ResolvedJavaField field, JavaConstant receiver) { + if (!field.isStatic() && (receiver == null || receiver.isNull())) { + return false; + } + ConstantNode result = b.getConstantFieldProvider().readConstantField(field, new ConstantFieldProvider.ConstantFieldTool<>() { + @Override + public JavaConstant readValue() { + JavaConstant hotSpotReceiver = receiver; + if (receiver instanceof SnippetObjectConstant objectConstant) { + hotSpotReceiver = asHotSpotConstant(objectConstant, b.getSnippetReflection()); + } + /* + * The result may be a HotSpotObjectConstant, which may also have field loads we + * need to fold. + */ + return b.getConstantReflection().readFieldValue(field, hotSpotReceiver); + } + + @Override + public JavaConstant getReceiver() { + return receiver; + } + + @Override + public Object getReason() { + return b.getGraph().currentNodeSourcePosition(); + } + + @Override + public ConstantNode foldConstant(JavaConstant ret) { + if (ret != null) { + return ConstantNode.forConstant(ret, b.getMetaAccess()); + } else { + return null; + } + } + + @Override + public ConstantNode foldStableArray(JavaConstant ret, int stableDimensions, boolean isDefaultStable) { + if (ret != null) { + return ConstantNode.forConstant(ret, stableDimensions, isDefaultStable, b.getMetaAccess()); + } else { + return null; + } + } + + @Override + public OptionValues getOptions() { + return b.getOptions(); + } + }); + if (result != null) { + result = b.getGraph().unique(result); + b.push(field.getJavaKind(), result); + return true; + } + return false; + } + } + static class SymbolicEncodedGraph extends EncodedGraph { private final ResolvedJavaType[] accessingClasses; private final String originalMethod; private final boolean allowCacheReplacements; - SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowObjectsMutations, NodeClassMap nodeClasses, String originalMethod, ResolvedJavaType... accessingClasses) { + SymbolicEncodedGraph(byte[] encoding, int startOffset, Object[] objects, boolean allowCacheReplacements, NodeClassMap nodeClasses, String originalMethod, + ResolvedJavaType... accessingClasses) { super(encoding, startOffset, objects, nodeClasses, null, null, false, false); this.accessingClasses = accessingClasses; this.originalMethod = originalMethod; - this.allowCacheReplacements = allowObjectsMutations; + this.allowCacheReplacements = allowCacheReplacements; } SymbolicEncodedGraph(EncodedGraph encodedGraph, ResolvedJavaType declaringClass, String originalMethod, boolean allowCacheReplacements) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index 5895c1acfdd1..6ea000c69ab1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -24,9 +24,7 @@ */ package jdk.graal.compiler.hotspot; -import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; import static jdk.vm.ci.common.InitTimer.timer; import jdk.graal.compiler.bytecode.BytecodeProvider; @@ -178,9 +176,7 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti HotSpotConstantReflectionProvider constantReflection = createConstantReflectionProvider(jvmci); afterJVMCIProvidersCreated(); TargetDescription target = codeCache.getTarget(); - if (inBuildtimeCode() || isUsingEncodedSnippets()) { - SnippetSignature.initPrimitiveKindCache(metaAccess); - } + SnippetSignature.initPrimitiveKindCache(metaAccess); ConstantFieldProvider constantFieldProvider = new HotSpotGraalConstantFieldProvider(config, metaAccess); HotSpotProviders providers; HotSpotReplacementsImpl replacements; diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java index 0fc684bd8b75..1974ac9ef08a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotHostBackend.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor.Transition.LEAF_NO_VZERO; import static jdk.graal.compiler.hotspot.meta.HotSpotForeignCallsProviderImpl.NO_LOCATIONS; @@ -34,11 +36,13 @@ import java.util.Collections; import jdk.graal.compiler.core.common.CompilationIdentifier; +import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.NumUtil; import jdk.graal.compiler.core.common.alloc.RegisterAllocationConfig; import jdk.graal.compiler.core.gen.LIRGenerationProvider; import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugDumpHandlersFactory; +import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.hotspot.meta.HotSpotForeignCallDescriptor; import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.graal.compiler.hotspot.meta.HotSpotLoweringProvider; @@ -53,6 +57,7 @@ import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.printer.GraalDebugHandlersFactory; +import jdk.graal.compiler.truffle.hotspot.HotSpotTruffleCompilerImpl; import jdk.graal.compiler.word.Word; import jdk.vm.ci.code.CallingConvention; import jdk.vm.ci.code.RegisterConfig; @@ -120,6 +125,51 @@ public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValue } providers.getReplacements().closeSnippetRegistration(); providers.getReplacements().getGraphBuilderPlugins().getInvocationPlugins().maybePrintIntrinsics(options); + maybeEncodeSnippets(options, jvmciRuntime); + } + + /** + * {@code true} when snippet encoding is in progress on jargraal. + *

+ * The purpose of tracking whether snippets are being encoded is to allow the backend + * initialization code to trigger the initialization of Truffle backends and break from the + * recursion. + */ + @LibGraalSupport.HostedOnly// + private static boolean snippetEncodingInProgress; + + /** + * Encodes snippets on jargraal if they are not already encoded (or being encoded by a caller). + * + * @param options option values + * @param jvmciRuntime the JVMCI runtime + */ + @SuppressWarnings("try") + private void maybeEncodeSnippets(OptionValues options, HotSpotJVMCIRuntime jvmciRuntime) { + if (!inRuntimeCode() && !inBuildtimeCode() && !HotSpotReplacementsImpl.snippetsAreEncoded() && !snippetEncodingInProgress) { + try (InitTimer st = timer("encodeSnippets")) { + GraalError.guarantee(getProviders().getReplayCompilationSupport() == null, "encode snippets without replay support"); + snippetEncodingInProgress = true; + /* + * Initialize Truffle backends to register their snippets. We must perform this + * initialization since those backends could be initialized at any time in the + * future. The backends must register the snippets to our encoder so we share it + * with them. + */ + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) getProviders().getReplacements(); + replacements.shareSnippetEncoder(); + HotSpotGraalRuntimeProvider truffleGraalRuntime = getRuntime(); + if (HotSpotTruffleCompilerImpl.Options.TruffleCompilerConfiguration.hasBeenSet(options)) { + CompilerConfigurationFactory compilerConfigurationFactory = CompilerConfigurationFactory.selectFactory( + HotSpotTruffleCompilerImpl.Options.TruffleCompilerConfiguration.getValue(options), options, jvmciRuntime); + truffleGraalRuntime = new HotSpotGraalRuntime("Truffle", jvmciRuntime, compilerConfigurationFactory, options, null); + } + HotSpotTruffleCompilerImpl.ensureBackendsInitialized(options, truffleGraalRuntime); + replacements.encode(options); + } finally { + snippetEncodingInProgress = false; + } + } } protected CallingConvention makeCallingConvention(StructuredGraph graph, Stub stub) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java index 80c59b7b0e43..502f4d23f93e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotReplacementsImpl.java @@ -27,8 +27,6 @@ import static jdk.graal.compiler.core.common.LibGraalSupport.inLibGraalRuntime; import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; -import static jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport.isReplayingLibgraalInJargraal; import java.util.BitSet; @@ -65,7 +63,6 @@ import jdk.graal.compiler.printer.GraalDebugHandlersFactory; import jdk.graal.compiler.replacements.IntrinsicGraphBuilder; import jdk.graal.compiler.replacements.ReplacementsImpl; -import jdk.graal.compiler.replacements.SnippetTemplate; import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -96,19 +93,12 @@ public HotSpotProviders getProviders() { return (HotSpotProviders) super.getProviders(); } - @LibGraalSupport.HostedOnly - public static void clearSnippetEncoder() { - synchronized (HotSpotReplacementsImpl.class) { - snippetEncoder = null; - } - } - @LibGraalSupport.HostedOnly public SymbolicSnippetEncoder maybeInitializeEncoder() { - synchronized (HotSpotReplacementsImpl.class) { - if (snippetEncoder == null) { - snippetEncoder = new SymbolicSnippetEncoder(this); - } + if (sharedSnippetEncoder != null) { + snippetEncoder = sharedSnippetEncoder; + } else { + snippetEncoder = new SymbolicSnippetEncoder(this); } return snippetEncoder; } @@ -200,10 +190,9 @@ public StructuredGraph getInlineSubstitution(ResolvedJavaMethod method, int invo @Override public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition, OptionValues options) { assert method.isStatic() || receiver != null : "must have a constant type for the receiver"; - if (isRegisteringSnippetMethods()) { - assert !snippetRegistrationClosed || System.getProperty("GraalUnitTest") != null : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); + if (!isAfterSnippetEncoding()) { + assert !snippetRegistrationClosed : "Cannot register snippet after registration is closed: " + method.format("%H.%n(%p)"); if (registeredSnippets.add(method)) { - snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { snippetEncoder.registerSnippet(method, original, receiver, trackNodeSourcePosition); } @@ -211,17 +200,6 @@ public void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod origin } } - /** - * Returns true if the current runtime or current compilation thread registers snippet methods - * to be encoded. This is true when building libgraal or when replaying a libgraal compilation - * in jargraal. - * - * @return true if snippets methods should be registered - */ - private static boolean isRegisteringSnippetMethods() { - return !inLibGraalRuntime() && (inBuildtimeCode() || isReplayingLibgraalInJargraal()); - } - @Override public SnippetParameterInfo getSnippetParameterInfo(ResolvedJavaMethod method) { if (isAfterSnippetEncoding()) { @@ -260,39 +238,69 @@ public static boolean snippetsAreEncoded() { @LibGraalSupport.HostedOnly// public static void setEncodedSnippets(EncodedSnippets encodedSnippets) { HotSpotReplacementsImpl.encodedSnippets = encodedSnippets; - SnippetTemplate.setHostedEncodedSnippets(snippetsAreEncoded()); } @LibGraalSupport.HostedOnly// - @SuppressWarnings("try") - public boolean encode(OptionValues options) { - SymbolicSnippetEncoder encoder = snippetEncoder; - if (encoder != null) { - try (DebugCloseable ignored = ReplayCompilationSupport.enterSnippetContext(getProviders())) { - return encoder.encode(options); - } - } - return false; + public void encode(OptionValues options) { + GraalError.guarantee(!snippetsAreEncoded(), "snippets should not be encoded yet"); + GraalError.guarantee(snippetEncoder != null && snippetEncoder == sharedSnippetEncoder, "only the shared encoder can encode snippets"); + setEncodedSnippets(snippetEncoder.encodeSnippets(options)); } + /** + * Opens a scope without encoded snippets, in which additional snippets can be registered and + * encoded. The previous encoded snippets are restored when the scope is closed. Useful for + * testing. + * + * @return a scope without encoded snippets + */ + @LibGraalSupport.HostedOnly + public DebugCloseable suppressEncodedSnippets() { + EncodedSnippets previous = encodedSnippets; + setEncodedSnippets(null); + return () -> setEncodedSnippets(previous); + } + + /** + * The global shared instance of encoded snippets. + */ private static volatile EncodedSnippets encodedSnippets; + /** + * The shared snippet encoder. The purpose of the shared encoder is to initialize other (i.e., + * Truffle) backends, which should register their snippets to the shared encoder. + */ @LibGraalSupport.HostedOnly// - private static SymbolicSnippetEncoder snippetEncoder; + private static volatile SymbolicSnippetEncoder sharedSnippetEncoder; + + /** + * The snippet encoder used by this instance. Before the encoder is used to encode snippets, it + * must be {@link #sharedSnippetEncoder shared} with Truffle backends to allow them to register + * their snippets. + */ + @LibGraalSupport.HostedOnly// + private SymbolicSnippetEncoder snippetEncoder; + + /** + * Shares this encoder with all subsequently initialized backends. Consequently, these backends + * will register their snippets to the encoder used by this instance. Only one encoder can be + * shared, and only the shared encoder can encode snippets. + */ + @LibGraalSupport.HostedOnly + public void shareSnippetEncoder() { + GraalError.guarantee(sharedSnippetEncoder == null, "only a single encoder can be shared"); + sharedSnippetEncoder = snippetEncoder; + } @SuppressWarnings("try") @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { - if (isUsingEncodedSnippets()) { + if (isAfterSnippetEncoding()) { // Snippets graphs can contain foreign object references and // outlive a single compilation. try (CompilationContext scope = HotSpotGraalServices.enterGlobalCompilationContext()) { - StructuredGraph graph = getEncodedSnippets().getEncodedSnippet(method, original, this, args, AllowAssumptions.NO, options); - if (graph == null) { - throw GraalError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); // ExcludeFromJacocoGeneratedReport - } - return graph; + return getEncodedSnippets().getEncodedSnippet(method, original, this, args, AllowAssumptions.NO, options); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java index 2c714cada6ac..07d06f36fa85 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotSnippetMetaAccessProvider.java @@ -24,11 +24,12 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; + import java.lang.reflect.Executable; import java.lang.reflect.Field; import jdk.graal.compiler.debug.GraalError; -import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; @@ -40,28 +41,16 @@ import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.SpeculationLog; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; - public class HotSpotSnippetMetaAccessProvider implements MetaAccessProvider { private final MetaAccessProvider delegate; - /** - * {@code true} if the compiler is recording/replaying a compilation. - */ - private final boolean replayCompilationEnabled; - - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate, boolean replayCompilationEnabled) { - this.delegate = delegate; - this.replayCompilationEnabled = replayCompilationEnabled; - } - public HotSpotSnippetMetaAccessProvider(MetaAccessProvider delegate) { - this(delegate, false); + this.delegate = delegate; } @Override public ResolvedJavaType lookupJavaType(Class clazz) { - if (isAfterSnippetEncoding()) { + if (inRuntimeCode()) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); if (type != null) { return type; @@ -84,20 +73,13 @@ public ResolvedJavaField lookupJavaField(Field reflectionField) { public ResolvedJavaType lookupJavaType(JavaConstant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { Class clazz = objectConstant.asObject(Object.class).getClass(); - if (isAfterSnippetEncoding() && HotSpotReplacementsImpl.isGraalClass(clazz)) { + if (HotSpotReplacementsImpl.isGraalClass(clazz)) { ResolvedJavaType type = HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(clazz); GraalError.guarantee(type != null, "Type of compiler object %s missing from encoded snippet types: %s", constant, clazz.getName()); return type; } return delegate.lookupJavaType(clazz); } - if (constant instanceof HotSpotObjectConstant hsConstant && !replayCompilationEnabled) { - Object object = hsConstant.asObject(Object.class); - if (object != null) { - Class clazz = object.getClass(); - return lookupJavaType(clazz); - } - } return delegate.lookupJavaType(constant); } 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 15658006810c..54676f8b4dd2 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 @@ -24,6 +24,7 @@ */ package jdk.graal.compiler.hotspot; +import static jdk.graal.compiler.core.common.NativeImageSupport.inBuildtimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.createIntrinsicInlineInfo; @@ -46,6 +47,7 @@ import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.bytecode.ResolvedJavaMethodBytecode; +import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.type.AbstractObjectStamp; @@ -60,7 +62,6 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; -import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationSupport; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -403,7 +404,9 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { snippetReplacements.setGraphBuilderPlugins(copy); copy.clearInlineInvokePlugins(); copy.appendInlineInvokePlugin(new SnippetInlineInvokePlugin()); - copy.appendNodePlugin(new SnippetCounterPlugin()); + if (inBuildtimeCode() || !GraalOptions.SnippetCounters.getValue(options)) { + copy.appendNodePlugin(new SnippetCounterPlugin()); + } EconomicMap preparedSnippetGraphs = EconomicMap.create(); MapCursor> cursor = pendingSnippetGraphs.getEntries(); @@ -424,13 +427,6 @@ public synchronized EncodedSnippets encodeSnippets(OptionValues options) { } synchronized void registerSnippet(ResolvedJavaMethod method, ResolvedJavaMethod original, Object receiver, boolean trackNodeSourcePosition) { - if (HotSpotReplacementsImpl.snippetsAreEncoded()) { - if (ReplayCompilationSupport.isReplayingLibgraalInJargraal()) { - return; - } - throw new GraalError("Snippet encoding has already been done"); - } - assert method.getAnnotation(Snippet.class) != null : "Snippet must be annotated with @" + Snippet.class.getSimpleName(); SnippetKey key = new SnippetKey(method, original, receiver); findSnippetMethod(method); @@ -533,7 +529,7 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic // Ensure a few well known types are available lookupSnippetType(GraalHotSpotVMConfig.class); lookupSnippetType(NamedLocationIdentity.class); - lookupSnippetType(SnippetTemplate.EagerSnippetInfo.class); + lookupSnippetType(SnippetTemplate.SnippetInfo.class); lookupSnippetType(ForeignCallStub.class); lookupSnippetType(HotSpotSpeculationLog.HotSpotSpeculation.class); @@ -560,19 +556,6 @@ private void registerAbstractForeignCallStubInfo() { findSnippetMethod(AbstractForeignCallStub.getGraphMethod(metaAccess)); } - /** - * Encode any outstanding graphs and return true if any work was done. - */ - @SuppressWarnings("try") - public synchronized boolean encode(OptionValues options) { - EncodedSnippets encodedSnippets = encodeSnippets(options); - if (encodedSnippets != null) { - HotSpotReplacementsImpl.setEncodedSnippets(encodedSnippets); - return true; - } - return false; - } - static class HotSpotSubstrateConstantReflectionProvider implements ConstantReflectionProvider { private final ConstantReflectionProvider constantReflection; @@ -734,7 +717,8 @@ private EncodedSnippets.SymbolicResolvedJavaMethod filterMethod(DebugContext deb if (symbolic != null) { return symbolic; } - if (HotSpotReplacementsImpl.isGraalClass(method.getDeclaringClass())) { + if (inBuildtimeCode() && HotSpotReplacementsImpl.isGraalClass(method.getDeclaringClass())) { + // Snippet counter methods in jargraal are allowed. throw new GraalError("Graal methods shouldn't leak into image: " + method); } UnresolvedJavaType type = (UnresolvedJavaType) filterType(debug, method.getDeclaringClass()); @@ -762,7 +746,8 @@ private JavaType filterType(DebugContext debug, ResolvedJavaType type) { if (unresolvedJavaType != null) { return unresolvedJavaType; } - if (HotSpotReplacementsImpl.isGraalClass(type)) { + if (inBuildtimeCode() && HotSpotReplacementsImpl.isGraalClass(type)) { + // Snippet counter types in jargraal are allowed. throw new GraalError("Graal types shouldn't leak into image: " + type); } unresolvedJavaType = UnresolvedJavaType.create(type.getName()); @@ -776,7 +761,8 @@ private Object filterFieldLocationIdentity(DebugContext debug, HotSpotResolvedJa } private Object filterField(DebugContext debug, HotSpotResolvedJavaField field) { - if (!field.getDeclaringClass().getName().startsWith("Ljava/lang/")) { + if (inBuildtimeCode() && !field.getDeclaringClass().getName().startsWith("Ljava/lang/")) { + // Snippet counter fields in jargraal are allowed. // Might require adjustments in HotSpotSubstrateConstantReflectionProvider throw new InternalError("All other fields must have been resolved: " + field); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java index 65ea199b8596..483a94a160ad 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotHostForeignCallsProvider.java @@ -28,7 +28,7 @@ import static jdk.graal.compiler.core.common.spi.ForeignCallDescriptor.CallSideEffect.NO_SIDE_EFFECT; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_DREM; import static jdk.graal.compiler.core.target.Backend.ARITHMETIC_FREM; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isUsingEncodedSnippets; +import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_PARTITION; import static jdk.graal.compiler.hotspot.HotSpotBackend.ARRAY_SORT; import static jdk.graal.compiler.hotspot.HotSpotBackend.BASE64_DECODE_BLOCK; @@ -379,7 +379,7 @@ private void registerStubCallFunctions(OptionValues options, HotSpotProviders pr } registerForeignCall(INVOKE_STATIC_METHOD_ONE_ARG, invokeJavaMethodAddress, NativeCall); - if (!isUsingEncodedSnippets()) { + if (!isAfterSnippetEncoding()) { /* * These functions are only used for testing purposes but their registration also * ensures that libgraal has support for InvokeJavaMethodStub built into the image, diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java index 975975f3087a..c3e723c6ee82 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotSnippetReflectionProvider.java @@ -24,7 +24,7 @@ */ package jdk.graal.compiler.hotspot.meta; -import static jdk.graal.compiler.hotspot.EncodedSnippets.isAfterSnippetEncoding; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; import java.lang.reflect.Executable; @@ -62,7 +62,7 @@ public HotSpotSnippetReflectionProvider(HotSpotGraalRuntimeProvider runtime, Hot @Override public JavaConstant forObject(Object object) { - if (isAfterSnippetEncoding()) { + if (inRuntimeCode()) { HotSpotReplacementsImpl.getEncodedSnippets().lookupSnippetType(object.getClass()); // This can only be a compiler object when in libgraal. return new SnippetObjectConstant(object); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index 1da729880499..abf8b60ff0bb 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -46,11 +46,8 @@ import jdk.graal.compiler.bytecode.BytecodeStream; import jdk.graal.compiler.core.common.CompilerProfiler; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; -import jdk.graal.compiler.graph.NodeClass; -import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; @@ -69,7 +66,6 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; -import jdk.graal.compiler.replacements.SnippetCounter; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -633,27 +629,6 @@ public static CompilerInterfaceDeclarations build() { .setDefaultValue(MetaAccessProviderProxy.decodeSpeculationMethod, SpeculationLog.NO_SPECULATION) .setStrategy(MetaAccessProviderProxy.getArrayBaseOffsetMethod, MethodStrategy.Passthrough) .setStrategy(MetaAccessProviderProxy.getArrayIndexScaleMethod, MethodStrategy.Passthrough) - .provideMethodCallsToRecord((input) -> { - List result = new ArrayList<>(); - if (!LibGraalSupport.inLibGraalRuntime()) { - // Record the calls needed for HotSpotGraalConstantFieldProvider in jargraal. - // Not needed in libgraal because the lookups are handled by HotSpotSnippetMetaAccessProvider. - for (Class clazz : List.of(GraalHotSpotVMConfig.class, SnippetCounter.class, NodeClass.class)) { - result.add(new MethodCallToRecord(input, MetaAccessProviderProxy.lookupJavaTypeClassMethod, MetaAccessProviderProxy.lookupJavaTypeClassInvokable, new Object[]{clazz})); - } - } - return result; - }) - .setFallbackInvocationHandler(MetaAccessProviderProxy.lookupJavaTypeClassMethod, (proxy, method, args, singletonObjects) -> { - // Needed for Word types when replaying libgraal compilations on jargraal. - Class clazz = (Class) args[0]; - MetaAccessProvider localMetaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType localMirror = localMetaAccess.lookupJavaType(clazz); - if (localMirror == null) { - throw new IllegalArgumentException(); - } - return localMirror; - }) .register(declarations); new RegistrationBuilder<>(HotSpotConstantReflectionProvider.class).setSingleton(true) .ensureRecorded(HotSpotConstantReflectionProviderProxy.forObjectMethod, HotSpotConstantReflectionProviderProxy.forObjectInvokable,(Object) null) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java index 4b48176c6bfd..7e8ced5f0548 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java @@ -24,12 +24,8 @@ */ package jdk.graal.compiler.hotspot.replaycomp; -import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; - -import java.util.List; import java.util.Objects; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.hotspot.HotSpotBackendFactoryDecorators; import jdk.graal.compiler.hotspot.HotSpotSnippetMetaAccessProvider; import jdk.graal.compiler.hotspot.SnippetObjectConstant; @@ -73,7 +69,7 @@ public void afterJVMCIProvidersCreated() { public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { // Do not record snippet types in libgraal - decorate the JVMCI meta access only. metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); - return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy, true); + return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy); } @Override @@ -91,17 +87,8 @@ private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider de this.delegate = delegate; } - private static final List allowedFields = List.of("TYPE", "COMPACT_STRINGS"); - @Override public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { - /* - * Prevents jargraal from encoding runtime constants in snippets (such as in boxing - * snippets). Follows the logic of HotSpotSubstrateConstantReflectionProvider. - */ - if (!LibGraalSupport.inLibGraalRuntime() && replayCompilationSupport.isInSnippetContext() && !isGraalClass(field.getDeclaringClass()) && !allowedFields.contains(field.getName())) { - return null; - } return delegate.readFieldValue(field, receiver); } @@ -152,7 +139,7 @@ public JavaConstant forString(String value) { public ResolvedJavaType asJavaType(Constant constant) { if (constant instanceof SnippetObjectConstant objectConstant) { /* - * Avoids recording an operation with the snippet constant, which is not + * Avoid recording an operation with the snippet constant, which is not * serializable. */ return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java index 504c0a705500..1e31d9d44721 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java @@ -1379,9 +1379,7 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize } } - public static final class RecordedCompilationUnitSerializer implements ObjectSerializer { - public static final String IS_LIBGRAAL_PROPERTY = "isLibgraal"; - + private static final class RecordedCompilationUnitSerializer implements ObjectSerializer { private static final String TAG = "recordedCompilationUnit"; @Override @@ -1401,7 +1399,7 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, objectBuilder.append("osName", unit.platform.osName()); objectBuilder.append("archName", unit.platform.archName()); objectBuilder.append("compilerConfiguration", unit.compilerConfiguration); - objectBuilder.append(IS_LIBGRAAL_PROPERTY, unit.isLibgraal); + objectBuilder.append("isLibgraal", unit.isLibgraal); objectBuilder.append("entryBCI", unit.request.getEntryBCI()); objectBuilder.append("compileId", unit.request.getId()); try (JsonBuilder.ArrayBuilder arrayBuilder = objectBuilder.append("operations").array()) { @@ -1421,7 +1419,7 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize String archName = (String) json.get("archName"); Platform platform = new Platform(osName, archName); String compilerConfiguration = (String) json.get("compilerConfiguration"); - boolean isLibgraal = (boolean) json.get(IS_LIBGRAAL_PROPERTY); + boolean isLibgraal = (boolean) json.get("isLibgraal"); int entryBCI = (int) json.get("entryBCI"); int compileId = (int) json.get("compileId"); List list = (List) json.get("operations"); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java index 025e14ab43d3..98e14350887a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java @@ -24,6 +24,8 @@ */ package jdk.graal.compiler.hotspot.replaycomp; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; + import java.io.Closeable; import java.io.FileReader; import java.io.IOException; @@ -42,7 +44,6 @@ import org.graalvm.collections.EconomicMap; import jdk.graal.compiler.core.GraalCompilerOptions; -import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; @@ -320,18 +321,11 @@ public static final class Reproducer implements Closeable { */ private final OptionValues options; - /** - * Whether the recorded compilation was performed on libgraal. - */ - private final boolean isLibgraal; - - private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options, - boolean isLibgraal) { + private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationRequest request, String finalGraph, OptionValues options) { this.replayCompiler = replayCompiler; this.request = request; this.finalGraph = finalGraph; this.options = options; - this.isLibgraal = isLibgraal; } /** @@ -352,6 +346,10 @@ private Reproducer(HotSpotGraalCompiler replayCompiler, HotSpotCompilationReques @SuppressWarnings("try") public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDeclarations declarations, HotSpotJVMCIRuntime runtime, OptionValues options, CompilerConfigurationFactory factory, GlobalMetrics globalMetrics, PrintStream out, EconomicMap internPool) throws ReplayLauncherFailure { + if (!inRuntimeCode() && !HotSpotReplacementsImpl.snippetsAreEncoded()) { + out.println("Encode snippets"); + HotSpotJVMCIRuntime.runtime().getCompiler(); + } ReplayCompilationProxies proxies = new ReplayCompilationProxies(declarations, globalMetrics, options); out.println("Loading " + fileName); RecordedOperationPersistence.RecordedCompilationUnit compilationUnit; @@ -368,38 +366,18 @@ public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDe throw new ReplayParserFailure("Parsing failed due to " + exception.getMessage()); } HotSpotCompilationRequest request = compilationUnit.request(); - boolean replayingLibgraalInJargraal = !LibGraalSupport.inLibGraalRuntime() && compilationUnit.isLibgraal(); - ReplayCompilationSupport.setReplayingLibgraalInJargraal(replayingLibgraalInJargraal); if (LibGraalSupport.inLibGraalRuntime() && !compilationUnit.isLibgraal()) { throw new ReplayLauncherFailure("Cannot replay jargraal compilation " + request + " in libgraal"); } - boolean encodeSnippets = replayingLibgraalInJargraal && !HotSpotReplacementsImpl.snippetsAreEncoded(); - if (encodeSnippets) { - /* - * Ensure the snippet encoder will be created and linked to the decorated providers - * created below. - */ - HotSpotReplacementsImpl.clearSnippetEncoder(); - } - OptionValues selectedOptions = options; - if (replayingLibgraalInJargraal) { - selectedOptions = new OptionValues(options, GraalOptions.EagerSnippets, true); - } out.println("Initializing the replay compiler for " + request); - HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, selectedOptions, factory, new ReplayCompilationSupport(proxies, factory.getName())); + HotSpotGraalCompiler replayCompiler = HotSpotGraalCompilerFactory.createCompiler("VM-replay", runtime, options, factory, new ReplayCompilationSupport(proxies, factory.getName())); HotSpotGraalRuntimeProvider graalRuntime = replayCompiler.getGraalRuntime(); if (!graalRuntime.getCompilerConfigurationName().equals(compilationUnit.compilerConfiguration())) { throw new ReplayLauncherFailure(("Compiler configuration mismatch: the task was compiled using " + compilationUnit.compilerConfiguration() + " but the initialized compiler is " + graalRuntime.getCompilerConfigurationName())); } - ReplayCompilationSupport support = graalRuntime.getReplayCompilationSupport(); - support.setRecordedForeignCallLinkages(compilationUnit.linkages()); - if (encodeSnippets) { - out.println("Encoding snippets"); - HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) graalRuntime.getHostProviders().getReplacements(); - replacements.encode(graalRuntime.getOptions()); - } - return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), selectedOptions, compilationUnit.isLibgraal()); + graalRuntime.getReplayCompilationSupport().setRecordedForeignCallLinkages(compilationUnit.linkages()); + return new Reproducer(replayCompiler, request, compilationUnit.finalGraph(), options); } /** @@ -409,7 +387,6 @@ public static Reproducer initializeFromFile(String fileName, CompilerInterfaceDe */ @SuppressWarnings("try") public ReplayResult compile() { - ReplayCompilationSupport.setReplayingLibgraalInJargraal(!LibGraalSupport.inLibGraalRuntime() && isLibgraal); ReplayCompilationSupport support = replayCompiler.getGraalRuntime().getReplayCompilationSupport(); CompilationRequestResult result = replayCompiler.compileMethod(request, true, options); ReplayCompilationSupport.CompilationArtifacts replayedArtifacts = support.clearCompilationArtifacts(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java index 19b390fea953..2ab23bbaecae 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java @@ -24,8 +24,6 @@ */ package jdk.graal.compiler.hotspot.replaycomp; -import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; - import java.nio.file.Path; import java.util.function.Predicate; @@ -36,7 +34,6 @@ import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.DebugOptions; -import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.debug.MethodFilter; import jdk.graal.compiler.debug.PathUtilities; import jdk.graal.compiler.debug.TTY; @@ -83,33 +80,22 @@ * {@link #decorateIntrinsificationTrustPredicate} return proxies for additional objects. * *

- * Compiler Instances. Since we hijack the compiler's backend factory, a dedicated compiler - * instance must be created for recording and replay. To modify the compiler's behavior even from - * places where an instance of this class cannot be reasonably obtained, this class tracks whether - * the current compiler thread is performing a replay of a libgraal compilation in jargraal - * ({@link #isReplayingLibgraalInJargraal()}) and whether it is in a snippet context - * ({@link #isInSnippetContext()}). During recording, separate compiler instances should be used for - * the recorded methods ({@link #matchesRecordCompilationFilter}) and the methods that are not - * recorded. This ensures that the recording overhead is paid for the recorded methods only. - * - *

- * Snippets. It is possible to record a libgraal compilation and replay it on jargraal. To - * ensure the replayed compilation matches the recorded one, we replay such compilations using - * encoded snippets ({@link #isReplayingLibgraalInJargraal()}). We must never mix raw JVMCI object - * and JVMCI proxies in a single graph, so we create proxies even during snippet parsing. Due to the - * need to replay libgraal compilations on jargraal and since snippets are compiler code rather than - * application code, the proxies do not record the operations during snippet parsing (i.e., inside - * snippet context {@link #enterSnippetContext}). When snippets are parsed during replay, the - * proxies may use local mirrors to query the information required for the snippets from the host VM - * instance. + * Compiler Instances and Snippets. Since we hijack the compiler's backend factory, a + * dedicated compiler instance must be created for recording and replay. During recording, separate + * compiler instances should be used for the recorded methods + * ({@link #matchesRecordCompilationFilter}) and the methods that are not recorded. This ensures + * that the recording overhead is paid for the recorded methods only. Snippets and stubs are + * considered part of the compiler rather than the application, and they should never be recorded. + * It is possible to record a libgraal compilation and replay it on jargraal. * *

* Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that - * was not recorded, including the information to parse snippets. There are also local-only proxies - * that do not originate from the recorded JSON but are instead created from local JVMCI objects - * (created using {@link CompilationProxies#proxify}). The exact rules when operations are delegated - * to local mirrors are dictated by the strategies defined in {@link CompilerInterfaceDeclarations}. + * was not recorded, including the information used to process snippets. There are also local-only + * proxies that do not originate from the recorded JSON but are instead created from local JVMCI + * objects (created using {@link CompilationProxies#proxify}). The exact rules when operations are + * delegated to local mirrors are dictated by the strategies defined in + * {@link CompilerInterfaceDeclarations}. * *

* Foreign Call Linkages. During recording, we capture the addresses and killed registers of @@ -128,26 +114,6 @@ public final class ReplayCompilationSupport { */ public static final boolean ENABLE_REPLAY_LAUNCHER = Boolean.parseBoolean(GraalServices.getSavedProperty(ENABLE_REPLAY_LAUNCHER_PROP)); - /** - * Returns whether this compiler thread is replaying a libgraal compilation in jargraal. - */ - public static boolean isReplayingLibgraalInJargraal() { - return !inRuntimeCode() && isReplayingLibgraalInJargraal.get(); - } - - /** - * Sets whether the current compiler thread is replaying a libgraal compilation in jargraal. - * - * @param replayingLibgraalInJargraal true if the current compiler thread is replaying a - * libgraal compilation in jargraal, false otherwise - */ - public static void setReplayingLibgraalInJargraal(boolean replayingLibgraalInJargraal) { - if (replayingLibgraalInJargraal) { - GraalError.guarantee(!inRuntimeCode(), "this option is only valid in jargraal"); - } - ReplayCompilationSupport.isReplayingLibgraalInJargraal.set(replayingLibgraalInJargraal); - } - /** * Checks whether the given method's compilation should be recorded according to the given * options. @@ -165,11 +131,6 @@ public static boolean matchesRecordCompilationFilter(OptionValues options, Resol } } - /** - * Whether the current compiler thread is replaying a libgraal compilation in jargraal. - */ - private static final ThreadLocal isReplayingLibgraalInJargraal = ThreadLocal.withInitial(() -> false); - /** * The proxies used for recording/replaying the compilations. */ @@ -185,11 +146,6 @@ public static boolean matchesRecordCompilationFilter(OptionValues options, Resol */ private RecordedForeignCallLinkages recordedForeignCallLinkages; - /** - * Whether the compiler thread is in a snippet context. - */ - private final ThreadLocal inSnippetContext = ThreadLocal.withInitial(() -> false); - /** * The compilation artifacts of the current compiler thread. */ @@ -249,28 +205,21 @@ public OptionValues filterOptions(OptionValues options) { } /** - * Enters a snippet context for the current compiler thread. In a recorded compilation, the - * proxies should not record JVMCI calls and results related to snippet parsing and - * optimization. In a replayed compilation, the proxies can delegate to the local mirrors to - * handle JVMCI calls. + * Enters a snippet context. In a recorded compilation, the proxies should not record JVMCI + * calls and results related to snippet processing. In a replayed compilation, the proxies can + * delegate to the local mirrors to handle JVMCI calls. * * @return a debug closeable that should be closed when exiting the context */ private DebugCloseable enterSnippetContext() { - boolean previous = inSnippetContext.get(); - inSnippetContext.set(true); - DebugCloseable closeable = proxies.enterSnippetContext(); - return () -> { - inSnippetContext.set(previous); - closeable.close(); - }; + return proxies.enterSnippetContext(); } /** * Enters a snippet context for the given providers. *

* If the providers have a non-null {@link ReplayCompilationSupport} instance, this method - * enters a snippet context for the current compiler thread. Otherwise, it returns {@code null}. + * enters a snippet context. Otherwise, it returns {@code null}. * * @param providers the providers to check for {@link ReplayCompilationSupport} * @return a scope representing the snippet context, or {@code null} if not supported @@ -282,8 +231,8 @@ public static DebugCloseable enterSnippetContext(HotSpotProviders providers) { /** * Enters a snippet context for the given {@link ReplayCompilationSupport} instance. *

- * If the provided {@code support} is not {@code null}, this method enters a snippet context for - * the current compiler thread. Otherwise, it returns {@code null}. + * If the provided {@code support} is not {@code null}, this method enters a snippet context. + * Otherwise, it returns {@code null}. * * @param support the instance to check * @return a scope representing the snippet context, or {@code null} if not supported @@ -296,13 +245,6 @@ public static DebugCloseable enterSnippetContext(ReplayCompilationSupport suppor } } - /** - * Returns whether this compiler thread is in a snippet context. - */ - public boolean isInSnippetContext() { - return inSnippetContext.get(); - } - /** * Enters a scope with a given debug context. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java index da960aab56f1..449bf4912831 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/HotSpotGraphKit.java @@ -24,10 +24,7 @@ */ package jdk.graal.compiler.hotspot.stubs; -import static jdk.graal.compiler.nodes.graphbuilderconf.IntrinsicContext.CompilationContext.INLINE_AFTER_PARSING; - import jdk.graal.compiler.core.common.CompilationIdentifier; -import jdk.graal.compiler.core.common.LibGraalSupport; import jdk.graal.compiler.debug.Assertions; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.graph.Node; @@ -84,22 +81,8 @@ public void inlineAsIntrinsic(Invoke invoke, String reason, String phase) { assert invoke instanceof Node : Assertions.errorMessage(invoke, reason, phase); Node invokeNode = (Node) invoke; ResolvedJavaMethod method = invoke.callTarget().targetMethod(); - - Plugins plugins = new Plugins(graphBuilderPlugins); - GraphBuilderConfiguration config = GraphBuilderConfiguration.getSnippetDefault(plugins); - - StructuredGraph calleeGraph; - if (LibGraalSupport.inLibGraalRuntime()) { - calleeGraph = getReplacements().getSnippet(method, null, null, null, false, null, invokeNode.getOptions()); - } else { - calleeGraph = new StructuredGraph.Builder(invokeNode.getOptions(), invokeNode.getDebug()).method(method).trackNodeSourcePosition( - invokeNode.graph().trackNodeSourcePosition()).setIsSubstitution(true).build(); - IntrinsicContext initialReplacementContext = new IntrinsicContext(method, method, getReplacements().getDefaultReplacementBytecodeProvider(), INLINE_AFTER_PARSING); - GraphBuilderPhase.Instance instance = createGraphBuilderInstance(config, OptimisticOptimizations.NONE, initialReplacementContext); - instance.apply(calleeGraph); - } + StructuredGraph calleeGraph = getReplacements().getSnippet(method, null, null, null, false, null, invokeNode.getOptions()); new DeadCodeEliminationPhase().apply(calleeGraph); - InliningUtil.inline(invoke, calleeGraph, false, method, reason, phase); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java index 240d54a188b9..638869f728d6 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/SnippetTemplate.java @@ -46,7 +46,6 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Objects; -import java.util.concurrent.atomic.AtomicReference; import java.util.function.Predicate; import org.graalvm.collections.EconomicMap; @@ -480,12 +479,12 @@ public class SnippetTemplate { * method that needs to be computed only once. The {@link SnippetInfo} should be created once * per snippet and then cached. */ - public abstract static class SnippetInfo { + public static final class SnippetInfo { - protected final ResolvedJavaMethod method; - protected final ResolvedJavaMethod original; - protected final LocationIdentity[] privateLocations; - protected final Object receiver; + private final ResolvedJavaMethod method; + private final ResolvedJavaMethod original; + private final LocationIdentity[] privateLocations; + private final Object receiver; public Object getReceiver() { return receiver; @@ -514,20 +513,22 @@ static boolean hasReceiver(ResolvedJavaMethod method) { private final TimerKey creationTimer; - protected final Snippet.SnippetType type; + private final Snippet.SnippetType type; - protected abstract SnippetParameterInfo info(); + private final SnippetParameterInfo snippetParameterInfo; - protected SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, Snippet.SnippetType type) { + private SnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, SnippetParameterInfo snippetParameterInfo, + Snippet.SnippetType type) { this.method = method; this.original = original; this.privateLocations = privateLocations; - instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName()); - instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName()); - creationCounter = DebugContext.counter("SnippetCreationCount[%s]", method.getName()); - creationTimer = DebugContext.timer("SnippetCreationTime[%s]", method.getName()); + this.instantiationCounter = DebugContext.counter("SnippetInstantiationCount[%s]", method.getName()); + this.instantiationTimer = DebugContext.timer("SnippetInstantiationTime[%s]", method.getName()); + this.creationCounter = DebugContext.counter("SnippetCreationCount[%s]", method.getName()); + this.creationTimer = DebugContext.timer("SnippetCreationTime[%s]", method.getName()); this.receiver = receiver; this.type = type; + this.snippetParameterInfo = snippetParameterInfo; } public boolean isPrivateLocation(LocationIdentity identity) { @@ -544,63 +545,32 @@ public ResolvedJavaMethod getMethod() { } public int getParameterCount() { - return info().getParameterCount(); + return snippetParameterInfo.getParameterCount(); } public boolean isConstantParameter(int paramIdx) { - return info().isConstantParameter(paramIdx); + return snippetParameterInfo.isConstantParameter(paramIdx); } public boolean isVarargsParameter(int paramIdx) { - return info().isVarargsParameter(paramIdx); + return snippetParameterInfo.isVarargsParameter(paramIdx); } public boolean isNonNullParameter(int paramIdx) { - return info().isNonNullParameter(paramIdx); + return snippetParameterInfo.isNonNullParameter(paramIdx); } public String getParameterName(int paramIdx) { - return info().getParameterName(paramIdx); - } - - @Override - public String toString() { - return getClass().getSimpleName() + ":" + method.format("%h.%n"); + return snippetParameterInfo.getParameterName(paramIdx); } - } - - protected static class LazySnippetInfo extends SnippetInfo { - protected final AtomicReference lazy = new AtomicReference<>(null); - protected LazySnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, Snippet.SnippetType type) { - super(method, original, privateLocations, receiver, type); + public SnippetInfo copyWith(ResolvedJavaMethod newMethod) { + return new SnippetInfo(newMethod, original, privateLocations, receiver, snippetParameterInfo, type); } @Override - protected SnippetParameterInfo info() { - if (lazy.get() == null) { - lazy.compareAndSet(null, new SnippetParameterInfo(method)); - } - return lazy.get(); - } - } - - public static class EagerSnippetInfo extends SnippetInfo { - protected final SnippetParameterInfo snippetParameterInfo; - - protected EagerSnippetInfo(ResolvedJavaMethod method, ResolvedJavaMethod original, LocationIdentity[] privateLocations, Object receiver, SnippetParameterInfo snippetParameterInfo, - Snippet.SnippetType type) { - super(method, original, privateLocations, receiver, type); - this.snippetParameterInfo = snippetParameterInfo; - } - - @Override - protected SnippetParameterInfo info() { - return snippetParameterInfo; - } - - public EagerSnippetInfo copyWith(ResolvedJavaMethod newMethod) { - return new EagerSnippetInfo(newMethod, original, privateLocations, receiver, snippetParameterInfo, type); + public String toString() { + return getClass().getSimpleName() + ":" + method.format("%h.%n"); } } @@ -962,12 +932,8 @@ protected SnippetInfo snippet(Providers providers, } providers.getReplacements().registerSnippet(javaMethod, original, receiver, GraalOptions.TrackNodeSourcePosition.getValue(options), options); LocationIdentity[] privateLocations = GraalOptions.SnippetCounters.getValue(options) ? SnippetCounterNode.addSnippetCounters(initialPrivateLocations) : initialPrivateLocations; - if (inRuntimeCode() || GraalOptions.EagerSnippets.getValue(options)) { - SnippetParameterInfo snippetParameterInfo = providers.getReplacements().getSnippetParameterInfo(javaMethod); - return new EagerSnippetInfo(javaMethod, original, privateLocations, receiver, snippetParameterInfo, type); - } else { - return new LazySnippetInfo(javaMethod, original, privateLocations, receiver, type); - } + SnippetParameterInfo snippetParameterInfo = providers.getReplacements().getSnippetParameterInfo(javaMethod); + return new SnippetInfo(javaMethod, original, privateLocations, receiver, snippetParameterInfo, type); } /** @@ -2929,34 +2895,17 @@ public String toString() { return buf.append(')').toString(); } - /** - * {@code true} if encoded snippets are in use in a hosted context. This is needed to disable - * assertions that are not supported with encoded snippets. {@code EncodedSnippets} is not - * referencable from this context, so this is the only way to check this fact. - */ - private static volatile boolean hostedEncodedSnippets = false; - - /** - * Notifies snippet templates whether snippets are encoded in a hosted context. If {@code true}, - * this call disables assertions that are not supported with encoded snippets. - * - * @param value whether snippets are encoded in a hosted context - */ - public static void setHostedEncodedSnippets(boolean value) { - hostedEncodedSnippets = value; - } - private static boolean checkTemplate(MetaAccessProvider metaAccess, Arguments args, ResolvedJavaMethod method) { Signature signature = method.getSignature(); int offset = args.info.hasReceiver() ? 1 : 0; for (int i = offset; i < args.info.getParameterCount(); i++) { if (args.info.isConstantParameter(i)) { JavaKind kind = signature.getParameterKind(i - offset); - assert inRuntimeCode() || hostedEncodedSnippets || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); + assert inRuntimeCode() || checkConstantArgument(metaAccess, method, signature, i - offset, args.info.getParameterName(i), args.values[i], kind); } else if (args.info.isVarargsParameter(i)) { assert args.values[i] instanceof Varargs : Assertions.errorMessage(args.values[i], args, method); Varargs varargs = (Varargs) args.values[i]; - assert inRuntimeCode() || hostedEncodedSnippets || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); + assert inRuntimeCode() || checkVarargs(metaAccess, method, signature, i - offset, args.info.getParameterName(i), varargs); } else if (args.info.isNonNullParameter(i)) { assert checkNonNull(method, args.info.getParameterName(i), args.values[i]); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java index 5b3828ca4b08..2761f74e80fa 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/replacements/TestSnippets.java @@ -90,4 +90,34 @@ public Templates(OptionValues options, Providers providers) { } } } + + public static class CounterTestSnippets implements Snippets { + @Snippet + public static void increase(@Snippet.ConstantParameter TestSnippetCounters counters) { + counters.increments.inc(); + counters.doubleIncrements.add(2); + } + + public static class Templates extends AbstractTemplates { + public final SnippetInfo increase; + + @SuppressWarnings("this-escape") + public Templates(OptionValues options, Providers providers) { + super(options, providers); + increase = snippet(providers, CounterTestSnippets.class, "increase"); + } + } + + public static class TestSnippetCounters { + public TestSnippetCounters(SnippetCounter.Group.Factory factory) { + SnippetCounter.Group allocations = factory.createSnippetCounterGroup("Increments"); + increments = new SnippetCounter(allocations, "increments", "number of increments"); + doubleIncrements = new SnippetCounter(allocations, "doubleIncrements", "number of increments times two"); + } + + public final SnippetCounter increments; + + public final SnippetCounter doubleIncrements; + } + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java index 38cb88f0eeb2..4c7b9b02218a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotTruffleCompilerImpl.java @@ -124,8 +124,30 @@ public static class Options { */ private final HotSpotGraalRuntimeProvider hotspotGraalRuntime; + /** + * Initialize and return Truffle backends. + * + * @param options option values + * @return a list of Truffle backends + */ public static List ensureBackendsInitialized(OptionValues options) { HotSpotGraalRuntimeProvider graalRuntime = (HotSpotGraalRuntimeProvider) getCompiler(options).getGraalRuntime(); + return ensureBackendsInitialized(options, graalRuntime); + } + + /** + * Initialize and return Truffle backends using the provided Graal runtime, which must match the + * {@link Options#TruffleCompilerConfiguration} or the host configuration if not set. + * + * @param options option values + * @param graalRuntime the Graal runtime + * @return a list of Truffle backends + */ + public static List ensureBackendsInitialized(OptionValues options, HotSpotGraalRuntimeProvider graalRuntime) { + if (Options.TruffleCompilerConfiguration.hasBeenSet(options)) { + GraalError.guarantee(graalRuntime.getCompilerConfigurationName().equals(Options.TruffleCompilerConfiguration.getValue(options)), + "the provided runtime must match the Truffle compiler configuration"); + } List backends = new ArrayList<>(); backends.add(createTruffleBackend(graalRuntime, options, null, null)); backends.add(createTruffleBackend(graalRuntime, options, null, EconomyCompilerConfigurationFactory.NAME)); diff --git a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java index aece96b5b7ea..deb8df3c7a15 100644 --- a/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java +++ b/substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java @@ -27,7 +27,6 @@ import java.util.HashSet; import java.util.Set; -import jdk.graal.compiler.core.common.GraalOptions; import jdk.graal.compiler.core.common.util.CompilationAlarm; import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.options.OptionKey; @@ -44,7 +43,6 @@ public final class IntentionallyUnsupportedOptions { static { unsupportedOptions.add(CompilerConfigurationFactory.Options.CompilerConfiguration); - unsupportedOptions.add(GraalOptions.EagerSnippets); unsupportedOptions.add(CompilationAlarm.Options.CompilationNoProgressPeriod); } 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 d7b07ee65504..1336fc434a0e 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 @@ -350,13 +350,7 @@ public NativeImageGenerator(ImageClassLoader loader, HostedOptionProvider option this.featureHandler = new FeatureHandler(); this.optionProvider = optionProvider; this.reporter = reporter; - /* - * Substrate VM parses all graphs, including snippets, early. We do not support bytecode - * parsing at run time. - */ - optionProvider.getHostedValues().put(GraalOptions.EagerSnippets, true); optionProvider.getHostedValues().put(CompilationAlarm.Options.CompilationNoProgressPeriod, 0D); - optionProvider.getRuntimeValues().put(GraalOptions.EagerSnippets, true); if (!optionProvider.getHostedValues().containsKey(BciBlockMapping.Options.MaxDuplicationFactor)) { /* diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java index 22837011f519..634c79351c32 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/AnalysisToHostedGraphTransplanter.java @@ -344,8 +344,8 @@ static Object replaceAnalysisObjects(Object obj, Node node, IdentityHashMap Date: Wed, 17 Sep 2025 14:30:24 +0200 Subject: [PATCH 39/49] Reapply "[GR-68990] [GR-69008] Fix graph equality when replaying libgraal compilation on jargraal and fix cache replacements" This reverts commit 85ece500855d66c84251cec06ebcfcfe200f791b. --- .../test/ReplayCompilationTest.java | 24 +++++++++++++++++ .../compiler/hotspot/EncodedSnippets.java | 11 +++++--- .../replacements/AssertionSnippets.java | 2 +- .../CompilerInterfaceDeclarations.java | 27 +++++++++++++++++++ .../proxy/HotSpotResolvedJavaTypeProxy.java | 2 +- 5 files changed, 60 insertions(+), 6 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java index 60eb1efb8085..fcc5bd708c58 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/replaycomp/test/ReplayCompilationTest.java @@ -38,6 +38,8 @@ import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; import com.oracle.truffle.api.Truffle; @@ -46,6 +48,7 @@ import jdk.graal.compiler.core.CompilationWrapper; import jdk.graal.compiler.core.GraalCompilerOptions; import jdk.graal.compiler.core.test.GraalCompilerTest; +import jdk.graal.compiler.debug.DebugCloseable; import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.LogStream; @@ -54,9 +57,11 @@ import jdk.graal.compiler.hotspot.CompilerConfigurationFactory; import jdk.graal.compiler.hotspot.HotSpotGraalCompiler; import jdk.graal.compiler.hotspot.HotSpotGraalCompilerFactory; +import jdk.graal.compiler.hotspot.HotSpotReplacementsImpl; import jdk.graal.compiler.hotspot.replaycomp.CompilerInterfaceDeclarations; import jdk.graal.compiler.hotspot.replaycomp.ReplayCompilationRunner; import jdk.graal.compiler.options.OptionValues; +import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.runtime.RuntimeProvider; import jdk.vm.ci.hotspot.HotSpotCompilationRequest; import jdk.vm.ci.hotspot.HotSpotCompilationRequestResult; @@ -69,6 +74,25 @@ * Tests for compilation recording and replay. */ public class ReplayCompilationTest extends GraalCompilerTest { + /** + * A separate encoded snippet scope is necessary in case the global encoded snippets have cache + * replacements. + */ + private static DebugCloseable snippetScope; + + @BeforeClass + public static void setup() { + Providers providers = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend().getProviders(); + HotSpotReplacementsImpl replacements = (HotSpotReplacementsImpl) providers.getReplacements(); + snippetScope = replacements.suppressEncodedSnippets(); + replacements.encode(getInitialOptions()); + } + + @AfterClass + public static void teardown() { + snippetScope.close(); + } + private static int[] lengthsSquared(List strings) { return strings.stream().mapToInt(String::length).map(i -> i * i).toArray(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java index 9acc8fffc452..73b2c868dd52 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/EncodedSnippets.java @@ -47,6 +47,7 @@ import jdk.graal.compiler.core.common.type.StampPair; import jdk.graal.compiler.core.common.type.SymbolicJVMCIReference; import jdk.graal.compiler.debug.DebugContext; +import jdk.graal.compiler.debug.DebugOptions; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.nodeinfo.Verbosity; import jdk.graal.compiler.nodes.ConstantNode; @@ -250,12 +251,14 @@ StructuredGraph getEncodedSnippet(ResolvedJavaMethod method, ResolvedJavaMethod declaringClass = replacements.getProviders().getMetaAccess().lookupJavaType(Object.class); } /* - * If this is a recorded/replayed compilation, we must not mutate the snippet objects. This - * ensures we record all relevant operations during recording and no proxies are stored in - * the snippet objects during replay. + * If there is a possibility of a recorded/replayed compilation, we must not mutate the + * snippet objects. During recording, this ensures that we record all relevant operations + * and the cached objects are resolved to proxies. During replay, this ensures that no + * proxies are stored in the snippet objects. */ boolean allowCacheReplacements = replacements.getProviders().getReplayCompilationSupport() == null && - GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose; + GraalCompilerOptions.CompilationFailureAction.getValue(options) != CompilationWrapper.ExceptionAction.Diagnose && + !DebugOptions.RecordForReplay.hasBeenSet(options); SymbolicEncodedGraph encodedGraph = new SymbolicEncodedGraph(snippetEncoding, startOffset, snippetObjects, allowCacheReplacements, snippetNodeClasses, data.originalMethod, declaringClass); return decodeSnippetGraph(encodedGraph, method, original, replacements, args, allowAssumptions, options, true); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java index 6d986a0e25cf..884eef48837b 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replacements/AssertionSnippets.java @@ -90,7 +90,7 @@ public void lower(AssertionNode assertionNode, LoweringTool tool) { Arguments args = new Arguments(graph.start() instanceof StubStartNode ? stubAssertion : assertion, graph, tool.getLoweringStage()); args.add("condition", assertionNode.condition()); args.add("message", - graph.unique(new ConstantNode(new CStringConstant("failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method() + ")"), + graph.unique(new ConstantNode(new CStringConstant("failed runtime assertion in snippet/stub: " + assertionNode.message() + " (" + graph.method().format("%H.%n(%p)") + ")"), StampFactory.pointer()))); args.add("l1", assertionNode.getL1()); args.add("l2", assertionNode.getL2()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index abf8b60ff0bb..999c66f0f743 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -30,6 +30,7 @@ import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; +import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; import java.lang.reflect.Proxy; @@ -48,6 +49,7 @@ import jdk.graal.compiler.core.common.CompilerProfiler; import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.hotspot.meta.HotSpotGraalConstantFieldProvider; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; @@ -66,6 +68,7 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SignatureProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; +import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -703,6 +706,7 @@ public static CompilerInterfaceDeclarations build() { } return List.of(); }) + .setFallbackInvocationHandler(HotSpotResolvedObjectTypeProxy.isInstanceMethod, CompilerInterfaceDeclarations::objectTypeIsInstanceFallback) .register(declarations); // Must come after HotSpotResolvedObjectType. Needed for HotSpotResolvedPrimitiveType. new RegistrationBuilder<>(HotSpotResolvedJavaType.class) @@ -921,4 +925,27 @@ private static ResolvedJavaType javaLangObjectSupplier(Object proxy, Compilation MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); return metaAccess.lookupJavaType(Object.class); } + + /** + * Implements a fallback for {@link HotSpotResolvedObjectType#isInstance} calls performed by + * {@link HotSpotGraalConstantFieldProvider} when replaying a libgraal compilation on jargraal. + *

+ * The provider performs checks like {@code getHotSpotVMConfigType().isInstance(receiver)}, + * which use snippet types on libgraal and HotSpot types on jargraal. Replay on jargraal needs + * to answer these queries when the receiver and argument are HotSpot proxies. + */ + @SuppressWarnings("unused") + @ExcludeFromJacocoGeneratedReport("related to replay of libgraal compilations on jargraal") + private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + HotSpotResolvedObjectType receiverType = (HotSpotResolvedObjectType) proxy; + if (!(args[0] instanceof HotSpotObjectConstant objectConstant)) { + return false; + } + HotSpotResolvedObjectType constantType = objectConstant.getType(); + if (isGraalClass(receiverType) && !isGraalClass(constantType)) { + // Assumes that only a Graal class can subtype a Graal class. + return false; + } + return receiverType.isAssignableFrom(constantType); + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java index a9eaefc24157..2dcd0363237a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -241,7 +241,7 @@ public final boolean isAssignableFrom(ResolvedJavaType other) { return (boolean) handle(isAssignableFromMethod, isAssignableFromInvokable, other); } - private static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); + public static final SymbolicMethod isInstanceMethod = method("isInstance", JavaConstant.class); private static final InvokableMethod isInstanceInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isInstance((JavaConstant) args[0]); @Override From 61d32136655170fcc86cd8a66fcff1aaa4d58338 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 14:30:28 +0200 Subject: [PATCH 40/49] Reapply "[GR-69070] Improve replayability with different compiler options" This reverts commit 2376d6772460ddd48e68073f8b9b6c84d253b55d. --- .../compiler/hotspot/HotSpotGraalRuntime.java | 2 +- .../hotspot/SymbolicSnippetEncoder.java | 3 + .../replaycomp/CompilationProxies.java | 7 + .../CompilerInterfaceDeclarations.java | 201 +++++++++++------- .../HotSpotProxyBackendFactory.java | 15 +- .../RecordedOperationPersistence.java | 112 ++++++---- .../RecordingCompilationProxies.java | 6 +- .../replaycomp/ReplayCompilationProxies.java | 41 +++- .../replaycomp/ReplayCompilationRunner.java | 2 + .../replaycomp/ReplayCompilationSupport.java | 31 +-- .../replaycomp/proxy/CompilationProxy.java | 25 ++- .../proxy/HotSpotConstantProxy.java | 88 ++++++++ .../proxy/HotSpotMetaspaceConstantProxy.java | 51 +---- .../proxy/HotSpotObjectConstantProxy.java | 48 +---- .../proxy/HotSpotResolvedJavaMethodProxy.java | 2 +- .../proxy/HotSpotResolvedJavaTypeProxy.java | 2 +- .../proxy/HotSpotResolvedObjectTypeProxy.java | 6 +- .../replaycomp/proxy/SignatureProxy.java | 4 +- 18 files changed, 379 insertions(+), 267 deletions(-) create mode 100644 compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java index 103d8ad3249e..9585292993a5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotGraalRuntime.java @@ -172,7 +172,7 @@ public GlobalMetrics getMetricValues() { throw new GraalError("No backend available for host architecture \"%s\"", hostArchitecture); } if (replayCompilationSupport != null) { - factory = replayCompilationSupport.decorateBackendFactory(factory); + factory = replayCompilationSupport.decorateBackendFactory(factory, jvmciRuntime); } hostBackend = registerBackend(factory.createBackend(this, compilerConfiguration, jvmciRuntime, null)); } 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 54676f8b4dd2..9c97f59fe2c9 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 @@ -62,6 +62,7 @@ import jdk.graal.compiler.graph.NodeMap; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.hotspot.meta.HotSpotProviders; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotResolvedObjectTypeProxy; import jdk.graal.compiler.hotspot.stubs.AbstractForeignCallStub; import jdk.graal.compiler.hotspot.stubs.ForeignCallStub; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; @@ -532,6 +533,8 @@ private synchronized EncodedSnippets encodeSnippets(DebugContext debug, Economic lookupSnippetType(SnippetTemplate.SnippetInfo.class); lookupSnippetType(ForeignCallStub.class); lookupSnippetType(HotSpotSpeculationLog.HotSpotSpeculation.class); + // Needed to pass constant type parameters to snippets when recording/replaying. + lookupSnippetType(HotSpotResolvedObjectTypeProxy.class); registerAbstractForeignCallStubInfo(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java index e419bc98e993..8b73cec11272 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilationProxies.java @@ -73,4 +73,11 @@ public interface CompilationProxies { * @return a debug closeable object representing the debug context */ DebugCloseable withDebugContext(DebugContext debugContext); + + /** + * Enters the context of a method compilation. + * + * @return a scope for the context + */ + DebugCloseable enterCompilationContext(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java index 999c66f0f743..8052190defd0 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/CompilerInterfaceDeclarations.java @@ -30,10 +30,11 @@ import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESPECIAL; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKESTATIC; import static jdk.graal.compiler.bytecode.Bytecodes.INVOKEVIRTUAL; +import static jdk.graal.compiler.core.common.NativeImageSupport.inRuntimeCode; import static jdk.graal.compiler.hotspot.HotSpotReplacementsImpl.isGraalClass; +import static jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy.wrapInvocationExceptions; import static jdk.graal.compiler.java.StableMethodNameFormatter.isMethodHandle; -import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collections; import java.util.Formattable; @@ -55,6 +56,7 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilerProfilerProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.ConstantPoolProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotCodeCacheProviderProxy; +import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotConstantReflectionProviderProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotMetaspaceConstantProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.HotSpotObjectConstantProxy; @@ -69,6 +71,8 @@ import jdk.graal.compiler.hotspot.replaycomp.proxy.SpeculationLogProxy; import jdk.graal.compiler.java.LambdaUtils; import jdk.graal.compiler.options.ExcludeFromJacocoGeneratedReport; +import jdk.vm.ci.code.CompiledCode; +import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; @@ -81,10 +85,14 @@ import jdk.vm.ci.hotspot.HotSpotResolvedJavaType; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; import jdk.vm.ci.hotspot.HotSpotResolvedPrimitiveType; +import jdk.vm.ci.hotspot.HotSpotRuntimeStub; import jdk.vm.ci.hotspot.HotSpotSignature; +import jdk.vm.ci.hotspot.HotSpotSpeculationLog; import jdk.vm.ci.hotspot.HotSpotVMConfigAccess; import jdk.vm.ci.meta.ConstantPool; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.MethodHandleAccessProvider; import jdk.vm.ci.meta.ProfilingInfo; @@ -221,10 +229,10 @@ public interface OperationResultSupplier { * @param proxy the proxy receiver * @param method the invoked method * @param args the arguments to the method - * @param singletonObjects a map of provider classes to instances + * @param metaAccess the host meta accces * @return the result of the operation */ - Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects); + Object apply(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess); } /** @@ -237,10 +245,12 @@ public interface LocalMirrorLocator { * found. * * @param proxy the proxy object - * @param singletonObjects a map of provider classes to instances + * @param metaAccess the unprofixied host meta access + * @param constantReflection the unproxified host constant reflection + * @param jvmciRuntime the JVMCI runtime * @return the local mirror or {@code null} */ - Object findLocalMirror(Object proxy, EconomicMap, Object> singletonObjects); + Object findLocalMirror(Object proxy, MetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotJVMCIRuntime jvmciRuntime); } /** @@ -335,15 +345,15 @@ public MethodStrategy findStrategy(CompilationProxy.SymbolicMethod method) { * @param proxy the proxy receiver object * @param method the invoked method * @param args the arguments passed to the invocation - * @param singletonObjects a map of provider classes to instances + * @param metaAccess the host meta access * @return the default value */ - public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + public Object findDefaultValue(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { MethodRegistration found = methods.get(method); if (found == null) { return null; } else if (found.defaultValueSupplier != null) { - return found.defaultValueSupplier.apply(proxy, method, args, singletonObjects); + return found.defaultValueSupplier.apply(proxy, method, args, metaAccess); } else { return found.defaultValue; } @@ -508,7 +518,7 @@ public RegistrationBuilder setDefaultValueSupplier(CompilationProxy.SymbolicM public RegistrationBuilder ensureRecorded(CompilationProxy.SymbolicMethod symbolicMethod, CompilationProxy.InvokableMethod invokableMethod, Object... arguments) { MethodRegistrationBuilder builder = findRegistrationBuilder(symbolicMethod); builder.callsToRecordArguments.add(arguments); - builder.invokableMethod = invokableMethod; + builder.invokableMethod = wrapInvocationExceptions(invokableMethod); return this; } @@ -638,7 +648,7 @@ public static CompilerInterfaceDeclarations build() { .setStrategy(HotSpotConstantReflectionProviderProxy.asJavaClassMethod, MethodStrategy.Passthrough) .setStrategy(HotSpotConstantReflectionProviderProxy.asObjectHubMethod, MethodStrategy.Passthrough) .setDefaultValueSupplier(HotSpotConstantReflectionProviderProxy.asJavaTypeMethod, - (proxy, method, args, singletonObjects) -> { + (proxy, method, args, metaAccess) -> { if (args[0] instanceof HotSpotMetaspaceConstant constant) { return constant.asResolvedJavaType(); } @@ -646,19 +656,16 @@ public static CompilerInterfaceDeclarations build() { }) .register(declarations); new RegistrationBuilder<>(MethodHandleAccessProvider.class) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); - return provider.getMethodHandleAccess(); - }) + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> + constantReflection.getMethodHandleAccess()) .register(declarations); new RegistrationBuilder<>(HotSpotMemoryAccessProvider.class) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - HotSpotConstantReflectionProvider provider = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); - return provider.getMemoryAccessProvider(); - }) + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> + constantReflection.getMemoryAccessProvider()) .register(declarations); new RegistrationBuilder<>(HotSpotCodeCacheProvider.class).setSingleton(true) .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.installCodeMethod, null) + .setDefaultValueSupplier(HotSpotCodeCacheProviderProxy.installCodeMethod, CompilerInterfaceDeclarations::installCodeReplacement) // Interpreter frame size is not tracked since the arguments are not serializable. .setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.interpreterFrameSizeMethod, 0) .register(declarations); @@ -670,20 +677,7 @@ public static CompilerInterfaceDeclarations build() { new RegistrationBuilder<>(HotSpotResolvedObjectType.class, HotSpotResolvedJavaType.class) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getNameMethod, HotSpotResolvedObjectTypeProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getModifiersMethod, HotSpotResolvedObjectTypeProxy.getModifiersInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; - Class clazz; - try { - clazz = Class.forName(type.toClassName()); - } catch (ClassNotFoundException e) { - return null; - } - if (Proxy.class.isAssignableFrom(clazz)) { - return null; - } - return metaAccess.lookupJavaType(clazz); - }) + .setLocalMirrorLocator(CompilerInterfaceDeclarations::findObjectTypeMirror) // getComponentType() is used by the default implementation of isArray(). .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) @@ -693,12 +687,15 @@ public static CompilerInterfaceDeclarations build() { HotSpotResolvedObjectTypeProxy.getInstanceFieldsInvokable, new Object[]{true}) // For snippet decoding .ensureRecorded(HotSpotResolvedObjectTypeProxy.getStaticFieldsMethod, HotSpotResolvedObjectTypeProxy.getStaticFieldsInvokable) // For snippet decoding .setDefaultValueStrategy(HotSpotResolvedObjectTypeProxy.getJavaKindMethod, JavaKind.Object) - .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, CompilerInterfaceDeclarations::javaLangObjectSupplier) + .setDefaultValueStrategy(HotSpotResolvedJavaTypeProxy.isPrimitiveMethod, false) + .setDefaultValueSupplier(HotSpotResolvedObjectTypeProxy.findLeastCommonAncestorMethod, (proxy1, method1, args1, metaAccess) -> metaAccess.lookupJavaType(Object.class)) .setDefaultValue(HotSpotResolvedObjectTypeProxy.isAssignableFromMethod, false) .ensureRecorded(HotSpotResolvedObjectTypeProxy.isInterfaceMethod, HotSpotResolvedObjectTypeProxy.isInterfaceInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.klassMethod, HotSpotResolvedObjectTypeProxy.klassInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getJavaMirrorMethod, HotSpotResolvedObjectTypeProxy.getJavaMirrorInvokable) .setDefaultValue(HotSpotResolvedObjectTypeProxy.isInitializedMethod, false) + .ensureRecorded(HotSpotResolvedObjectTypeProxy.isPrimaryTypeMethod, HotSpotResolvedObjectTypeProxy.isPrimaryTypeInvokable) // For InstanceOfSnippets after divergence + .setDefaultValue(HotSpotResolvedObjectTypeProxy.superCheckOffsetMethod, 0) // For InstanceOfSnippets after divergence .provideMethodCallsToRecord((input) -> { HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) input; if (!type.isArray() && !type.isInterface()) { @@ -713,7 +710,8 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaTypeProxy.getNameMethod, HotSpotResolvedJavaTypeProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedJavaTypeProxy.getJavaKindMethod, HotSpotResolvedJavaTypeProxy.getJavaKindInvokable) .ensureRecorded(HotSpotResolvedObjectTypeProxy.getComponentTypeMethod, HotSpotResolvedObjectTypeProxy.getComponentTypeInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { + .setDefaultValueStrategy(HotSpotResolvedJavaTypeProxy.isPrimitiveMethod, true) + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { HotSpotResolvedJavaType type = (HotSpotResolvedJavaType) proxy; return HotSpotResolvedPrimitiveType.forKind(type.getJavaKind()); }) @@ -727,8 +725,9 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaMethodProxy.isConstructorMethod, HotSpotResolvedJavaMethodProxy.isConstructorInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundMethod, HotSpotResolvedJavaMethodProxy.canBeStaticallyBoundInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getCodeMethod, HotSpotResolvedJavaMethodProxy.getCodeInvokable) + .setDefaultValue(HotSpotResolvedJavaMethodProxy.vtableEntryOffsetMethod, 0) // For LoadMethodNode lowering after divergence .setStrategy(HotSpotResolvedJavaMethodProxy.formatToMethod, MethodStrategy.DefaultValue) - .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, singletonObjects) -> { + .setDefaultValueSupplier(HotSpotResolvedJavaMethodProxy.formatToMethod, (proxy, method, args, metaAccess) -> { ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; Formatter formatter = (Formatter) args[0]; int flags = (int) args[1]; @@ -738,11 +737,11 @@ public static CompilerInterfaceDeclarations build() { return null; }) .ensureRecorded(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, HotSpotResolvedJavaMethodProxy.asStackTraceElementInvokable, -1) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, singletonObjects) -> { + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.asStackTraceElementMethod, (proxy, method, args, metaAccess) -> { ResolvedJavaMethod receiver = (ResolvedJavaMethod) proxy; return receiver.asStackTraceElement(-1); }) - .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, singletonObjects) -> { + .setFallbackInvocationHandler(HotSpotResolvedJavaMethodProxy.getCodeSizeMethod, (proxy, method, args, metaAccess) -> { byte[] code = ((ResolvedJavaMethod) proxy).getCode(); if (code == null) { return 0; @@ -752,22 +751,14 @@ public static CompilerInterfaceDeclarations build() { }) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getDeclaringClassMethod, HotSpotResolvedJavaMethodProxy.getDeclaringClassInvokable) .ensureRecorded(HotSpotResolvedJavaMethodProxy.getSignatureMethod, HotSpotResolvedJavaMethodProxy.getSignatureInvokable) - .setLocalMirrorLocator((proxy, singletonObjects) -> { + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { ResolvedJavaMethod method = (ResolvedJavaMethod) proxy; - String methodName = method.getName(); - String methodDescriptor = method.getSignature().toMethodDescriptor(); - ResolvedJavaType holder = method.getDeclaringClass(); - Class clazz; - try { - clazz = Class.forName(holder.toClassName()); - } catch (ClassNotFoundException e) { - return null; - } - if (Proxy.class.isAssignableFrom(clazz)) { + ResolvedJavaType holderMirror = findObjectTypeMirror(method.getDeclaringClass(), metaAccess, constantReflection, jvmciRuntime); + if (holderMirror == null) { return null; } - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType holderMirror = metaAccess.lookupJavaType(clazz); + String methodName = method.getName(); + String methodDescriptor = method.getSignature().toMethodDescriptor(); if (method.isConstructor()) { for (ResolvedJavaMethod candidate : holderMirror.getDeclaredConstructors()) { if (candidate.getSignature().toMethodDescriptor().equals(methodDescriptor)) { @@ -788,7 +779,7 @@ public static CompilerInterfaceDeclarations build() { .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationsMethod, MethodStrategy.Passthrough) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getDeclaredAnnotationsMethod, MethodStrategy.Passthrough) .setStrategy(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, MethodStrategy.Passthrough) - .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, singletonObjects) -> { + .setFallbackInvocationHandler(CompilationProxyBase.CompilationProxyAnnotatedBase.getAnnotationMethod, (proxy, method, args, metaAccess) -> { // The HostInliningPhase can query Truffle-related annotations during replay on jargraal. It is safe to return null. return null; }) @@ -836,14 +827,12 @@ public static CompilerInterfaceDeclarations build() { Signature signature = (Signature) input; int count = signature.getParameterCount(false); List calls = new ArrayList<>(); - CompilationProxy.SymbolicMethod symbolicMethod = new CompilationProxy.SymbolicMethod(Signature.class, "getParameterType", int.class, ResolvedJavaType.class); - CompilationProxy.InvokableMethod invokableMethod = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); for (int i = 0; i < count; i++) { - calls.add(new MethodCallToRecord(input, symbolicMethod, invokableMethod, new Object[]{i, null})); + calls.add(new MethodCallToRecord(input, SignatureProxy.getParameterTypeMethod, SignatureProxy.getParameterTypeInvokable, new Object[]{i, null})); } return calls; }) - .setLocalMirrorLocator((proxy, singletonObjects) -> { + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { Signature signature = (Signature) proxy; return new HotSpotSignature(HotSpotJVMCIRuntime.runtime(), signature.toMethodDescriptor()); }) @@ -856,47 +845,42 @@ public static CompilerInterfaceDeclarations build() { .ensureRecorded(HotSpotResolvedJavaFieldProxy.getNameMethod, HotSpotResolvedJavaFieldProxy.getNameInvokable) .ensureRecorded(HotSpotResolvedJavaFieldProxy.getModifiersMethod, HotSpotResolvedJavaFieldProxy.getModifiersInvokable) // For graph dumps (BinaryGraphPrinter) .ensureRecorded(HotSpotResolvedJavaFieldProxy.getTypeMethod, HotSpotResolvedJavaFieldProxy.getTypeInvokable) // For graph dumps (BinaryGraphPrinter) - .setLocalMirrorLocator((proxy, singletonObjects) -> { + .setLocalMirrorLocator((proxy, metaAccess, constantReflection, jvmciRuntime) -> { ResolvedJavaField field = (ResolvedJavaField) proxy; - ResolvedJavaType holderProxy = field.getDeclaringClass(); - Class holderClazz; - try { - holderClazz = Class.forName(holderProxy.toClassName()); - } catch (ClassNotFoundException e) { + ResolvedJavaType holderMirror = findObjectTypeMirror(field.getDeclaringClass(), metaAccess, constantReflection, jvmciRuntime); + if (holderMirror == null) { return null; } - if (Proxy.class.isAssignableFrom(holderClazz)) { - return null; - } - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - ResolvedJavaType holder = metaAccess.lookupJavaType(holderClazz); String name = field.getName(); boolean isStatic = field.isStatic(); - ResolvedJavaField[] fields = (isStatic) ? holder.getStaticFields() : holder.getInstanceFields(false); + ResolvedJavaField[] fields = (isStatic) ? holderMirror.getStaticFields() : holderMirror.getInstanceFields(false); for (ResolvedJavaField candidate : fields) { if (name.equals(candidate.getName())) { return candidate; } } - throw new IllegalStateException("Cannot find mirror for " + field + ": the local holder does not contain a matching field"); + return null; }) .register(declarations); new RegistrationBuilder<>(HotSpotObjectConstant.class) - .ensureRecorded(HotSpotObjectConstantProxy.toValueStringMethod, HotSpotObjectConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotObjectConstantProxy.isCompressedMethod, HotSpotObjectConstantProxy.isCompressedInvokable) - .ensureRecorded(HotSpotObjectConstantProxy.getTypeMethod, HotSpotObjectConstantProxy.getTypeInvokable) + .ensureRecorded(HotSpotConstantProxy.toValueStringMethod, HotSpotConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotConstantProxy.isCompressibleMethod, HotSpotConstantProxy.isCompressibleInvokable) + .ensureRecorded(HotSpotConstantProxy.isCompressedMethod, HotSpotConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotConstantProxy.compressMethod, HotSpotConstantProxy.compressInvokable) + .ensureRecorded(HotSpotConstantProxy.uncompressMethod, HotSpotConstantProxy.uncompressInvokable) + .setDefaultValueStrategy(HotSpotConstantProxy.isDefaultForKindMethod, false) .setDefaultValueStrategy(HotSpotObjectConstantProxy.isNullMethod, false) .setDefaultValueStrategy(HotSpotObjectConstantProxy.getJavaKindMethod, JavaKind.Object) - .setDefaultValueSupplier(HotSpotObjectConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) - .setDefaultValueSupplier(HotSpotObjectConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) .register(declarations); new RegistrationBuilder<>(HotSpotMetaspaceConstant.class) - .ensureRecorded(HotSpotMetaspaceConstantProxy.toValueStringMethod, HotSpotMetaspaceConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) - .ensureRecorded(HotSpotMetaspaceConstantProxy.isCompressedMethod, HotSpotMetaspaceConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotConstantProxy.toValueStringMethod, HotSpotConstantProxy.toValueStringInvokable) // For graph dumps (BinaryGraphPrinter) + .ensureRecorded(HotSpotConstantProxy.isCompressibleMethod, HotSpotConstantProxy.isCompressibleInvokable) + .ensureRecorded(HotSpotConstantProxy.isCompressedMethod, HotSpotConstantProxy.isCompressedInvokable) + .ensureRecorded(HotSpotConstantProxy.compressMethod, HotSpotConstantProxy.compressInvokable) + .ensureRecorded(HotSpotConstantProxy.uncompressMethod, HotSpotConstantProxy.uncompressInvokable) + .setDefaultValueStrategy(HotSpotConstantProxy.isDefaultForKindMethod, false) .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaTypeMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaTypeInvokable) .ensureRecorded(HotSpotMetaspaceConstantProxy.asResolvedJavaMethodMethod, HotSpotMetaspaceConstantProxy.asResolvedJavaMethodInvokable) - .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.compressMethod, (proxy, method, args, singletonObjects) -> proxy) - .setDefaultValueSupplier(HotSpotMetaspaceConstantProxy.uncompressMethod, (proxy, method, args, singletonObjects) -> proxy) .register(declarations); new RegistrationBuilder<>(HotSpotProfilingInfo.class) .setDefaultValueStrategy(ProfilingInfoProxy.setCompilerIRSizeMethod, false) @@ -912,7 +896,12 @@ public static CompilerInterfaceDeclarations build() { .register(declarations); new RegistrationBuilder<>(SpeculationLog.class) .setDefaultValue(SpeculationLogProxy.maySpeculateMethod, true) - .setDefaultValue(SpeculationLogProxy.speculateMethod, SpeculationLog.NO_SPECULATION) + .setDefaultValueSupplier(SpeculationLogProxy.speculateMethod, (Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) -> { + // Some callers expect to get an actual speculation rather than NO_SPECULATION. + SpeculationLog.SpeculationReason reason = (SpeculationLog.SpeculationReason) args[0]; + JavaConstant id = JavaConstant.forLong(-1); + return new HotSpotSpeculationLog.HotSpotSpeculation(reason, id, new byte[0]); + }) .register(declarations); new RegistrationBuilder<>(Predicate.class).setSingleton(true) .register(declarations); // Intrinsification trust predicate. @@ -920,10 +909,41 @@ public static CompilerInterfaceDeclarations build() { return declarations; } + /** + * Finds a local mirror for an object type proxy by resolving the class name on the host JVM. + * + * @param proxy the object type proxy + * @param metaAccess the host meta access + * @param constantReflection the host constant reflection + * @param jvmciRuntime the host JVMCI runtime + * @return the object type mirror or {@code null} if it cannot be resolved + */ @SuppressWarnings("unused") - private static ResolvedJavaType javaLangObjectSupplier(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { - MetaAccessProvider metaAccess = (MetaAccessProvider) singletonObjects.get(MetaAccessProvider.class); - return metaAccess.lookupJavaType(Object.class); + private static HotSpotResolvedObjectType findObjectTypeMirror(Object proxy, MetaAccessProvider metaAccess, HotSpotConstantReflectionProvider constantReflection, HotSpotJVMCIRuntime jvmciRuntime) { + HotSpotResolvedObjectType type = (HotSpotResolvedObjectType) proxy; + String typeName = type.getName(); + if (typeName.contains("$Proxy") || typeName.contains(".0x")) { + // Skip dynamic proxies and hidden classes, which have unstable names. + return null; + } + Class accessingClass = (inRuntimeCode()) ? Object.class : CompilerInterfaceDeclarations.class; + HotSpotResolvedObjectType accessingType = (HotSpotResolvedObjectType) metaAccess.lookupJavaType(accessingClass); + try { + JavaType result = jvmciRuntime.lookupType(typeName, accessingType, true); + if (result instanceof HotSpotResolvedObjectType mirror) { + /* + * Initialize the type to avoid reducing whole snippets to a deopt when replay + * diverges and depends on the mirrors (e.g., BoxingSnippets on libgraal). + */ + synchronized (CompilerInterfaceDeclarations.class) { + mirror.initialize(); + } + return mirror; + } + } catch (LinkageError | Exception ignored) { + // Ignore LinkageError or TranslatedException. + } + return null; } /** @@ -936,7 +956,7 @@ private static ResolvedJavaType javaLangObjectSupplier(Object proxy, Compilation */ @SuppressWarnings("unused") @ExcludeFromJacocoGeneratedReport("related to replay of libgraal compilations on jargraal") - private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, EconomicMap, Object> singletonObjects) { + private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { HotSpotResolvedObjectType receiverType = (HotSpotResolvedObjectType) proxy; if (!(args[0] instanceof HotSpotObjectConstant objectConstant)) { return false; @@ -948,4 +968,21 @@ private static boolean objectTypeIsInstanceFallback(Object proxy, CompilationPro } return receiverType.isAssignableFrom(constantType); } + + /** + * Implements {@link HotSpotCodeCacheProvider#installCode} for replay compilation. + */ + @SuppressWarnings("unused") + private static InstalledCode installCodeReplacement(Object proxy, CompilationProxy.SymbolicMethod method, Object[] args, MetaAccessProvider metaAccess) { + ResolvedJavaMethod installedCodeOwner = (ResolvedJavaMethod) args[0]; + CompiledCode compiledCode = (CompiledCode) args[1]; + InstalledCode installedCode = (InstalledCode) args[2]; + if (installedCodeOwner == null) { + // This is an installation of a stub which was not compiled during recording. + return new HotSpotRuntimeStub(compiledCode.toString()); // ExcludeFromJacocoGeneratedReport + } else { + // For method installations, the return value is not important. + return installedCode; + } + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java index 7e8ced5f0548..a97408fd5c0a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/HotSpotProxyBackendFactory.java @@ -32,6 +32,7 @@ import jdk.graal.compiler.hotspot.meta.HotSpotHostForeignCallsProvider; import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.MemoryAccessProvider; @@ -48,11 +49,12 @@ class HotSpotProxyBackendFactory implements HotSpotBackendFactoryDecorators { private final ReplayCompilationSupport replayCompilationSupport; - private MetaAccessProvider metaAccessProviderProxy; + private final HotSpotJVMCIRuntime jvmciRuntime; - HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport) { + HotSpotProxyBackendFactory(CompilationProxies proxies, ReplayCompilationSupport replayCompilationSupport, HotSpotJVMCIRuntime jvmciRuntime) { this.proxies = proxies; this.replayCompilationSupport = replayCompilationSupport; + this.jvmciRuntime = jvmciRuntime; } @Override @@ -62,14 +64,13 @@ public void afterJVMCIProvidersCreated() { * mirrors. We must identify the local mirrors before initialization continues to avoid * creating duplicate proxies for equivalent local mirrors. */ - replayCompilationSupport.findLocalMirrors(); + replayCompilationSupport.findLocalMirrors(jvmciRuntime); } @Override public MetaAccessProvider decorateMetaAccessProvider(MetaAccessProvider metaAccess) { // Do not record snippet types in libgraal - decorate the JVMCI meta access only. - metaAccessProviderProxy = (MetaAccessProvider) proxies.proxify(metaAccess); - return new HotSpotSnippetMetaAccessProvider(metaAccessProviderProxy); + return new HotSpotSnippetMetaAccessProvider((MetaAccessProvider) proxies.proxify(metaAccess)); } @Override @@ -79,7 +80,7 @@ public HotSpotConstantReflectionProvider decorateConstantReflectionProvider(HotS return new DecoratedConstantReflectionProvider(delegate); } - private final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { + private static final class DecoratedConstantReflectionProvider extends HotSpotConstantReflectionProvider { private final HotSpotConstantReflectionProvider delegate; private DecoratedConstantReflectionProvider(HotSpotConstantReflectionProvider delegate) { @@ -142,7 +143,7 @@ public ResolvedJavaType asJavaType(Constant constant) { * Avoid recording an operation with the snippet constant, which is not * serializable. */ - return metaAccessProviderProxy.lookupJavaType(objectConstant.asObject(Object.class).getClass()); + return objectConstant.asObject(ResolvedJavaType.class); } else { return delegate.asJavaType(constant); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java index 1e31d9d44721..11e96f435754 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordedOperationPersistence.java @@ -144,6 +144,20 @@ private interface RecursiveDeserializer { Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException; Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException; + + /** + * Sets the {@link Architecture} parsed by this deserializer. + * + * @param arch the architecture + */ + void setArchitecture(Architecture arch); + + /** + * Gets the {@link Architecture} parsed by this deserializer. + * + * @return the architecture + */ + Architecture getArchitecture(); } private sealed interface ObjectSerializer { @@ -805,7 +819,6 @@ public Object deserialize(EconomicMap json, RecursiveDeserialize } private static final class RegisterSerializer implements ObjectSerializer { - @Override public Class clazz() { return Register.class; @@ -820,20 +833,17 @@ public String tag() { public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, RecursiveSerializer serializer) throws IOException { Register register = (Register) instance; objectBuilder.append("number", register.number); - objectBuilder.append("name", register.name); - objectBuilder.append("encoding", register.encoding); - objectBuilder.append("catName", register.getRegisterCategory().toString()); - objectBuilder.append("containsRef", register.mayContainReference()); } @Override - public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) { + public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { int number = (int) json.get("number"); - String name = (String) json.get("name"); - int encoding = (int) json.get("encoding"); - String catName = (String) json.get("catName"); - boolean containsRef = (boolean) json.get("containsRef"); - return new Register(number, encoding, name, new Register.RegisterCategory(catName, containsRef)); + for (Register register : deserializer.getArchitecture().getRegisters()) { + if (register.number == number) { + return register; + } + } + throw new DeserializationException(this, json, "Register not found"); } } @@ -1687,12 +1697,14 @@ public void serialize(Object instance, JsonBuilder.ObjectBuilder objectBuilder, public Object deserialize(EconomicMap json, RecursiveDeserializer deserializer, ProxyFactory proxyFactory) throws DeserializationException { String name = (String) json.get("name"); EnumSet features = (EnumSet) deserializer.deserialize(json.get("features"), proxyFactory); - return switch (name) { + Architecture architecture = switch (name) { case "AMD64" -> new AMD64((EnumSet) features); case "riscv64" -> new RISCV64((EnumSet) features); case "aarch64" -> new AArch64((EnumSet) features); default -> throw new IllegalStateException("Unexpected value: " + name); }; + deserializer.setArchitecture(architecture); + return architecture; } } @@ -1932,41 +1944,55 @@ public void dump(RecordedCompilationUnit compilationUnit, JsonWriter writer) thr recursiveSerializer.serialize(compilationUnit, writer.valueBuilder(), RecordedCompilationUnitSerializer.TAG); } - private final RecursiveDeserializer recursiveDeserializer = new RecursiveDeserializer() { - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - String tag = (String) map.get("tag"); - if (tag == null) { - throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); - } - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); + private RecursiveDeserializer createRecursiveDeserializer() { + return new RecursiveDeserializer() { + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + String tag = (String) map.get("tag"); + if (tag == null) { + throw new IllegalArgumentException("The JSON map does not contain a tag: " + map); + } + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); + } + return deserializer.deserialize(map, this, proxyFactory); + } else { + return json; } - return deserializer.deserialize(map, this, proxyFactory); - } else { - return json; } - } - @Override - @SuppressWarnings("unchecked") - public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { - if (json instanceof EconomicMap) { - EconomicMap map = (EconomicMap) json; - ObjectSerializer deserializer = tagSerializers.get(tag); - if (deserializer == null) { - throw new IllegalArgumentException("No deserializer registered for tag " + tag); + @Override + @SuppressWarnings("unchecked") + public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) throws DeserializationException { + if (json instanceof EconomicMap) { + EconomicMap map = (EconomicMap) json; + ObjectSerializer deserializer = tagSerializers.get(tag); + if (deserializer == null) { + throw new IllegalArgumentException("No deserializer registered for tag " + tag); + } + return deserializer.deserialize(map, this, proxyFactory); + } else { + throw new IllegalArgumentException("Expected a map."); } - return deserializer.deserialize(map, this, proxyFactory); - } else { - throw new IllegalArgumentException("Expected a map."); } - } - }; + + private Architecture architecture; + + @Override + public void setArchitecture(Architecture arch) { + architecture = arch; + } + + @Override + public Architecture getArchitecture() { + return architecture; + } + }; + } /** * Loads a recorded compilation unit from the given reader. @@ -1979,6 +2005,6 @@ public Object deserialize(Object json, ProxyFactory proxyFactory, String tag) th */ public RecordedCompilationUnit load(Reader source, ProxyFactory proxyFactory) throws IOException, DeserializationException { JsonParser parser = new JsonParser(source); - return (RecordedCompilationUnit) recursiveDeserializer.deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); + return (RecordedCompilationUnit) createRecursiveDeserializer().deserialize(parser.parse(), proxyFactory, RecordedCompilationUnitSerializer.TAG); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java index d264db2bd57b..2b1db7602c46 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java @@ -139,11 +139,7 @@ public List collectOperationsForSerializati return recorder.getCurrentRecordedOperations(); } - /** - * Enters the context of a method compilation for the current compilation thread. - * - * @return a scope for the context - */ + @Override public DebugCloseable enterCompilationContext() { return recorder.enterCompilationContext(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java index 47b6fcc4d06b..af7efd89df89 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationProxies.java @@ -41,6 +41,8 @@ import jdk.graal.compiler.debug.GlobalMetrics; import jdk.graal.compiler.debug.GraalError; import jdk.graal.compiler.debug.TimerKey; +import jdk.graal.compiler.hotspot.CompilationContext; +import jdk.graal.compiler.hotspot.HotSpotGraalServices; import jdk.graal.compiler.hotspot.Platform; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxy; import jdk.graal.compiler.hotspot.replaycomp.proxy.CompilationProxyBase; @@ -49,7 +51,10 @@ import jdk.graal.compiler.options.OptionType; import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.code.TargetDescription; +import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; import jdk.vm.ci.meta.Constant; +import jdk.vm.ci.meta.MetaAccessProvider; //JaCoCo Exclude @@ -66,7 +71,7 @@ * memory usage low, which is important when replaying many compilations on libgraal and * benchmarking compile time. *

- * It is necessary to call {@link #findLocalMirrors()} after the operations are loaded and JVMCI + * It is necessary to call {@link #findLocalMirrors} after the operations are loaded and JVMCI * providers are created. The local mirrors may be required during a replayed compilation to query * information from the local VM, which is needed for snippet parsing. * @@ -143,6 +148,11 @@ public void setLocalMirror(Object newLocalMirror) { */ private final EconomicMap, Object> singletonObjects; + /** + * The host meta access provider. + */ + private MetaAccessProvider hostMetaAccess; + /** * Proxifies and unproxifies composite objects. */ @@ -214,6 +224,17 @@ public DebugCloseable withDebugContext(DebugContext debugContext) { }; } + @Override + public DebugCloseable enterCompilationContext() { + // The handles created during replay are cached across compilations. + CompilationContext context = HotSpotGraalServices.enterGlobalCompilationContext(); + if (context == null) { + return DebugCloseable.VOID_CLOSEABLE; + } else { + return context::close; + } + } + /** * Loads the recorded operations from a collection. * @@ -330,14 +351,17 @@ private static Object intern(Object object, EconomicMap internPo *

* During snippet parsing, the compiler may discover a JVMCI object which has no matching proxy. * For such objects, local-only proxies are created using {@link #proxify(Object)}. + * + * @param jvmciRuntime the JVMCI runtime */ - public void findLocalMirrors() { + public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) { + HotSpotConstantReflectionProvider constantReflection = (HotSpotConstantReflectionProvider) singletonObjects.get(HotSpotConstantReflectionProvider.class); var cursor = createdProxies.getEntries(); while (cursor.advance()) { CompilationProxy proxy = cursor.getKey(); CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(proxy); if (registration.mirrorLocator() != null) { - Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, singletonObjects); + Object localMirror = registration.mirrorLocator().findLocalMirror(proxy, hostMetaAccess, constantReflection, jvmciRuntime); if (localMirror != null) { Object previousProxy = localMirrorToProxy.put(localMirror, proxy); GraalError.guarantee(previousProxy == null, "there must be at most one proxy instance for an object"); @@ -402,6 +426,9 @@ public CompilationProxy proxify(Object input) { localMirrorToProxy.put(input, proxy); if (registration.singleton()) { singletonObjects.put(registration.clazz(), input); + if (input instanceof MetaAccessProvider metaAccess) { + hostMetaAccess = metaAccess; + } } return proxy; } @@ -461,13 +488,13 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r if (proxyInfo.localMirror == null) { CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess)); } } GraalError.guarantee(proxyInfo.localMirror != null, "a proxy with passthrough strategy must have a local mirror or fallback handler"); return callback.invoke(proxyInfo.localMirror, args); } else if (strategy == CompilerInterfaceDeclarations.MethodStrategy.DefaultValue) { - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess)); } Object result = findResult(proxyInfo, method, args); if (result != SpecialResultMarker.NO_RESULT_MARKER) { @@ -495,7 +522,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r } CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method); if (handler != null) { - return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, singletonObjects)); + return proxyMapper.proxifyRecursive(handler.apply(proxy, method, args, hostMetaAccess)); } if (args != null) { for (Object arg : args) { @@ -507,7 +534,7 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r if (divergenceIsFailure) { failOnDivergence(proxy, proxyInfo, method, args); } - return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, singletonObjects)); + return proxyMapper.proxifyRecursive(registration.findDefaultValue(proxy, method, args, hostMetaAccess)); } }); if (registration.singleton()) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java index 98e14350887a..28c0ca445ef5 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationRunner.java @@ -181,6 +181,7 @@ public static ExitStatus run(String[] args, PrintStream out) { codeHash = codeHash * 31 + Arrays.hashCode(replayResult.replayedArtifacts().result().getTargetCode()); } catch (Exception e) { out.println("Replay failed: " + e); + e.printStackTrace(out); return ExitStatus.Failure; } } @@ -206,6 +207,7 @@ public static ExitStatus run(String[] args, PrintStream out) { task.setFailureReason(failure.getMessage()); } catch (Exception e) { out.println("Replay failed: " + e); + e.printStackTrace(out); return ExitStatus.Failure; } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java index 2ab23bbaecae..564687fbdbef 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/ReplayCompilationSupport.java @@ -90,7 +90,7 @@ * *

* Local Mirrors. During replay, we search for equivalent JVMCI objects for some of the - * proxies ({@link #findLocalMirrors()}). This is useful when the compiler queries information that + * proxies ({@link #findLocalMirrors}). This is useful when the compiler queries information that * was not recorded, including the information used to process snippets. There are also local-only * proxies that do not originate from the recorded JSON but are instead created from local JVMCI * objects (created using {@link CompilationProxies#proxify}). The exact rules when operations are @@ -263,18 +263,16 @@ public DebugCloseable withDebugContext(DebugContext debug) { * @return a debug closeable that should be closed after the compilation */ public DebugCloseable enterCompilationContext(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { - if (proxies instanceof RecordingCompilationProxies recordingCompilationProxies) { - DebugCloseable context = recordingCompilationProxies.enterCompilationContext(); - return () -> { - try { + DebugCloseable context = proxies.enterCompilationContext(); + return () -> { + try { + if (proxies instanceof RecordingCompilationProxies) { serializeRecordedCompilation(originalRequest, initialOptions); - } finally { - context.close(); } - }; - } else { - return DebugCloseable.VOID_CLOSEABLE; - } + } finally { + context.close(); + } + }; } private void serializeRecordedCompilation(HotSpotCompilationRequest originalRequest, OptionValues initialOptions) { @@ -322,10 +320,12 @@ public boolean finalizeForeignCallLinkage(ForeignCallSignature signature, HotSpo * Finds local mirrors for the parsed proxies during replay compilation. This should be invoked * just after the core JVMCI providers are created because they are needed to look up the * mirrors. + * + * @param jvmciRuntime the JVMCI runtime */ - public void findLocalMirrors() { + public void findLocalMirrors(HotSpotJVMCIRuntime jvmciRuntime) { if (proxies instanceof ReplayCompilationProxies replayCompilationProxies) { - replayCompilationProxies.findLocalMirrors(); + replayCompilationProxies.findLocalMirrors(jvmciRuntime); } } @@ -333,10 +333,11 @@ public void findLocalMirrors() { * Decorates a backend factory. * * @param factory the backend factory to decorate + * @param jvmciRuntime the JVMCI runtime * @return the decorated backend factory */ - public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory) { - return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this)); + public HotSpotBackendFactory decorateBackendFactory(HotSpotBackendFactory factory, HotSpotJVMCIRuntime jvmciRuntime) { + return new HotSpotDecoratedBackendFactory(factory, new HotSpotProxyBackendFactory(proxies, this, jvmciRuntime)); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java index 35eb865bf83f..c1af98865630 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/CompilationProxy.java @@ -229,13 +229,7 @@ interface InvocationHandler { */ static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod method, InvokableMethod invokable, Object... args) { try { - return handler.handle(proxy, method, (Object receiver, Object[] actualArgs) -> { - try { - return invokable.invoke(receiver, actualArgs); - } catch (Throwable e) { - throw new InvocationTargetException(e); - } - }, (args.length == 0) ? null : args); + return handler.handle(proxy, method, wrapInvocationExceptions(invokable), (args.length == 0) ? null : args); } catch (RuntimeException | Error e) { throw e; } catch (Throwable e) { @@ -243,6 +237,23 @@ static Object handle(InvocationHandler handler, Object proxy, SymbolicMethod met } } + /** + * Returns a new invokable method that wraps the exceptions thrown by the provided invokable + * method. + * + * @param invokable an invokable method that can throw an unwrapped exception + * @return an invokable method that can throw an {@link InvocationTargetException} + */ + static InvokableMethod wrapInvocationExceptions(InvokableMethod invokable) { + return (Object receiver, Object[] actualArgs) -> { + try { + return invokable.invoke(receiver, actualArgs); + } catch (Throwable e) { + throw new InvocationTargetException(e); + } + }; + } + /** * Creates a new compilation proxy instance for the specified class and invocation handler. * diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java new file mode 100644 index 000000000000..9f644e8fbe17 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotConstantProxy.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.graal.compiler.hotspot.replaycomp.proxy; + +import jdk.vm.ci.hotspot.HotSpotConstant; +import jdk.vm.ci.meta.Constant; + +//JaCoCo Exclude + +public sealed class HotSpotConstantProxy extends CompilationProxyBase implements HotSpotConstant permits HotSpotMetaspaceConstantProxy, HotSpotObjectConstantProxy { + HotSpotConstantProxy(InvocationHandler handler) { + super(handler); + } + + private static SymbolicMethod method(String name, Class... params) { + return new SymbolicMethod(HotSpotConstant.class, name, params); + } + + public static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); + private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isDefaultForKind(); + + @Override + public boolean isDefaultForKind() { + return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + } + + public static final SymbolicMethod toValueStringMethod = method("toValueString"); + public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotConstant) receiver).toValueString(); + + @Override + public String toValueString() { + return (String) handle(toValueStringMethod, toValueStringInvokable); + } + + public static final SymbolicMethod isCompressedMethod = method("isCompressed"); + public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isCompressed(); + + @Override + public boolean isCompressed() { + return (boolean) handle(isCompressedMethod, isCompressedInvokable); + } + + public static final SymbolicMethod isCompressibleMethod = method("isCompressible"); + public static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotConstant) receiver).isCompressible(); + + @Override + public boolean isCompressible() { + return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); + } + + public static final SymbolicMethod compressMethod = method("compress"); + public static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotConstant) receiver).compress(); + + @Override + public Constant compress() { + return (Constant) handle(compressMethod, compressInvokable); + } + + public static final SymbolicMethod uncompressMethod = method("uncompress"); + public static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotConstant) receiver).uncompress(); + + @Override + public Constant uncompress() { + return (Constant) handle(uncompressMethod, uncompressInvokable); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java index 52599c0f2c72..7f31474d396a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotMetaspaceConstantProxy.java @@ -27,11 +27,10 @@ import jdk.vm.ci.hotspot.HotSpotMetaspaceConstant; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; -import jdk.vm.ci.meta.Constant; //JaCoCo Exclude -public final class HotSpotMetaspaceConstantProxy extends CompilationProxyBase implements HotSpotMetaspaceConstant { +public final class HotSpotMetaspaceConstantProxy extends HotSpotConstantProxy implements HotSpotMetaspaceConstant { HotSpotMetaspaceConstantProxy(InvocationHandler handler) { super(handler); } @@ -40,54 +39,6 @@ private static SymbolicMethod method(String name, Class... params) { return new SymbolicMethod(HotSpotMetaspaceConstant.class, name, params); } - private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); - private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isDefaultForKind(); - - @Override - public boolean isDefaultForKind() { - return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); - } - - public static final SymbolicMethod toValueStringMethod = method("toValueString"); - public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).toValueString(); - - @Override - public String toValueString() { - return (String) handle(toValueStringMethod, toValueStringInvokable); - } - - public static final SymbolicMethod isCompressedMethod = method("isCompressed"); - public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressed(); - - @Override - public boolean isCompressed() { - return (boolean) handle(isCompressedMethod, isCompressedInvokable); - } - - private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); - private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).isCompressible(); - - @Override - public boolean isCompressible() { - return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); - } - - public static final SymbolicMethod compressMethod = method("compress"); - private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).compress(); - - @Override - public Constant compress() { - return (Constant) handle(compressMethod, compressInvokable); - } - - public static final SymbolicMethod uncompressMethod = method("uncompress"); - private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).uncompress(); - - @Override - public Constant uncompress() { - return (Constant) handle(uncompressMethod, uncompressInvokable); - } - public static final SymbolicMethod asResolvedJavaTypeMethod = method("asResolvedJavaType"); public static final InvokableMethod asResolvedJavaTypeInvokable = (receiver, args) -> ((HotSpotMetaspaceConstant) receiver).asResolvedJavaType(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java index 034db556df9d..1b96b42a1b90 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotObjectConstantProxy.java @@ -33,7 +33,7 @@ //JaCoCo Exclude -public final class HotSpotObjectConstantProxy extends CompilationProxyBase implements HotSpotObjectConstant { +public final class HotSpotObjectConstantProxy extends HotSpotConstantProxy implements HotSpotObjectConstant { HotSpotObjectConstantProxy(InvocationHandler handler) { super(handler); } @@ -42,22 +42,6 @@ private static SymbolicMethod method(String name, Class... params) { return new SymbolicMethod(HotSpotObjectConstant.class, name, params); } - public static final SymbolicMethod compressMethod = method("compress"); - private static final InvokableMethod compressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).compress(); - - @Override - public JavaConstant compress() { - return (JavaConstant) handle(compressMethod, compressInvokable); - } - - public static final SymbolicMethod uncompressMethod = method("uncompress"); - private static final InvokableMethod uncompressInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).uncompress(); - - @Override - public JavaConstant uncompress() { - return (JavaConstant) handle(uncompressMethod, uncompressInvokable); - } - public static final SymbolicMethod getTypeMethod = method("getType"); public static final InvokableMethod getTypeInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).getType(); @@ -172,35 +156,13 @@ public double asDouble() { return (double) handle(asDoubleMethod, asDoubleInvokable); } - public static final SymbolicMethod isCompressedMethod = method("isCompressed"); - public static final InvokableMethod isCompressedInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressed(); - - @Override - public boolean isCompressed() { - return (boolean) handle(isCompressedMethod, isCompressedInvokable); - } - - private static final SymbolicMethod isCompressibleMethod = method("isCompressible"); - private static final InvokableMethod isCompressibleInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isCompressible(); - @Override - public boolean isCompressible() { - return (boolean) handle(isCompressibleMethod, isCompressibleInvokable); - } - - private static final SymbolicMethod isDefaultForKindMethod = method("isDefaultForKind"); - private static final InvokableMethod isDefaultForKindInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).isDefaultForKind(); - - @Override - public boolean isDefaultForKind() { - return (boolean) handle(isDefaultForKindMethod, isDefaultForKindInvokable); + public JavaConstant compress() { + return (JavaConstant) super.compress(); } - public static final SymbolicMethod toValueStringMethod = method("toValueString"); - public static final InvokableMethod toValueStringInvokable = (receiver, args) -> ((HotSpotObjectConstant) receiver).toValueString(); - @Override - public String toValueString() { - return (String) handle(toValueStringMethod, toValueStringInvokable); + public JavaConstant uncompress() { + return (JavaConstant) super.uncompress(); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java index a81654130ee6..e548431b9dd2 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaMethodProxy.java @@ -372,7 +372,7 @@ public boolean hasCompiledCodeAtLevel(int level) { return (boolean) handle(hasCompiledCodeAtLevelMethod, hasCompiledCodeAtLevelInvokable, level); } - private static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); + public static final SymbolicMethod vtableEntryOffsetMethod = method("vtableEntryOffset", ResolvedJavaType.class); private static final InvokableMethod vtableEntryOffsetInvokable = (receiver, args) -> ((HotSpotResolvedJavaMethod) receiver).vtableEntryOffset((ResolvedJavaType) args[0]); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java index 2dcd0363237a..e18ae3bd4bb3 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedJavaTypeProxy.java @@ -281,7 +281,7 @@ public final HotSpotResolvedObjectType findLeastCommonAncestor(ResolvedJavaType return (HotSpotResolvedObjectType) handle(findLeastCommonAncestorMethod, findLeastCommonAncestorInvokable, otherType); } - private static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); + public static final SymbolicMethod isPrimitiveMethod = method("isPrimitive"); private static final InvokableMethod isPrimitiveInvokable = (receiver, args) -> ((HotSpotResolvedJavaType) receiver).isPrimitive(); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java index 7e1d52812e29..053daae2c5f1 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/HotSpotResolvedObjectTypeProxy.java @@ -89,15 +89,15 @@ public Constant klass() { return (Constant) handle(klassMethod, klassInvokable); } - private static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); - private static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); + public static final SymbolicMethod isPrimaryTypeMethod = method("isPrimaryType"); + public static final InvokableMethod isPrimaryTypeInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).isPrimaryType(); @Override public boolean isPrimaryType() { return (boolean) handle(isPrimaryTypeMethod, isPrimaryTypeInvokable); } - private static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); + public static final SymbolicMethod superCheckOffsetMethod = method("superCheckOffset"); private static final InvokableMethod superCheckOffsetInvokable = (receiver, args) -> ((HotSpotResolvedObjectType) receiver).superCheckOffset(); @Override diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java index 935e03bf1934..4e8c6b612de7 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/proxy/SignatureProxy.java @@ -47,8 +47,8 @@ public int getParameterCount(boolean rec) { return (int) handle(getParameterCountMethod, getParameterCountInvokable, rec); } - private static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); - private static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); + public static final SymbolicMethod getParameterTypeMethod = method("getParameterType", int.class, ResolvedJavaType.class); + public static final InvokableMethod getParameterTypeInvokable = (receiver, args) -> ((Signature) receiver).getParameterType((int) args[0], (ResolvedJavaType) args[1]); @Override public JavaType getParameterType(int index, ResolvedJavaType accessingClass) { From e055fb2fec8b1578efe720f0a70edbf8b8cd8b3c Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Tue, 8 Jul 2025 22:34:02 +0200 Subject: [PATCH 41/49] Adapt JDK-8361569: [JVMCI] Further refine JVMCI-compiled nmethod that should not collect deoptimiztaion profile (cherry picked from commit 106d7202fcff1518c0c139700907b7fb0007e564) --- .../compiler/core/test/GraalCompilerTest.java | 12 ++--- .../core/test/tutorial/InvokeGraal.java | 2 +- .../test/DeoptimizeReasonAccountingTest.java | 2 +- .../hotspot/test/JVMCIInfopointErrorTest.java | 2 +- .../test/DeoptimizeOnIntegerExactTest.java | 4 +- .../graal/compiler/core/target/Backend.java | 48 ++----------------- .../compiler/hotspot/CompilationTask.java | 3 ++ .../aarch64/AArch64HotSpotBackend.java | 3 +- .../meta/UnimplementedGraalIntrinsics.java | 4 +- .../graal/compiler/hotspot/stubs/Stub.java | 2 +- .../compiler/truffle/TruffleCompilerImpl.java | 2 +- .../jvmci/DummyCodeCacheProvider.java | 2 +- .../IsolateAwareCodeCacheProvider.java | 6 +-- .../meta/SubstrateCodeCacheProvider.java | 4 +- .../hosted/code/HostedCodeCacheProvider.java | 4 +- 15 files changed, 29 insertions(+), 71 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java index a60f09de8c86..5f8d751becf5 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/GraalCompilerTest.java @@ -1009,7 +1009,7 @@ protected Result test(ResolvedJavaMethod method, Object receiver, Object... args protected Result test(OptionValues options, ResolvedJavaMethod method, Object receiver, Object... args) { Result expect = executeExpected(method, receiver, args); if (getCodeCache() != null) { - testAgainstExpected(options, method, expect, receiver, args); + testAgainstExpected(options, method, expect, CollectionsUtil.setOf(), receiver, args); } return expect; } @@ -1035,10 +1035,6 @@ protected final void testAgainstExpected(ResolvedJavaMethod method, Result expec testAgainstExpected(getInitialOptions(), method, expect, CollectionsUtil.setOf(), receiver, args); } - protected void testAgainstExpected(ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { - testAgainstExpected(getInitialOptions(), method, expect, shouldNotDeopt, receiver, args); - } - protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Object receiver, Object... args) { testAgainstExpected(options, method, expect, CollectionsUtil.setOf(), receiver, args); } @@ -1048,7 +1044,8 @@ protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod meth assertEquals(expect, actual); } - protected Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, Object... args) { + protected final Result executeActualCheckDeopt(OptionValues options, ResolvedJavaMethod method, Set shouldNotDeopt, Object receiver, + Object... args) { Map deoptCounts = new EnumMap<>(DeoptimizationReason.class); ProfilingInfo profile = method.getProfilingInfo(); for (DeoptimizationReason reason : shouldNotDeopt) { @@ -1187,7 +1184,6 @@ protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, Str } catch (Throwable e) { throw debug.handle(e); } - if (useCache) { cache.get().put(installedCodeOwner, Pair.create(options, installedCode)); } @@ -1369,7 +1365,7 @@ protected SpeculationLog createSpeculationLog() { } protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { - return backend.addInstalledCode(debug, method, null, compilationResult); + return backend.createInstalledCode(debug, method, null, compilationResult, null, false, true, null); } protected InstalledCode addDefaultMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java index a17fa2ad1acf..e744110062e4 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/tutorial/InvokeGraal.java @@ -145,7 +145,7 @@ protected InstalledCode compileAndInstallMethod(ResolvedJavaMethod method) { * Install the compilation result into the VM, i.e., copy the byte[] array that contains * the machine code into an actual executable memory location. */ - return backend.addInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult); + return backend.createInstalledCode(debug, method, asCompilationRequest(compilationId), compilationResult, null, false, true, null); } catch (Throwable ex) { throw debug.handle(ex); } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java index 7839506a4d40..aa8ea90c7690 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/DeoptimizeReasonAccountingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java index 5976d66f24a2..9444c4b2d7fe 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/test/JVMCIInfopointErrorTest.java @@ -159,7 +159,7 @@ private void test(DebugContext debug, TestSpec spec) { CompilationResult compResult = compile(method, graph); CodeCacheProvider codeCache = getCodeCache(); HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, method, null, compResult, getInitialOptions()); - codeCache.addCode(method, compiledCode, null, null); + codeCache.addCode(method, compiledCode, null, null, true); } @Test(expected = Error.class) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java index 1ea45a7b582d..d3d07743ef3b 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/DeoptimizeOnIntegerExactTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -135,6 +135,6 @@ public void testNegateExact() throws InvalidInstalledCodeException { @Override protected InstalledCode addMethod(DebugContext debug, final ResolvedJavaMethod method, final CompilationResult compilationResult) { assert getSpeculationLog() == compilationResult.getSpeculationLog(); - return getBackend().createInstalledCode(debug, method, compilationResult, null, false); + return getBackend().createInstalledCode(debug, method, null, compilationResult, null, false, true, null); } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java index b7e6431b6b0e..1e042a05f212 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/core/target/Backend.java @@ -134,32 +134,6 @@ public > CodeEmissionOrder newBlockOrder(int original */ protected abstract CompiledCode createCompiledCode(ResolvedJavaMethod method, CompilationRequest compilationRequest, CompilationResult compilationResult, boolean isDefault, OptionValues options); - /** - * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, - * CompilationResult, InstalledCode, boolean, Object[]) - */ - public InstalledCode createInstalledCode(DebugContext debug, - ResolvedJavaMethod method, - CompilationResult compilationResult, - InstalledCode predefinedInstalledCode, - boolean isDefault) { - return createInstalledCode(debug, method, null, compilationResult, predefinedInstalledCode, isDefault, null); - } - - /** - * @see #createInstalledCode(DebugContext, ResolvedJavaMethod, CompilationRequest, - * CompilationResult, InstalledCode, boolean, Object[]) - */ - @SuppressWarnings("try") - public InstalledCode createInstalledCode(DebugContext debug, - ResolvedJavaMethod method, - CompilationRequest compilationRequest, - CompilationResult compilationResult, - InstalledCode predefinedInstalledCode, - boolean isDefault) { - return createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, null); - } - /** * Installs code based on a given compilation result. * @@ -188,6 +162,7 @@ public InstalledCode createInstalledCode(DebugContext debug, CompilationResult compilationResult, InstalledCode predefinedInstalledCode, boolean isDefault, + boolean profileDeopt, Object[] context) { Object[] debugContext = context != null ? context : new Object[]{getProviders().getCodeCache(), method, compilationResult}; CodeInstallationTask[] tasks; @@ -204,7 +179,7 @@ public InstalledCode createInstalledCode(DebugContext debug, try { preCodeInstallationTasks(tasks, compilationResult); CompiledCode compiledCode = createCompiledCode(method, compilationRequest, compilationResult, isDefault, debug.getOptions()); - installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault); + installedCode = getProviders().getCodeCache().installCode(method, compiledCode, predefinedInstalledCode, compilationResult.getSpeculationLog(), isDefault, profileDeopt); assert predefinedInstalledCode == null || installedCode == predefinedInstalledCode : Assertions.errorMessage(predefinedInstalledCode, installedCode); } catch (Throwable t) { failCodeInstallationTasks(tasks, t); @@ -242,23 +217,6 @@ private static void postCodeInstallationTasks(CodeInstallationTask[] tasks, Comp } } - /** - * Installs code based on a given compilation result. - * - * @param method the method compiled to produce {@code compiledCode} or {@code null} if the - * input to {@code compResult} was not a {@link ResolvedJavaMethod} - * @param compilationRequest the request or {@code null} - * @param compilationResult the compiled code - * @return a reference to the compiled and ready-to-run installed code - * @throws BailoutException if the code installation failed - */ - public InstalledCode addInstalledCode(DebugContext debug, - ResolvedJavaMethod method, - CompilationRequest compilationRequest, - CompilationResult compilationResult) { - return createInstalledCode(debug, method, compilationRequest, compilationResult, null, false); - } - /** * Installs code based on a given compilation result and sets it as the default code to be used * when {@code method} is invoked. @@ -270,7 +228,7 @@ public InstalledCode addInstalledCode(DebugContext debug, * @throws BailoutException if the code installation failed */ public InstalledCode createDefaultInstalledCode(DebugContext debug, ResolvedJavaMethod method, CompilationResult compilationResult) { - return createInstalledCode(debug, method, compilationResult, null, true); + return createInstalledCode(debug, method, null, compilationResult, (InstalledCode) null, true, true, null); } /** diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java index ced10d5179f4..42758b7c446e 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/CompilationTask.java @@ -697,12 +697,15 @@ protected void installMethod(HotSpotBackend backend, DebugContext debug, Structu Object[] context = {new DebugDumpScope(getIdString(), true), backend.getProviders().getCodeCache(), getMethod(), compResult}; try (DebugContext.Scope s = debug.scope("CodeInstall", context, graph)) { HotSpotCompilationRequest request = getRequest(); + // By default, we only profile deoptimizations for compiled methods installed as + // default. installedCode = (HotSpotInstalledCode) backend.createInstalledCode(debug, request.getMethod(), request, compResult, null, installAsDefault, + installAsDefault, context); } catch (Throwable e) { throw debug.handle(e); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java index f0ce7da5f738..3a9079dde0ed 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/aarch64/AArch64HotSpotBackend.java @@ -159,6 +159,7 @@ public InstalledCode createInstalledCode(DebugContext debug, CompilationResult compilationResult, InstalledCode predefinedInstalledCode, boolean isDefault, + boolean profileDeopt, Object[] context) { boolean isStub = (method == null); if (!isStub) { @@ -170,7 +171,7 @@ public InstalledCode createInstalledCode(DebugContext debug, // in manually assembled code in CodeGenTest cases. assert hasInvalidatePlaceholder(compilationResult); } - return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, context); + return super.createInstalledCode(debug, method, compilationRequest, compilationResult, predefinedInstalledCode, isDefault, profileDeopt, context); } private boolean hasInvalidatePlaceholder(CompilationResult compilationResult) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index 9eb14fa71905..46fb01ff6ce8 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -97,11 +97,11 @@ public UnimplementedGraalIntrinsics(Architecture arch) { // JDK-8353786: Migrate Vector API math library support to FFM API "jdk/internal/vm/vector/VectorSupport.libraryBinaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.libraryUnaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", + "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.maybeRebox(Ljdk/internal/vm/vector/VectorSupport$VectorPayload;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.selectFromOp(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorSelectFromOp;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.selectFromTwoVectorOp(Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$SelectFromTwoVector;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" + "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" // @formatter:on ); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java index 12fee728f48e..6e4f47b6f66a 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/stubs/Stub.java @@ -225,7 +225,7 @@ public synchronized InstalledCode getCode(final Backend backend) { DebugContext.Activation a = debug.activate()) { assert destroyedCallerRegisters != null; HotSpotCompiledCode compiledCode = HotSpotCompiledCodeBuilder.createCompiledCode(codeCache, null, null, compResult, options); - code = codeCache.installCode(null, compiledCode, null, null, false); + code = codeCache.installCode(null, compiledCode, null, null, false, false); } catch (Throwable e) { throw debug.handle(e); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java index 7855f91fcf67..e9febd36db38 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/TruffleCompilerImpl.java @@ -679,7 +679,7 @@ public CompilationResult compilePEGraph(StructuredGraph graph, try (DebugCloseable a = CodeInstallationTime.start(debug); DebugCloseable c = CodeInstallationMemUse.start(debug)) { InstalledCode installedCode = createInstalledCode(compilable); assert graph.getSpeculationLog() == result.getSpeculationLog() : Assertions.errorMessage(graph, graph.getSpeculationLog(), result, result.getSpeculationLog()); - tier.backend().createInstalledCode(debug, graph.method(), compilationRequest, result, installedCode, false); + tier.backend().createInstalledCode(debug, graph.method(), compilationRequest, result, installedCode, false, false, null); if (outInstalledCode != null) { outInstalledCode[0] = installedCode; } diff --git a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java index ea93f35c2416..e15e2cc3bfa4 100644 --- a/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java +++ b/espresso/src/com.oracle.truffle.espresso.jvmci/src/com/oracle/truffle/espresso/jvmci/DummyCodeCacheProvider.java @@ -39,7 +39,7 @@ public DummyCodeCacheProvider(TargetDescription target) { } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { throw JVMCIError.unimplemented(); } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java index 2c3322530f6d..861b7ce79b8a 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/IsolateAwareCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,9 +48,9 @@ public IsolateAwareCodeCacheProvider(TargetDescription target, RegisterConfig re } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { if (!SubstrateOptions.shouldCompileInIsolates()) { - return super.installCode(method, compiledCode, predefinedInstalledCode, log, isDefault); + return super.installCode(method, compiledCode, predefinedInstalledCode, log, isDefault, profileDeopt); } VMError.guarantee(!isDefault); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java index a29e8da48cd0..237f8367fb76 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ protected SubstrateCodeCacheProvider(TargetDescription target, RegisterConfig re @Override @SuppressFBWarnings(value = {"BC_UNCONFIRMED_CAST"}, justification = "We know what we are doing.") - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode predefinedInstalledCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { VMError.guarantee(!isDefault); SubstrateInstalledCode substrateInstalledCode; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java index 9b01a1aa2394..58a9389c9d86 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedCodeCacheProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ public class HostedCodeCacheProvider extends SharedCodeCacheProvider { } @Override - public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault) { + public InstalledCode installCode(ResolvedJavaMethod method, CompiledCode compiledCode, InstalledCode installedCode, SpeculationLog log, boolean isDefault, boolean profileDeopt) { throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport } } From bfd9c238dcc1b8d30bac0064638b84053915362c Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 15:13:51 +0200 Subject: [PATCH 42/49] undo galahad ci changes to reduce diff --- ci/ci_common/galahad-common.libsonnet | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/ci_common/galahad-common.libsonnet b/ci/ci_common/galahad-common.libsonnet index 200913fca05d..3b89df1fcd77 100644 --- a/ci/ci_common/galahad-common.libsonnet +++ b/ci/ci_common/galahad-common.libsonnet @@ -11,9 +11,9 @@ local utils = import "common-utils.libsonnet"; , # Return true if this is a gate job. local is_gate(b) = - std.find("gate", b.targets) != [] + std.setInter(["gate", "tier1", "tier2", "tier3"], b.targets) != [] , - local gate_or_postmerge_targets = ["gate", "post-merge", "deploy"], + local gate_or_postmerge_targets = ["gate", "tier1", "tier2", "tier3", "post-merge", "deploy"], # Return true if this is a gate or post-merge/deployment job. local is_gate_or_postmerge(b) = std.setInter(gate_or_postmerge_targets, b.targets) != [] From 127558801296490f705caffca11351e277e4f4ad Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 15:21:21 +0200 Subject: [PATCH 43/49] compiler: use CollectionsUtil.setOf instead of emptySet --- .../src/jdk/graal/compiler/core/test/SubWordInputTest.java | 4 ++-- .../src/jdk/graal/compiler/core/test/SubWordInputTest2.java | 4 ++-- .../src/jdk/graal/compiler/jtt/except/BC_getfield1.java | 5 +++-- .../compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java index c2866623c904..ba94e086cfd7 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java @@ -33,7 +33,6 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.junit.Test; @@ -41,6 +40,7 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; +import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @RunWith(Parameterized.class) @@ -78,7 +78,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, Collections.emptySet(), null, value); + testAgainstExpected(wrapper, expected, CollectionsUtil.setOf(), null, value); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java index 5256b17ef227..3ad99501d9ae 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java @@ -33,13 +33,13 @@ import java.lang.constant.ClassDesc; import java.lang.constant.MethodTypeDesc; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @RunWith(Parameterized.class) @@ -76,7 +76,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, Collections.emptySet(), null, value); + testAgainstExpected(wrapper, expected, CollectionsUtil.setOf(), null, value); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java index 148c772bf71d..f0072dcccf86 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/except/BC_getfield1.java @@ -26,9 +26,10 @@ */ package jdk.graal.compiler.jtt.except; +import org.junit.Test; + import jdk.graal.compiler.jtt.JTTTest; import jdk.graal.compiler.phases.OptimisticOptimizations; -import org.junit.Test; public class BC_getfield1 extends JTTTest { @@ -55,7 +56,7 @@ public void run0() throws Throwable { @Test public void run1() throws Throwable { // tests that the null check isn't removed along with the read - runTest(EMPTY, "test", (Object) null); + runTest("test", (Object) null); } @Test diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java index 9e23d4233090..b66057236065 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/jdk/Unsafe_compareAndSwapNullCheck.java @@ -57,6 +57,6 @@ public static void test(Unsafe_compareAndSwapNullCheck u, long expected, long ne @Test public void run0() throws Throwable { - runTest(EMPTY, "test", null, 1L, 2L); + runTest("test", null, 1L, 2L); } } From 9aee68edcf8bd61fa2e9feb8a904a1c6d2dc330b Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Wed, 17 Sep 2025 15:29:52 +0200 Subject: [PATCH 44/49] compiler: undo some more changes --- .../compiler/core/test/SubWordInputTest.java | 3 +-- .../compiler/core/test/SubWordInputTest2.java | 3 +-- .../lir/test/BenchmarkCounterOverflowTest.java | 18 ++++++++---------- .../src/jdk/graal/compiler/jtt/JTTTest.java | 4 +--- .../compiler/jtt/lang/LambdaEagerTest.java | 10 +++++----- .../jdk/graal/compiler/jtt/lang/Math_pow.java | 6 +++--- .../jdk/graal/compiler/jtt/lang/UnaryMath.java | 3 +-- .../replacements/test/CountPositivesTest.java | 6 ++---- 8 files changed, 22 insertions(+), 31 deletions(-) diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java index ba94e086cfd7..98e57026c802 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest.java @@ -40,7 +40,6 @@ import org.junit.runners.Parameterized; import org.junit.runners.Parameterized.Parameters; -import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @RunWith(Parameterized.class) @@ -78,7 +77,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, CollectionsUtil.setOf(), null, value); + testAgainstExpected(wrapper, expected, null, new Object[]{value}); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java index 3ad99501d9ae..2aa030f3ded3 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/core/test/SubWordInputTest2.java @@ -39,7 +39,6 @@ import org.junit.runner.RunWith; import org.junit.runners.Parameterized; -import jdk.graal.compiler.util.CollectionsUtil; import jdk.vm.ci.meta.ResolvedJavaMethod; @RunWith(Parameterized.class) @@ -76,7 +75,7 @@ public void testSubWordInput() throws ClassNotFoundException { getCode(getResolvedJavaMethod(testClass, GET), null, false, true, getInitialOptions()); assertEquals(executeExpected(wrapper, null, value), expected); // test with inlining - testAgainstExpected(wrapper, expected, CollectionsUtil.setOf(), null, value); + testAgainstExpected(wrapper, expected, null, new Object[]{value}); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java index 4499e640862b..fac768ca56af 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/hotspot/lir/test/BenchmarkCounterOverflowTest.java @@ -35,22 +35,20 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.junit.Assert; +import org.junit.Assume; +import org.junit.Before; +import org.junit.Test; + import jdk.graal.compiler.api.directives.GraalDirectives; -import jdk.graal.compiler.core.test.GraalCompilerTest; -import jdk.graal.compiler.jtt.JTTTest; -import jdk.graal.compiler.lir.jtt.LIRTest; -import jdk.graal.compiler.lir.jtt.LIRTestSpecification; import jdk.graal.compiler.core.common.LIRKind; import jdk.graal.compiler.hotspot.HotSpotBackend; import jdk.graal.compiler.hotspot.debug.BenchmarkCounters; import jdk.graal.compiler.lir.ConstantValue; import jdk.graal.compiler.lir.gen.LIRGeneratorTool; +import jdk.graal.compiler.lir.jtt.LIRTest; +import jdk.graal.compiler.lir.jtt.LIRTestSpecification; import jdk.graal.compiler.test.SubprocessUtil; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Before; -import org.junit.Test; - import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -97,7 +95,7 @@ public void incrementCounter() { Object[] args = new Object[]{Integer.MAX_VALUE * 4L}; ResolvedJavaMethod method = getResolvedJavaMethod("test"); - executeActualCheckDeopt(GraalCompilerTest.getInitialOptions(), method, JTTTest.EMPTY, null, args); + executeActual(method, null, args); } @Test diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java index 6b36d08534e4..79a95ff5646e 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/JTTTest.java @@ -30,7 +30,6 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.Arrays; -import java.util.Collections; import java.util.Formatter; import java.util.ListIterator; import java.util.Optional; @@ -81,7 +80,6 @@ public class JTTTest extends GraalCompilerTest { public static final class DummyTestClass { } - protected static final Set EMPTY = Collections. emptySet(); /** * The arguments which, if non-null, will replace the Locals in the test method's graph. */ @@ -192,7 +190,7 @@ protected void runTest(OptionValues options, Set shouldNot * to the usual compilation using {@link GraalCompilerTest#testAgainstExpected}. */ @Override - protected void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { + protected final void testAgainstExpected(OptionValues options, ResolvedJavaMethod method, Result expect, Set shouldNotDeopt, Object receiver, Object... args) { if (Boolean.getBoolean(COMPILATION_PLAN_FUZZING_SYSTEM_PROPERTY)) { testAgainstExpectedWithFuzzedCompilationPlan(options, method, expect, shouldNotDeopt, receiver, args); } else { diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java index 8fda9b6f40c5..139ff653bce5 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/LambdaEagerTest.java @@ -29,11 +29,11 @@ import java.util.EnumSet; import java.util.function.IntBinaryOperator; +import org.junit.Test; + import jdk.graal.compiler.core.test.GraalCompilerTest; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; -import org.junit.Test; - import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -65,19 +65,19 @@ public static int capturing(int x, int y, int z) { @Test public void testEagerResolveNonCapturing01() { Result expected = new Result(3, null); - testAgainstExpected(getResolvedJavaMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2); + testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("nonCapturing"), expected, UNRESOLVED_UNREACHED, 1, 2); } @Test public void testEagerResolveNonCapturing02() { Result expected = new Result(3, null); - testAgainstExpected(getResolvedJavaMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2); + testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("nonCapturing2"), expected, UNRESOLVED_UNREACHED, 1, 2); } @Test public void testEagerResolveCapturing() { Result expected = new Result(0, null); - testAgainstExpected(getResolvedJavaMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3); + testAgainstExpected(getInitialOptions(), getResolvedJavaMethod("capturing"), expected, UNRESOLVED_UNREACHED, 1, 2, 3); } @Override diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java index 3cc1f05c1d1d..14cc31ff171e 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/Math_pow.java @@ -24,10 +24,10 @@ */ package jdk.graal.compiler.jtt.lang; -import jdk.graal.compiler.jtt.JTTTest; -import jdk.graal.compiler.options.OptionValues; import org.junit.Test; +import jdk.graal.compiler.jtt.JTTTest; +import jdk.graal.compiler.options.OptionValues; import jdk.vm.ci.meta.ResolvedJavaMethod; /* @@ -137,7 +137,7 @@ public void run12() { private void testOne(OptionValues options, ResolvedJavaMethod method, Object receiver, long testIteration, long l, double x, double y) throws AssertionError { Result expect = executeExpected(method, receiver, x, y); try { - testAgainstExpected(options, method, expect, EMPTY, receiver, x, y); + testAgainstExpected(options, method, expect, receiver, x, y); } catch (AssertionError e) { throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, x, l, l), e); } diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java index 5fc61533c61a..bd2ca8b0a19a 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/jtt/lang/UnaryMath.java @@ -26,7 +26,6 @@ import jdk.graal.compiler.jtt.JTTTest; import jdk.graal.compiler.options.OptionValues; - import jdk.vm.ci.meta.ResolvedJavaMethod; public abstract class UnaryMath extends JTTTest { @@ -60,7 +59,7 @@ void testManyValues(OptionValues options, ResolvedJavaMethod method) throws Asse double d = Double.longBitsToDouble(l); Result expect = executeExpected(method, receiver, d); try { - testAgainstExpected(options, method, expect, EMPTY, receiver, d); + testAgainstExpected(options, method, expect, receiver, d); testIteration++; } catch (AssertionError e) { throw new AssertionError(String.format("%d: While testing %g [long: %d, hex: %x]", testIteration, d, l, l), e); diff --git a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java index 985f71df7a09..590ec168c4ef 100644 --- a/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java +++ b/compiler/src/jdk.graal.compiler.test/src/jdk/graal/compiler/replacements/test/CountPositivesTest.java @@ -24,15 +24,13 @@ */ package jdk.graal.compiler.replacements.test; -import java.util.Collections; +import org.junit.Test; import jdk.graal.compiler.core.common.CompilationIdentifier; import jdk.graal.compiler.hotspot.test.HotSpotGraalCompilerTest; import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.test.AddExports; -import org.junit.Test; - import jdk.vm.ci.meta.ResolvedJavaMethod; @AddExports("java.base/java.lang") @@ -70,7 +68,7 @@ public void testStringCoding() throws ClassNotFoundException { for (int off : new int[]{0, 2, -2}) { for (int len : new int[]{bytes.length, 2, 0, -2}) { Result expect = executeExpected(method, null, bytes, off, len); - Result actual = executeActualCheckDeopt(getInitialOptions(), method, Collections.emptySet(), null, bytes, off, len); + Result actual = executeActual(method, null, bytes, off, len); if (expect.returnValue == null) { assertEquals(expect, actual); From 3a7f52eeb389426ee82853fbb248d0f69df101e0 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 18 Sep 2025 08:52:58 +0200 Subject: [PATCH 45/49] svm/ci: remove oraclejdk-helloworld --- substratevm/ci/ci.jsonnet | 3 --- 1 file changed, 3 deletions(-) diff --git a/substratevm/ci/ci.jsonnet b/substratevm/ci/ci.jsonnet index 857bb7a082a2..f66891cb9873 100644 --- a/substratevm/ci/ci.jsonnet +++ b/substratevm/ci/ci.jsonnet @@ -140,9 +140,6 @@ "linux:amd64:jdk-latest": tier2 + partial(2) + gdb("14.2") + t("40:00"), }, }), - "oraclejdk-helloworld": mxgate("build,helloworld,hellomodule") + maven + jsonschema + platform_spec(no_jobs) + platform_spec({ - "linux:amd64:jdk-latest": tier1 + use_oraclejdk_latest + t("30:00"), - }), }, // END MAIN BUILD DEFINITION processed_builds::run_spec.process(task_dict), From b7733eccf4ac360d4f7164cc9a8c52fd7517a812 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Thu, 18 Sep 2025 11:17:15 +0200 Subject: [PATCH 46/49] update labsjdk-latest imports --- common.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/common.json b/common.json index 9d8b15342877..341f06ff71ca 100644 --- a/common.json +++ b/common.json @@ -55,12 +55,12 @@ "graalvm-ee-25-ea": {"name": "graalvm-jdk", "version": "25.0.0", "ea": "36", "platformspecific": true }, "oraclejdk-latest": {"name": "jpg-jdk", "version": "25", "build_id": "jdk-25+37", "platformspecific": true, "extrabundles": ["static-libs"]}, - "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769", "platformspecific": true }, - "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769-debug", "platformspecific": true }, - "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-20250914203105-3d9e209769-sulong", "platformspecific": true }, - "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970", "platformspecific": true }, - "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970-debug", "platformspecific": true }, - "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-20250914203105-3d9e209769+e50a360970-sulong", "platformspecific": true } + "labsjdk-ce-latest": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02", "platformspecific": true }, + "labsjdk-ce-latestDebug": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-debug", "platformspecific": true }, + "labsjdk-ce-latest-llvm": {"name": "labsjdk", "version": "ce-25+37-jvmci-b02-sulong", "platformspecific": true }, + "labsjdk-ee-latest": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02", "platformspecific": true }, + "labsjdk-ee-latestDebug": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-debug", "platformspecific": true }, + "labsjdk-ee-latest-llvm": {"name": "labsjdk", "version": "ee-25+37-jvmci-b02-sulong", "platformspecific": true } }, "eclipse": { From 77fefaa5c4e5ad45af9ddf854a2489d4d410dc39 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 19 Sep 2025 06:22:38 +0000 Subject: [PATCH 47/49] Improve comment in HostInliningTest --- .../src/jdk/graal/compiler/truffle/test/HostInliningTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 7412f023738b..ed363a5cf15c 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 @@ -151,7 +151,7 @@ public void test() { runTest("testImplicitCast"); runTest("testNativeCall"); runTest("testBCDSLPrologIfVersion"); - // temporarily disabled + // temporarily disabled because it fails with JDK 25 (GR-69866) // runTest("testInliningRoot"); } From 3b848e145db117dcd207462b018cc87f439b5f48 Mon Sep 17 00:00:00 2001 From: Yudi Zheng Date: Fri, 19 Sep 2025 10:20:54 +0200 Subject: [PATCH 48/49] Update UmimplementedGraalIntrinsics --- .../compiler/hotspot/meta/UnimplementedGraalIntrinsics.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java index 46fb01ff6ce8..9eb14fa71905 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/UnimplementedGraalIntrinsics.java @@ -97,11 +97,11 @@ public UnimplementedGraalIntrinsics(Architecture arch) { // JDK-8353786: Migrate Vector API math library support to FFM API "jdk/internal/vm/vector/VectorSupport.libraryBinaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$VectorPayload;Ljdk/internal/vm/vector/VectorSupport$BinaryOperation;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.libraryUnaryOp(JLjava/lang/Class;Ljava/lang/Class;ILjava/lang/String;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$UnaryOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", + "jdk/internal/vm/vector/VectorSupport.loadWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$LoadVectorOperationWithMap;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.maybeRebox(Ljdk/internal/vm/vector/VectorSupport$VectorPayload;)Ljdk/internal/vm/vector/VectorSupport$VectorPayload;", "jdk/internal/vm/vector/VectorSupport.selectFromOp(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljdk/internal/vm/vector/VectorSupport$VectorSelectFromOp;)Ljdk/internal/vm/vector/VectorSupport$Vector;", "jdk/internal/vm/vector/VectorSupport.selectFromTwoVectorOp(Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$SelectFromTwoVector;)Ljdk/internal/vm/vector/VectorSupport$Vector;", - "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;ILjava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" + "jdk/internal/vm/vector/VectorSupport.storeWithMap(Ljava/lang/Class;Ljava/lang/Class;Ljava/lang/Class;ILjava/lang/Class;Ljava/lang/Object;JLjdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$Vector;Ljdk/internal/vm/vector/VectorSupport$VectorMask;Ljava/lang/Object;I[IILjdk/internal/vm/vector/VectorSupport$StoreVectorOperationWithMap;)V" // @formatter:on ); From b68de125a30436bd4ba0801fb777a38ce36ee122 Mon Sep 17 00:00:00 2001 From: Josef Eisl Date: Fri, 19 Sep 2025 18:14:44 +0200 Subject: [PATCH 49/49] truffle: make OptimizedTruffleRuntime work with master labsjdk25 [GR-69866] --- .../truffle/test/HostInliningTest.java | 3 +-- .../runtime/OptimizedTruffleRuntime.java | 20 ++++++++++++++++++- 2 files changed, 20 insertions(+), 3 deletions(-) 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 ed363a5cf15c..291d23c22667 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 @@ -151,8 +151,7 @@ public void test() { runTest("testImplicitCast"); runTest("testNativeCall"); runTest("testBCDSLPrologIfVersion"); - // temporarily disabled because it fails with JDK 25 (GR-69866) - // runTest("testInliningRoot"); + runTest("testInliningRoot"); } /* 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 f9e9827833f1..0d2736ba9700 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 @@ -170,6 +170,24 @@ public abstract class OptimizedTruffleRuntime implements TruffleRuntime, Truffle private static final int JAVA_SPECIFICATION_VERSION = Runtime.version().feature(); + private static final class Lazy { + /** + * True if the {@link InliningRoot} annotation is supported by the compiler. + */ + private static final boolean INLINING_ROOT_SUPPORTED; + + static { + boolean supported; + try { + HostMethodInfo.class.getDeclaredConstructor(boolean.class, boolean.class, boolean.class, boolean.class, boolean.class); + supported = true; + } catch (NoSuchMethodException e) { + supported = false; + } + INLINING_ROOT_SUPPORTED = supported; + } + } + /** * Used only to reset state for native image compilation. */ @@ -540,7 +558,7 @@ protected void installDefaultListeners() { @Override public HostMethodInfo getHostMethodInfo(ResolvedJavaMethod method) { - if (JAVA_SPECIFICATION_VERSION >= 26) { + if (Lazy.INLINING_ROOT_SUPPORTED) { return new HostMethodInfo(isTruffleBoundary(method), isBytecodeInterpreterSwitch(method), isBytecodeInterpreterSwitchBoundary(method),