From 8e0fbfdec498a4dfcf881e8bef8c0bb4f16c3f75 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 18 Sep 2024 15:57:00 +0200 Subject: [PATCH 01/98] initial support for inline types --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 13 +++++++++++++ src/hotspot/share/jvmci/jvmciRuntime.hpp | 2 ++ src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 5 +++++ .../ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 5 +++++ .../classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + .../classes/jdk/vm/ci/meta/ResolvedJavaType.java | 9 +++++++++ 6 files changed, 35 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index c88a4390590..e12d77cfb9a 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -413,6 +413,19 @@ JRT_LEAF(jboolean, JVMCIRuntime::object_notify(JavaThread* current, oopDesc* obj JRT_END +JRT_ENTRY(jboolean, JVMCIRuntime::substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right)) + JavaCallArguments args; + args.push_oop(Handle(THREAD, left)); + args.push_oop(Handle(THREAD, right)); + JavaValue result(T_BOOLEAN); + JavaCalls::call_static(&result, + vmClasses::ValueObjectMethods_klass(), + vmSymbols::isSubstitutable_name(), + vmSymbols::object_object_boolean_signature(), + &args, CHECK_0); + return result.get_jboolean(); +JRT_END + // Object.notifyAll() fast path, caller does slow path JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread* current, oopDesc* obj)) assert(current == JavaThread::current(), "pre-condition"); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 884d11f792e..613f9718160 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -526,6 +526,8 @@ class JVMCIRuntime: public CHeapObj { static void monitorexit (JavaThread* current, oopDesc* obj, BasicLock* lock); static jboolean object_notify(JavaThread* current, oopDesc* obj); static jboolean object_notifyAll(JavaThread* current, oopDesc* obj); + static jboolean substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right); + static void vm_error(JavaThread* current, jlong where, jlong format, jlong value); static oopDesc* load_and_clear_exception(JavaThread* thread); static void log_printf(JavaThread* thread, const char* format, jlong v1, jlong v2, jlong v3); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index cfefd0cf967..bd2371252dd 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -494,6 +494,7 @@ declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM) \ declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \ declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE) \ + declare_preprocessor_constant("JVM_ACC_IDENTITY", JVM_ACC_IDENTITY) \ \ declare_constant(JVM_CONSTANT_Utf8) \ declare_constant(JVM_CONSTANT_Unicode) \ @@ -817,6 +818,9 @@ \ declare_constant(markWord::no_hash_in_place) \ declare_constant(markWord::no_lock_in_place) \ + declare_constant(markWord::inline_type_pattern) \ + declare_constant(markWord::inline_type_mask_in_place) \ + declare_constant(markWord::inline_type_bit_in_place) \ // Helper macro to support ZGC pattern where the function itself isn't exported #define DECLARE_FUNCTION_FROM_ADDR(declare_function_with_value, name) \ @@ -869,6 +873,7 @@ declare_function(JVMCIRuntime::exception_handler_for_pc) \ declare_function(JVMCIRuntime::monitorenter) \ declare_function(JVMCIRuntime::monitorexit) \ + declare_function(JVMCIRuntime::substitutability_check) \ declare_function(JVMCIRuntime::object_notify) \ declare_function(JVMCIRuntime::object_notifyAll) \ declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 91c9e73b532..dfb126f57eb 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -465,6 +465,11 @@ public boolean isInterface() { return (getAccessFlags() & config().jvmAccInterface) != 0; } + @Override + public boolean isIdentity() { + return (getAccessFlags() & config().jvmAccIdentity) != 0; + } + @Override public boolean isAssignableFrom(ResolvedJavaType other) { assert other != null; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 7205b453e40..4eb85365ce1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -126,6 +126,7 @@ static String getHostArchitectureName() { final int jvmAccVarargs = getConstant("JVM_ACC_VARARGS", Integer.class); final int jvmAccEnum = getConstant("JVM_ACC_ENUM", Integer.class); final int jvmAccInterface = getConstant("JVM_ACC_INTERFACE", Integer.class); + final int jvmAccIdentity = getConstant("JVM_ACC_IDENTITY", Integer.class); final int jvmMiscFlagsHasDefaultMethods = getConstant("InstanceKlassFlags::_misc_has_nonstatic_concrete_methods", Integer.class); final int jvmMiscFlagsDeclaresDefaultMethods = getConstant("InstanceKlassFlags::_misc_declares_nonstatic_concrete_methods", Integer.class); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 272f821b7ca..aaf14217a0a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -407,4 +407,13 @@ default ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, default boolean isConcrete() { return isArray() || !isAbstract(); } + + /** + * Checks whether this type has an identity. + * + * @return {@code true} if this type has an identity + */ + default boolean isIdentity() { + return true; + } } From f3efd5c0e4ed0e5da138e57edb82617b151447d7 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 30 Sep 2024 18:39:42 +0200 Subject: [PATCH 02/98] adaption of isIdentity check --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 +- .../jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java | 6 ++++++ .../share/classes/jdk/vm/ci/meta/ResolvedJavaType.java | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index bd2371252dd..c5e79bbce0f 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -494,7 +494,7 @@ declare_preprocessor_constant("JVM_ACC_ENUM", JVM_ACC_ENUM) \ declare_preprocessor_constant("JVM_ACC_SYNTHETIC", JVM_ACC_SYNTHETIC) \ declare_preprocessor_constant("JVM_ACC_INTERFACE", JVM_ACC_INTERFACE) \ - declare_preprocessor_constant("JVM_ACC_IDENTITY", JVM_ACC_IDENTITY) \ + declare_preprocessor_constant("JVM_ACC_IDENTITY", JVM_ACC_IDENTITY) \ \ declare_constant(JVM_CONSTANT_Utf8) \ declare_constant(JVM_CONSTANT_Unicode) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index d95824998bc..8e9bf6f00c7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -24,6 +24,7 @@ import static java.util.Objects.requireNonNull; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import java.lang.annotation.Annotation; import java.lang.reflect.Modifier; @@ -177,6 +178,11 @@ public boolean isInterface() { return false; } + @Override + public boolean isIdentity() { + return false; + } + @Override public boolean isAssignableFrom(ResolvedJavaType other) { assert other != null; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index aaf14217a0a..03a036bfd8a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -413,7 +413,7 @@ default boolean isConcrete() { * * @return {@code true} if this type has an identity */ - default boolean isIdentity() { - return true; + default boolean isIdentity(){ + throw new UnsupportedOperationException("isIdentity is unsupported"); } } From 6c7419344c46e13add6e62c144b1fc915215e9b5 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 2 Oct 2024 16:12:53 +0200 Subject: [PATCH 03/98] added markWord prototype to jvmci --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index c5e79bbce0f..7ac2aa3ca6f 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -269,6 +269,7 @@ nonstatic_field(Klass, _super_check_offset, juint) \ volatile_nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ + nonstatic_field(Klass, _prototype_header, markWord) \ nonstatic_field(Klass, _name, Symbol*) \ volatile_nonstatic_field(Klass, _next_sibling, Klass*) \ nonstatic_field(Klass, _java_mirror, OopHandle) \ From 093fe26ee0ce9e07fb8b3de47b944e52b9835c86 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 8 Oct 2024 18:41:04 +0200 Subject: [PATCH 04/98] making acmp profile information available over jvmci --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 6 +- .../jdk/vm/ci/hotspot/ACmpDataAccessor.java | 11 ++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 11 +- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 152 +++++++++++++++++- .../vm/ci/hotspot/HotSpotProfilingInfo.java | 12 ++ .../jdk/vm/ci/hotspot/SingleTypeEntry.java | 24 +++ .../jdk/vm/ci/meta/DefaultProfilingInfo.java | 8 + .../classes/jdk/vm/ci/meta/ProfilingInfo.java | 13 ++ 8 files changed, 232 insertions(+), 5 deletions(-) create mode 100644 src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java create mode 100644 src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 7fdfc9ce3a2..f323bf78813 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -442,7 +442,7 @@ C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, ARGUMENT_PAIR( return JVMCIENV->get_jobject(result); } -C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed)) +C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed, jlong mask)) JVMCIObject base_object = JVMCIENV->wrap(base); if (base_object.is_null()) { JVMCI_THROW_MSG_NULL(NullPointerException, "base object is null"); @@ -505,7 +505,7 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject b } } else if (JVMCIENV->isa_HotSpotMethodData(base_object)) { jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object); - klass = *((Klass**) (intptr_t) (base_address + offset)); + klass = *((Klass**) (intptr_t) ((base_address + offset)&mask)); if (klass == nullptr || !klass->is_loader_alive()) { // Klasses in methodData might be concurrently unloading so return null in that case. return nullptr; @@ -3304,7 +3304,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "asResolvedJavaMethod", CC "(" EXECUTABLE ")" HS_METHOD, FN_PTR(asResolvedJavaMethod)}, {CC "getResolvedJavaMethod", CC "(" OBJECTCONSTANT "J)" HS_METHOD, FN_PTR(getResolvedJavaMethod)}, {CC "getConstantPool", CC "(" OBJECT "JZ)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)}, - {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, + {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZJ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, {CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)}, {CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)}, {CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java new file mode 100644 index 00000000000..afc21f5d2fb --- /dev/null +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java @@ -0,0 +1,11 @@ +package jdk.vm.ci.hotspot; + +public interface ACmpDataAccessor { + public SingleTypeEntry getLeft(); + + public SingleTypeEntry getRight(); + + public static ACmpDataAccessor create(){ + return new HotSpotMethodData.ACmpData.ACmpDataAccessorImpl(); + } +} diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 9c64126c62d..b3d08ed2dd6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -992,7 +992,16 @@ HotSpotConstantPool getConstantPool(MetaspaceObject object) { * @return null or the resolved method for this location * @throws NullPointerException if {@code base == null} */ - private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed); + + private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed, long mask); + + HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed){ + return getResolvedJavaType0(base, displacement, compressed, -1); + } + + HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, long mask){ + return getResolvedJavaType0(base, displacement, false, mask); + } HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotConstantPool base, long displacement) { return getResolvedJavaType0(base, displacement, false); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index 4f6dfd20ffc..0e171a964c7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -77,6 +77,13 @@ static final class VMState { final int branchDataSize = cellIndexToOffset(3); final int notTakenCountOffset = cellIndexToOffset(config.branchDataNotTakenOffset); + // inherits from branch and two cells for types + final int acmpDataSize = branchDataSize+ cellsToBytes(1)*2; + final int leftOperandOffset = cellIndexToOffset(3); + final int rightOperandOffset = cellIndexToOffset(4); + final int leftInlineTypeFlag = 1; + final int rightInlineTypeFlag = 1<<1; + final int arrayDataLengthOffset = cellIndexToOffset(config.arrayDataArrayLenOffset); final int arrayDataStartOffset = cellIndexToOffset(config.arrayDataArrayStartOffset); @@ -107,7 +114,7 @@ static final class VMState { new UnknownProfileData(this, config.dataLayoutSpeculativeTrapDataTag), new UnknownProfileData(this, config.dataLayoutArrayStoreDataTag), new UnknownProfileData(this, config.dataLayoutArrayLoadDataTag), - new UnknownProfileData(this, config.dataLayoutACmpDataTag), + new ACmpData(this, config.dataLayoutACmpDataTag), }; // @formatter:on @@ -291,6 +298,11 @@ private int readUnsignedIntAsSignedInt(int position, int offsetInBytes) { return VMState.truncateLongToInt(value); } + private long readPointer(int position, int offsetInBytes) { + long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes); + return UNSAFE.getAddress(methodDataPointer + fullOffsetInBytes); + } + /** * Since the values are stored in cells (platform words) this method uses * {@link Unsafe#getAddress} to read the right value on both little and big endian machines. @@ -693,6 +705,10 @@ static class BranchData extends JumpData { super(state, tag, state.branchDataSize); } + protected BranchData(VMState state, int tag, int staticSize) { + super(state, tag, staticSize); + } + @Override public double getBranchTakenProbability(HotSpotMethodData data, int position) { long takenCount = data.readUnsignedInt(position, state.takenCountOffset); @@ -717,6 +733,140 @@ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) } } + static class ACmpData extends BranchData { + + static class SingleTypeEntryImpl implements SingleTypeEntry { + final long value; + final boolean inlineType; + final HotSpotMethodData data; + final int offset; + HotSpotResolvedObjectType validType; + + final static long nullSeen =1; + final static long typeMask = ~nullSeen; + final static long typeUnknown = 2; + final static long statusBits = nullSeen | typeUnknown; + final static long typeKlassMask = ~statusBits; + + SingleTypeEntryImpl(long value, boolean inlineType, HotSpotMethodData data, int offset) { + this.value = value; + this.inlineType = inlineType; + this.data = data; + this.offset = offset; + this.validType = computeValidType(); + } + + + @Override + public boolean isTypeNone(){ + return (value & typeMask) == 0; + } + + @Override + public boolean isTypeUnknown(){ + return (value & typeUnknown) != 0; + } + + @Override + public boolean wasNullSeen(){ + return (value & nullSeen) != 0; + } + + @Override + public long klassPart(){ + return value & typeKlassMask; + } + + private HotSpotResolvedObjectType computeValidType(){ + if(!isTypeNone() && ! isTypeUnknown()){ + return compilerToVM().getResolvedJavaType(data, offset, typeKlassMask); + }else{ + return null; + } + + } + + @Override + public HotSpotResolvedObjectType getValidType(){ + return validType; + } + + @Override + public boolean maybeNull(){ + return wasNullSeen() && isTypeNone(); + } + + @Override + public boolean neverNull(){ + return wasNullSeen(); + } + + @Override + public boolean alwaysNull(){ + return maybeNull(); + } + + @Override + public boolean inlineType(){ + return inlineType; + } + + } + + static class ACmpDataAccessorImpl implements ACmpDataAccessor{ + + private final SingleTypeEntry left; + private final SingleTypeEntry right; + + ACmpDataAccessorImpl(ACmpData aCmpData, HotSpotMethodData data, int position){ + left = aCmpData.getLeft(data, position); + right = aCmpData.getRight(data, position); + } + + ACmpDataAccessorImpl(){ +// left = new SingleTypeEntryImpl(1, true, null, 0); +// right = new SingleTypeEntryImpl(1, false, null, 0); + left = null; + right = null; + } + + @Override + public SingleTypeEntry getLeft() { + return left; + } + + @Override + public SingleTypeEntry getRight() { + return right; + } + } + + + ACmpData(VMState state, int tag) { + super(state, tag, state.acmpDataSize); + } + + private SingleTypeEntry getLeft(HotSpotMethodData data, int position) { + return new SingleTypeEntryImpl(data.readPointer(position, state.leftOperandOffset), inlineType(data, position, true), data, state.computeFullOffset(position, state.leftOperandOffset)); + } + + private SingleTypeEntry getRight(HotSpotMethodData data, int position) { + return new SingleTypeEntryImpl(data.readPointer(position, state.rightOperandOffset), inlineType(data, position, false), data, state.computeFullOffset(position, state.rightOperandOffset)); + } + + private boolean inlineType(HotSpotMethodData data, int position, boolean left){ + if(left){ + return (getFlags(data, position) & state.leftInlineTypeFlag) !=0; + } + return (getFlags(data, position) & state.rightInlineTypeFlag) !=0; + } + + public ACmpDataAccessor getACmpAccessor(HotSpotMethodData data, int position){ + return new ACmpDataAccessorImpl(this, data, position); + } + + } + static class ArrayData extends HotSpotMethodDataAccessor { ArrayData(VMState state, int tag, int staticSize) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index 97deccf0dcf..c37108c591f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -124,6 +124,18 @@ public TriState getExceptionSeen(int bci) { return dataAccessor.getExceptionSeen(methodData, position); } + @Override + public ACmpDataAccessor getAcmpData(int bci) { +// if (!isMature) { +// return null; +// } + findBCI(bci); + if(dataAccessor instanceof HotSpotMethodData.ACmpData aCmpData){ + return aCmpData.getACmpAccessor(methodData, position); + } + return null; + } + @Override public TriState getNullSeen(int bci) { findBCI(bci); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java new file mode 100644 index 00000000000..2167a1e68af --- /dev/null +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java @@ -0,0 +1,24 @@ +package jdk.vm.ci.hotspot; + +public interface SingleTypeEntry{ + + + boolean isTypeNone(); + + boolean isTypeUnknown(); + + boolean wasNullSeen(); + + long klassPart(); + + HotSpotResolvedObjectType getValidType(); + + boolean maybeNull(); + + boolean neverNull(); + + boolean alwaysNull(); + + boolean inlineType(); + +} diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index a0df0a2e809..c66b5ec10d0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.meta; +import jdk.vm.ci.hotspot.ACmpDataAccessor; + /** * An implementation of {@link ProfilingInfo} that can used in the absence of real profile * information. @@ -67,6 +69,12 @@ public TriState getExceptionSeen(int bci) { return exceptionSeen; } + @Override + public ACmpDataAccessor getAcmpData(int bci) { + //return ACmpDataAccessor.create(); + return null; + } + @Override public TriState getNullSeen(int bci) { return TriState.UNKNOWN; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java index 7eaa8e96670..6ab71c383a8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.meta; +import jdk.vm.ci.hotspot.ACmpDataAccessor; + /** * Provides access to the profiling information of one specific method. Every accessor method * returns the information that is available at the time of invocation. If a method is invoked @@ -75,6 +77,13 @@ public interface ProfilingInfo { */ TriState getExceptionSeen(int bci); + /** + * Returns the AcmpProfile for the given BCI. + * + * @return Returns a AcmpData object, or null if not available. + */ + ACmpDataAccessor getAcmpData(int bci); + /** * Returns information if null was ever seen for the given BCI. This information is collected * for the aastore, checkcast and instanceof bytecodes. @@ -171,6 +180,10 @@ default String toString(ResolvedJavaMethod method, String sep) { buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep)); } + if (getAcmpData(i) != null) { + buf.append("acmp_found\n"); + } + JavaTypeProfile typeProfile = getTypeProfile(i); MetaUtil.appendProfile(buf, typeProfile, i, "types", sep); From 5fa64b0e96c86de891a7b42b5ac5eaafc7abf1a9 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 9 Oct 2024 12:25:53 +0200 Subject: [PATCH 05/98] fixed wrong access to klass object --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 5 ++++- .../classes/jdk/vm/ci/hotspot/HotSpotMethodData.java | 8 ++++---- .../classes/jdk/vm/ci/meta/DefaultProfilingInfo.java | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index f323bf78813..6b17ccb6dbd 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -505,7 +505,10 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject b } } else if (JVMCIENV->isa_HotSpotMethodData(base_object)) { jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object); - klass = *((Klass**) (intptr_t) ((base_address + offset)&mask)); + Klass* temp = *((Klass**) (intptr_t) (base_address + offset)); + temp = (Klass*)(((uintptr_t) temp)&mask); + klass = temp; + //klass = *((Klass**) (intptr_t) (base_address + offset)); if (klass == nullptr || !klass->is_loader_alive()) { // Klasses in methodData might be concurrently unloading so return null in that case. return nullptr; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index 0e171a964c7..2480f288df4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -824,10 +824,10 @@ static class ACmpDataAccessorImpl implements ACmpDataAccessor{ } ACmpDataAccessorImpl(){ -// left = new SingleTypeEntryImpl(1, true, null, 0); -// right = new SingleTypeEntryImpl(1, false, null, 0); - left = null; - right = null; + left = new SingleTypeEntryImpl(1, false, null, 0); + right = new SingleTypeEntryImpl(1, false, null, 0); +// left = null; +// right = null; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index c66b5ec10d0..6ec36ad11b5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -71,8 +71,8 @@ public TriState getExceptionSeen(int bci) { @Override public ACmpDataAccessor getAcmpData(int bci) { - //return ACmpDataAccessor.create(); - return null; + return ACmpDataAccessor.create(); +// return null; } @Override From a00ca7590898894adab80e702e9511bc28500d41 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 10 Oct 2024 11:40:32 +0200 Subject: [PATCH 06/98] refactor jvmci code for acmp profile data --- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 110 +++++++++++++----- .../vm/ci/hotspot/HotSpotProfilingInfo.java | 2 +- .../jdk/vm/ci/meta/DefaultProfilingInfo.java | 4 +- .../classes/jdk/vm/ci/meta/ProfilingInfo.java | 11 +- 4 files changed, 91 insertions(+), 36 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index 2480f288df4..feee26a9aa9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -735,12 +735,11 @@ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) static class ACmpData extends BranchData { - static class SingleTypeEntryImpl implements SingleTypeEntry { + abstract static class SingleTypeEntryImpl implements SingleTypeEntry { final long value; - final boolean inlineType; - final HotSpotMethodData data; - final int offset; - HotSpotResolvedObjectType validType; + final int flags; + final VMState state; + final HotSpotResolvedObjectType validType; final static long nullSeen =1; final static long typeMask = ~nullSeen; @@ -748,14 +747,24 @@ static class SingleTypeEntryImpl implements SingleTypeEntry { final static long statusBits = nullSeen | typeUnknown; final static long typeKlassMask = ~statusBits; - SingleTypeEntryImpl(long value, boolean inlineType, HotSpotMethodData data, int offset) { - this.value = value; - this.inlineType = inlineType; - this.data = data; - this.offset = offset; - this.validType = computeValidType(); + SingleTypeEntryImpl(ACmpData aCmpData, HotSpotMethodData data, int position) { + this.state = aCmpData.state; + this.flags = aCmpData.getFlags(data, position); + this.value = data.readPointer(position, getOperandOffset()); + int offset = state.computeFullOffset(position, getOperandOffset()); + this.validType = computeValidType(data, offset); } + SingleTypeEntryImpl() { + this.value = 0; + this.state = null; + this.flags = 0; + this.validType = null; + } + + abstract int getOperandOffset(); + abstract int getInlineFlag(); + @Override public boolean isTypeNone(){ @@ -777,7 +786,7 @@ public long klassPart(){ return value & typeKlassMask; } - private HotSpotResolvedObjectType computeValidType(){ + private HotSpotResolvedObjectType computeValidType(HotSpotMethodData data, int offset){ if(!isTypeNone() && ! isTypeUnknown()){ return compilerToVM().getResolvedJavaType(data, offset, typeKlassMask); }else{ @@ -808,9 +817,47 @@ public boolean alwaysNull(){ @Override public boolean inlineType(){ - return inlineType; + return (flags & getInlineFlag()) !=0; + } + + } + + static class LeftSingleTypeEntryImpl extends SingleTypeEntryImpl { + + LeftSingleTypeEntryImpl(ACmpData aCmpData,HotSpotMethodData data, int position) { + super(aCmpData, data, position); + } + + LeftSingleTypeEntryImpl(){} + + @Override + int getOperandOffset(){ + return state.leftOperandOffset; + } + + @Override + int getInlineFlag(){ + return state.leftInlineTypeFlag; + } + } + + static class RightSingleTypeEntryImpl extends SingleTypeEntryImpl { + + RightSingleTypeEntryImpl(ACmpData aCmpData, HotSpotMethodData data, int position) { + super(aCmpData, data, position); + } + + RightSingleTypeEntryImpl(){} + + @Override + int getOperandOffset(){ + return state.rightOperandOffset; } + @Override + int getInlineFlag(){ + return state.rightInlineTypeFlag; + } } static class ACmpDataAccessorImpl implements ACmpDataAccessor{ @@ -819,15 +866,25 @@ static class ACmpDataAccessorImpl implements ACmpDataAccessor{ private final SingleTypeEntry right; ACmpDataAccessorImpl(ACmpData aCmpData, HotSpotMethodData data, int position){ - left = aCmpData.getLeft(data, position); - right = aCmpData.getRight(data, position); + left = aCmpData.getLeft(aCmpData, data, position); + right = aCmpData.getRight(aCmpData, data, position); } ACmpDataAccessorImpl(){ - left = new SingleTypeEntryImpl(1, false, null, 0); - right = new SingleTypeEntryImpl(1, false, null, 0); -// left = null; -// right = null; +// left = new SingleTypeEntryImpl(1, false, null, 0); +// right = new SingleTypeEntryImpl(1, false, null, 0); + left = new LeftSingleTypeEntryImpl(){ + @Override + int getInlineFlag() { + return 0; + } + }; + right = new RightSingleTypeEntryImpl(){ + @Override + int getInlineFlag() { + return 0; + } + }; } @Override @@ -846,19 +903,12 @@ public SingleTypeEntry getRight() { super(state, tag, state.acmpDataSize); } - private SingleTypeEntry getLeft(HotSpotMethodData data, int position) { - return new SingleTypeEntryImpl(data.readPointer(position, state.leftOperandOffset), inlineType(data, position, true), data, state.computeFullOffset(position, state.leftOperandOffset)); + private SingleTypeEntry getLeft(ACmpData aCmpData, HotSpotMethodData data, int position) { + return new LeftSingleTypeEntryImpl(aCmpData, data, position); } - private SingleTypeEntry getRight(HotSpotMethodData data, int position) { - return new SingleTypeEntryImpl(data.readPointer(position, state.rightOperandOffset), inlineType(data, position, false), data, state.computeFullOffset(position, state.rightOperandOffset)); - } - - private boolean inlineType(HotSpotMethodData data, int position, boolean left){ - if(left){ - return (getFlags(data, position) & state.leftInlineTypeFlag) !=0; - } - return (getFlags(data, position) & state.rightInlineTypeFlag) !=0; + private SingleTypeEntry getRight(ACmpData aCmpData, HotSpotMethodData data, int position) { + return new RightSingleTypeEntryImpl(aCmpData, data, position); } public ACmpDataAccessor getACmpAccessor(HotSpotMethodData data, int position){ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index c37108c591f..de1ff7277f7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -125,7 +125,7 @@ public TriState getExceptionSeen(int bci) { } @Override - public ACmpDataAccessor getAcmpData(int bci) { + public ACmpDataAccessor getACmpData(int bci) { // if (!isMature) { // return null; // } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index 6ec36ad11b5..003e0dd5e31 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -70,9 +70,9 @@ public TriState getExceptionSeen(int bci) { } @Override - public ACmpDataAccessor getAcmpData(int bci) { + public ACmpDataAccessor getACmpData(int bci) { return ACmpDataAccessor.create(); -// return null; + //return null; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java index 6ab71c383a8..0092a66746c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java @@ -23,6 +23,7 @@ package jdk.vm.ci.meta; import jdk.vm.ci.hotspot.ACmpDataAccessor; +import jdk.vm.ci.hotspot.SingleTypeEntry; /** * Provides access to the profiling information of one specific method. Every accessor method @@ -82,7 +83,7 @@ public interface ProfilingInfo { * * @return Returns a AcmpData object, or null if not available. */ - ACmpDataAccessor getAcmpData(int bci); + ACmpDataAccessor getACmpData(int bci); /** * Returns information if null was ever seen for the given BCI. This information is collected @@ -180,8 +181,12 @@ default String toString(ResolvedJavaMethod method, String sep) { buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep)); } - if (getAcmpData(i) != null) { - buf.append("acmp_found\n"); + if (getACmpData(i) != null) { + SingleTypeEntry left = getACmpData(i).getLeft(); + String formatString = "ACmpType@%d: %s alwaysNull:%b inlineType:%b%s"; + buf.append(String.format(formatString, i, left.getValidType(), left.alwaysNull(), left.inlineType(), sep)); + SingleTypeEntry right = getACmpData(i).getRight(); + buf.append(String.format(formatString, i, right.getValidType(), right.alwaysNull(), right.inlineType(), sep)); } JavaTypeProfile typeProfile = getTypeProfile(i); From bd0f11c6f60a0fc2e07a5581435198c23eec3bd8 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Oct 2024 11:34:44 +0200 Subject: [PATCH 07/98] expanding interface for acmp profiling data --- .../jdk/vm/ci/hotspot/ACmpDataAccessor.java | 9 ++-- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 47 +++++++++++++++++-- .../vm/ci/hotspot/HotSpotProfilingInfo.java | 6 +-- .../jdk/vm/ci/hotspot/SingleTypeEntry.java | 3 ++ .../jdk/vm/ci/meta/DefaultProfilingInfo.java | 4 +- 5 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java index afc21f5d2fb..30873072aaa 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java @@ -1,11 +1,14 @@ package jdk.vm.ci.hotspot; public interface ACmpDataAccessor { - public SingleTypeEntry getLeft(); + SingleTypeEntry getLeft(); - public SingleTypeEntry getRight(); + SingleTypeEntry getRight(); - public static ACmpDataAccessor create(){ + void setDeoptClassCheck(); + void setDeoptNullCheck(); + + static ACmpDataAccessor create(){ return new HotSpotMethodData.ACmpData.ACmpDataAccessorImpl(); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index feee26a9aa9..be4211f3996 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -739,7 +739,11 @@ abstract static class SingleTypeEntryImpl implements SingleTypeEntry { final long value; final int flags; final VMState state; - final HotSpotResolvedObjectType validType; + HotSpotResolvedObjectType validType; + boolean maybeNull; + boolean neverNull; + boolean alwaysNull; + boolean inlineType; final static long nullSeen =1; final static long typeMask = ~nullSeen; @@ -753,6 +757,10 @@ abstract static class SingleTypeEntryImpl implements SingleTypeEntry { this.value = data.readPointer(position, getOperandOffset()); int offset = state.computeFullOffset(position, getOperandOffset()); this.validType = computeValidType(data, offset); + this.maybeNull =wasNullSeen() && isTypeNone(); + this.neverNull = wasNullSeen(); + this.alwaysNull= maybeNull(); + this.inlineType =(flags & getInlineFlag()) !=0; } SingleTypeEntryImpl() { @@ -760,6 +768,10 @@ abstract static class SingleTypeEntryImpl implements SingleTypeEntry { this.state = null; this.flags = 0; this.validType = null; + this.maybeNull =wasNullSeen() && isTypeNone(); + this.neverNull = wasNullSeen(); + this.alwaysNull= maybeNull(); + this.inlineType =false; } abstract int getOperandOffset(); @@ -802,22 +814,35 @@ public HotSpotResolvedObjectType getValidType(){ @Override public boolean maybeNull(){ - return wasNullSeen() && isTypeNone(); + return maybeNull; } @Override public boolean neverNull(){ - return wasNullSeen(); + return neverNull; } @Override public boolean alwaysNull(){ - return maybeNull(); + return alwaysNull; } @Override public boolean inlineType(){ - return (flags & getInlineFlag()) !=0; + return inlineType; + } + + @Override + public void setDeoptClassCheck(){ + this.validType=null; + this.inlineType=true; + } + + @Override + public void setDeoptNullCheck(){ + this.alwaysNull=false; + this.neverNull=false; + this.maybeNull=false; } } @@ -896,6 +921,18 @@ public SingleTypeEntry getLeft() { public SingleTypeEntry getRight() { return right; } + + @Override + public void setDeoptClassCheck() { + left.setDeoptClassCheck(); + right.setDeoptClassCheck(); + } + + @Override + public void setDeoptNullCheck() { + left.setDeoptNullCheck(); + right.setDeoptNullCheck(); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index de1ff7277f7..dca9e4d4e67 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -126,9 +126,9 @@ public TriState getExceptionSeen(int bci) { @Override public ACmpDataAccessor getACmpData(int bci) { -// if (!isMature) { -// return null; -// } + if (!isMature) { + return null; + } findBCI(bci); if(dataAccessor instanceof HotSpotMethodData.ACmpData aCmpData){ return aCmpData.getACmpAccessor(methodData, position); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java index 2167a1e68af..96a83ef0791 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java @@ -21,4 +21,7 @@ public interface SingleTypeEntry{ boolean inlineType(); + void setDeoptClassCheck(); + void setDeoptNullCheck(); + } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index 003e0dd5e31..cac1ef5d1ef 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -71,8 +71,8 @@ public TriState getExceptionSeen(int bci) { @Override public ACmpDataAccessor getACmpData(int bci) { - return ACmpDataAccessor.create(); - //return null; + //return ACmpDataAccessor.create(); + return null; } @Override From 2f5c93514e87e76e08998067a0e2ba75b0c41f75 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 15 Oct 2024 18:38:05 +0200 Subject: [PATCH 08/98] bug fixing and refactoring --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 6 ++--- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 ++ src/hotspot/share/oops/methodData.hpp | 6 +++-- .../jdk/vm/ci/hotspot/CompilerToVM.java | 10 +++----- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 25 +++++++++++-------- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 2 ++ 6 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 6b17ccb6dbd..2430207a6f8 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -442,7 +442,7 @@ C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, ARGUMENT_PAIR( return JVMCIENV->get_jobject(result); } -C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed, jlong mask)) +C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed)) JVMCIObject base_object = JVMCIENV->wrap(base); if (base_object.is_null()) { JVMCI_THROW_MSG_NULL(NullPointerException, "base object is null"); @@ -506,7 +506,7 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject b } else if (JVMCIENV->isa_HotSpotMethodData(base_object)) { jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object); Klass* temp = *((Klass**) (intptr_t) (base_address + offset)); - temp = (Klass*)(((uintptr_t) temp)&mask); + temp = (Klass*)(((uintptr_t) temp)& WordAlignmentMask); klass = temp; //klass = *((Klass**) (intptr_t) (base_address + offset)); if (klass == nullptr || !klass->is_loader_alive()) { @@ -3307,7 +3307,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "asResolvedJavaMethod", CC "(" EXECUTABLE ")" HS_METHOD, FN_PTR(asResolvedJavaMethod)}, {CC "getResolvedJavaMethod", CC "(" OBJECTCONSTANT "J)" HS_METHOD, FN_PTR(getResolvedJavaMethod)}, {CC "getConstantPool", CC "(" OBJECT "JZ)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)}, - {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZJ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, + {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, {CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)}, {CC "installCode0", CC "(JJZ" HS_COMPILED_CODE "[" OBJECT INSTALLED_CODE "J[B)I", FN_PTR(installCode0)}, {CC "getInstallCodeFlags", CC "()I", FN_PTR(getInstallCodeFlags)}, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 7ac2aa3ca6f..f1120ffa05a 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -534,6 +534,8 @@ declare_constant(BitData::exception_seen_flag) \ declare_constant(BitData::null_seen_flag) \ declare_constant(BranchData::not_taken_off_set) \ + declare_constant(ACmpData::left_inline_type_flag) \ + declare_constant(ACmpData::right_inline_type_flag) \ \ declare_constant_with_value("CardTable::dirty_card", CardTable::dirty_card_val()) \ declare_constant_with_value("LockStack::_end_offset", LockStack::end_offset()) \ diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 95df989fec6..dcef8ac8418 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -2016,12 +2016,14 @@ class ArrayLoadData : public ProfileData { }; class ACmpData : public BranchData { -private: + friend class VMStructs; + friend class JVMCIVMStructs; +protected: enum { left_inline_type_flag = DataLayout::first_flag, right_inline_type_flag }; - +private: SingleTypeEntry _left; SingleTypeEntry _right; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index b3d08ed2dd6..cf98a2ee681 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -993,14 +993,10 @@ HotSpotConstantPool getConstantPool(MetaspaceObject object) { * @throws NullPointerException if {@code base == null} */ - private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed, long mask); + private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed); - HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed){ - return getResolvedJavaType0(base, displacement, compressed, -1); - } - - HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement, long mask){ - return getResolvedJavaType0(base, displacement, false, mask); + HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement){ + return getResolvedJavaType0(base, displacement, false); } HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotConstantPool base, long displacement) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index be4211f3996..49f13576614 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -78,11 +78,12 @@ static final class VMState { final int notTakenCountOffset = cellIndexToOffset(config.branchDataNotTakenOffset); // inherits from branch and two cells for types - final int acmpDataSize = branchDataSize+ cellsToBytes(1)*2; + final int acmpDataSize = branchDataSize + cellsToBytes(1)*2; + // TODO: get values from VM final int leftOperandOffset = cellIndexToOffset(3); final int rightOperandOffset = cellIndexToOffset(4); - final int leftInlineTypeFlag = 1; - final int rightInlineTypeFlag = 1<<1; + final int leftInlineTypeFlag = 1 << config.leftInlineTypeFlag; + final int rightInlineTypeFlag = 1 << config.rightInlineTypeFlag; final int arrayDataLengthOffset = cellIndexToOffset(config.arrayDataArrayLenOffset); final int arrayDataStartOffset = cellIndexToOffset(config.arrayDataArrayStartOffset); @@ -757,9 +758,13 @@ abstract static class SingleTypeEntryImpl implements SingleTypeEntry { this.value = data.readPointer(position, getOperandOffset()); int offset = state.computeFullOffset(position, getOperandOffset()); this.validType = computeValidType(data, offset); - this.maybeNull =wasNullSeen() && isTypeNone(); - this.neverNull = wasNullSeen(); - this.alwaysNull= maybeNull(); + if(!wasNullSeen()){ + this.neverNull = true; + }else if(isTypeNone()){ + this.alwaysNull = true; + }else{ + this.maybeNull = true; + } this.inlineType =(flags & getInlineFlag()) !=0; } @@ -768,9 +773,9 @@ abstract static class SingleTypeEntryImpl implements SingleTypeEntry { this.state = null; this.flags = 0; this.validType = null; - this.maybeNull =wasNullSeen() && isTypeNone(); - this.neverNull = wasNullSeen(); - this.alwaysNull= maybeNull(); + this.maybeNull = wasNullSeen() && !isTypeNone(); + this.neverNull = !wasNullSeen(); + this.alwaysNull= isTypeNone(); this.inlineType =false; } @@ -800,7 +805,7 @@ public long klassPart(){ private HotSpotResolvedObjectType computeValidType(HotSpotMethodData data, int offset){ if(!isTypeNone() && ! isTypeUnknown()){ - return compilerToVM().getResolvedJavaType(data, offset, typeKlassMask); + return compilerToVM().getResolvedJavaType(data, offset); }else{ return null; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 4eb85365ce1..23c47885fd8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -389,4 +389,6 @@ String getCodeInstallResultDescription(int codeInstallResult) { final int arrayDataArrayLenOffset = getConstant("ArrayData::array_len_off_set", Integer.class); final int arrayDataArrayStartOffset = getConstant("ArrayData::array_start_off_set", Integer.class); final int multiBranchDataPerCaseCellCount = getConstant("MultiBranchData::per_case_cell_count", Integer.class); + final int leftInlineTypeFlag = getConstant("ACmpData::left_inline_type_flag", Integer.class); + final int rightInlineTypeFlag = getConstant("ACmpData::right_inline_type_flag", Integer.class); } From a5e4058890a9257e7807cc4376d639c7cd0d811b Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 17 Oct 2024 11:37:46 +0200 Subject: [PATCH 09/98] refactoring of acmp data profiling interface --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 8 +- .../jdk/vm/ci/hotspot/ACmpDataAccessor.java | 4 - .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 89 ++++++------------- .../jdk/vm/ci/hotspot/SingleTypeEntry.java | 8 -- .../jdk/vm/ci/meta/DefaultProfilingInfo.java | 1 - 5 files changed, 30 insertions(+), 80 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 2430207a6f8..e7468c2fd3d 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -505,10 +505,10 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject b } } else if (JVMCIENV->isa_HotSpotMethodData(base_object)) { jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object); - Klass* temp = *((Klass**) (intptr_t) (base_address + offset)); - temp = (Klass*)(((uintptr_t) temp)& WordAlignmentMask); - klass = temp; - //klass = *((Klass**) (intptr_t) (base_address + offset)); + intptr_t temp = (intptr_t) *((Klass**) (intptr_t) (base_address + offset)); + // clear the bits used for acmp data profiling + clear_bits(temp, 0b011); + klass = (Klass*) temp; if (klass == nullptr || !klass->is_loader_alive()) { // Klasses in methodData might be concurrently unloading so return null in that case. return nullptr; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java index 30873072aaa..2e2622e5bd9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java @@ -7,8 +7,4 @@ public interface ACmpDataAccessor { void setDeoptClassCheck(); void setDeoptNullCheck(); - - static ACmpDataAccessor create(){ - return new HotSpotMethodData.ACmpData.ACmpDataAccessorImpl(); - } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index 49f13576614..fbcab80058e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -737,74 +737,58 @@ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) static class ACmpData extends BranchData { abstract static class SingleTypeEntryImpl implements SingleTypeEntry { - final long value; - final int flags; - final VMState state; - HotSpotResolvedObjectType validType; - boolean maybeNull; - boolean neverNull; - boolean alwaysNull; - boolean inlineType; + private final long value; + private final VMState state; + private HotSpotResolvedObjectType validType; + private boolean maybeNull; + private boolean neverNull; + private boolean alwaysNull; + private boolean inlineType; final static long nullSeen =1; final static long typeMask = ~nullSeen; final static long typeUnknown = 2; - final static long statusBits = nullSeen | typeUnknown; - final static long typeKlassMask = ~statusBits; SingleTypeEntryImpl(ACmpData aCmpData, HotSpotMethodData data, int position) { this.state = aCmpData.state; - this.flags = aCmpData.getFlags(data, position); this.value = data.readPointer(position, getOperandOffset()); + int offset = state.computeFullOffset(position, getOperandOffset()); - this.validType = computeValidType(data, offset); - if(!wasNullSeen()){ + this.validType = computeValidType(this.value, data, offset); + + if(!wasNullSeen(this.value)){ this.neverNull = true; - }else if(isTypeNone()){ + }else if(isTypeNone(this.value)){ this.alwaysNull = true; }else{ this.maybeNull = true; } - this.inlineType =(flags & getInlineFlag()) !=0; - } - SingleTypeEntryImpl() { - this.value = 0; - this.state = null; - this.flags = 0; - this.validType = null; - this.maybeNull = wasNullSeen() && !isTypeNone(); - this.neverNull = !wasNullSeen(); - this.alwaysNull= isTypeNone(); - this.inlineType =false; + int flags = aCmpData.getFlags(data, position); + this.inlineType =(flags & getInlineFlag()) !=0; } abstract int getOperandOffset(); abstract int getInlineFlag(); + protected VMState getState(){ + return state; + } - @Override - public boolean isTypeNone(){ + private static boolean isTypeNone(long value){ return (value & typeMask) == 0; } - @Override - public boolean isTypeUnknown(){ + private static boolean isTypeUnknown(long value){ return (value & typeUnknown) != 0; } - @Override - public boolean wasNullSeen(){ + private static boolean wasNullSeen(long value){ return (value & nullSeen) != 0; } - @Override - public long klassPart(){ - return value & typeKlassMask; - } - - private HotSpotResolvedObjectType computeValidType(HotSpotMethodData data, int offset){ - if(!isTypeNone() && ! isTypeUnknown()){ + private HotSpotResolvedObjectType computeValidType(long value, HotSpotMethodData data, int offset){ + if(!isTypeNone(value) && ! isTypeUnknown(value)){ return compilerToVM().getResolvedJavaType(data, offset); }else{ return null; @@ -858,16 +842,14 @@ static class LeftSingleTypeEntryImpl extends SingleTypeEntryImpl { super(aCmpData, data, position); } - LeftSingleTypeEntryImpl(){} - @Override int getOperandOffset(){ - return state.leftOperandOffset; + return getState().leftOperandOffset; } @Override int getInlineFlag(){ - return state.leftInlineTypeFlag; + return getState().leftInlineTypeFlag; } } @@ -877,16 +859,14 @@ static class RightSingleTypeEntryImpl extends SingleTypeEntryImpl { super(aCmpData, data, position); } - RightSingleTypeEntryImpl(){} - @Override int getOperandOffset(){ - return state.rightOperandOffset; + return getState().rightOperandOffset; } @Override int getInlineFlag(){ - return state.rightInlineTypeFlag; + return getState().rightInlineTypeFlag; } } @@ -900,23 +880,6 @@ static class ACmpDataAccessorImpl implements ACmpDataAccessor{ right = aCmpData.getRight(aCmpData, data, position); } - ACmpDataAccessorImpl(){ -// left = new SingleTypeEntryImpl(1, false, null, 0); -// right = new SingleTypeEntryImpl(1, false, null, 0); - left = new LeftSingleTypeEntryImpl(){ - @Override - int getInlineFlag() { - return 0; - } - }; - right = new RightSingleTypeEntryImpl(){ - @Override - int getInlineFlag() { - return 0; - } - }; - } - @Override public SingleTypeEntry getLeft() { return left; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java index 96a83ef0791..6a2ad9dcca7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java @@ -3,14 +3,6 @@ public interface SingleTypeEntry{ - boolean isTypeNone(); - - boolean isTypeUnknown(); - - boolean wasNullSeen(); - - long klassPart(); - HotSpotResolvedObjectType getValidType(); boolean maybeNull(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index cac1ef5d1ef..72fcc122d55 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -71,7 +71,6 @@ public TriState getExceptionSeen(int bci) { @Override public ACmpDataAccessor getACmpData(int bci) { - //return ACmpDataAccessor.create(); return null; } From 443eacad0d5f1458f0d51cac4d753abcd24ce68c Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 29 Oct 2024 09:46:43 +0100 Subject: [PATCH 10/98] support for hashCode on inline types --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 12 ++++++++++++ src/hotspot/share/jvmci/jvmciRuntime.hpp | 3 ++- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index e12d77cfb9a..d0b86a0f1ab 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -426,6 +426,18 @@ JRT_ENTRY(jboolean, JVMCIRuntime::substitutability_check(JavaThread* current, oo return result.get_jboolean(); JRT_END +JRT_ENTRY(jint, JVMCIRuntime::value_object_hashCode(JavaThread* current, oopDesc* obj)) + JavaCallArguments args; + args.push_oop(Handle(THREAD, obj)); + JavaValue result(T_INT); + JavaCalls::call_static(&result, + vmClasses::ValueObjectMethods_klass(), + vmSymbols::valueObjectHashCode_name(), + vmSymbols::object_int_signature(), + &args, CHECK_0); + return result.get_jint(); +JRT_END + // Object.notifyAll() fast path, caller does slow path JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread* current, oopDesc* obj)) assert(current == JavaThread::current(), "pre-condition"); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 613f9718160..8d6c6121ed7 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -521,13 +521,14 @@ class JVMCIRuntime: public CHeapObj { static void vm_message(jboolean vmError, jlong format, jlong v1, jlong v2, jlong v3); static jint identity_hash_code(JavaThread* current, oopDesc* obj); + static jint value_object_hashCode(JavaThread* current, oopDesc* obj); static address exception_handler_for_pc(JavaThread* current); static void monitorenter(JavaThread* current, oopDesc* obj, BasicLock* lock); static void monitorexit (JavaThread* current, oopDesc* obj, BasicLock* lock); static jboolean object_notify(JavaThread* current, oopDesc* obj); static jboolean object_notifyAll(JavaThread* current, oopDesc* obj); static jboolean substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right); - + static void vm_error(JavaThread* current, jlong where, jlong format, jlong value); static oopDesc* load_and_clear_exception(JavaThread* thread); static void log_printf(JavaThread* thread, const char* format, jlong v1, jlong v2, jlong v3); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index f1120ffa05a..bfc30fc43f2 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -877,6 +877,7 @@ declare_function(JVMCIRuntime::monitorenter) \ declare_function(JVMCIRuntime::monitorexit) \ declare_function(JVMCIRuntime::substitutability_check) \ + declare_function(JVMCIRuntime::value_object_hashCode) \ declare_function(JVMCIRuntime::object_notify) \ declare_function(JVMCIRuntime::object_notifyAll) \ declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \ From 838d4e2d9be135a0a126a8479ba84c213730d274 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 8 Nov 2024 18:11:53 +0100 Subject: [PATCH 11/98] support for getfield and putfield on null-restricted flattened fields --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 7 +- src/hotspot/share/jvmci/jvmciEnv.cpp | 4 +- src/hotspot/share/jvmci/jvmciJavaClasses.hpp | 3 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 8 + src/hotspot/share/oops/fieldInfo.hpp | 1 + src/hotspot/share/oops/instanceKlass.hpp | 2 + .../hotspot/HotSpotResolvedJavaFieldImpl.java | 23 ++- .../ci/hotspot/HotSpotResolvedObjectType.java | 1 + .../HotSpotResolvedObjectTypeImpl.java | 177 ++++++++++++++---- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 9 + .../jdk/vm/ci/meta/ResolvedJavaField.java | 23 +++ 11 files changed, 209 insertions(+), 49 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index e7468c2fd3d..d8d387713f2 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -47,6 +47,7 @@ #include "oops/constantPool.inline.hpp" #include "oops/instanceKlass.inline.hpp" #include "oops/instanceMirrorKlass.hpp" +#include "oops/methodData.hpp" #include "oops/method.inline.hpp" #include "oops/objArrayKlass.inline.hpp" #include "oops/typeArrayOop.inline.hpp" @@ -506,9 +507,9 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject b } else if (JVMCIENV->isa_HotSpotMethodData(base_object)) { jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object); intptr_t temp = (intptr_t) *((Klass**) (intptr_t) (base_address + offset)); - // clear the bits used for acmp data profiling - clear_bits(temp, 0b011); - klass = (Klass*) temp; + + // profiled type: cell without bit 0 and 1 + klass = (Klass*) (temp & TypeEntries::type_klass_mask); if (klass == nullptr || !klass->is_loader_alive()) { // Klasses in methodData might be concurrently unloading so return null in that case. return nullptr; diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 78f5bca4769..71e9a83b0c0 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1594,6 +1594,7 @@ JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) { HotSpotJVMCI::FieldInfo::set_classfileFlags(JVMCIENV, obj_h(), (jint)fieldinfo->access_flags().as_field_flags()); HotSpotJVMCI::FieldInfo::set_internalFlags(JVMCIENV, obj_h(), (jint)fieldinfo->field_flags().as_uint()); HotSpotJVMCI::FieldInfo::set_initializerIndex(JVMCIENV, obj_h(), (jint)fieldinfo->initializer_index()); + HotSpotJVMCI::FieldInfo::set_nullMarkerOffset(JVMCIENV, obj_h(), (jint)fieldinfo->null_marker_offset()); return wrap(obj_h()); } else { JNIAccessMark jni(this, THREAD); @@ -1604,7 +1605,8 @@ JVMCIObject JVMCIEnv::new_FieldInfo(FieldInfo* fieldinfo, JVMCI_TRAPS) { (jint)fieldinfo->offset(), (jint)fieldinfo->access_flags().as_field_flags(), (jint)fieldinfo->field_flags().as_uint(), - (jint)fieldinfo->initializer_index()); + (jint)fieldinfo->initializer_index(), + (jint)fieldinfo->null_marker_offset()); return wrap(result); } diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index d5fcd2aaaba..fe1bf265c26 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -79,7 +79,8 @@ int_field(FieldInfo, classfileFlags) \ int_field(FieldInfo, internalFlags) \ int_field(FieldInfo, initializerIndex) \ - jvmci_constructor(FieldInfo, "(IIIIII)V") \ + int_field(FieldInfo, nullMarkerOffset) \ + jvmci_constructor(FieldInfo, "(IIIIIII)V") \ end_class \ start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) \ long_field(HotSpotResolvedJavaMethodImpl, methodHandle) \ diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index bfc30fc43f2..6ff96e6343a 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -267,6 +267,10 @@ nonstatic_field(Klass, _secondary_supers, Array*) \ nonstatic_field(Klass, _super, Klass*) \ nonstatic_field(Klass, _super_check_offset, juint) \ + nonstatic_field(InstanceKlass, _adr_inlineklass_fixed_block, InlineKlassFixedBlock*) \ + nonstatic_field(InlineKlassFixedBlock, _first_field_offset, int) \ + nonstatic_field(InlineKlassFixedBlock, _internal_null_marker_offset, int) \ + nonstatic_field(FieldInfo, _null_marker_offset, u4) \ volatile_nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ nonstatic_field(Klass, _prototype_header, markWord) \ @@ -489,6 +493,10 @@ \ declare_constant(FieldInfo::FieldFlags::_ff_injected) \ declare_constant(FieldInfo::FieldFlags::_ff_stable) \ + declare_constant(FieldInfo::FieldFlags::_ff_flat) \ + declare_constant(FieldInfo::FieldFlags::_ff_null_free_inline_type) \ + declare_constant(FieldInfo::FieldFlags::_ff_null_marker) \ + declare_constant(FieldInfo::FieldFlags::_ff_internal_null_marker) \ declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \ declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE) \ declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \ diff --git a/src/hotspot/share/oops/fieldInfo.hpp b/src/hotspot/share/oops/fieldInfo.hpp index 07fed489ee3..74186abf602 100644 --- a/src/hotspot/share/oops/fieldInfo.hpp +++ b/src/hotspot/share/oops/fieldInfo.hpp @@ -60,6 +60,7 @@ class FieldInfo { friend class FieldStreamBase; friend class FieldInfoReader; friend class VMStructs; + friend class JVMCIVMStructs; public: diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 4227ee0e996..edb426c82e0 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -140,6 +140,8 @@ struct JvmtiCachedClassFileData; class SigEntry; class InlineKlassFixedBlock { + friend class JVMCIVMStructs; + Array** _extended_sig; Array** _return_regs; address* _pack_handler; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 6eb4dfb9b02..767219cd4c7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -33,11 +33,7 @@ import java.util.List; import jdk.internal.vm.VMSupport; -import jdk.vm.ci.meta.AnnotationData; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaType; -import jdk.vm.ci.meta.UnresolvedJavaType; +import jdk.vm.ci.meta.*; /** * Represents a field in a HotSpot type. @@ -51,7 +47,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { * Offset (in bytes) of field from start of its storage container (i.e. {@code instanceOop} or * {@code Klass*}). */ - private final int offset; + private int offset; /** * Value of {@code fieldDescriptor::index()}. @@ -108,6 +104,16 @@ public boolean isInternal() { return (internalFlags & (1 << config().jvmFieldFlagInternalShift)) != 0; } + @Override + public boolean isNullFreeInlineType() { + return (internalFlags & (1 << config().jvmFieldFlagNullFreeInlineTypeShift)) != 0; + } + + @Override + public boolean isFlat(){ + return (internalFlags & (1 << config().jvmFieldFlagFlatShift)) != 0; + } + /** * Determines if a given object contains this field. * @@ -159,6 +165,11 @@ public int getOffset() { return offset; } + @Override + public ResolvedJavaField changeOffset(int newOffset) { + return new HotSpotResolvedJavaFieldImpl(holder, type, newOffset, classfileFlags, internalFlags, index); + } + /** * Gets the value of this field's index (i.e. {@code fieldDescriptor::index()} in the encoded * fields of the declaring class. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 0417a761fc4..ae9b2fd7e4d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -97,6 +97,7 @@ default JavaKind getJavaKind() { boolean isPrimaryType(); int superCheckOffset(); + int firstFieldOffset(); long prototypeMarkWord(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index dfb126f57eb..04ba8b4b785 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -22,6 +22,17 @@ */ package jdk.vm.ci.hotspot; +import jdk.internal.vm.VMSupport; +import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.meta.*; +import jdk.vm.ci.meta.Assumptions.*; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.ByteOrder; +import java.util.*; + import static java.util.Objects.requireNonNull; import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; import static jdk.vm.ci.hotspot.HotSpotConstantPool.isSignaturePolymorphicHolder; @@ -30,34 +41,6 @@ import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.ByteOrder; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.List; - -import jdk.internal.vm.VMSupport; -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.meta.AnnotationData; -import jdk.vm.ci.meta.Assumptions.AssumptionResult; -import jdk.vm.ci.meta.Assumptions.ConcreteMethod; -import jdk.vm.ci.meta.Assumptions.ConcreteSubtype; -import jdk.vm.ci.meta.Assumptions.LeafType; -import jdk.vm.ci.meta.Assumptions.NoFinalizableSubclass; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -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; - /** * Implementation of {@link JavaType} for resolved non-primitive HotSpot classes. This class is not * an {@link MetaspaceHandleObject} because it doesn't have to be scanned for GC. It's liveness is @@ -104,7 +87,7 @@ static HotSpotResolvedObjectTypeImpl getJavaLangObject() { /** * Gets the JVMCI mirror from a HotSpot type. - * + *

* Called from the VM. * * @param klassPointer a native pointer to the Klass* @@ -699,24 +682,35 @@ static class FieldInfo { private final int classfileFlags; private final int internalFlags; private final int initializerIndex; + private final int nullMarkerOffset; /** * Creates a field info with the provided indices. * - * @param nameIndex index of field's name in the constant pool - * @param signatureIndex index of field's signature in the constant pool - * @param offset field's offset - * @param classfileFlags field's access flags (from the class file) - * @param internalFlags field's internal flags (from the VM) + * @param nameIndex index of field's name in the constant pool + * @param signatureIndex index of field's signature in the constant pool + * @param offset field's offset + * @param classfileFlags field's access flags (from the class file) + * @param internalFlags field's internal flags (from the VM) * @param initializerIndex field's initial value index in the constant pool */ - FieldInfo(int nameIndex, int signatureIndex, int offset, int classfileFlags, int internalFlags, int initializerIndex) { +// FieldInfo(int nameIndex, int signatureIndex, int offset, int classfileFlags, int internalFlags, int initializerIndex) { +// this.nameIndex = nameIndex; +// this.signatureIndex = signatureIndex; +// this.offset = offset; +// this.classfileFlags = classfileFlags; +// this.internalFlags = internalFlags; +// this.initializerIndex = initializerIndex; +// } + + FieldInfo(int nameIndex, int signatureIndex, int offset, int classfileFlags, int internalFlags, int initializerIndex, int nullMarkerOffset) { this.nameIndex = nameIndex; this.signatureIndex = signatureIndex; this.offset = offset; this.classfileFlags = classfileFlags; this.internalFlags = internalFlags; this.initializerIndex = initializerIndex; + this.nullMarkerOffset = nullMarkerOffset; } private int getClassfileFlags() { @@ -743,9 +737,14 @@ public int getOffset() { return offset; } + public int getNullMarkerOffset() { + return nullMarkerOffset; + } + /** * Returns the name of this field as a {@link String}. If the field is an internal field the * name index is pointing into the vmSymbols table. + * * @param klass field's holder class */ public String getName(HotSpotResolvedObjectTypeImpl klass) { @@ -755,6 +754,7 @@ public String getName(HotSpotResolvedObjectTypeImpl klass) { /** * Returns the signature of this field as {@link String}. If the field is an internal field * the signature index is pointing into the vmSymbols table. + * * @param klass field's holder class */ public String getSignature(HotSpotResolvedObjectTypeImpl klass) { @@ -782,6 +782,28 @@ private boolean isInternal() { return (getInternalFlags() & (1 << config().jvmFieldFlagInternalShift)) != 0; } + private boolean isFlat() { + return (getInternalFlags() & (1 << config().jvmFieldFlagFlatShift)) != 0; + } + + private boolean isNullFreeInlineType() { + return (getInternalFlags() & (1 << config().jvmFieldFlagNullFreeInlineTypeShift)) != 0; + } + + private boolean hasNullMarker() { + return (getInternalFlags() & (1 << config().jvmFieldFlagNullMarkerShift)) != 0; + } + + private boolean hasInternalNullMarker() { + return (getInternalFlags() & (1 << config().jvmFieldFlagInternalNullMarkerShift)) != 0; + } + +// private int internalNullMarkerOffset() { +// HotSpotVMConfig config = config(); +// long fixedBlockPointer = UNSAFE.getAddress(getKlassPointer() + config.inlineKlassFixedBlockAdr); +// return UNSAFE.getInt(fixedBlockPointer + config.internalNullMarkerOffset); +// } + public boolean isStatic() { return Modifier.isStatic(getClassfileFlags()); } @@ -795,6 +817,10 @@ public int compare(ResolvedJavaField a, ResolvedJavaField b) { @Override public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { + return getInstanceFields(includeSuperclasses, true); + } + + public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses, boolean flat) { if (instanceFields == null) { if (isArray() || isInterface()) { instanceFields = NO_FIELDS; @@ -803,7 +829,12 @@ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { if (getSuperclass() != null) { prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); } - instanceFields = getFields(false, prepend); + if (flat) { + instanceFields = getFlattenedFields(prepend); + } else { + instanceFields = getFields(false, prepend); + } + } } if (!includeSuperclasses && getSuperclass() != null) { @@ -840,12 +871,75 @@ public ResolvedJavaField[] getStaticFields() { } } + /** + * Gets the (flattened) instance fields of this class. + * + * @param prepend an array to be prepended to the returned result + */ + private HotSpotResolvedJavaField[] getFlattenedFields(HotSpotResolvedJavaField[] prepend) { + + + HotSpotVMConfig config = config(); + int resultCount = 0; + int index = 0; + + + for (index = 0; index < getFieldInfo().length; index++) { + if (!getFieldInfo(index).isStatic()) { + resultCount++; + } + } + + if (resultCount == 0) { + return prepend; + } + + List resultList = new ArrayList<>(Arrays.asList(prepend)); + + int prependLength = prepend.length; + resultCount = 0; + resultCount += prependLength; + + for (index = 0; index < getFieldInfo().length; index++) { + if (getFieldInfo(index).isStatic()) continue; + + FieldInfo fieldInfo = getFieldInfo(index); + int fieldOffset = fieldInfo.getOffset(); + if (fieldInfo.isFlat()) { + HotSpotResolvedJavaField resolvedJavaField = createField(getFieldInfo(index).getType(this), fieldInfo.getOffset(), fieldInfo.getClassfileFlags(), fieldInfo.getInternalFlags(), index); + JavaType field = resolvedJavaField.getType(); + + if (field instanceof HotSpotResolvedObjectType resolvedFieldType) { + ResolvedJavaField[] innerFields = resolvedFieldType.getInstanceFields(true); + resultCount += innerFields.length; + + // compute all flattened fields recursively + for (int i = 0; i < innerFields.length; ++i) { + // holder has no header so remove the header offset + int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.firstFieldOffset()); + HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; + resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset)); + } + } + + } else { + HotSpotResolvedJavaField resolvedJavaField = createField(fieldInfo.getType(this), fieldInfo.getOffset(), fieldInfo.getClassfileFlags(), fieldInfo.getInternalFlags(), index); + resultCount++; + resultList.add(resolvedJavaField); + } + } + assert resultList.size() == resultCount : "wrong flat field count"; + resultList.sort(fieldSortingMethod); + return resultList.toArray(new HotSpotResolvedJavaField[resultList.size()]); + } + /** * Gets the instance or static fields of this class. * * @param retrieveStaticFields specifies whether to return instance or static fields - * @param prepend an array to be prepended to the returned result + * @param prepend an array to be prepended to the returned result */ + private HotSpotResolvedJavaField[] getFields(boolean retrieveStaticFields, HotSpotResolvedJavaField[] prepend) { HotSpotVMConfig config = config(); int resultCount = 0; @@ -971,7 +1065,7 @@ public boolean isDefinitelyResolvedWithRespectTo(ResolvedJavaType accessingClass private boolean hasSameClassLoader(HotSpotResolvedObjectTypeImpl otherMirror) { return UnsafeAccess.UNSAFE.getAddress(getKlassPointer() + config().classLoaderDataOffset) == UnsafeAccess.UNSAFE.getAddress( - otherMirror.getKlassPointer() + config().classLoaderDataOffset); + otherMirror.getKlassPointer() + config().classLoaderDataOffset); } @Override @@ -1002,6 +1096,13 @@ public int superCheckOffset() { return UNSAFE.getInt(getKlassPointer() + config.superCheckOffsetOffset); } + @Override + public int firstFieldOffset() { + HotSpotVMConfig config = config(); + long fixedBlockPointer = UNSAFE.getAddress(getKlassPointer() + config.inlineKlassFixedBlockAdr); + return UNSAFE.getInt(fixedBlockPointer + config.firstFieldOffset); + } + @Override public long prototypeMarkWord() { HotSpotVMConfig config = config(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 23c47885fd8..6698da85026 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -76,6 +76,10 @@ static String getHostArchitectureName() { final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*"); final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint"); final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*"); + final int firstFieldOffset = getFieldOffset("InlineKlassFixedBlock::_first_field_offset", Integer.class, "int"); + final int internalNullMarkerOffset = getFieldOffset("InlineKlassFixedBlock::_internal_null_marker_offset", Integer.class, "int"); + final int nullMarkerOffset = getFieldOffset("FieldInfo::_null_marker_offset", Integer.class, "u4"); + final int inlineKlassFixedBlockAdr = getFieldOffset("InstanceKlass::_adr_inlineklass_fixed_block", Integer.class, "InlineKlassFixedBlock*"); final int classLoaderDataOffset = getFieldOffset("Klass::_class_loader_data", Integer.class, "ClassLoaderData*"); @@ -117,6 +121,11 @@ static String getHostArchitectureName() { final int jvmAccHasFinalizer = getConstant("KlassFlags::_misc_has_finalizer", Integer.class); final int jvmFieldFlagInternalShift = getConstant("FieldInfo::FieldFlags::_ff_injected", Integer.class); final int jvmFieldFlagStableShift = getConstant("FieldInfo::FieldFlags::_ff_stable", Integer.class); + final int jvmFieldFlagFlatShift = getConstant("FieldInfo::FieldFlags::_ff_flat", Integer.class); + final int jvmFieldFlagNullFreeInlineTypeShift = getConstant("FieldInfo::FieldFlags::_ff_null_free_inline_type", Integer.class); + final int jvmFieldFlagNullMarkerShift = getConstant("FieldInfo::FieldFlags::_ff_null_marker", Integer.class); + final int jvmFieldFlagInternalNullMarkerShift = getConstant("FieldInfo::FieldFlags::_ff_internal_null_marker", Integer.class); + final int jvmAccIsCloneableFast = getConstant("KlassFlags::_misc_is_cloneable_fast", Integer.class); // These modifiers are not public in Modifier so we get them via vmStructs. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index cb891ab2e1b..ab701664f9c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -46,6 +46,13 @@ public interface ResolvedJavaField extends JavaField, ModifiersProvider, Annotat */ int getOffset(); + /** + * returns a new instance with a changed offset of the field relative to the base of its storage container + */ + default ResolvedJavaField changeOffset(int newOffset) { + throw new UnsupportedOperationException(); + } + default boolean isFinal() { return ModifiersProvider.super.isFinalFlagSet(); } @@ -56,6 +63,22 @@ default boolean isFinal() { */ boolean isInternal(); + /** + * Determines if this field is flat. Such a field, for example, is not derived + * from a class file. + */ + default boolean isFlat() { + throw new UnsupportedOperationException(); + } + + /** + * Determines if this field is a null free inline type. Such a field, for example, is not derived + * from a class file. + */ + default boolean isNullFreeInlineType() { + throw new UnsupportedOperationException(); + } + /** * Determines if this field is a synthetic field as defined by the Java Language Specification. */ From e5cddc2d4d535df271f7bc26aaec3c7dd33710d8 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 12 Nov 2024 19:41:21 +0100 Subject: [PATCH 12/98] first approach to support nullable flattened inline types --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 3 +- .../hotspot/HotSpotResolvedJavaFieldImpl.java | 47 +++++++++++++++---- .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 19 ++++---- .../jdk/vm/ci/meta/ResolvedJavaField.java | 15 ++++++ 4 files changed, 64 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 6ff96e6343a..14056e9814a 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -267,7 +267,7 @@ nonstatic_field(Klass, _secondary_supers, Array*) \ nonstatic_field(Klass, _super, Klass*) \ nonstatic_field(Klass, _super_check_offset, juint) \ - nonstatic_field(InstanceKlass, _adr_inlineklass_fixed_block, InlineKlassFixedBlock*) \ + nonstatic_field(InstanceKlass, _adr_inlineklass_fixed_block, InlineKlassFixedBlock const *) \ nonstatic_field(InlineKlassFixedBlock, _first_field_offset, int) \ nonstatic_field(InlineKlassFixedBlock, _internal_null_marker_offset, int) \ nonstatic_field(FieldInfo, _null_marker_offset, u4) \ @@ -300,6 +300,7 @@ nonstatic_field(Method, _flags._status, u4) \ volatile_nonstatic_field(Method, _code, nmethod*) \ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ + volatile_nonstatic_field(Method, _from_compiled_inline_entry, address) \ \ nonstatic_field(MethodCounters, _invoke_mask, int) \ nonstatic_field(MethodCounters, _backedge_mask, int) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 767219cd4c7..a69e631bf20 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -22,18 +22,18 @@ */ package jdk.vm.ci.hotspot; -import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; -import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; -import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; +import jdk.internal.vm.VMSupport; +import jdk.vm.ci.meta.*; import java.lang.annotation.Annotation; import java.util.Collections; import java.util.List; -import jdk.internal.vm.VMSupport; -import jdk.vm.ci.meta.*; +import static jdk.internal.misc.Unsafe.ADDRESS_SIZE; +import static jdk.vm.ci.hotspot.CompilerToVM.compilerToVM; +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.HotSpotVMConfig.config; +import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; /** * Represents a field in a HotSpot type. @@ -110,15 +110,42 @@ public boolean isNullFreeInlineType() { } @Override - public boolean isFlat(){ + public boolean isFlat() { return (internalFlags & (1 << config().jvmFieldFlagFlatShift)) != 0; } + @Override + public int getNullMarkerOffset() { + return holder.getFieldInfo(index).getNullMarkerOffset(); + } + + @Override + public HotSpotResolvedJavaField getNullMarkerField() { + HotSpotResolvedJavaType byteType = HotSpotResolvedPrimitiveType.forKind(JavaKind.Byte); + return new HotSpotResolvedJavaFieldImpl(holder, byteType, getNullMarkerOffset(), 0, 0, -1) { + @Override + public String getName() { + return "nullMarkerOffset"; + } + + @Override + public int getNullMarkerOffset() { + return -1; + } + + @Override + public JavaConstant getConstantValue() { + return null; + } + }; + //return new HotSpotResolvedJavaFieldImpl(holder, byteType, getNullMarkerOffset(), 0, 0, -1); + } + /** * Determines if a given object contains this field. * * @return true iff this is a non-static field and its declaring class is assignable from - * {@code object}'s class + * {@code object}'s class */ @Override public boolean isInObject(JavaConstant object) { @@ -195,7 +222,7 @@ public boolean isSynthetic() { */ @Override public boolean isStable() { - return (1 << (config().jvmFieldFlagStableShift ) & internalFlags) != 0; + return (1 << (config().jvmFieldFlagStableShift) & internalFlags) != 0; } private boolean hasAnnotations() { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 6698da85026..85a677f1ab0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -22,17 +22,16 @@ */ package jdk.vm.ci.hotspot; -import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; - -import jdk.vm.ci.common.JVMCIError; -import jdk.vm.ci.services.Services; import jdk.internal.misc.Unsafe; import jdk.internal.util.Architecture; +import jdk.vm.ci.common.JVMCIError; + +import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; +import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; /** * Used to access native configuration details. - * + *

* All non-static, public fields in this class are so that they can be compiled as constants. */ class HotSpotVMConfig extends HotSpotVMConfigAccess { @@ -58,8 +57,10 @@ static HotSpotVMConfig config() { static String getHostArchitectureName() { Architecture arch = Architecture.current(); switch (arch) { - case X64: return "amd64"; - default: return arch.name().toLowerCase(); + case X64: + return "amd64"; + default: + return arch.name().toLowerCase(); } } @@ -79,7 +80,7 @@ static String getHostArchitectureName() { final int firstFieldOffset = getFieldOffset("InlineKlassFixedBlock::_first_field_offset", Integer.class, "int"); final int internalNullMarkerOffset = getFieldOffset("InlineKlassFixedBlock::_internal_null_marker_offset", Integer.class, "int"); final int nullMarkerOffset = getFieldOffset("FieldInfo::_null_marker_offset", Integer.class, "u4"); - final int inlineKlassFixedBlockAdr = getFieldOffset("InstanceKlass::_adr_inlineklass_fixed_block", Integer.class, "InlineKlassFixedBlock*"); + final int inlineKlassFixedBlockAdr = getFieldOffset("InstanceKlass::_adr_inlineklass_fixed_block", Integer.class, "InlineKlassFixedBlock const *"); final int classLoaderDataOffset = getFieldOffset("Klass::_class_loader_data", Integer.class, "ClassLoaderData*"); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index ab701664f9c..5e44e9786e8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -53,6 +53,13 @@ default ResolvedJavaField changeOffset(int newOffset) { throw new UnsupportedOperationException(); } + /** + * returns a resolved java field which represents the null marker field of a flattened inline type + */ + default ResolvedJavaField getNullMarkerField() { + throw new UnsupportedOperationException(); + } + default boolean isFinal() { return ModifiersProvider.super.isFinalFlagSet(); } @@ -79,6 +86,14 @@ default boolean isNullFreeInlineType() { throw new UnsupportedOperationException(); } + /** + * Returns the null marker offset for nullable flattened fields. Such a field, for example, is not derived + * from a class file. + */ + default int getNullMarkerOffset() { + throw new UnsupportedOperationException(); + } + /** * Determines if this field is a synthetic field as defined by the Java Language Specification. */ From bc97d22d5cdcb990c7247d86300ea60573bd58ba Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 15 Nov 2024 18:30:01 +0100 Subject: [PATCH 13/98] first approach to support access on flattened arrays with a constant index --- src/hotspot/share/jvmci/jvmciEnv.cpp | 1 + src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 ++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 19 ++++++++---------- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 9 +++++++++ .../ci/hotspot/HotSpotMetaAccessProvider.java | 5 +++++ .../ci/hotspot/HotSpotResolvedObjectType.java | 7 +++++++ .../HotSpotResolvedObjectTypeImpl.java | 20 +++++++++++++++++++ .../jdk/vm/ci/hotspot/HotSpotVMConfig.java | 4 ++++ .../jdk/vm/ci/meta/MetaAccessProvider.java | 8 ++++++-- 9 files changed, 62 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 71e9a83b0c0..2f7c0383489 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1714,6 +1714,7 @@ BasicType JVMCIEnv::typeCharToBasicType(jchar ch, JVMCI_TRAPS) { case 'J': return T_LONG; case 'D': return T_DOUBLE; case 'A': return T_OBJECT; + case 'Q': return T_PRIMITIVE_OBJECT; case '-': return T_ILLEGAL; default: JVMCI_ERROR_(T_ILLEGAL, "unexpected type char: %c", ch); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 14056e9814a..aeef2ccf057 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -278,6 +278,7 @@ volatile_nonstatic_field(Klass, _next_sibling, Klass*) \ nonstatic_field(Klass, _java_mirror, OopHandle) \ nonstatic_field(Klass, _access_flags, AccessFlags) \ + nonstatic_field(Klass, _kind, Klass::KlassKind const) \ nonstatic_field(Klass, _class_loader_data, ClassLoaderData*) \ nonstatic_field(Klass, _secondary_supers_bitmap, uintx) \ nonstatic_field(Klass, _hash_slot, uint8_t) \ @@ -772,6 +773,7 @@ declare_constant(Klass::_lh_instance_slow_path_bit) \ declare_constant(Klass::_lh_log2_element_size_shift) \ declare_constant(Klass::_lh_log2_element_size_mask) \ + declare_constant(Klass::FlatArrayKlassKind) \ declare_constant(Klass::_lh_element_type_shift) \ declare_constant(Klass::_lh_element_type_mask) \ declare_constant(Klass::_lh_header_size_shift) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index cf98a2ee681..955596af6b2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -23,26 +23,21 @@ package jdk.vm.ci.hotspot; -import java.lang.reflect.Executable; -import java.lang.reflect.Field; - import jdk.internal.misc.Unsafe; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.code.InvalidInstalledCodeException; import jdk.vm.ci.code.stack.InspectedFrameVisitor; import jdk.vm.ci.common.InitTimer; -import static jdk.vm.ci.common.InitTimer.timer; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; +import jdk.vm.ci.meta.*; + +import java.lang.reflect.Executable; +import java.lang.reflect.Field; + +import static jdk.vm.ci.common.InitTimer.timer; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantReflectionProvider; -import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.ResolvedJavaMethod; -import jdk.vm.ci.meta.ResolvedJavaType; /** * Calls from Java into HotSpot. The behavior of all the methods in this class that take a native @@ -74,6 +69,7 @@ final class CompilerToVM { final int ARRAY_FLOAT_BASE_OFFSET; final int ARRAY_DOUBLE_BASE_OFFSET; final int ARRAY_OBJECT_BASE_OFFSET; + final int ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET; final int ARRAY_BOOLEAN_INDEX_SCALE; final int ARRAY_BYTE_INDEX_SCALE; final int ARRAY_SHORT_INDEX_SCALE; @@ -97,6 +93,7 @@ final class CompilerToVM { ARRAY_FLOAT_BASE_OFFSET = arrayBaseOffset(JavaKind.Float.getTypeChar()); ARRAY_DOUBLE_BASE_OFFSET = arrayBaseOffset(JavaKind.Double.getTypeChar()); ARRAY_OBJECT_BASE_OFFSET = arrayBaseOffset(JavaKind.Object.getTypeChar()); + ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET = arrayBaseOffset('Q'); ARRAY_BOOLEAN_INDEX_SCALE = arrayIndexScale(JavaKind.Boolean.getTypeChar()); ARRAY_BYTE_INDEX_SCALE = arrayIndexScale(JavaKind.Byte.getTypeChar()); ARRAY_SHORT_INDEX_SCALE = arrayIndexScale(JavaKind.Short.getTypeChar()); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 0943b0f8162..9c7d2bee2e1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -1163,6 +1163,15 @@ public int getArrayBaseOffset(JavaKind kind) { } + /** + * The offset from the origin of a flat array to the first element. + * + * @return the offset in bytes + */ + public int getFlatArrayBaseOffset() { + return compilerToVm.ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET; + } + /** * The scale used for the index when accessing elements of an array of this kind. * diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 0bc6fce0ce2..8728a485d58 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -340,6 +340,11 @@ public int getArrayBaseOffset(JavaKind kind) { return runtime.getArrayBaseOffset(kind); } + @Override + public int getFlatArrayBaseOffset() { + return runtime.getFlatArrayBaseOffset(); + } + @Override public int getArrayIndexScale(JavaKind kind) { return runtime.getArrayIndexScale(kind); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index ae9b2fd7e4d..189ada04b94 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -75,6 +75,13 @@ default JavaKind getJavaKind() { */ int instanceSize(); + /** + * Gets the component size in an array + */ + int getLog2ComponentSize(); + + boolean isFlatArray(); + int getVtableLength(); @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 04ba8b4b785..920e4e79188 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -533,6 +533,26 @@ public int instanceSize() { return needsSlowPath ? -size : size; } + @Override + public int getLog2ComponentSize() { + assert isArray(); + HotSpotVMConfig config = config(); + final int layoutHelper = layoutHelper(); + // assert(lh < (jint)_lh_neutral_value, "must be array"); + // int l2esz = (lh >> _lh_log2_element_size_shift) & _lh_log2_element_size_mask; + assert layoutHelper < config.klassLayoutHelperNeutralValue : "must be array"; + int l2esz = (layoutHelper >> config.klassLayoutHelperLog2ElementSizeShift) & config.klassLayoutHelperLog2ElementSizeMask; + return l2esz; + } + + @Override + public boolean isFlatArray() { + HotSpotVMConfig config = config(); + assert isArray(); + assert getKlassPointer() != 0 : getName(); + return UNSAFE.getInt(getKlassPointer() + config.klassKind) == config.klassFlatArray; + } + @Override public int layoutHelper() { HotSpotVMConfig config = config(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 85a677f1ab0..3e6d2b18d78 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -94,6 +94,10 @@ static String getHostArchitectureName() { final int klassLayoutHelperNeutralValue = getConstant("Klass::_lh_neutral_value", Integer.class); final int klassLayoutHelperInstanceSlowPathBit = getConstant("Klass::_lh_instance_slow_path_bit", Integer.class); + final int klassLayoutHelperLog2ElementSizeShift = getConstant("Klass::_lh_log2_element_size_shift", Integer.class); + final int klassLayoutHelperLog2ElementSizeMask = getConstant("Klass::_lh_log2_element_size_mask", Integer.class); + final int klassKind = getFieldOffset("Klass::_kind", Integer.class, "Klass::KlassKind const"); + final int klassFlatArray = getConstant("Klass::FlatArrayKlassKind", Integer.class); final int vtableEntrySize = getFieldValue("CompilerToVM::Data::sizeof_vtableEntry", Integer.class, "int"); final int vtableEntryMethodOffset = getFieldOffset("vtableEntry::_method", Integer.class, "Method*"); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java index 2686ab1737f..e3ea36fdb89 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java @@ -22,13 +22,13 @@ */ package jdk.vm.ci.meta; +import jdk.vm.ci.meta.SpeculationLog.Speculation; + import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.lang.reflect.Field; import java.lang.reflect.Method; -import jdk.vm.ci.meta.SpeculationLog.Speculation; - /** * Provides access to the metadata of a class typically provided in a class file. */ @@ -123,5 +123,9 @@ default ResolvedJavaType[] lookupJavaTypes(Class[] classes) { int getArrayBaseOffset(JavaKind elementKind); + default int getFlatArrayBaseOffset() { + throw new UnsupportedOperationException(); + } + int getArrayIndexScale(JavaKind elementKind); } From 06baad1804895851e5ee8260c45a8c6fc28951b1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 23 Nov 2024 12:05:52 +0100 Subject: [PATCH 14/98] make access to flat array pattern in klass object available for jvmci --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index aeef2ccf057..cba49aad348 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -835,6 +835,7 @@ declare_constant(markWord::inline_type_pattern) \ declare_constant(markWord::inline_type_mask_in_place) \ declare_constant(markWord::inline_type_bit_in_place) \ + declare_constant(markWord::flat_array_pattern) \ // Helper macro to support ZGC pattern where the function itself isn't exported #define DECLARE_FUNCTION_FROM_ADDR(declare_function_with_value, name) \ From b560b1124fd735251123ddd8b9c74cccfaf7e9cd Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 23 Nov 2024 18:36:39 +0100 Subject: [PATCH 15/98] make access to null free array attributes in klass object available for jvmci --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index cba49aad348..0f3c45434fe 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -781,6 +781,8 @@ declare_constant(Klass::_lh_array_tag_shift) \ declare_constant(Klass::_lh_array_tag_type_value) \ declare_constant(Klass::_lh_array_tag_obj_value) \ + declare_constant(Klass::_lh_null_free_shift) \ + declare_constant(Klass::_lh_null_free_mask) \ \ declare_constant(markWord::no_hash) \ \ @@ -836,6 +838,7 @@ declare_constant(markWord::inline_type_mask_in_place) \ declare_constant(markWord::inline_type_bit_in_place) \ declare_constant(markWord::flat_array_pattern) \ + declare_constant(markWord::null_free_array_pattern) \ // Helper macro to support ZGC pattern where the function itself isn't exported #define DECLARE_FUNCTION_FROM_ADDR(declare_function_with_value, name) \ From 3f77ad4970b0dd598edb6719524804660a915495 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 25 Nov 2024 21:56:15 +0100 Subject: [PATCH 16/98] provide access to flat array classes --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 19 +++++++++++++++++++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 7 +++++++ .../ci/hotspot/HotSpotResolvedJavaType.java | 11 +++++++++++ .../ci/hotspot/HotSpotResolvedObjectType.java | 5 +++++ .../HotSpotResolvedObjectTypeImpl.java | 14 ++++++++++++++ .../hotspot/HotSpotResolvedPrimitiveType.java | 5 +++++ .../jdk/vm/ci/meta/ResolvedJavaType.java | 4 ++++ 7 files changed, 65 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index d8d387713f2..a975b8ec164 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -679,6 +679,24 @@ C2V_VMENTRY_NULL(jobject, getArrayType, (JNIEnv* env, jobject, jchar type_char, return JVMCIENV->get_jobject(result); C2V_END +C2V_VMENTRY_NULL(jobject, getFlatArrayType, (JNIEnv* env, jobject, jchar type_char, ARGUMENT_PAIR(klass))) + JVMCIKlassHandle array_klass(THREAD); + Klass* klass = UNPACK_PAIR(Klass, klass); + + if(klass->is_inline_klass()){ + InlineKlass* inline_klass = InlineKlass::cast(klass); + // Request a flat array, but we might not actually get it...either way "null-free" are the aaload/aastore semantics + ArrayKlass* flat_array_klass = (ArrayKlass*)inline_klass->value_array_klass(CHECK_NULL); + array_klass = flat_array_klass; + assert(array_klass->is_null_free_array_klass(), "Expect a null-free array class here"); + //assert(array_klass->is_flatArray_klass, "Expect a flat array class here"); + }else{ + array_klass = klass->array_klass(CHECK_NULL); + } + JVMCIObject result = JVMCIENV->get_jvmci_type(array_klass, JVMCI_CHECK_NULL); + return JVMCIENV->get_jobject(result); +C2V_END + C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror)) requireInHotSpot("lookupClass", JVMCI_CHECK_NULL); if (mirror == nullptr) { @@ -3280,6 +3298,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "lookupJClass", CC "(J)" HS_RESOLVED_TYPE, FN_PTR(lookupJClass)}, {CC "getJObjectValue", CC "(" OBJECTCONSTANT ")J", FN_PTR(getJObjectValue)}, {CC "getArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getArrayType)}, + {CC "getFlatArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getFlatArrayType)}, {CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)}, {CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL2 "II)" STRING, FN_PTR(lookupNameInPool)}, {CC "lookupNameAndTypeRefIndexInPool", CC "(" HS_CONSTANT_POOL2 "II)I", FN_PTR(lookupNameAndTypeRefIndexInPool)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 955596af6b2..891410eae74 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1101,6 +1101,13 @@ HotSpotResolvedObjectTypeImpl getArrayType(char primitiveTypeChar, HotSpotResolv native HotSpotResolvedObjectTypeImpl getArrayType(char typeChar, HotSpotResolvedObjectTypeImpl klass, long klassPointer); + HotSpotResolvedObjectTypeImpl getFlatArrayType(HotSpotResolvedObjectTypeImpl nonPrimitiveKlass) { + long nonPrimitiveKlassPointer = nonPrimitiveKlass.getKlassPointer(); + return getFlatArrayType((char) 0, nonPrimitiveKlass, nonPrimitiveKlassPointer); + } + + native HotSpotResolvedObjectTypeImpl getFlatArrayType(char typeChar, HotSpotResolvedObjectTypeImpl klass, long klassPointer); + /** * Forces initialization of {@code klass}. */ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java index fbb5a3fc9b5..e60f37238f4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaType.java @@ -28,6 +28,7 @@ public abstract class HotSpotResolvedJavaType extends HotSpotJavaType implements ResolvedJavaType { HotSpotResolvedObjectTypeImpl arrayOfType; + HotSpotResolvedObjectTypeImpl flatArrayOfType; HotSpotResolvedJavaType(String name) { super(name); @@ -45,6 +46,8 @@ public final int hashCode() { abstract HotSpotResolvedObjectTypeImpl getArrayType(); + abstract HotSpotResolvedObjectTypeImpl getFlatArrayType(); + @Override public final HotSpotResolvedObjectType getArrayClass() { if (arrayOfType == null) { @@ -53,6 +56,14 @@ public final HotSpotResolvedObjectType getArrayClass() { return arrayOfType; } + @Override + public final HotSpotResolvedObjectType getFlatArrayClass() { + if (flatArrayOfType == null) { + flatArrayOfType = getFlatArrayType(); + } + return flatArrayOfType; + } + /** * Checks whether this type is currently being initialized. If a type is being initialized it * implies that it was {@link #isLinked() linked} and that the static initializer is currently diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 189ada04b94..32ab5a2f8c2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -39,6 +39,11 @@ public interface HotSpotResolvedObjectType extends ResolvedJavaType { @Override HotSpotResolvedObjectType getArrayClass(); + @Override + HotSpotResolvedObjectType getFlatArrayClass(); + + HotSpotResolvedObjectType convertToFlatArray(); + @Override ResolvedJavaType getComponentType(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 920e4e79188..e7554435444 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -690,6 +690,20 @@ HotSpotResolvedObjectTypeImpl getArrayType() { return runtime().compilerToVm.getArrayType((char) 0, this); } + @Override + public HotSpotResolvedObjectTypeImpl getFlatArrayType() { + return runtime().compilerToVm.getFlatArrayType(this); + } + + @Override + public HotSpotResolvedObjectTypeImpl convertToFlatArray() { + assert isArray() : "only an array class can be converted to flat array class"; + ResolvedJavaType componentType = this.getComponentType(); + assert componentType != null : "component type must not be null"; + if (!(componentType instanceof HotSpotResolvedObjectTypeImpl)) return this; + return runtime().compilerToVm.getFlatArrayType((HotSpotResolvedObjectTypeImpl) componentType); + } + /** * This class represents the field information for one field contained in the fields array of an * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index 8e9bf6f00c7..b989772da43 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -93,6 +93,11 @@ HotSpotResolvedObjectTypeImpl getArrayType() { return runtime().compilerToVm.getArrayType(getJavaKind().getTypeChar(), null); } + @Override + HotSpotResolvedObjectTypeImpl getFlatArrayType() { + return getArrayType(); + } + @Override public ResolvedJavaType getElementalType() { return this; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 03a036bfd8a..684619be7c8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -237,6 +237,10 @@ default ResolvedJavaType getElementalType() { @Override ResolvedJavaType getArrayClass(); + default ResolvedJavaType getFlatArrayClass() { + throw new UnsupportedOperationException(); + } + /** * Resolves the method implementation for virtual dispatches on objects of this dynamic type. * This resolution process only searches "up" the class hierarchy of this type. A broader search From a5a1a2406a6a3e96550e274f55948e72f28c29c9 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 10 Dec 2024 18:08:14 +0100 Subject: [PATCH 17/98] modifications of jtreg testcases to get them working with Graal --- .../valhalla/inlinetypes/InlineTypes.java | 2 +- .../TestAllocationMergeAndFolding.java | 4 +- .../compiler/valhalla/inlinetypes/TestC1.java | 12 +- .../valhalla/inlinetypes/TestC2CCalls.java | 20 +-- .../inlinetypes/TestCallingConventionC1.java | 11 +- .../inlinetypes/TestCastMismatch.java | 2 +- .../TestDeadAllocationRemoval.java | 2 +- .../inlinetypes/TestFlatArrayThreshold.java | 7 +- .../valhalla/inlinetypes/TestGenerated.java | 4 +- .../inlinetypes/TestGetfieldChains.java | 9 +- .../inlinetypes/TestMismatchHandling.java | 28 ---- .../valhalla/inlinetypes/TestNewAcmp.java | 11 +- .../TestSafepointAtPollReturn.java | 2 +- .../inlinetypes/TestValueConstruction.java | 158 ------------------ .../inlinetypes/TestWithSpeculativeTypes.java | 2 +- .../bootstrap/TestBootClassloader.java | 10 +- 16 files changed, 48 insertions(+), 236 deletions(-) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java index 853475ced1e..7f97c8b9530 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java @@ -121,7 +121,7 @@ public class InlineTypes { "-XX:+UseFieldFlattening", "-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields" - ) + ) */ }; public static TestFramework getFramework() { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java index b52ca86bd46..5201fcab4ea 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java @@ -43,8 +43,8 @@ public class TestAllocationMergeAndFolding { public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(InlineTypes.DEFAULT_SCENARIOS) - .addScenarios(new Scenario(6, "--enable-preview", "-XX:-UseCompressedOops")) - .addScenarios(new Scenario(7, "--enable-preview", "-XX:+UseCompressedOops")) + //.addScenarios(new Scenario(6, "--enable-preview", "-XX:-UseCompressedOops")) + //.addScenarios(new Scenario(7, "--enable-preview", "-XX:+UseCompressedOops")) .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java index 582b5d670bb..a36658c8341 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java @@ -56,12 +56,12 @@ public static void main(String[] args) { new Scenario(0, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"), // C2 only. (Make sure the tests are correctly written) new Scenario(1, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation"), - // interpreter only - new Scenario(2, "-Xint"), - // Xcomp Only C1. - new Scenario(3, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"), - // Xcomp Only C2. - new Scenario(4, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp") +// // interpreter only +// new Scenario(2, "-Xint"), +// // Xcomp Only C1. +// new Scenario(3, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"), +// // Xcomp Only C2. +// new Scenario(4, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp") }; InlineTypes.getFramework() diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java index 3184c2b9d44..96a28fe801f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java @@ -29,28 +29,12 @@ * @enablePreview * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * TestC2CCalls - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch - * -XX:CompileCommand=compileonly,TestC2CCalls*::test* - * -XX:CompileCommand=dontinline,TestC2CCalls*::test* - * TestC2CCalls - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch -XX:-ProfileInterpreter + * -XX:-UseBimorphicInlining -Xbatch -XX:-TieredCompilation * -XX:CompileCommand=compileonly,TestC2CCalls*::test* * -XX:CompileCommand=dontinline,TestC2CCalls*::test* * TestC2CCalls - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch - * -XX:CompileCommand=compileonly,TestC2CCalls::test* - * -XX:CompileCommand=dontinline,TestC2CCalls*::test* - * TestC2CCalls - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch -XX:-ProfileInterpreter - * -XX:CompileCommand=compileonly,TestC2CCalls::test* - * -XX:CompileCommand=dontinline,TestC2CCalls*::test* - * TestC2CCalls */ import java.lang.reflect.Method; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java index 80a0584295b..f8b8053760e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java @@ -57,15 +57,15 @@ public static void main(String[] args) { "--enable-preview", "-XX:CICompilerCount=2", "-XX:TieredStopAtLevel=4", - "-XX:+TieredCompilation"), + "-XX:+TieredCompilation") , // Default: both C1 and C2 are enabled, tiered compilation enabled new Scenario(1, "--enable-preview", "-XX:CICompilerCount=2", "-XX:TieredStopAtLevel=4", "-XX:+TieredCompilation", - "-XX:+IgnoreUnrecognizedVMOptions", - "-XX:+StressInlineTypeReturnedAsFields"), + "-XX:+IgnoreUnrecognizedVMOptions"/*, + "-XX:+StressInlineTypeReturnedAsFields"*/), // Same as above, but flip all the compLevel=CompLevel.C1_SIMPLE and compLevel=CompLevel.C2, so we test // the compliment of the above scenario. new Scenario(2, @@ -80,12 +80,13 @@ public static void main(String[] args) { "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-XX:+IgnoreUnrecognizedVMOptions", - "-XX:-PatchALot"), + "-XX:-PatchALot")/*, + // Only C2. new Scenario(4, "--enable-preview", "-XX:TieredStopAtLevel=4", - "-XX:-TieredCompilation") + "-XX:-TieredCompilation") */ }; System.gc(); // Resolve this call, to avoid C1 code patching in the test cases. diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCastMismatch.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCastMismatch.java index ca6a914282e..523c74acbf2 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCastMismatch.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCastMismatch.java @@ -27,7 +27,7 @@ * @summary Fix mismatch inline type issue during method calls * @library /test/lib * @enablePreview - * @run main/othervm -XX:-TieredCompilation -Xcomp + * @run main/othervm -XX:-TieredCompilation * compiler.valhalla.inlinetypes.TestCastMismatch */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java index a20081d09c6..c802d7cdf58 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeadAllocationRemoval.java @@ -28,7 +28,7 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -Xbatch TestDeadAllocationRemoval + * @run main/othervm TestDeadAllocationRemoval */ import jdk.internal.vm.annotation.ImplicitlyConstructible; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java index eb6b99e1e79..e9f96601bc6 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java @@ -28,13 +28,12 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -Xbatch + * @run main/othervm * TestFlatArrayThreshold - * @run main/othervm -XX:FlatArrayElementMaxOops=1 -Xbatch + * @run main/othervm -XX:FlatArrayElementMaxOops=1 * TestFlatArrayThreshold - * @run main/othervm -XX:+UseArrayFlattening -Xbatch + * @run main/othervm -XX:+UseArrayFlattening * TestFlatArrayThreshold - */ import jdk.test.lib.Asserts; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java index b163ecb2eef..547bc3e2eae 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java @@ -28,9 +28,9 @@ * @enablePreview * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation - * @run main/othervm -Xbatch + * @run main/othervm * compiler.valhalla.inlinetypes.TestGenerated - * @run main/othervm -Xbatch -XX:-UseArrayFlattening + * @run main/othervm -XX:-UseArrayFlattening * compiler.valhalla.inlinetypes.TestGenerated */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java index 2dc1a387174..43f153fb03d 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java @@ -86,7 +86,12 @@ public class TestGetfieldChains { public static void main(String[] args) { final Scenario[] scenarios = { - new Scenario(0, + new Scenario(0, + "--enable-preview", + "-XX:CICompilerCount=2", + "-XX:TieredStopAtLevel=4", + "-XX:+TieredCompilation") +/* new Scenario(0, // C1 only "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"), @@ -108,7 +113,7 @@ public static void main(String[] args) { "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-XX:-OmitStackTraceInFastThrow", - "-Xcomp") + "-Xcomp") */ }; InlineTypes.getFramework() diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java index f2cabb1845d..39d47c95a89 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java @@ -32,34 +32,6 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile - * -XX:CompileCommand=compileonly,TestMismatchHandling::test* - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile - * -XX:CompileCommand=compileonly,*::method - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile - * -XX:-InlineTypePassFieldsAsArgs - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile - * -XX:-InlineTypeReturnedAsFields - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeNMethodBarriersALot - * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch - * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * TestMismatchHandling */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java index 1c006291aba..f1469ffbefc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNewAcmp.java @@ -1871,11 +1871,14 @@ private static void enumerateVMOptions() throws Exception { "-Xbootclasspath/a:.", "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", - "-Xbatch", + "-XX:-TieredCompilation", + "-XX:CompileThreshold=1000", + //"-Xbatch", "-XX:TypeProfileLevel=222", + "-XX:-BackgroundCompilation", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", - "-XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestNewAcmp::test*", - "-XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestNewAcmp::cmp*"}; + "-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestNewAcmp::test*", + "-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestNewAcmp::cmp*"}; String SCENARIOS = System.getProperty("Scenarios", ""); List scenarios = null; @@ -1885,7 +1888,7 @@ private static void enumerateVMOptions() throws Exception { int scenario = -1; for (int nullMode = 0; nullMode <= 2; nullMode++) { // null mode - for (int incrInline = 0; incrInline < 2; incrInline++) { // 0 = default, 1 = -XX:+AlwaysIncrementalInline + for (int incrInline = 0; incrInline < 1; incrInline++) { // 0 = default, 1 = -XX:+AlwaysIncrementalInline scenario++; System.out.println("Scenario #" + scenario + " -------------------"); String[] cmds = baseOptions; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java index 1a65f7ef828..cb8c98ee00b 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java @@ -26,7 +26,7 @@ * @summary Test that oop fields of value classes are preserved over safepoints at returns. * @enablePreview * @run main/othervm -XX:CompileCommand=dontinline,TestSafepointAtPollReturn::test* -XX:+UnlockDiagnosticVMOptions - * -XX:+SafepointALot -XX:-TieredCompilation TestSafepointAtPollReturn + * -XX:+SafepointALot -XX:+TieredCompilation TestSafepointAtPollReturn */ public class TestSafepointAtPollReturn { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java index 617fedc59b4..d8285442685 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java @@ -37,169 +37,11 @@ * @enablePreview * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=DeoptimizeALot - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=CompileonlyTest - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:CompileCommand=compileonly,*TestValueConstruction::test* -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/** - * @test id=DontInlineHelper - * @summary Test construction of value objects. - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch - * -XX:CompileCommand=dontinline,compiler*::helper* - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=DontInlineMyValueInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:CompileCommand=dontinline,*MyValue*:: -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=DontInlineObjectInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:CompileCommand=dontinline,*Object:: -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=DontInlineObjectInitDeoptimizeALot - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions - * -XX:+DeoptimizeALot -XX:CompileCommand=dontinline,*Object:: -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=DontInlineMyAbstractInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:CompileCommand=dontinline,*MyAbstract:: -Xbatch - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=StressIncrementalInlining - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch - * -XX:-TieredCompilation -XX:+StressIncrementalInlining - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=StressIncrementalInliningCompileOnlyTest - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=compileonly,*TestValueConstruction::test* -Xbatch * compiler.valhalla.inlinetypes.TestValueConstruction */ -/* @test id=StressIncrementalInliningDontInlineMyValueInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-TieredCompilation -XX:+StressIncrementalInlining - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*MyValue*:: -Xbatch - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=StressIncrementalInliningDontInlineObjectInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-TieredCompilation -XX:+StressIncrementalInlining - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*Object:: -Xbatch - * compiler.valhalla.inlinetypes.TestValueConstruction - */ - -/* - * @test id=StressIncrementalInliningDontInlineMyAbstractInit - * @key randomness - * @library /testlibrary /test/lib /compiler/whitebox / - * @enablePreview - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-TieredCompilation -XX:+StressIncrementalInlining - * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*MyAbstract:: -Xbatch - * compiler.valhalla.inlinetypes.TestValueConstruction - */ public class TestValueConstruction { static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithSpeculativeTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithSpeculativeTypes.java index 7f3a4b8db43..41d1a9bdefc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithSpeculativeTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestWithSpeculativeTypes.java @@ -28,7 +28,7 @@ * @library /test/lib * @enablePreview * @run main/othervm -XX:CompileCommand=dontinline,TestWithSpeculativeTypes::* - * -XX:TypeProfileLevel=222 -XX:-TieredCompilation -Xbatch + * -XX:TypeProfileLevel=222 -XX:-TieredCompilation * TestWithSpeculativeTypes */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/bootstrap/TestBootClassloader.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/bootstrap/TestBootClassloader.java index 7b85a8398ef..37d7505ed29 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/bootstrap/TestBootClassloader.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/bootstrap/TestBootClassloader.java @@ -45,8 +45,10 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm InstallBootstrapClasses * @run main/othervm -Xbootclasspath/a:boot -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestBootClassloader::test* - * -XX:CompileCommand=inline,*::get* TestBootClassloader + * -Xbatch -XX:-TieredCompilation -XX:CompileCommand=compileonly,TestBootClassloader::test* -XX:CompileCommand=compileonly,*Wrapper1::get + * -XX:CompileCommand=compileonly,*Wrapper1::get* TestBootClassloader + * -XX:CompileCommand='print,*TestBootClassloader.test' + * -XX:CompileCommand='print,*Wrapper1.get' */ public class TestBootClassloader { @@ -102,6 +104,10 @@ public static void main(String[] args) throws Exception { Asserts.assertTrue(WB.isMethodCompilable(method, COMP_LEVEL_FULL_OPTIMIZATION, false), "Test1 method not compilable"); Asserts.assertTrue(WB.isMethodCompiled(method), "Test1 method not compiled"); + method = Wrapper1.class.getDeclaredMethod("get"); + Asserts.assertTrue(WB.isMethodCompilable(method, COMP_LEVEL_FULL_OPTIMIZATION, false), "Test1 method not compilable"); + Asserts.assertTrue(WB.isMethodCompiled(method), "Test1 method not compiled"); + method = TestBootClassloader.class.getDeclaredMethod("test2", Wrapper2.class); Asserts.assertTrue(WB.isMethodCompilable(method, COMP_LEVEL_FULL_OPTIMIZATION, false), "Test2 method not compilable"); Asserts.assertTrue(WB.isMethodCompiled(method), "Test2 method not compiled"); From 1a9bf07a12117675c58667d5a1a1755310c67ae2 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 12 Dec 2024 10:55:34 +0100 Subject: [PATCH 18/98] support a runtime call for flat arrays with an unknown type --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 15 +++++++++++++++ src/hotspot/share/jvmci/jvmciRuntime.hpp | 2 ++ src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 ++ 3 files changed, 19 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index d0b86a0f1ab..7663dab54af 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -438,6 +438,21 @@ JRT_ENTRY(jint, JVMCIRuntime::value_object_hashCode(JavaThread* current, oopDesc return result.get_jint(); JRT_END +JRT_BLOCK_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArrayOopDesc* array, int index)) + JRT_BLOCK; + flatArrayHandle vah(current, array); + oop buffer = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, THREAD); + current->set_vm_result(buffer); + JRT_BLOCK_END; +JRT_END + +JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(instanceOopDesc* buffer, flatArrayOopDesc* array, int index)) +{ + assert(buffer != nullptr, "can't store null into flat array"); + array->value_copy_to_index(buffer, index); +} +JRT_END + // Object.notifyAll() fast path, caller does slow path JRT_LEAF(jboolean, JVMCIRuntime::object_notifyAll(JavaThread* current, oopDesc* obj)) assert(current == JavaThread::current(), "pre-condition"); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 8d6c6121ed7..3e31d6ad730 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -528,6 +528,8 @@ class JVMCIRuntime: public CHeapObj { static jboolean object_notify(JavaThread* current, oopDesc* obj); static jboolean object_notifyAll(JavaThread* current, oopDesc* obj); static jboolean substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right); + static void load_unknown_inline(JavaThread* thread, flatArrayOopDesc* array, int index); + static void store_unknown_inline(instanceOopDesc* buffer, flatArrayOopDesc* array, int index); static void vm_error(JavaThread* current, jlong where, jlong format, jlong value); static oopDesc* load_and_clear_exception(JavaThread* thread); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 0f3c45434fe..a0166051e51 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -893,6 +893,8 @@ declare_function(JVMCIRuntime::monitorexit) \ declare_function(JVMCIRuntime::substitutability_check) \ declare_function(JVMCIRuntime::value_object_hashCode) \ + declare_function(JVMCIRuntime::load_unknown_inline) \ + declare_function(JVMCIRuntime::store_unknown_inline) \ declare_function(JVMCIRuntime::object_notify) \ declare_function(JVMCIRuntime::object_notifyAll) \ declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \ From 7107f8c25c697f851cde465fb5e93ebfdb160106 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 12 Dec 2024 20:26:18 +0100 Subject: [PATCH 19/98] fixed wrong signature of flat array runtime call --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 20 +++++++++++--------- src/hotspot/share/jvmci/jvmciRuntime.hpp | 4 ++-- 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 7663dab54af..d7576e03d37 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -438,19 +438,21 @@ JRT_ENTRY(jint, JVMCIRuntime::value_object_hashCode(JavaThread* current, oopDesc return result.get_jint(); JRT_END -JRT_BLOCK_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArrayOopDesc* array, int index)) +JRT_BLOCK_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, oopDesc* array, jint index)) JRT_BLOCK; - flatArrayHandle vah(current, array); - oop buffer = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, THREAD); - current->set_vm_result(buffer); + assert(array->klass()->is_flatArray_klass(), "should not be called"); + flatArrayOopDesc* flat_array = (flatArrayOopDesc*) array; + flatArrayHandle vah(current, flat_array); + oop obj = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, current); + current->set_vm_result(obj); JRT_BLOCK_END; JRT_END -JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(instanceOopDesc* buffer, flatArrayOopDesc* array, int index)) -{ - assert(buffer != nullptr, "can't store null into flat array"); - array->value_copy_to_index(buffer, index); -} +JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, oopDesc* array, jint index, oopDesc* value)) + assert(array->klass()->is_flatArray_klass(), "should not be called"); + assert(value != nullptr, "can't store null into flat array"); + flatArrayOopDesc* flat_array = (flatArrayOopDesc*) array; + flat_array->value_copy_to_index(value, index); JRT_END // Object.notifyAll() fast path, caller does slow path diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 3e31d6ad730..f3eaff5642a 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -528,8 +528,8 @@ class JVMCIRuntime: public CHeapObj { static jboolean object_notify(JavaThread* current, oopDesc* obj); static jboolean object_notifyAll(JavaThread* current, oopDesc* obj); static jboolean substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right); - static void load_unknown_inline(JavaThread* thread, flatArrayOopDesc* array, int index); - static void store_unknown_inline(instanceOopDesc* buffer, flatArrayOopDesc* array, int index); + static void load_unknown_inline(JavaThread* thread, oopDesc* array, jint index); + static void store_unknown_inline(JavaThread* thread, oopDesc* array, jint index, oopDesc* value); static void vm_error(JavaThread* current, jlong where, jlong format, jlong value); static oopDesc* load_and_clear_exception(JavaThread* thread); From 62e08d22a23bf900e61ef55e25b0223b84e41977 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 12 Dec 2024 23:52:42 +0100 Subject: [PATCH 20/98] flat array runtime call produces error, try to fix it --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 27 ++++++++++++++---------- src/hotspot/share/jvmci/jvmciRuntime.hpp | 7 ++++-- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index d7576e03d37..05310d6a822 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -44,6 +44,8 @@ #include "oops/objArrayKlass.hpp" #include "oops/oop.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "oops/flatArrayKlass.hpp" +#include "oops/flatArrayOop.inline.hpp" #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "runtime/arguments.hpp" @@ -53,6 +55,7 @@ #include "runtime/frame.inline.hpp" #include "runtime/java.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/handles.inline.hpp" #include "runtime/mutex.hpp" #include "runtime/reflection.hpp" #include "runtime/sharedRuntime.hpp" @@ -438,21 +441,23 @@ JRT_ENTRY(jint, JVMCIRuntime::value_object_hashCode(JavaThread* current, oopDesc return result.get_jint(); JRT_END -JRT_BLOCK_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, oopDesc* array, jint index)) - JRT_BLOCK; +JRT_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index)) assert(array->klass()->is_flatArray_klass(), "should not be called"); - flatArrayOopDesc* flat_array = (flatArrayOopDesc*) array; - flatArrayHandle vah(current, flat_array); - oop obj = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, current); + + assert(array->length() > 0 && index < array->length(), "already checked"); + flatArrayHandle vah(current, array); + oop obj = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK); current->set_vm_result(obj); - JRT_BLOCK_END; JRT_END -JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, oopDesc* array, jint index, oopDesc* value)) - assert(array->klass()->is_flatArray_klass(), "should not be called"); - assert(value != nullptr, "can't store null into flat array"); - flatArrayOopDesc* flat_array = (flatArrayOopDesc*) array; - flat_array->value_copy_to_index(value, index); +JRT_ENTRY(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index, oopDesc* value)) + if (value == nullptr) { + assert(array->klass()->is_flatArray_klass() || array->klass()->is_null_free_array_klass(), "should not be called"); + SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_NullPointerException()); + } else { + assert(array->klass()->is_flatArray_klass(), "should not be called"); + array->value_copy_to_index(value, index); + } JRT_END // Object.notifyAll() fast path, caller does slow path diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index f3eaff5642a..abf93288ac3 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -30,6 +30,9 @@ #include "jvmci/jvmci.hpp" #include "jvmci/jvmciExceptions.hpp" #include "jvmci/jvmciObject.hpp" +#include "runtime/handles.inline.hpp" +#include "oops/flatArrayKlass.hpp" +#include "oops/flatArrayOop.inline.hpp" #include "utilities/linkedlist.hpp" #if INCLUDE_G1GC #include "gc/g1/g1CardTable.hpp" @@ -528,8 +531,8 @@ class JVMCIRuntime: public CHeapObj { static jboolean object_notify(JavaThread* current, oopDesc* obj); static jboolean object_notifyAll(JavaThread* current, oopDesc* obj); static jboolean substitutability_check(JavaThread* current, oopDesc* left, oopDesc* right); - static void load_unknown_inline(JavaThread* thread, oopDesc* array, jint index); - static void store_unknown_inline(JavaThread* thread, oopDesc* array, jint index, oopDesc* value); + static void load_unknown_inline(JavaThread* thread, flatArrayOopDesc* array, jint index); + static void store_unknown_inline(JavaThread* thread, flatArrayOopDesc* array, jint index, oopDesc* value); static void vm_error(JavaThread* current, jlong where, jlong format, jlong value); static oopDesc* load_and_clear_exception(JavaThread* thread); From 6ae556936d5e11e155fa3593c4fe29cbedc3df3e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 14 Dec 2024 12:51:54 +0100 Subject: [PATCH 21/98] make mask value for flat and null-free arrays available over JVMCI --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index a0166051e51..1af98f9641e 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -838,7 +838,9 @@ declare_constant(markWord::inline_type_mask_in_place) \ declare_constant(markWord::inline_type_bit_in_place) \ declare_constant(markWord::flat_array_pattern) \ + declare_constant(markWord::flat_array_mask_in_place) \ declare_constant(markWord::null_free_array_pattern) \ + declare_constant(markWord::null_free_array_mask_in_place) \ // Helper macro to support ZGC pattern where the function itself isn't exported #define DECLARE_FUNCTION_FROM_ADDR(declare_function_with_value, name) \ From 30257c32cd86cc6e1f54e6a9a7265cb6872a042c Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 17 Dec 2024 14:56:30 +0100 Subject: [PATCH 22/98] no safepoint needed for store in flat array --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 05310d6a822..42d0d659e28 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -450,14 +450,9 @@ JRT_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArray current->set_vm_result(obj); JRT_END -JRT_ENTRY(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index, oopDesc* value)) - if (value == nullptr) { - assert(array->klass()->is_flatArray_klass() || array->klass()->is_null_free_array_klass(), "should not be called"); - SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_NullPointerException()); - } else { +JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index, oopDesc* value)) assert(array->klass()->is_flatArray_klass(), "should not be called"); array->value_copy_to_index(value, index); - } JRT_END // Object.notifyAll() fast path, caller does slow path From 4ee39c369764e9d7fedc0976521f5a5414178f91 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 17 Dec 2024 14:58:55 +0100 Subject: [PATCH 23/98] allow jtreg test cases to test graal with additional options --- .../lib/ir_framework/TestFramework.java | 16 +- .../valhalla/inlinetypes/InlineTypes.java | 8 +- .../TestAllocationMergeAndFolding.java | 5 +- .../inlinetypes/TestArrayCopyWithOops.java | 4 +- .../valhalla/inlinetypes/TestArrays.java | 2 + .../inlinetypes/TestBasicFunctionality.java | 3 + .../compiler/valhalla/inlinetypes/TestC1.java | 9 +- .../inlinetypes/TestCallingConventionC1.java | 9 +- .../inlinetypes/TestFlatArrayThreshold.java | 4 + .../inlinetypes/TestFlatInArraysFolding.java | 1 + .../valhalla/inlinetypes/TestGenerated.java | 1 + .../inlinetypes/TestGetfieldChains.java | 11 +- .../TestInlineFieldNonFlattened.java | 2 + .../valhalla/inlinetypes/TestJNICalls.java | 1 + .../valhalla/inlinetypes/TestLWorld.java | 3 + .../inlinetypes/TestLWorldProfiling.java | 3 +- .../inlinetypes/TestMismatchHandling.java | 28 +++ .../inlinetypes/TestOnStackReplacement.java | 1 + .../TestSafepointAtPollReturn.java | 4 +- .../TestUninitializedValueClass.java | 2 +- .../TestUnloadedInlineTypeField.java | 1 + .../inlinetypes/TestValueClasses.java | 1 + .../inlinetypes/TestValueConstruction.java | 159 ++++++++++++++++++ 23 files changed, 254 insertions(+), 24 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 2bf29580977..38979790987 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -267,6 +267,17 @@ public TestFramework addFlags(String... flags) { return this; } + public TestFramework setCompileOnlyTestMethods(Class clazz) { + //addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::test*", "-XX:InlineFieldMaxFlatSize=-1", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); + addFlags("-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::test*"); + return this; + } + + public TestFramework setGraalLog() { + addFlags("-Djdk.graal.CompilationFailureAction=Diagnose", "-Djdk.graal.LogFile=/home/michael/projects/logs/log.txt"); + return this; + } + /** * Add helper classes that can specify additional compile command annotations ({@link ForceCompile @ForceCompile}, * {@link DontCompile @DontCompile}, {@link ForceInline @ForceInline}, {@link DontInline @DontInline}) to be applied @@ -323,6 +334,7 @@ public TestFramework addScenarios(Scenario... scenarios) { this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); + addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-XX:InlineFieldMaxFlatSize=-1", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); return this; } @@ -721,7 +733,9 @@ private void start(Scenario scenario) { List scenarioFlags = scenario.getFlags(); String scenarioFlagsString = scenarioFlags.isEmpty() ? "" : " - [" + String.join(", ", scenarioFlags) + "]"; System.out.println("Scenario #" + scenario.getIndex() + scenarioFlagsString + ":"); - additionalFlags.addAll(scenarioFlags); + //additionalFlags.addAll(scenarioFlags); + scenarioFlags.addAll(additionalFlags); + additionalFlags = scenarioFlags; } String frameworkAndScenarioFlags = additionalFlags.isEmpty() ? "" : " - [" + String.join(", ", additionalFlags) + "]"; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java index 7f97c8b9530..d22d5517459 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java @@ -62,6 +62,8 @@ public class InlineTypes { "-XX:+UseFieldFlattening", "-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields" + + ), new Scenario(2, "--enable-preview", @@ -121,11 +123,13 @@ public class InlineTypes { "-XX:+UseFieldFlattening", "-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields" - ) */ + ) }; public static TestFramework getFramework() { StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); - return new TestFramework(walker.getCallerClass()).setDefaultWarmup(251); + TestFramework framework = new TestFramework(walker.getCallerClass()).setDefaultWarmup(251); + framework.addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363"); + return framework; } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java index 5201fcab4ea..7ff92270ac4 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java @@ -43,8 +43,9 @@ public class TestAllocationMergeAndFolding { public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(InlineTypes.DEFAULT_SCENARIOS) - //.addScenarios(new Scenario(6, "--enable-preview", "-XX:-UseCompressedOops")) - //.addScenarios(new Scenario(7, "--enable-preview", "-XX:+UseCompressedOops")) + .addScenarios(new Scenario(6, "--enable-preview", "-XX:-UseCompressedOops")) + .addScenarios(new Scenario(7, "--enable-preview", "-XX:+UseCompressedOops")) + .setCompileOnlyTestMethods(TestAllocationMergeAndFolding.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java index f6a119e2c30..3b72f348bd5 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java @@ -31,11 +31,11 @@ * java.base/jdk.internal.vm.annotation * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* - * -Xbatch + * * compiler.valhalla.inlinetypes.TestArrayCopyWithOops * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* - * -Xbatch -XX:-UseArrayFlattening + * -XX:-UseArrayFlattening * compiler.valhalla.inlinetypes.TestArrayCopyWithOops * @run main/othervm compiler.valhalla.inlinetypes.TestArrayCopyWithOops */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java index a16c0187901..55e3a7bf018 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrays.java @@ -65,6 +65,8 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestArrays.class).setGraalLog() + //.addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrays::test*") .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class) .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java index a16760744a9..b5e1284e20e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestBasicFunctionality.java @@ -53,8 +53,11 @@ public class TestBasicFunctionality { public static void main(String[] args) { + //InlineTypes.DEFAULT_SCENARIOS[0].addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestBasicFunctionality::test*"); InlineTypes.getFramework() .addScenarios(InlineTypes.DEFAULT_SCENARIOS) + .setCompileOnlyTestMethods(TestBasicFunctionality.class).setGraalLog() + //.addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestBasicFunctionality::test*") .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java index a36658c8341..1e460ad9eff 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java @@ -56,10 +56,10 @@ public static void main(String[] args) { new Scenario(0, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"), // C2 only. (Make sure the tests are correctly written) new Scenario(1, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation"), -// // interpreter only -// new Scenario(2, "-Xint"), -// // Xcomp Only C1. -// new Scenario(3, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"), + // interpreter only + new Scenario(2, "-Xint"), + // Xcomp Only C1. + new Scenario(3, "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-Xcomp"), // // Xcomp Only C2. // new Scenario(4, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp") }; @@ -69,6 +69,7 @@ public static void main(String[] args) { .addFlags("--enable-preview", "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED") + .setCompileOnlyTestMethods(TestC1.class).setGraalLog() .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java index f8b8053760e..38537de5a1e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java @@ -64,8 +64,8 @@ public static void main(String[] args) { "-XX:CICompilerCount=2", "-XX:TieredStopAtLevel=4", "-XX:+TieredCompilation", - "-XX:+IgnoreUnrecognizedVMOptions"/*, - "-XX:+StressInlineTypeReturnedAsFields"*/), + "-XX:+IgnoreUnrecognizedVMOptions", + "-XX:+StressInlineTypeReturnedAsFields"), // Same as above, but flip all the compLevel=CompLevel.C1_SIMPLE and compLevel=CompLevel.C2, so we test // the compliment of the above scenario. new Scenario(2, @@ -80,19 +80,20 @@ public static void main(String[] args) { "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", "-XX:+IgnoreUnrecognizedVMOptions", - "-XX:-PatchALot")/*, + "-XX:-PatchALot"), // Only C2. new Scenario(4, "--enable-preview", "-XX:TieredStopAtLevel=4", - "-XX:-TieredCompilation") */ + "-XX:-TieredCompilation") }; System.gc(); // Resolve this call, to avoid C1 code patching in the test cases. InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestCallingConventionC1.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java index e9f96601bc6..8dcf0d1a4b9 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java @@ -34,6 +34,10 @@ * TestFlatArrayThreshold * @run main/othervm -XX:+UseArrayFlattening * TestFlatArrayThreshold + * @run main/othervm -XX:FlatArrayElementMaxOops=1 + * TestFlatArrayThreshold + * @run main/othervm -XX:FlatArrayElementMaxSize=1 + * TestFlatArrayThreshold */ import jdk.test.lib.Asserts; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatInArraysFolding.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatInArraysFolding.java index e05b92d3dcb..93948e91e7a 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatInArraysFolding.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatInArraysFolding.java @@ -100,6 +100,7 @@ public static void main(String[] args) { } Scenario noMethodTraps = new Scenario(5, "-XX:PerMethodTrapLimit=0", "-Xbatch"); testFramework.addScenarios(noMethodTraps); + testFramework.setCompileOnlyTestMethods(TestFlatInArraysFolding.class).setGraalLog(); testFramework.start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java index 547bc3e2eae..f9ba55febeb 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java @@ -29,6 +29,7 @@ * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation * @run main/othervm + * * compiler.valhalla.inlinetypes.TestGenerated * @run main/othervm -XX:-UseArrayFlattening * compiler.valhalla.inlinetypes.TestGenerated diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java index 43f153fb03d..bcb549bc9cb 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGetfieldChains.java @@ -86,12 +86,12 @@ public class TestGetfieldChains { public static void main(String[] args) { final Scenario[] scenarios = { - new Scenario(0, + /*new Scenario(0, "--enable-preview", "-XX:CICompilerCount=2", "-XX:TieredStopAtLevel=4", - "-XX:+TieredCompilation") -/* new Scenario(0, + "-XX:+TieredCompilation")*/ + new Scenario(0, // C1 only "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation"), @@ -102,8 +102,8 @@ public static void main(String[] args) { "-XX:-OmitStackTraceInFastThrow"), new Scenario(2, // interpreter only - "-Xint"), - new Scenario(3, + "-Xint")/*, + new Scenario(3, // Xcomp Only C1 "-XX:TieredStopAtLevel=1", "-XX:+TieredCompilation", @@ -121,6 +121,7 @@ public static void main(String[] args) { .addFlags("--enable-preview", "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED", "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED") + .setCompileOnlyTestMethods(TestGetfieldChains.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java index 166ed3033d8..ed2ec6caf06 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java @@ -99,6 +99,8 @@ public static void main(String[] args) { "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", "-XX:-TieredCompilation", "-XX:-UseFieldFlattening") + "-XX:InlineFieldMaxFlatSize=0") + .setCompileOnlyTestMethods(TestInlineFieldNonFlattened.class).setGraalLog() .start(); } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java index e780d765fca..fa666e0bc89 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestJNICalls.java @@ -49,6 +49,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestJNICalls.class).setGraalLog() .addHelperClasses(MyValue1.class) .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java index f82031a051b..0b5df74e282 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java @@ -64,6 +64,7 @@ public static void main(String[] args) { // Make sure Test141Value is linked but not initialized Class class2 = Test141Value.class; class2.getDeclaredFields(); + //System.out.println(TestLWorld.class.getCanonicalName()+"\n\n\n\n"); Scenario[] scenarios = InlineTypes.DEFAULT_SCENARIOS; scenarios[3].addFlags("-XX:-MonomorphicArrayCheck", "-XX:+UseArrayFlattening"); @@ -71,6 +72,8 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestLWorld.class).setGraalLog() + //.addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestLWorld::test*") .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java index 6b3615a7448..27171f04974 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorldProfiling.java @@ -102,9 +102,10 @@ public static void main(String[] args) { .addScenarios(scenarios) .addFlags("-XX:+IgnoreUnrecognizedVMOptions", "--enable-preview", "--add-exports", "java.base/jdk.internal.vm.annotation=ALL-UNNAMED", - "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED") + "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", "-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestLWorldProfiling::test*") .addHelperClasses(MyValue1.class, MyValue2.class) + .setCompileOnlyTestMethods(TestLWorldProfiling.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java index 39d47c95a89..6f57c729e0d 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java @@ -32,6 +32,34 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile + * -XX:CompileCommand=compileonly,TestMismatchHandling::test* + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile + * -XX:CompileCommand=compileonly,*::method + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile + * -XX:-InlineTypePassFieldsAsArgs + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile + * -XX:-InlineTypeReturnedAsFields + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+DeoptimizeNMethodBarriersALot + * TestMismatchHandling + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * TestMismatchHandling */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java index bb83f28c4e4..75dce7d763e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestOnStackReplacement.java @@ -55,6 +55,7 @@ public static void main(String[] args) throws Throwable { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestOnStackReplacement.class).setGraalLog() .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java index cb8c98ee00b..06d4a8b23c0 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java @@ -25,8 +25,8 @@ * @test * @summary Test that oop fields of value classes are preserved over safepoints at returns. * @enablePreview - * @run main/othervm -XX:CompileCommand=dontinline,TestSafepointAtPollReturn::test* -XX:+UnlockDiagnosticVMOptions - * -XX:+SafepointALot -XX:+TieredCompilation TestSafepointAtPollReturn + * @run main/othervm -XX:CompileCommand=compileonly,TestSafepointAtPollReturn::test* -XX:+UnlockDiagnosticVMOptions + * -XX:+SafepointALot -XX:-TieredCompilation TestSafepointAtPollReturn */ public class TestSafepointAtPollReturn { diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUninitializedValueClass.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUninitializedValueClass.java index c46b4a96903..948b7ccc9b1 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUninitializedValueClass.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUninitializedValueClass.java @@ -28,7 +28,7 @@ * @bug 8282569 * @summary Test that uninitialized default value class is properly handled by C2. * @enablePreview - * @run main/othervm -XX:CompileCommand=compileonly,*:: -Xcomp -XX:-TieredCompilation + * @run main/othervm -XX:CompileCommand=compileonly,*:: -XX:-TieredCompilation * compiler.valhalla.inlinetypes.TestUninitializedValueClass */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java index b47825f350f..b77970478bc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestUnloadedInlineTypeField.java @@ -68,6 +68,7 @@ public static void main(String[] args) { "-DIgnoreCompilerControls=true", // Some tests trigger frequent re-compilation. Don't mark them as non-compilable. "-XX:PerMethodRecompilationCutoff=-1", "-XX:PerBytecodeRecompilationCutoff=-1") + .setCompileOnlyTestMethods(TestUnloadedInlineTypeField.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueClasses.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueClasses.java index fa1fa4ff790..a135f0960b5 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueClasses.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueClasses.java @@ -60,6 +60,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestValueClasses.class).setGraalLog() .addHelperClasses(MyValueClass1.class, MyValueClass2.class, MyValueClass2Inline.class) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java index d8285442685..7da68a29f8f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java @@ -37,8 +37,167 @@ * @enablePreview * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=DeoptimizeALot + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:+DeoptimizeALot + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=CompileonlyTest + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=compileonly,*TestValueConstruction::test* + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/** + * @test id=DontInlineHelper + * @summary Test construction of value objects. + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=dontinline,compiler*::helper* + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=DontInlineMyValueInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=dontinline,*MyValue*:: + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=DontInlineObjectInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=dontinline,*Object:: + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=DontInlineObjectInitDeoptimizeALot + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions + * -XX:+DeoptimizeALot -XX:CompileCommand=dontinline,*Object:: + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=DontInlineMyAbstractInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:CompileCommand=dontinline,*MyAbstract:: + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=StressIncrementalInlining + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-TieredCompilation -XX:+StressIncrementalInlining + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=StressIncrementalInliningCompileOnlyTest + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-TieredCompilation -XX:+StressIncrementalInlining + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * -XX:CompileCommand=compileonly,*TestValueConstruction::test* + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* @test id=StressIncrementalInliningDontInlineMyValueInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-TieredCompilation -XX:+StressIncrementalInlining + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * -XX:CompileCommand=dontinline,*MyValue*:: + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=StressIncrementalInliningDontInlineObjectInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-TieredCompilation -XX:+StressIncrementalInlining + * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * -XX:CompileCommand=dontinline,*Object:: + * compiler.valhalla.inlinetypes.TestValueConstruction + */ + +/* + * @test id=StressIncrementalInliningDontInlineMyAbstractInit + * @key randomness + * @library /testlibrary /test/lib /compiler/whitebox / + * @enablePreview + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt + * -XX:CompileCommand=dontinline,*MyAbstract:: * compiler.valhalla.inlinetypes.TestValueConstruction */ From a2dbe6d2283facba6bf82bd2f4a75fcbc76f03a2 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 19 Dec 2024 18:05:26 +0100 Subject: [PATCH 24/98] Extend JVMCI such that Graal can handle null-restricted, non-flat inline type fields correctly --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 10 ++++++++++ .../share/classes/jdk/vm/ci/hotspot/CompilerToVM.java | 7 +++++++ .../vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 7 +++++++ .../jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java | 2 ++ .../vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 5 +++++ .../classes/jdk/vm/ci/meta/ResolvedJavaField.java | 8 ++++++++ 6 files changed, 39 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index a975b8ec164..cb09ee07354 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -697,6 +697,15 @@ C2V_VMENTRY_NULL(jobject, getFlatArrayType, (JNIEnv* env, jobject, jchar type_ch return JVMCIENV->get_jobject(result); C2V_END +C2V_VMENTRY_NULL(jobject, getDefaultInlineTypeInstance, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) + JVMCIKlassHandle array_klass(THREAD); + Klass* klass = UNPACK_PAIR(Klass, klass); + + assert(klass->is_inline_klass(), "Should only be called for inline types"); + oop default_value = InlineKlass::cast(klass)->default_value(); + return JVMCIENV->get_jobject(JVMCIENV->get_object_constant(default_value)); +C2V_END + C2V_VMENTRY_NULL(jobject, lookupClass, (JNIEnv* env, jobject, jclass mirror)) requireInHotSpot("lookupClass", JVMCI_CHECK_NULL); if (mirror == nullptr) { @@ -3299,6 +3308,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getJObjectValue", CC "(" OBJECTCONSTANT ")J", FN_PTR(getJObjectValue)}, {CC "getArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getArrayType)}, {CC "getFlatArrayType", CC "(C" HS_KLASS2 ")" HS_KLASS, FN_PTR(getFlatArrayType)}, + {CC "getDefaultInlineTypeInstance", CC "(" HS_KLASS2 ")" JAVACONSTANT, FN_PTR(getDefaultInlineTypeInstance)}, {CC "lookupClass", CC "(" CLASS ")" HS_RESOLVED_TYPE, FN_PTR(lookupClass)}, {CC "lookupNameInPool", CC "(" HS_CONSTANT_POOL2 "II)" STRING, FN_PTR(lookupNameInPool)}, {CC "lookupNameAndTypeRefIndexInPool", CC "(" HS_CONSTANT_POOL2 "II)I", FN_PTR(lookupNameAndTypeRefIndexInPool)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 891410eae74..672090731ec 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1108,6 +1108,13 @@ HotSpotResolvedObjectTypeImpl getFlatArrayType(HotSpotResolvedObjectTypeImpl non native HotSpotResolvedObjectTypeImpl getFlatArrayType(char typeChar, HotSpotResolvedObjectTypeImpl klass, long klassPointer); + JavaConstant getDefaultInlineTypeInstance(HotSpotResolvedObjectTypeImpl nonPrimitiveKlass) { + long nonPrimitiveKlassPointer = nonPrimitiveKlass.getKlassPointer(); + return getDefaultInlineTypeInstance(nonPrimitiveKlass, nonPrimitiveKlassPointer); + } + + native JavaConstant getDefaultInlineTypeInstance(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + /** * Forces initialization of {@code klass}. */ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index a69e631bf20..630cb090fa2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -26,6 +26,7 @@ import jdk.vm.ci.meta.*; import java.lang.annotation.Annotation; +import java.lang.reflect.Field; import java.util.Collections; import java.util.List; @@ -114,6 +115,12 @@ public boolean isFlat() { return (internalFlags & (1 << config().jvmFieldFlagFlatShift)) != 0; } + @Override + public boolean isInitialized() { + assert isStatic() : "should only be called on static fields"; + return UNSAFE.getAddress(holder.getKlassPointer(), this.offset) != 0; + } + @Override public int getNullMarkerOffset() { return holder.getFieldInfo(index).getNullMarkerOffset(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 32ab5a2f8c2..996f8da1fde 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -44,6 +44,8 @@ public interface HotSpotResolvedObjectType extends ResolvedJavaType { HotSpotResolvedObjectType convertToFlatArray(); + JavaConstant getDefaultInlineTypeInstance(); + @Override ResolvedJavaType getComponentType(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index e7554435444..5ba3babc9ca 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -704,6 +704,11 @@ public HotSpotResolvedObjectTypeImpl convertToFlatArray() { return runtime().compilerToVm.getFlatArrayType((HotSpotResolvedObjectTypeImpl) componentType); } + @Override + public JavaConstant getDefaultInlineTypeInstance() { + return runtime().compilerToVm.getDefaultInlineTypeInstance(this); + } + /** * This class represents the field information for one field contained in the fields array of an * {@code InstanceKlass}. The implementation is similar to the native {@code FieldInfo} class. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index 5e44e9786e8..bd74d7d50b0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -78,6 +78,14 @@ default boolean isFlat() { throw new UnsupportedOperationException(); } + /** + * Determines if a null-restricted static field is already initialized. Such a field, for example, is not derived + * from a class file. + */ + default boolean isInitialized() { + throw new UnsupportedOperationException(); + } + /** * Determines if this field is a null free inline type. Such a field, for example, is not derived * from a class file. From 3edbd380e69e256dddfe47c504ed27c9d538183e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 23 Dec 2024 08:28:40 +0100 Subject: [PATCH 25/98] Declared new entry points --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 7 +++++++ src/hotspot/share/jvmci/jvmciCodeInstaller.hpp | 3 +++ src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 3 +++ 3 files changed, 13 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 24515d3ff9b..7f34339df21 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1315,9 +1315,16 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, HotSpotCompile case UNVERIFIED_ENTRY: _offsets.set_value(CodeOffsets::Entry, pc_offset); break; + case INLINE_ENTRY: + _offsets.set_value(CodeOffsets::Inline_Entry, pc_offset); + break; case VERIFIED_ENTRY: _offsets.set_value(CodeOffsets::Verified_Entry, pc_offset); + break; + case VERIFIED_INLINE_ENTRY: _offsets.set_value(CodeOffsets::Verified_Inline_Entry, pc_offset); + break; + case VERIFIED_INLINE_ENTRY_RO: _offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, pc_offset); break; case OSR_ENTRY: diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp index b493c48e348..7e27bce62d4 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp @@ -147,7 +147,10 @@ class CodeInstaller : public StackObj { enum MarkId { INVALID_MARK, VERIFIED_ENTRY, + VERIFIED_INLINE_ENTRY, + VERIFIED_INLINE_ENTRY_RO, UNVERIFIED_ENTRY, + INLINE_ENTRY, OSR_ENTRY, EXCEPTION_HANDLER_ENTRY, DEOPT_HANDLER_ENTRY, diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 1af98f9641e..db0d13ab0fb 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -553,7 +553,10 @@ declare_constant_with_value("OMCache::oop_to_monitor_difference", OMCache::oop_to_monitor_difference()) \ \ declare_constant(CodeInstaller::VERIFIED_ENTRY) \ + declare_constant(CodeInstaller::VERIFIED_INLINE_ENTRY) \ + declare_constant(CodeInstaller::VERIFIED_INLINE_ENTRY_RO) \ declare_constant(CodeInstaller::UNVERIFIED_ENTRY) \ + declare_constant(CodeInstaller::INLINE_ENTRY) \ declare_constant(CodeInstaller::OSR_ENTRY) \ declare_constant(CodeInstaller::EXCEPTION_HANDLER_ENTRY) \ declare_constant(CodeInstaller::DEOPT_HANDLER_ENTRY) \ From 6fdc233eb9da5ce2f77a60cd7b8223b07524ffef Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 23 Dec 2024 17:36:57 +0100 Subject: [PATCH 26/98] Made scalarized calling convention available over JVMCI --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 29 ++++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 56 +++++++ .../HotSpotResolvedJavaMethodImpl.java | 137 ++++++++++++++++-- .../HotSpotResolvedObjectTypeImpl.java | 5 + .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 14 ++ 5 files changed, 226 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index cb09ee07354..4116a02e1ea 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -369,6 +369,31 @@ C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, ARGUMENT_PAIR(m return JVMCIENV->get_jbyteArray(result); C2V_END +C2V_VMENTRY_0(jboolean, isScalarizedParameter, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jint idx)) + Method* method = UNPACK_PAIR(Method, method); + return method->is_scalarized_arg(idx); +C2V_END + +C2V_VMENTRY_0(jboolean, hasScalarizedParameters, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) + Method* method = UNPACK_PAIR(Method, method); + return method->has_scalarized_args(); +C2V_END + +C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) + Method* method = UNPACK_PAIR(Method, method); + Klass* klass = UNPACK_PAIR(Klass, klass); + assert(klass->is_inlinetype(), "Klass should be inline type"); + InlineKlass* inlineKlass = InlineKlass::cast(klass); + return !method->is_native() && inlineKlass->can_be_returned_as_fields(); +C2V_END + +C2V_VMENTRY_0(jboolean, canBePassedAsFields, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) + Klass* klass = UNPACK_PAIR(Klass, klass); + assert(klass->is_inlinetype(), "Klass should be an inline type"); + InlineKlass* inlineKlass = InlineKlass::cast(klass); + return inlineKlass->can_be_passed_as_fields(); +C2V_END + C2V_VMENTRY_0(jint, getExceptionTableLength, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) Method* method = UNPACK_PAIR(Method, method); return method->exception_table_length(); @@ -3293,6 +3318,10 @@ C2V_VMENTRY_0(jint, getCompilationActivityMode, (JNIEnv* env, jobject)) JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, + {CC "isScalarizedParameter", CC "(" HS_METHOD2 "I)Z", FN_PTR(isScalarizedParameter)}, + {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, + {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, + {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, {CC "getExceptionTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getExceptionTableStart)}, {CC "getExceptionTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getExceptionTableLength)}, {CC "findUniqueConcreteMethod", CC "(" HS_KLASS2 HS_METHOD2 ")" HS_METHOD, FN_PTR(findUniqueConcreteMethod)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 672090731ec..6b6a0c8140c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -129,6 +129,62 @@ byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) { private native byte[] getBytecode(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** + * Determines if the parameter {@code index} in the {@code method} is scalarized. + * + * @return true if the parameter is scalarized + */ + boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, int index) { + return isScalarizedParameter(method, method.getMethodPointer(), index); + } + + private native boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, long methodPointer, int index); + + /** + * Determines if any parameter in the {@code method} is scalarized. + * + * @return true if any parameter is scalarized + */ + boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method) { + return hasScalarizedParameters(method, method.getMethodPointer()); + } + + private native boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method, long methodPointer); + + /** + * Determines if the return value of the {@code method} is scalarized. + * + * @return true if the return value is scalarized + */ + boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl inlineType) { + return hasScalarizedReturn(method, method.getMethodPointer(), inlineType, inlineType.getMetaspacePointer()); + } + + private native boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, long methodPointer, HotSpotResolvedObjectTypeImpl returnType, long inlineTypePointer); + + /** + * Computes the scalarized signature of the {@code method}. + * + * @return the scalarized signature + */ + HotSpotSignature getScalarizedSignature(HotSpotResolvedJavaMethodImpl method) { + return getScalarizedSignature(method, method.getMethodPointer()); + } + + private native HotSpotSignature getScalarizedSignature(HotSpotResolvedJavaMethodImpl method, long methodPointer); + + /** + * Determines if a inline type can be passed scalarized as an argument. + * + * @return true if the inline type can be scalarized + */ + boolean canBePassedAsFields(HotSpotResolvedObjectTypeImpl type) { + return canBePassedAsFields(type, type.getKlassPointer()); + } + + private native boolean canBePassedAsFields(HotSpotResolvedObjectTypeImpl type, long klassPointer); + + /** * Gets the number of entries in {@code method}'s exception handler table or 0 if it has no * exception handler table. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 4fbd4796024..ad87ca52ae3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -35,6 +35,7 @@ import java.lang.reflect.Executable; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.util.ArrayList; import java.util.BitSet; import java.util.Collections; import java.util.List; @@ -43,21 +44,7 @@ import jdk.internal.vm.VMSupport; import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; -import jdk.vm.ci.meta.AnnotationData; -import jdk.vm.ci.meta.Constant; -import jdk.vm.ci.meta.ConstantPool; -import jdk.vm.ci.meta.DefaultProfilingInfo; -import jdk.vm.ci.meta.ExceptionHandler; -import jdk.vm.ci.meta.JavaMethod; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.LineNumberTable; -import jdk.vm.ci.meta.Local; -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.SpeculationLog; -import jdk.vm.ci.meta.TriState; +import jdk.vm.ci.meta.*; /** * Implementation of {@link JavaMethod} for resolved HotSpot methods. @@ -790,4 +777,124 @@ public BitSet getOopMapAt(int bci) { compilerToVM().getOopMapAt(this, bci, oopMap); return BitSet.valueOf(oopMap); } + + @Override + // see ciMethod::is_scalarized_arg + public boolean isScalarizedParameter(int index) { + return compilerToVM().isScalarizedParameter(this, index); + } + + @Override + // see ciMethod::has_scalarized_args + public boolean hasScalarizedParameters() { + return compilerToVM().hasScalarizedParameters(this); + } + + @Override + public boolean hasScalarizedReturn() { + if (!returnsInlineType()) return false; + return compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); + } + + @Override + // see ciMethod::get_sig_cc() + public HotSpotSignature getScalarizedSignature() { + return compilerToVM().getScalarizedSignature(this); + } + + + @Override + /* + * + * see TypeTuple::make_range in opto/type.cpp + */ + public ResolvedJavaType[] getScalarizedReturn() { + if (!returnsInlineType() || hasScalarizedReturn()) return null; + HotSpotResolvedObjectType returnType = getReturnedInlineType(); + ResolvedJavaField[] fields = returnType.getInstanceFields(true); + + // two extra fields for oop (for already allocated buffer) and isInit (shows if scalarized value represents null) + ResolvedJavaType[] types = new ResolvedJavaType[fields.length + 2]; + types[0] = returnType; + for (int i = 1; i < types.length - 1; i++) { + JavaType type = fields[i - 1].getType(); + assert type instanceof ResolvedJavaType : "Resolved Java type expected"; + types[i] = (ResolvedJavaType) type; + } + types[types.length - 1] = HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean); + return types; + } + + + private boolean returnsInlineType() { + JavaType returnType = signature.getReturnType(getDeclaringClass()); + + // check if the method returns an object + if (returnType instanceof HotSpotResolvedObjectType type) { + // check if the returned value is an inline type + return !type.isInterface() && !type.isAbstract() && !type.isIdentity(); + } + return false; + } + + private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { + return (HotSpotResolvedObjectTypeImpl) signature.getReturnType(getDeclaringClass()); + } + + public ResolvedJavaType[] getScalarizedParameter(int index) { + assert isScalarizedParameter(index) : "Expected scalarized parameter"; + JavaType type = signature.getParameterType(index, getDeclaringClass()); + assert type instanceof ResolvedJavaType : "Resolved Java type expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + return (ResolvedJavaType[]) getFields((HotSpotResolvedObjectTypeImpl) resolvedType, true).toArray(); + } + + public boolean hasScalarizedReceiver() { + return !isStatic() && isScalarizedParameter(0); + } + + public ResolvedJavaType[] getScalarizedReceiver() { + assert hasScalarizedReceiver() : "Expected scalarized receiver"; + return (ResolvedJavaType[]) getFields(getDeclaringClass(), false).toArray(); + } + + @Override + /* + * + * see TypeTuple::make_domain in opto/type.cpp + */ + public ResolvedJavaType[] getScalarizedParameters() { + ArrayList types = new ArrayList<>(); + if (!isStatic() && isScalarizedParameter(0)) { + types.addAll(getFields(getDeclaringClass(), false)); + } + for (int i = 0; i < signature.getParameterCount(false); i++) { + JavaType type = signature.getParameterType(i, getDeclaringClass()); + assert type instanceof ResolvedJavaType : "Resolved Java type expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + + if (isScalarizedParameter(i + (isStatic() ? 0 : 1))) { + assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, true)); + } else { + types.add(resolvedType); + } + } + + return types.toArray(new ResolvedJavaType[types.size()]); + } + + + private static ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { + ResolvedJavaField[] fields = holder.getInstanceFields(true); + ArrayList types = new ArrayList<>(fields.length + (isInit ? 1 : 0)); + for (int i = 0; i < fields.length; i++) { + JavaType type = fields[i].getType(); + assert type instanceof ResolvedJavaType : "Resolved Java type expected"; + types.add((ResolvedJavaType) type); + } + if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean)); + return types; + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 5ba3babc9ca..0381e947d24 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1283,4 +1283,9 @@ private List getAnnotationData0(ResolvedJavaType... filter) { byte[] encoded = compilerToVM().getEncodedClassAnnotationData(this, filter); return VMSupport.decodeAnnotations(encoded, AnnotationDataDecoder.INSTANCE); } + + public boolean canBePassedAsFields() { + if (isStatic() || isInterface() || !isIdentity()) return false; + return compilerToVM().canBePassedAsFields(this); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index 760ff068005..86ea2cf0174 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.meta; +import jdk.vm.ci.hotspot.HotSpotSignature; + import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; @@ -480,4 +482,16 @@ default boolean isScoped() { * responsibility to ensure the same speculation log is used throughout a compilation. */ SpeculationLog getSpeculationLog(); + + boolean isScalarizedParameter(int index); + + boolean hasScalarizedParameters(); + + boolean hasScalarizedReturn(); + + HotSpotSignature getScalarizedSignature(); + + ResolvedJavaType[] getScalarizedReturn(); + + ResolvedJavaType[] getScalarizedParameters(); } From 8f532a5a9565ae8e8ce8c0cf43744188a1427d24 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 23 Dec 2024 21:00:52 +0100 Subject: [PATCH 27/98] Small adaptions on interface for new calling convention --- .../HotSpotResolvedJavaMethodImpl.java | 41 +++++++++++-------- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 6 +++ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index ad87ca52ae3..dfdee50e6a5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -781,7 +781,8 @@ public BitSet getOopMapAt(int bci) { @Override // see ciMethod::is_scalarized_arg public boolean isScalarizedParameter(int index) { - return compilerToVM().isScalarizedParameter(this, index); + // if method is non-static index 0 refers to receiver, therefore adapt the index + return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); } @Override @@ -809,7 +810,7 @@ public HotSpotSignature getScalarizedSignature() { * see TypeTuple::make_range in opto/type.cpp */ public ResolvedJavaType[] getScalarizedReturn() { - if (!returnsInlineType() || hasScalarizedReturn()) return null; + assert hasScalarizedReturn() : "Scalarized return presumed"; HotSpotResolvedObjectType returnType = getReturnedInlineType(); ResolvedJavaField[] fields = returnType.getInstanceFields(true); @@ -818,8 +819,7 @@ public ResolvedJavaType[] getScalarizedReturn() { types[0] = returnType; for (int i = 1; i < types.length - 1; i++) { JavaType type = fields[i - 1].getType(); - assert type instanceof ResolvedJavaType : "Resolved Java type expected"; - types[i] = (ResolvedJavaType) type; + types[i] = type.resolve(getDeclaringClass()); } types[types.length - 1] = HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean); return types; @@ -841,22 +841,24 @@ private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { return (HotSpotResolvedObjectTypeImpl) signature.getReturnType(getDeclaringClass()); } + @Override public ResolvedJavaType[] getScalarizedParameter(int index) { - assert isScalarizedParameter(index) : "Expected scalarized parameter"; + assert isScalarizedParameter(index) : "Scalarized parameter presumed"; JavaType type = signature.getParameterType(index, getDeclaringClass()); - assert type instanceof ResolvedJavaType : "Resolved Java type expected"; - ResolvedJavaType resolvedType = (ResolvedJavaType) type; + ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return (ResolvedJavaType[]) getFields((HotSpotResolvedObjectTypeImpl) resolvedType, true).toArray(); + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, true); } + @Override public boolean hasScalarizedReceiver() { - return !isStatic() && isScalarizedParameter(0); + return !isStatic() && compilerToVM().isScalarizedParameter(this, 0); } + @Override public ResolvedJavaType[] getScalarizedReceiver() { - assert hasScalarizedReceiver() : "Expected scalarized receiver"; - return (ResolvedJavaType[]) getFields(getDeclaringClass(), false).toArray(); + assert hasScalarizedReceiver() : "Scalarized receiver presumed"; + return getFieldsArray(getDeclaringClass(), false); } @Override @@ -865,16 +867,16 @@ public ResolvedJavaType[] getScalarizedReceiver() { * see TypeTuple::make_domain in opto/type.cpp */ public ResolvedJavaType[] getScalarizedParameters() { + assert hasScalarizedParameters() : "Any scalarized parameters presumed"; ArrayList types = new ArrayList<>(); - if (!isStatic() && isScalarizedParameter(0)) { + if (hasScalarizedReceiver()) { types.addAll(getFields(getDeclaringClass(), false)); } for (int i = 0; i < signature.getParameterCount(false); i++) { JavaType type = signature.getParameterType(i, getDeclaringClass()); - assert type instanceof ResolvedJavaType : "Resolved Java type expected"; - ResolvedJavaType resolvedType = (ResolvedJavaType) type; + ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); - if (isScalarizedParameter(i + (isStatic() ? 0 : 1))) { + if (isScalarizedParameter(i)) { assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, true)); } else { @@ -891,10 +893,15 @@ private static ArrayList getFields(HotSpotResolvedObjectTypeIm ArrayList types = new ArrayList<>(fields.length + (isInit ? 1 : 0)); for (int i = 0; i < fields.length; i++) { JavaType type = fields[i].getType(); - assert type instanceof ResolvedJavaType : "Resolved Java type expected"; - types.add((ResolvedJavaType) type); + ResolvedJavaType resolvedType = type.resolve(holder); + types.add(resolvedType); } if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean)); return types; } + + private static ResolvedJavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { + ArrayList list = getFields(holder, isInit); + return list.toArray(new ResolvedJavaType[list.size()]); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index 86ea2cf0174..a69d9cd51e1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -489,9 +489,15 @@ default boolean isScoped() { boolean hasScalarizedReturn(); + boolean hasScalarizedReceiver(); + HotSpotSignature getScalarizedSignature(); ResolvedJavaType[] getScalarizedReturn(); ResolvedJavaType[] getScalarizedParameters(); + + ResolvedJavaType[] getScalarizedParameter(int index); + + ResolvedJavaType[] getScalarizedReceiver(); } From d047d51f8a687ea2c401894bb1950e3f79a24768 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 26 Dec 2024 11:20:51 +0100 Subject: [PATCH 28/98] Extended the amd64 register interface for the new return convention (returning multiple values in registers) --- .../jdk/vm/ci/code/RegisterConfig.java | 7 +++ .../amd64/AMD64HotSpotRegisterConfig.java | 55 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java index 09360885c0b..f650bdd79ea 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java @@ -39,6 +39,13 @@ public interface RegisterConfig { */ Register getReturnRegister(JavaKind kind); + /** + * Gets the registers to be used for returning multiple values e.g. used for a scalarized inline object. + */ + default Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { + throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); + } + /** * Gets the maximum allowed size of the frame. */ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 705f0b997bb..0f37d9e7c94 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -104,6 +104,7 @@ public RegisterAttributes[] getAttributesMap() { } private final RegisterArray javaGeneralParameterRegisters; + private final RegisterArray javaGeneralReturnRegisters; private final RegisterArray nativeGeneralParameterRegisters; private final RegisterArray javaXMMParameterRegisters; private final RegisterArray nativeXMMParameterRegisters; @@ -151,11 +152,14 @@ public AMD64HotSpotRegisterConfig(TargetDescription target, RegisterArray alloca if (windowsOS) { javaGeneralParameterRegisters = new RegisterArray(rdx, r8, r9, rdi, rsi, rcx); + // see assembler_x86.hpp and SharedRuntime::java_return_convention in sharedRuntime_x86_64.cpp + javaGeneralReturnRegisters = new RegisterArray(rax, rcx, rsi, rdi, r9, r8, rdx); nativeGeneralParameterRegisters = new RegisterArray(rcx, rdx, r8, r9); nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3); this.needsNativeStackHomeSpace = true; } else { javaGeneralParameterRegisters = new RegisterArray(rsi, rdx, rcx, r8, r9, rdi); + javaGeneralReturnRegisters = new RegisterArray(rax, rdi, r9, r8, rcx, rdx, rsi); nativeGeneralParameterRegisters = new RegisterArray(rdi, rsi, rdx, rcx, r8, r9); nativeXMMParameterRegisters = new RegisterArray(xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7); this.needsNativeStackHomeSpace = false; @@ -200,6 +204,10 @@ public CallingConvention getCallingConvention(Type type, JavaType returnType, Ja return callingConvention(javaGeneralParameterRegisters, javaXMMParameterRegisters, false, returnType, parameterTypes, hotspotType, valueKindFactory); } +// public ReturnConvention getReturnConvention() { +// return null; +// } + @Override public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) { HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type; @@ -309,6 +317,53 @@ public Register getReturnRegister(JavaKind kind) { } } + @Override + public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { + Register[] registers = new Register[kinds.length]; + RegisterArray generalReturnRegisters = javaGeneralReturnRegisters; + RegisterArray xmmReturnRegisters = javaXMMParameterRegisters; + + int currentGeneral = includeRax ? 0 : 1; + int currentXMM = 0; + + Register register; + for (int i = 0; i < kinds.length; i++) { + final JavaKind kind = kinds[i]; + + switch (kind) { + case Byte: + case Boolean: + case Short: + case Char: + case Int: + case Long: + case Object: + assert currentGeneral < generalReturnRegisters.size() : "return values can only be stored in registers"; + registers[i] = generalReturnRegisters.get(currentGeneral++); + + break; + case Float: + case Double: + registers[i] = xmmReturnRegisters.get(currentXMM); + break; + default: + throw JVMCIError.shouldNotReachHere(); + } + + assert registers[i] != null : "return values can only be stored in registers"; + } + return registers; + } + + public AllocatableValue[] getReturnLocations(Register[] registers, JavaType[] returnTypes, ValueKindFactory valueKindFactory) { + AllocatableValue[] locations = new AllocatableValue[returnTypes.length]; + for (int i = 0; i < registers.length; i++) { + final JavaKind kind = returnTypes[i].getJavaKind().getStackKind(); + locations[i] = registers[i].asValue(valueKindFactory.getValueKind(kind)); + } + return locations; + } + @Override public Register getFrameRegister() { return rsp; From 2704d032ecc3973f39df136446493651cf50d934 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 30 Dec 2024 17:17:40 +0100 Subject: [PATCH 29/98] First basic implementations to support the scalarized return convention also in Graal. Introduced nullable virtual objects, to support framestates at invokes returning nullable scalarized values --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 12 +++++++++++- .../share/classes/jdk/vm/ci/code/RegisterConfig.java | 8 ++++---- .../share/classes/jdk/vm/ci/code/VirtualObject.java | 9 +++++++++ .../jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java | 10 ++++++++++ .../ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java | 12 +++++++++--- 5 files changed, 43 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 7f34339df21..a19fd9bef23 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1098,9 +1098,19 @@ void CodeInstaller::read_virtual_objects(HotSpotCompiledCodeStream* stream, JVMC if (is_auto_box) { _has_auto_box = true; } + // see code in output.cpp line 812 (PhaseOutput::FillLocArray line) + bool check_oop_or_hub = stream->read_bool("checkOopOrHub"); + ScopeValue *is_init = nullptr; + if (check_oop_or_hub) { + ScopeValue* cur_second = nullptr; + BasicType type = (BasicType) stream->read_u1("basicType"); + ScopeValue* value; + u1 tag = stream->read_u1("tag"); + is_init = get_scope_value(stream, tag, type, cur_second, JVMCI_CHECK); + } oop javaMirror = klass->java_mirror(); ScopeValue *klass_sv = new ConstantOopWriteValue(JNIHandles::make_local(javaMirror)); - ObjectValue* sv = is_auto_box ? new AutoBoxObjectValue(id, klass_sv) : new ObjectValue(id, klass_sv); + ObjectValue* sv = is_auto_box ? new AutoBoxObjectValue(id, klass_sv) : new ObjectValue(id, klass_sv, true, is_init); objects->at_put(id, sv); } // All the values which could be referenced by the VirtualObjects diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java index f650bdd79ea..87fcfe76cc7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java @@ -23,10 +23,7 @@ package jdk.vm.ci.code; import jdk.vm.ci.code.CallingConvention.Type; -import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; -import jdk.vm.ci.meta.PlatformKind; -import jdk.vm.ci.meta.ValueKind; +import jdk.vm.ci.meta.*; /** * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical @@ -69,6 +66,9 @@ default int getMaximumFrameSize() { */ CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory valueKindFactory); + default AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeRax) { + throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); + } /** * Gets the ordered set of registers that are can be used to pass parameters according to a * given calling convention. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java index d26b135a405..3915a3250b6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java @@ -44,6 +44,7 @@ public final class VirtualObject implements JavaValue { private JavaKind[] slotKinds; private final int id; private boolean isAutoBox; + private JavaValue[] oopOrHub; /** * Creates a new {@link VirtualObject} for the given type, with the given fields. If @@ -240,6 +241,10 @@ public JavaValue[] getValues() { return values; } + public JavaValue[] getOopOrHub() { + return oopOrHub; + } + /** * Returns the kind of the value at {@code index}. */ @@ -279,6 +284,10 @@ public void setValues(JavaValue[] values, JavaKind[] slotKinds) { this.slotKinds = slotKinds; } + public void setOopOrHub(JavaValue[] oopOrHub) { + this.oopOrHub = oopOrHub; + } + @Override public int hashCode() { return 42 + type.hashCode(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 49dfdcea5a2..fdfb7ce0808 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -983,6 +983,16 @@ private void writeVirtualObjects(VirtualObject[] virtualObjects) { VirtualObject vo = virtualObjects[i]; writeObjectType("type", vo.getType()); writeBoolean("isAutoBox", vo.isAutoBox()); + + // if virtual object can be nullable e.g. framestate of invoke with scalarized return values, also insert null indication + writeBoolean("checkOopOrHub", vo.getOopOrHub() != null); + if (vo.getOopOrHub() != null) { + //writeJavaValue(vo.getOopOrHub()[0], JavaKind.Object); + writeBasicType(JavaKind.Object); + JavaValue jv = vo.getOopOrHub()[0]; + writeJavaValue(jv, JavaKind.Object); + } + } for (int i = 0; i < length; i++) { VirtualObject vo = virtualObjects[i]; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 0f37d9e7c94..493c7700cba 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -45,6 +45,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.stream.Stream; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.CallingConvention; @@ -204,9 +205,14 @@ public CallingConvention getCallingConvention(Type type, JavaType returnType, Ja return callingConvention(javaGeneralParameterRegisters, javaXMMParameterRegisters, false, returnType, parameterTypes, hotspotType, valueKindFactory); } -// public ReturnConvention getReturnConvention() { -// return null; -// } + @Override + public AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeRax) { + JavaKind[] kinds = new JavaKind[returnTypes.length]; + for (int i = 0; i < returnTypes.length; i++) { + kinds[i] = returnTypes[i].getJavaKind().getStackKind(); + } + return getReturnLocations(getReturnRegisters(kinds, includeRax), returnTypes, valueKindFactory); + } @Override public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) { From 42f2bf3337a565e56401f5323731653a8027c41f Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 31 Dec 2024 20:24:45 +0100 Subject: [PATCH 30/98] Changed interface that checks for a scalarized return --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 7 ++----- .../share/classes/jdk/vm/ci/hotspot/CompilerToVM.java | 6 +++--- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 5 +++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 4116a02e1ea..7126f5b9f85 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -381,10 +381,7 @@ C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) Method* method = UNPACK_PAIR(Method, method); - Klass* klass = UNPACK_PAIR(Klass, klass); - assert(klass->is_inlinetype(), "Klass should be inline type"); - InlineKlass* inlineKlass = InlineKlass::cast(klass); - return !method->is_native() && inlineKlass->can_be_returned_as_fields(); + return method->has_scalarized_return(); C2V_END C2V_VMENTRY_0(jboolean, canBePassedAsFields, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) @@ -3320,7 +3317,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, {CC "isScalarizedParameter", CC "(" HS_METHOD2 "I)Z", FN_PTR(isScalarizedParameter)}, {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, - {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, + {CC "hasScalarizedReturn", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedReturn)}, {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, {CC "getExceptionTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getExceptionTableStart)}, {CC "getExceptionTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getExceptionTableLength)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 6b6a0c8140c..71130d04d75 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -156,11 +156,11 @@ boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method) { * * @return true if the return value is scalarized */ - boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl inlineType) { - return hasScalarizedReturn(method, method.getMethodPointer(), inlineType, inlineType.getMetaspacePointer()); + boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method) { + return hasScalarizedReturn(method, method.getMethodPointer()); } - private native boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, long methodPointer, HotSpotResolvedObjectTypeImpl returnType, long inlineTypePointer); + private native boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, long methodPointer); /** * Computes the scalarized signature of the {@code method}. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index dfdee50e6a5..2593976d77f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -793,8 +793,8 @@ public boolean hasScalarizedParameters() { @Override public boolean hasScalarizedReturn() { - if (!returnsInlineType()) return false; - return compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); + //if (!returnsInlineType()) return false; + return compilerToVM().hasScalarizedReturn(this); } @Override @@ -827,6 +827,7 @@ public ResolvedJavaType[] getScalarizedReturn() { private boolean returnsInlineType() { + //runtime().reflection.getType() JavaType returnType = signature.getReturnType(getDeclaringClass()); // check if the method returns an object From a31a07c98772a90a9240942c5831eb434056afa7 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 31 Dec 2024 20:57:34 +0100 Subject: [PATCH 31/98] Fixed bug in code which computes the floating point return registers --- .../jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 493c7700cba..8c43b08949e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -350,7 +350,7 @@ public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { break; case Float: case Double: - registers[i] = xmmReturnRegisters.get(currentXMM); + registers[i] = xmmReturnRegisters.get(currentXMM++); break; default: throw JVMCIError.shouldNotReachHere(); From 7dbe6f865ab6828c4857430a7f0869c2c4e54b77 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 1 Jan 2025 14:29:06 +0100 Subject: [PATCH 32/98] Undo wrong changes on return convention interface again. Doesn't deliver correct information if also enough registers are available to scalarize. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 9 ++- .../jdk/vm/ci/hotspot/CompilerToVM.java | 56 +++++++++---------- .../HotSpotResolvedJavaMethodImpl.java | 5 +- .../amd64/AMD64HotSpotRegisterConfig.java | 1 + 4 files changed, 37 insertions(+), 34 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 7126f5b9f85..dd354c33967 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -381,7 +381,10 @@ C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) Method* method = UNPACK_PAIR(Method, method); - return method->has_scalarized_return(); + Klass* klass = UNPACK_PAIR(Klass, klass); + assert(klass->is_inlinetype(), "Klass should be inline type"); + InlineKlass* inlineKlass = InlineKlass::cast(klass); + return !method->is_native() && inlineKlass->can_be_returned_as_fields(); C2V_END C2V_VMENTRY_0(jboolean, canBePassedAsFields, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) @@ -3317,8 +3320,8 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, {CC "isScalarizedParameter", CC "(" HS_METHOD2 "I)Z", FN_PTR(isScalarizedParameter)}, {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, - {CC "hasScalarizedReturn", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedReturn)}, - {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, + {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, + {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, {CC "getExceptionTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getExceptionTableStart)}, {CC "getExceptionTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getExceptionTableLength)}, {CC "findUniqueConcreteMethod", CC "(" HS_KLASS2 HS_METHOD2 ")" HS_METHOD, FN_PTR(findUniqueConcreteMethod)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 71130d04d75..ecbecde08a7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -156,11 +156,11 @@ boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method) { * * @return true if the return value is scalarized */ - boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method) { - return hasScalarizedReturn(method, method.getMethodPointer()); + boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, HotSpotResolvedObjectTypeImpl inlineType) { + return hasScalarizedReturn(method, method.getMethodPointer(), inlineType, inlineType.getMetaspacePointer()); } - private native boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, long methodPointer); + private native boolean hasScalarizedReturn(HotSpotResolvedJavaMethodImpl method, long methodPointer, HotSpotResolvedObjectTypeImpl returnType, long inlineTypePointer); /** * Computes the scalarized signature of the {@code method}. @@ -480,11 +480,11 @@ HotSpotResolvedJavaMethodImpl lookupMethodInPool(HotSpotConstantPool constantPoo } private native HotSpotResolvedJavaMethodImpl lookupMethodInPool(HotSpotConstantPool constantPool, - long constantPoolPointer, - int cpi, - byte opcode, - HotSpotResolvedJavaMethodImpl caller, - long callerMethodPointer); + long constantPoolPointer, + int cpi, + byte opcode, + HotSpotResolvedJavaMethodImpl caller, + long callerMethodPointer); /** * Converts the indy index operand of an invokedynamic instruction @@ -520,10 +520,10 @@ int decodeFieldIndexToCPIndex(HotSpotConstantPool constantPool, int rawIndex) { * @return {@code JVM_CONSTANT_MethodRef} or {@code JVM_CONSTANT_InterfaceMethodRef} constant pool entry index for the instruction */ int decodeMethodIndexToCPIndex(HotSpotConstantPool constantPool, int rawIndex) { - return decodeMethodIndexToCPIndex(constantPool, constantPool.getConstantPoolPointer(), rawIndex); - } + return decodeMethodIndexToCPIndex(constantPool, constantPool.getConstantPoolPointer(), rawIndex); + } - private native int decodeMethodIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int rawIndex); + private native int decodeMethodIndexToCPIndex(HotSpotConstantPool constantPool, long constantPoolPointer, int rawIndex); /** * Resolves the details for invoking the bootstrap method associated with the @@ -644,7 +644,7 @@ HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPoo } private native HotSpotResolvedObjectTypeImpl resolveFieldInPool(HotSpotConstantPool constantPool, long constantPoolPointer, - int rawIndex, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info); + int rawIndex, HotSpotResolvedJavaMethodImpl method, long methodPointer, byte opcode, int[] info); /** * Gets the appendix object (if any) associated with the entry identified by {@code which}. @@ -689,13 +689,13 @@ int installCode(HotSpotCompiledCode compiledCode, InstalledCode code, long faile } native int installCode0(long compiledCodeBuffer, - long serializationNS, - boolean withTypeInfo, - HotSpotCompiledCode compiledCode, - Object[] objectPool, - InstalledCode code, - long failedSpeculationsAddress, - byte[] speculations); + long serializationNS, + boolean withTypeInfo, + HotSpotCompiledCode compiledCode, + Object[] objectPool, + InstalledCode code, + long failedSpeculationsAddress, + byte[] speculations); /** * Gets flags specifying optional parts of code info. Only if a flag is set, will the @@ -750,8 +750,8 @@ HotSpotResolvedJavaMethodImpl resolveMethod(HotSpotResolvedObjectTypeImpl exactR } private native HotSpotResolvedJavaMethodImpl resolveMethod(HotSpotResolvedObjectTypeImpl exactReceiver, long exactReceiverKlass, - HotSpotResolvedJavaMethodImpl method, long methodPointer, - HotSpotResolvedObjectTypeImpl caller, long callerKlass); + HotSpotResolvedJavaMethodImpl method, long methodPointer, + HotSpotResolvedObjectTypeImpl caller, long callerKlass); /** * Gets the static initializer of {@code type}. @@ -1491,7 +1491,7 @@ void notifyCompilerInliningEvent(int compileId, HotSpotResolvedJavaMethodImpl ca } native void notifyCompilerInliningEvent(int compileId, HotSpotResolvedJavaMethodImpl caller, long callerPointer, - HotSpotResolvedJavaMethodImpl callee, long calleePointer, boolean succeeded, String message, int bci); + HotSpotResolvedJavaMethodImpl callee, long calleePointer, boolean succeeded, String message, int bci); /** * Gets the serialized annotation info for {@code type} by calling @@ -1500,12 +1500,12 @@ native void notifyCompilerInliningEvent(int compileId, HotSpotResolvedJavaMethod byte[] getEncodedClassAnnotationData(HotSpotResolvedObjectTypeImpl type, ResolvedJavaType[] filter) { try (KlassPointers a = new KlassPointers(filter)) { return getEncodedClassAnnotationData(type, type.getKlassPointer(), - a.types, a.types.length, a.buffer()); + a.types, a.types.length, a.buffer()); } } native byte[] getEncodedClassAnnotationData(HotSpotResolvedObjectTypeImpl type, long klassPointer, - Object filter, int filterLength, long filterKlassPointers); + Object filter, int filterLength, long filterKlassPointers); /** * Gets the serialized annotation info for {@code method} by calling @@ -1514,12 +1514,12 @@ native byte[] getEncodedClassAnnotationData(HotSpotResolvedObjectTypeImpl type, byte[] getEncodedExecutableAnnotationData(HotSpotResolvedJavaMethodImpl method, ResolvedJavaType[] filter) { try (KlassPointers a = new KlassPointers(filter)) { return getEncodedExecutableAnnotationData(method, method.getMethodPointer(), - a.types, a.types.length, a.buffer()); + a.types, a.types.length, a.buffer()); } } native byte[] getEncodedExecutableAnnotationData(HotSpotResolvedJavaMethodImpl method, long methodPointer, - Object filter, int filterLength, long filterKlassPointers); + Object filter, int filterLength, long filterKlassPointers); /** * Gets the serialized annotation info for the field denoted by {@code holder} and @@ -1528,12 +1528,12 @@ native byte[] getEncodedExecutableAnnotationData(HotSpotResolvedJavaMethodImpl m byte[] getEncodedFieldAnnotationData(HotSpotResolvedObjectTypeImpl holder, int fieldIndex, ResolvedJavaType[] filter) { try (KlassPointers a = new KlassPointers(filter)) { return getEncodedFieldAnnotationData(holder, holder.getKlassPointer(), fieldIndex, - a.types, a.types.length, a.buffer()); + a.types, a.types.length, a.buffer()); } } native byte[] getEncodedFieldAnnotationData(HotSpotResolvedObjectTypeImpl holder, long klassPointer, int fieldIndex, - Object filterTypes, int filterLength, long filterKlassPointers); + Object filterTypes, int filterLength, long filterKlassPointers); /** * Helper for passing {@Klass*} values to native code. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 2593976d77f..dfdee50e6a5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -793,8 +793,8 @@ public boolean hasScalarizedParameters() { @Override public boolean hasScalarizedReturn() { - //if (!returnsInlineType()) return false; - return compilerToVM().hasScalarizedReturn(this); + if (!returnsInlineType()) return false; + return compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); } @Override @@ -827,7 +827,6 @@ public ResolvedJavaType[] getScalarizedReturn() { private boolean returnsInlineType() { - //runtime().reflection.getType() JavaType returnType = signature.getReturnType(getDeclaringClass()); // check if the method returns an object diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 8c43b08949e..53969b6ac79 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -350,6 +350,7 @@ public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { break; case Float: case Double: + assert currentXMM < xmmReturnRegisters.size() : "return values can only be stored in registers"; registers[i] = xmmReturnRegisters.get(currentXMM++); break; default: From fe455ecd59fc351108edb9177f3a16be7941ed74 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 1 Jan 2025 19:44:26 +0100 Subject: [PATCH 33/98] Refactored interface for scalarized return --- .../HotSpotResolvedJavaMethodImpl.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index dfdee50e6a5..399a5daa3fc 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -797,6 +797,11 @@ public boolean hasScalarizedReturn() { return compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); } + @Override + public boolean hasScalarizedReceiver() { + return !isStatic() && compilerToVM().isScalarizedParameter(this, 0); + } + @Override // see ciMethod::get_sig_cc() public HotSpotSignature getScalarizedSignature() { @@ -814,14 +819,13 @@ public ResolvedJavaType[] getScalarizedReturn() { HotSpotResolvedObjectType returnType = getReturnedInlineType(); ResolvedJavaField[] fields = returnType.getInstanceFields(true); - // two extra fields for oop (for already allocated buffer) and isInit (shows if scalarized value represents null) - ResolvedJavaType[] types = new ResolvedJavaType[fields.length + 2]; + // one extra field for oop (for already allocated buffer) + ResolvedJavaType[] types = new ResolvedJavaType[fields.length + 1]; types[0] = returnType; - for (int i = 1; i < types.length - 1; i++) { + for (int i = 1; i < types.length; i++) { JavaType type = fields[i - 1].getType(); types[i] = type.resolve(getDeclaringClass()); } - types[types.length - 1] = HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean); return types; } @@ -841,6 +845,9 @@ private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { return (HotSpotResolvedObjectTypeImpl) signature.getReturnType(getDeclaringClass()); } + + // ignore the next funtions for the moment + @Override public ResolvedJavaType[] getScalarizedParameter(int index) { assert isScalarizedParameter(index) : "Scalarized parameter presumed"; @@ -850,10 +857,6 @@ public ResolvedJavaType[] getScalarizedParameter(int index) { return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, true); } - @Override - public boolean hasScalarizedReceiver() { - return !isStatic() && compilerToVM().isScalarizedParameter(this, 0); - } @Override public ResolvedJavaType[] getScalarizedReceiver() { From 1f04746b3935fef4e11433f985a896e58e0e84a1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 4 Jan 2025 14:58:41 +0100 Subject: [PATCH 34/98] Fixed bug, isInit information should be int no oop --- .../classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index fdfb7ce0808..74b0c3dfb9d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -988,9 +988,9 @@ private void writeVirtualObjects(VirtualObject[] virtualObjects) { writeBoolean("checkOopOrHub", vo.getOopOrHub() != null); if (vo.getOopOrHub() != null) { //writeJavaValue(vo.getOopOrHub()[0], JavaKind.Object); - writeBasicType(JavaKind.Object); + writeBasicType(JavaKind.Int); JavaValue jv = vo.getOopOrHub()[0]; - writeJavaValue(jv, JavaKind.Object); + writeJavaValue(jv, JavaKind.Int); } } From b4a6492f9c82fdce7cc75efc8c3a6606d296b2f1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 4 Jan 2025 16:07:29 +0100 Subject: [PATCH 35/98] Renamed non null information in debug info to isNotNull --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 4 ++-- .../share/classes/jdk/vm/ci/code/VirtualObject.java | 10 +++++----- .../jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java | 7 +++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index a19fd9bef23..57a5a0663a6 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1099,9 +1099,9 @@ void CodeInstaller::read_virtual_objects(HotSpotCompiledCodeStream* stream, JVMC _has_auto_box = true; } // see code in output.cpp line 812 (PhaseOutput::FillLocArray line) - bool check_oop_or_hub = stream->read_bool("checkOopOrHub"); + bool check_is_not_null = stream->read_bool("isNotNull"); ScopeValue *is_init = nullptr; - if (check_oop_or_hub) { + if (check_is_not_null) { ScopeValue* cur_second = nullptr; BasicType type = (BasicType) stream->read_u1("basicType"); ScopeValue* value; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java index 3915a3250b6..7fe999b0fef 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java @@ -44,7 +44,7 @@ public final class VirtualObject implements JavaValue { private JavaKind[] slotKinds; private final int id; private boolean isAutoBox; - private JavaValue[] oopOrHub; + private JavaValue[] isNotNull; /** * Creates a new {@link VirtualObject} for the given type, with the given fields. If @@ -241,8 +241,8 @@ public JavaValue[] getValues() { return values; } - public JavaValue[] getOopOrHub() { - return oopOrHub; + public JavaValue[] getIsNotNull() { + return isNotNull; } /** @@ -284,8 +284,8 @@ public void setValues(JavaValue[] values, JavaKind[] slotKinds) { this.slotKinds = slotKinds; } - public void setOopOrHub(JavaValue[] oopOrHub) { - this.oopOrHub = oopOrHub; + public void setIsNotNull(JavaValue[] isNotNull) { + this.isNotNull = isNotNull; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 74b0c3dfb9d..6f84050633d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -985,11 +985,10 @@ private void writeVirtualObjects(VirtualObject[] virtualObjects) { writeBoolean("isAutoBox", vo.isAutoBox()); // if virtual object can be nullable e.g. framestate of invoke with scalarized return values, also insert null indication - writeBoolean("checkOopOrHub", vo.getOopOrHub() != null); - if (vo.getOopOrHub() != null) { - //writeJavaValue(vo.getOopOrHub()[0], JavaKind.Object); + writeBoolean("isNotNull", vo.getIsNotNull() != null); + if (vo.getIsNotNull() != null) { writeBasicType(JavaKind.Int); - JavaValue jv = vo.getOopOrHub()[0]; + JavaValue jv = vo.getIsNotNull()[0]; writeJavaValue(jv, JavaKind.Int); } From 824afbe7a60e33e21704e5342387eebaa4e4caa4 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 7 Jan 2025 07:34:46 +0100 Subject: [PATCH 36/98] Updated test framework, include TestCallingConvention test --- .../lib/ir_framework/TestFramework.java | 2 +- .../valhalla/inlinetypes/InlineTypes.java | 2 +- .../valhalla/inlinetypes/TestC2CCalls.java | 22 ++++++++++++++++++- .../inlinetypes/TestCallingConvention.java | 3 ++- 4 files changed, 25 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 38979790987..07b8de3fd63 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -334,7 +334,7 @@ public TestFramework addScenarios(Scenario... scenarios) { this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); - addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-XX:InlineFieldMaxFlatSize=-1", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); + addFlags("-XX:-InlineTypePassFieldsAsArgs", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); return this; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java index d22d5517459..89812f65f58 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java @@ -129,7 +129,7 @@ public class InlineTypes { public static TestFramework getFramework() { StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); TestFramework framework = new TestFramework(walker.getCallerClass()).setDefaultWarmup(251); - framework.addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363"); + framework.addFlags("-XX:-InlineTypePassFieldsAsArgs", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363"); return framework; } } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java index 96a28fe801f..f2f618bc61e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java @@ -31,12 +31,32 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch -XX:-TieredCompilation + * TestC2CCalls + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-UseBimorphicInlining * -XX:CompileCommand=compileonly,TestC2CCalls*::test* * -XX:CompileCommand=dontinline,TestC2CCalls*::test* * TestC2CCalls + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-UseBimorphicInlining -XX:-ProfileInterpreter + * -XX:CompileCommand=compileonly,TestC2CCalls*::test* + * -XX:CompileCommand=dontinline,TestC2CCalls*::test* + * TestC2CCalls + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-UseBimorphicInlining + * -XX:CompileCommand=compileonly,TestC2CCalls::test* + * -XX:CompileCommand=dontinline,TestC2CCalls*::test* + * TestC2CCalls + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:-UseBimorphicInlining -XX:-ProfileInterpreter + * -XX:CompileCommand=compileonly,TestC2CCalls::test* + * -XX:CompileCommand=dontinline,TestC2CCalls*::test* + * TestC2CCalls + * */ +//-XX:-InlineTypePassFieldsAsArgs + import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java index 4726919da1a..fa5253bf984 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConvention.java @@ -51,7 +51,7 @@ * @modules java.base/jdk.internal.value * java.base/jdk.internal.vm.annotation * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm/timeout=450 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.valhalla.inlinetypes.TestCallingConvention + * @run main/othervm/timeout=300 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.valhalla.inlinetypes.TestCallingConvention */ @ForceCompileClassInitializer @@ -95,6 +95,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestCallingConvention.class).setGraalLog() .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, From c57d9e5af22c5ccfc2bec62e03eda3dfbea98f66 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 10 Jan 2025 21:15:58 +0100 Subject: [PATCH 37/98] Some changes on interface for new calling convention --- .../classes/jdk/vm/ci/code/CodeUtil.java | 14 +++++++++++ .../HotSpotResolvedJavaMethodImpl.java | 25 +++++++++++++++---- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 10 +++++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java index 59af250a695..d9d99ad7cf4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java @@ -437,4 +437,18 @@ public static CallingConvention getCallingConvention(CodeCacheProvider codeCache RegisterConfig registerConfig = codeCache.getRegisterConfig(); return registerConfig.getCallingConvention(type, retType, argTypes, valueKindFactory); } + + /** + * Create a calling convention from a {@link ResolvedJavaMethod} with the parameters scalarized. + * + * @param scalarizeReceiver decides if also the receiver should be scalarized + */ + public static CallingConvention getScalarizedCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory valueKindFactory, boolean scalarizeReceiver) { + Signature sig = method.getSignature(); + JavaType[] argTypes = method.getScalarizedParameters(scalarizeReceiver); + JavaType retType = sig.getReturnType(null); + RegisterConfig registerConfig = codeCache.getRegisterConfig(); + return registerConfig.getCallingConvention(type, retType, argTypes, valueKindFactory); + } + } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 399a5daa3fc..f35bc6a0f68 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -785,6 +785,11 @@ public boolean isScalarizedParameter(int index) { return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); } + public boolean isParameterNullFree(int index) { + // maybe for the future + return false; + } + @Override // see ciMethod::has_scalarized_args public boolean hasScalarizedParameters() { @@ -854,7 +859,13 @@ public ResolvedJavaType[] getScalarizedParameter(int index) { JavaType type = signature.getParameterType(index, getDeclaringClass()); ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, true); + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, false); + } + + @Override + public ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { + assert isScalarizedParameter(index) && isParameterNullFree(index) : "Scalarized nullable parameter presumed"; + return HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean); } @@ -869,11 +880,15 @@ public ResolvedJavaType[] getScalarizedReceiver() { * * see TypeTuple::make_domain in opto/type.cpp */ - public ResolvedJavaType[] getScalarizedParameters() { + public ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver) { assert hasScalarizedParameters() : "Any scalarized parameters presumed"; ArrayList types = new ArrayList<>(); if (hasScalarizedReceiver()) { - types.addAll(getFields(getDeclaringClass(), false)); + if (scalarizeReceiver) { + types.addAll(getFields(getDeclaringClass(), false)); + } else { + types.add(getDeclaringClass()); + } } for (int i = 0; i < signature.getParameterCount(false); i++) { JavaType type = signature.getParameterType(i, getDeclaringClass()); @@ -881,7 +896,7 @@ public ResolvedJavaType[] getScalarizedParameters() { if (isScalarizedParameter(i)) { assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, true)); + types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, !isParameterNullFree(i))); } else { types.add(resolvedType); } @@ -894,12 +909,12 @@ public ResolvedJavaType[] getScalarizedParameters() { private static ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { ResolvedJavaField[] fields = holder.getInstanceFields(true); ArrayList types = new ArrayList<>(fields.length + (isInit ? 1 : 0)); + if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean)); for (int i = 0; i < fields.length; i++) { JavaType type = fields[i].getType(); ResolvedJavaType resolvedType = type.resolve(holder); types.add(resolvedType); } - if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean)); return types; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index a69d9cd51e1..ddcdd03d91b 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -485,6 +485,10 @@ default boolean isScoped() { boolean isScalarizedParameter(int index); + default boolean isParameterNullFree(int index) { + throw new UnsupportedOperationException("isParameterNullFree not implemented yet"); + } + boolean hasScalarizedParameters(); boolean hasScalarizedReturn(); @@ -495,9 +499,13 @@ default boolean isScoped() { ResolvedJavaType[] getScalarizedReturn(); - ResolvedJavaType[] getScalarizedParameters(); + ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver); ResolvedJavaType[] getScalarizedParameter(int index); + default ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { + throw new UnsupportedOperationException("getScalarizedParameterIsNotNull is not supported"); + } + ResolvedJavaType[] getScalarizedReceiver(); } From 8d2ec5589c1a87d2df519602cb29724d61b2ce8b Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 13 Jan 2025 21:58:35 +0100 Subject: [PATCH 38/98] Include the receiver in utility functions for new calling convention. Fixed bug in getScalarizedCallingConvention. Disallow inlining for the moment. --- .../classes/jdk/vm/ci/code/CodeUtil.java | 1 + .../HotSpotResolvedJavaMethodImpl.java | 74 ++++++++++++++++--- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 19 +++++ 3 files changed, 84 insertions(+), 10 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java index d9d99ad7cf4..67cf35e4d14 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java @@ -444,6 +444,7 @@ public static CallingConvention getCallingConvention(CodeCacheProvider codeCache * @param scalarizeReceiver decides if also the receiver should be scalarized */ public static CallingConvention getScalarizedCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory valueKindFactory, boolean scalarizeReceiver) { + if (!method.hasScalarizedParameters()) return getCallingConvention(codeCache, type, method, valueKindFactory); Signature sig = method.getSignature(); JavaType[] argTypes = method.getScalarizedParameters(scalarizeReceiver); JavaType retType = sig.getReturnType(null); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index f35bc6a0f68..70d32cff00b 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -570,13 +570,14 @@ public Type[] getGenericParameterTypes() { @Override public boolean canBeInlined() { - if (isForceInline()) { - return true; - } - if (hasNeverInlineDirective()) { - return false; - } - return compilerToVM().isCompilable(this); +// if (isForceInline()) { +// return true; +// } +// if (hasNeverInlineDirective()) { +// return false; +// } +// return compilerToVM().isCompilable(this); + return false; } @Override @@ -785,11 +786,29 @@ public boolean isScalarizedParameter(int index) { return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); } + @Override + public boolean isScalarizedParameter(int index, boolean withReceiver) { + if (withReceiver) { + return compilerToVM().isScalarizedParameter(this, index); + } else { + return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); + } + } + + @Override public boolean isParameterNullFree(int index) { // maybe for the future return false; } + @Override + public boolean isParameterNullFree(int index, boolean withReceiver) { + // maybe for the future + if (!withReceiver) return false; + if (!isStatic() && index == 0) return true; + return false; + } + @Override // see ciMethod::has_scalarized_args public boolean hasScalarizedParameters() { @@ -813,6 +832,10 @@ public HotSpotSignature getScalarizedSignature() { return compilerToVM().getScalarizedSignature(this); } + public boolean needsStackRepair() { + return getScalarizedParameters(true).length > getSignature().getParameterCount(true) || getScalarizedParameters(true).length > getScalarizedParameters(false).length; + } + @Override /* @@ -862,10 +885,41 @@ public ResolvedJavaType[] getScalarizedParameter(int index) { return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, false); } + @Override + public ResolvedJavaType[] getScalarizedParameter(int index, boolean withReceiver) { + assert isScalarizedParameter(index, withReceiver) : "Scalarized parameter presumed"; + boolean includeReceiver = withReceiver && !isStatic(); + if (includeReceiver) { + if (index == 0) { + return getScalarizedReceiver(); + } else { + index--; + } + } + JavaType type = signature.getParameterType(index, getDeclaringClass()); + ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); + assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, !isParameterNullFree(index)); + + } + + @Override + public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withReceiver) { + boolean includeReceiver = withReceiver && !isStatic(); + if (includeReceiver) { + if (index == 0) { + getDeclaringClass().getInstanceFields(true); + } else { + index--; + } + } + return getSignature().getParameterType(index, getDeclaringClass()).resolve(getDeclaringClass()).getInstanceFields(true); + } + @Override public ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { - assert isScalarizedParameter(index) && isParameterNullFree(index) : "Scalarized nullable parameter presumed"; - return HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean); + assert isScalarizedParameter(index) && !isParameterNullFree(index) : "Scalarized nullable parameter presumed"; + return HotSpotResolvedPrimitiveType.forKind(JavaKind.Byte); } @@ -909,7 +963,7 @@ public ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver) { private static ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { ResolvedJavaField[] fields = holder.getInstanceFields(true); ArrayList types = new ArrayList<>(fields.length + (isInit ? 1 : 0)); - if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Boolean)); + if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Byte)); for (int i = 0; i < fields.length; i++) { JavaType type = fields[i].getType(); ResolvedJavaType resolvedType = type.resolve(holder); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index ddcdd03d91b..ed0fdceb8b1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -485,10 +485,18 @@ default boolean isScoped() { boolean isScalarizedParameter(int index); + default boolean isScalarizedParameter(int index, boolean withReceiver) { + throw new UnsupportedOperationException("isScalarizedParameter not implemented yet"); + } + default boolean isParameterNullFree(int index) { throw new UnsupportedOperationException("isParameterNullFree not implemented yet"); } + default boolean isParameterNullFree(int index, boolean withReceiver) { + throw new UnsupportedOperationException("isParameterNullFree not implemented yet"); + } + boolean hasScalarizedParameters(); boolean hasScalarizedReturn(); @@ -503,9 +511,20 @@ default boolean isParameterNullFree(int index) { ResolvedJavaType[] getScalarizedParameter(int index); + ResolvedJavaType[] getScalarizedParameter(int index, boolean withReceiver); + + default ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withReceiver) { + throw new UnsupportedOperationException("getParameterFields is not supported"); + } + + default ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { throw new UnsupportedOperationException("getScalarizedParameterIsNotNull is not supported"); } + default JavaKind getScalarizedParameterIsNotNullKind() { + return JavaKind.Byte; + } + ResolvedJavaType[] getScalarizedReceiver(); } From a601bf2426861706d5ec6b4228177b6bd6ab46be Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 14 Jan 2025 09:39:54 +0100 Subject: [PATCH 39/98] Fixed bug in interface responsible for retrieving scalarized parameters --- .../vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 70d32cff00b..6f7b4b55622 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -908,7 +908,7 @@ public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withR boolean includeReceiver = withReceiver && !isStatic(); if (includeReceiver) { if (index == 0) { - getDeclaringClass().getInstanceFields(true); + return getDeclaringClass().getInstanceFields(true); } else { index--; } @@ -937,12 +937,10 @@ public ResolvedJavaType[] getScalarizedReceiver() { public ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver) { assert hasScalarizedParameters() : "Any scalarized parameters presumed"; ArrayList types = new ArrayList<>(); - if (hasScalarizedReceiver()) { - if (scalarizeReceiver) { - types.addAll(getFields(getDeclaringClass(), false)); - } else { - types.add(getDeclaringClass()); - } + if (hasScalarizedReceiver() && scalarizeReceiver) { + types.addAll(getFields(getDeclaringClass(), false)); + } else if (!isStatic()) { + types.add(getDeclaringClass()); } for (int i = 0; i < signature.getParameterCount(false); i++) { JavaType type = signature.getParameterType(i, getDeclaringClass()); From 1ecef2ed2d3e7b461727a61ce51a3b6927ba575e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 18 Jan 2025 16:12:14 +0100 Subject: [PATCH 40/98] Use the verified_inline_entry point for calls from the interpreter to a jvmci nmethod. Export _from_compiled_inline_ro_entry and use is_inline_klass in compilerToVM assertion --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 4 ++-- src/hotspot/share/jvmci/jvmciEnv.cpp | 2 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index dd354c33967..82c9cae965f 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -382,14 +382,14 @@ C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) Method* method = UNPACK_PAIR(Method, method); Klass* klass = UNPACK_PAIR(Klass, klass); - assert(klass->is_inlinetype(), "Klass should be inline type"); + assert(klass->is_inline_klass(), "Klass should be inline type"); InlineKlass* inlineKlass = InlineKlass::cast(klass); return !method->is_native() && inlineKlass->can_be_returned_as_fields(); C2V_END C2V_VMENTRY_0(jboolean, canBePassedAsFields, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); - assert(klass->is_inlinetype(), "Klass should be an inline type"); + assert(klass->is_inline_klass(), "Klass should be an inline type"); InlineKlass* inlineKlass = InlineKlass::cast(klass); return inlineKlass->can_be_passed_as_fields(); C2V_END diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 2f7c0383489..45289bdcc8b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1743,7 +1743,7 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c if (cb->is_nmethod()) { nmethod* nm = cb->as_nmethod_or_null(); if (nm->is_in_use()) { - set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_entry_point()); + set_InstalledCode_entryPoint(installed_code, (jlong) nm->verified_inline_entry_point()); } } else { set_InstalledCode_entryPoint(installed_code, (jlong) cb->code_begin()); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index db0d13ab0fb..97c6ab21345 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -301,7 +301,7 @@ nonstatic_field(Method, _flags._status, u4) \ volatile_nonstatic_field(Method, _code, nmethod*) \ volatile_nonstatic_field(Method, _from_compiled_entry, address) \ - volatile_nonstatic_field(Method, _from_compiled_inline_entry, address) \ + volatile_nonstatic_field(Method, _from_compiled_inline_ro_entry, address) \ \ nonstatic_field(MethodCounters, _invoke_mask, int) \ nonstatic_field(MethodCounters, _backedge_mask, int) \ From 3ec246dcc643fb4374a9750c7686b610b3cfb2f7 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 20 Jan 2025 20:34:14 +0100 Subject: [PATCH 41/98] Fix access to static field in class object --- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 630cb090fa2..1d69da9bd51 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -118,7 +118,8 @@ public boolean isFlat() { @Override public boolean isInitialized() { assert isStatic() : "should only be called on static fields"; - return UNSAFE.getAddress(holder.getKlassPointer(), this.offset) != 0; + holder.initialize(); + return !runtime().getCompilerToVM().readStaticFieldValue(holder, this.offset, JavaKind.Object.getTypeChar()).isNull(); } @Override From 03e2ee8777bc6363fbb8a292ad78f33d82bc9579 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 20 Jan 2025 20:41:53 +0100 Subject: [PATCH 42/98] Avoid null check for virtual calls with jvmci as caller and a scalarized receiver --- .../share/interpreter/linkResolver.cpp | 19 ++++++++++++++++--- .../share/interpreter/linkResolver.hpp | 6 ++++-- src/hotspot/share/runtime/sharedRuntime.cpp | 9 +++++++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 0811a71c5c1..a41356baf0b 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1705,7 +1705,20 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantP switch (byte) { case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; case Bytecodes::_invokespecial : resolve_invokespecial (result, recv, pool, index, CHECK); break; - case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break; + case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, true, CHECK); break; + case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; + case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; + case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; + default : break; + } + return; +} + +void LinkResolver::resolve_invoke_jvmci(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, bool check_null_or_abstract, TRAPS) { + switch (byte) { + case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; + case Bytecodes::_invokespecial : resolve_invokespecial (result, recv, pool, index, CHECK); break; + case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, check_null_or_abstract, CHECK); break; case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; @@ -1757,12 +1770,12 @@ void LinkResolver::resolve_invokespecial(CallInfo& result, Handle recv, void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, + const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS) { LinkInfo link_info(pool, index, Bytecodes::_invokevirtual, CHECK); Klass* recvrKlass = recv.is_null() ? (Klass*)nullptr : recv->klass(); - resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); + resolve_virtual_call(result, recv, recvrKlass, link_info, check_null_or_abstract, CHECK); } diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index f7463aa6d03..5ee59bca645 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -271,7 +271,7 @@ class LinkResolver: AllStatic { static void resolve_invokespecial (CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokevirtual (CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, TRAPS); + const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS); static void resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokedynamic (CallInfo& result, @@ -357,7 +357,9 @@ class LinkResolver: AllStatic { // runtime resolving from attached method static void resolve_invoke(CallInfo& result, Handle& recv, const methodHandle& attached_method, - Bytecodes::Code byte, bool check_null_and_abstract, TRAPS); + Bytecodes::Code byte, bool check_null_or_abstract, TRAPS); + + static void resolve_invoke_jvmci(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, bool check_null_or_abstract, TRAPS); // Only resolved method known. static void throw_abstract_method_error(const methodHandle& resolved_method, TRAPS) { diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 0f1ef202e8b..18777e753fc 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1280,7 +1280,8 @@ Handle SharedRuntime::find_callee_info_helper(vframeStream& vfst, Bytecodes::Cod // If the receiver is an inline type that is passed as fields, no oop is available // Resolve the call without receiver null checking. assert(!callee->mismatch(), "calls with inline type receivers should never mismatch"); - assert(attached_method.not_null() && !attached_method->is_abstract(), "must have non-abstract attached method"); + // TODO: create a correct check for JVMCI, attached_method.not_null() fails + //assert(attached_method.not_null() && !attached_method->is_abstract(), "must have non-abstract attached method"); if (bc == Bytecodes::_invokeinterface) { bc = Bytecodes::_invokevirtual; // C2 optimistically replaces interface calls by virtual calls } @@ -1302,7 +1303,11 @@ Handle SharedRuntime::find_callee_info_helper(vframeStream& vfst, Bytecodes::Cod } else { // Parameterized by bytecode. constantPoolHandle constants(current, caller->constants()); - LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_NH); + if(vfst.nm()->is_compiled_by_jvmci()){ + LinkResolver::resolve_invoke_jvmci(callinfo, receiver, constants, bytecode_index, bc, check_null_and_abstract, CHECK_NH); + }else{ + LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_NH); + } } #ifdef ASSERT From 8b44917cfd64cbc4523797b08e89233ce037d8ed Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 20 Jan 2025 20:43:05 +0100 Subject: [PATCH 43/98] Include jvmci in condition --- src/hotspot/share/code/nmethod.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 50b590ffb64..33da93ac677 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -727,7 +727,7 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map // If inline types are passed as fields, use the extended signature // which contains the types of all (oop) fields of the inline type. - if (is_compiled_by_c2() && callee->has_scalarized_args()) { + if ((is_compiled_by_c2() || is_compiled_by_jvmci()) && callee->has_scalarized_args()) { const GrowableArray* sig = callee->adapter()->get_sig_cc(); assert(sig != nullptr, "sig should never be null"); TempNewSymbol tmp_sig = SigEntry::create_symbol(sig); From 48cb2abbbf509b7d7377cf2933a26dd9afe08eed Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 20 Jan 2025 21:50:45 +0100 Subject: [PATCH 44/98] Do an extra case check for JVMCI at the moment because method attachement fails. --- src/hotspot/share/code/nmethod.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 33da93ac677..71592321d8f 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -738,6 +738,24 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map } else { SimpleScopeDesc ssd(this, pc); + if(is_compiled_by_jvmci()){ + callee = ssd.method(); + has_receiver = !(callee->access_flags().is_static()); + has_appendix = false; + signature = callee->signature(); + + // If inline types are passed as fields, use the extended signature + // which contains the types of all (oop) fields of the inline type. + if (callee->has_scalarized_args()) { + const GrowableArray* sig = callee->adapter()->get_sig_cc(); + assert(sig != nullptr, "sig should never be null"); + TempNewSymbol tmp_sig = SigEntry::create_symbol(sig); + has_receiver = false; // The extended signature contains the receiver type + fr.oops_compiled_arguments_do(tmp_sig, has_receiver, has_appendix, reg_map, f); + return; + } + } + Bytecode_invoke call(methodHandle(Thread::current(), ssd.method()), ssd.bci()); has_receiver = call.has_receiver(); has_appendix = call.has_appendix(); From e3d9a78881c8e2f191c04de43b11d67a910da2d5 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 22 Jan 2025 15:51:24 +0100 Subject: [PATCH 45/98] Avoid null check on receiver for invokeinterface with scalarized arguments using constant pool lookup --- src/hotspot/share/interpreter/linkResolver.cpp | 8 ++++---- src/hotspot/share/interpreter/linkResolver.hpp | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index a41356baf0b..72284cc32ed 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1708,7 +1708,7 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantP case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, true, CHECK); break; case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; - case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; + case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, true, CHECK); break; default : break; } return; @@ -1721,7 +1721,7 @@ void LinkResolver::resolve_invoke_jvmci(CallInfo& result, Handle recv, const con case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, check_null_or_abstract, CHECK); break; case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; - case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; + case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, check_null_or_abstract, CHECK); break; default : break; } return; @@ -1779,10 +1779,10 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, } -void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { +void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS) { LinkInfo link_info(pool, index, Bytecodes::_invokeinterface, CHECK); Klass* recvrKlass = recv.is_null() ? (Klass*)nullptr : recv->klass(); - resolve_interface_call(result, recv, recvrKlass, link_info, true, CHECK); + resolve_interface_call(result, recv, recvrKlass, link_info, check_null_or_abstract, CHECK); } bool LinkResolver::resolve_previously_linked_invokehandle(CallInfo& result, const LinkInfo& link_info, const constantPoolHandle& pool, int index, TRAPS) { diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index 5ee59bca645..735cca47fe4 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -273,7 +273,7 @@ class LinkResolver: AllStatic { static void resolve_invokevirtual (CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS); static void resolve_invokeinterface(CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, TRAPS); + const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS); static void resolve_invokedynamic (CallInfo& result, const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokehandle (CallInfo& result, From 65bcc812243c06e43ed8779f6734d672b83e6e9b Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 22 Jan 2025 18:53:45 +0100 Subject: [PATCH 46/98] frame::sender_for_compiled_frame in frame_x86.inline.hpp causes SIGSEV because jvmci nmethod is not checked for stack repair --- src/hotspot/share/code/nmethod.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index bdabcdf624c..7105426c14e 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -685,7 +685,7 @@ class nmethod : public CodeBlob { bool needs_stack_repair() const { if (is_compiled_by_c1()) { return method()->c1_needs_stack_repair(); - } else if (is_compiled_by_c2()) { + } else if (is_compiled_by_c2() || is_compiled_by_jvmci()) { return method()->c2_needs_stack_repair(); } else { return false; From f3eb699ad134b11e18e1f2487afd4d89a595a366 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 29 Jan 2025 19:09:21 +0100 Subject: [PATCH 47/98] Don't try to initialize holder class when doing a check if static field is initialized --- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 1d69da9bd51..94503721b42 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -118,8 +118,10 @@ public boolean isFlat() { @Override public boolean isInitialized() { assert isStatic() : "should only be called on static fields"; - holder.initialize(); - return !runtime().getCompilerToVM().readStaticFieldValue(holder, this.offset, JavaKind.Object.getTypeChar()).isNull(); + if (getDeclaringClass().isInitialized()) { + return !runtime().getCompilerToVM().readStaticFieldValue(getDeclaringClass(), getOffset(), JavaKind.Object.getTypeChar()).isNull(); + } + return false; } @Override From 47636b755bbcfd21ea2778185cd4c2e091bba9da Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 29 Jan 2025 19:15:22 +0100 Subject: [PATCH 48/98] Undo changes made because JIT method was not attached in by Graal --- src/hotspot/share/code/nmethod.cpp | 18 ------------- .../share/interpreter/linkResolver.cpp | 25 +++++-------------- .../share/interpreter/linkResolver.hpp | 4 +-- src/hotspot/share/runtime/sharedRuntime.cpp | 9 ++----- 4 files changed, 10 insertions(+), 46 deletions(-) diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 71592321d8f..33da93ac677 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -738,24 +738,6 @@ void nmethod::preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map } else { SimpleScopeDesc ssd(this, pc); - if(is_compiled_by_jvmci()){ - callee = ssd.method(); - has_receiver = !(callee->access_flags().is_static()); - has_appendix = false; - signature = callee->signature(); - - // If inline types are passed as fields, use the extended signature - // which contains the types of all (oop) fields of the inline type. - if (callee->has_scalarized_args()) { - const GrowableArray* sig = callee->adapter()->get_sig_cc(); - assert(sig != nullptr, "sig should never be null"); - TempNewSymbol tmp_sig = SigEntry::create_symbol(sig); - has_receiver = false; // The extended signature contains the receiver type - fr.oops_compiled_arguments_do(tmp_sig, has_receiver, has_appendix, reg_map, f); - return; - } - } - Bytecode_invoke call(methodHandle(Thread::current(), ssd.method()), ssd.bci()); has_receiver = call.has_receiver(); has_appendix = call.has_appendix(); diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 72284cc32ed..b1cdc2cfb0b 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1705,23 +1705,10 @@ void LinkResolver::resolve_invoke(CallInfo& result, Handle recv, const constantP switch (byte) { case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; case Bytecodes::_invokespecial : resolve_invokespecial (result, recv, pool, index, CHECK); break; - case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, true, CHECK); break; + case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, CHECK); break; case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; - case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, true, CHECK); break; - default : break; - } - return; -} - -void LinkResolver::resolve_invoke_jvmci(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, bool check_null_or_abstract, TRAPS) { - switch (byte) { - case Bytecodes::_invokestatic : resolve_invokestatic (result, pool, index, CHECK); break; - case Bytecodes::_invokespecial : resolve_invokespecial (result, recv, pool, index, CHECK); break; - case Bytecodes::_invokevirtual : resolve_invokevirtual (result, recv, pool, index, check_null_or_abstract, CHECK); break; - case Bytecodes::_invokehandle : resolve_invokehandle (result, pool, index, CHECK); break; - case Bytecodes::_invokedynamic : resolve_invokedynamic (result, pool, index, CHECK); break; - case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, check_null_or_abstract, CHECK); break; + case Bytecodes::_invokeinterface: resolve_invokeinterface(result, recv, pool, index, CHECK); break; default : break; } return; @@ -1770,19 +1757,19 @@ void LinkResolver::resolve_invokespecial(CallInfo& result, Handle recv, void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, bool check_null_or_abstract, + const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, Bytecodes::_invokevirtual, CHECK); Klass* recvrKlass = recv.is_null() ? (Klass*)nullptr : recv->klass(); - resolve_virtual_call(result, recv, recvrKlass, link_info, check_null_or_abstract, CHECK); + resolve_virtual_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); } -void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS) { +void LinkResolver::resolve_invokeinterface(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS) { LinkInfo link_info(pool, index, Bytecodes::_invokeinterface, CHECK); Klass* recvrKlass = recv.is_null() ? (Klass*)nullptr : recv->klass(); - resolve_interface_call(result, recv, recvrKlass, link_info, check_null_or_abstract, CHECK); + resolve_interface_call(result, recv, recvrKlass, link_info, /*check_null_or_abstract*/true, CHECK); } bool LinkResolver::resolve_previously_linked_invokehandle(CallInfo& result, const LinkInfo& link_info, const constantPoolHandle& pool, int index, TRAPS) { diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index 735cca47fe4..8fab5a703f3 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -271,9 +271,9 @@ class LinkResolver: AllStatic { static void resolve_invokespecial (CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokevirtual (CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokeinterface(CallInfo& result, Handle recv, - const constantPoolHandle& pool, int index, bool check_null_or_abstract, TRAPS); + const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokedynamic (CallInfo& result, const constantPoolHandle& pool, int index, TRAPS); static void resolve_invokehandle (CallInfo& result, diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 18777e753fc..0f1ef202e8b 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1280,8 +1280,7 @@ Handle SharedRuntime::find_callee_info_helper(vframeStream& vfst, Bytecodes::Cod // If the receiver is an inline type that is passed as fields, no oop is available // Resolve the call without receiver null checking. assert(!callee->mismatch(), "calls with inline type receivers should never mismatch"); - // TODO: create a correct check for JVMCI, attached_method.not_null() fails - //assert(attached_method.not_null() && !attached_method->is_abstract(), "must have non-abstract attached method"); + assert(attached_method.not_null() && !attached_method->is_abstract(), "must have non-abstract attached method"); if (bc == Bytecodes::_invokeinterface) { bc = Bytecodes::_invokevirtual; // C2 optimistically replaces interface calls by virtual calls } @@ -1303,11 +1302,7 @@ Handle SharedRuntime::find_callee_info_helper(vframeStream& vfst, Bytecodes::Cod } else { // Parameterized by bytecode. constantPoolHandle constants(current, caller->constants()); - if(vfst.nm()->is_compiled_by_jvmci()){ - LinkResolver::resolve_invoke_jvmci(callinfo, receiver, constants, bytecode_index, bc, check_null_and_abstract, CHECK_NH); - }else{ - LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_NH); - } + LinkResolver::resolve_invoke(callinfo, receiver, constants, bytecode_index, bc, CHECK_NH); } #ifdef ASSERT From 06d853a21dcecaea3ca168fe220b1f20c2cb59ba Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 29 Jan 2025 19:17:25 +0100 Subject: [PATCH 49/98] Attach a JIT method during relocation if the method has a scalarized argument --- .../cpu/x86/jvmciCodeInstaller_x86.cpp | 27 ++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 9e6a4789dc2..11c4050497e 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -164,9 +164,15 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); + if(method()->has_scalarized_args()) { _instructions->relocate(call->instruction_address(), - virtual_call_Relocation::spec(_invoke_mark_pc), + virtual_call_Relocation::spec(_invoke_mark_pc, _oop_recorder->find_index(method())), Assembler::call32_operand); + } else { + _instructions->relocate(call->instruction_address(), + virtual_call_Relocation::spec(_invoke_mark_pc), + Assembler::call32_operand); + } break; } case INVOKESTATIC: { @@ -174,16 +180,31 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - _instructions->relocate(call->instruction_address(), + if(method()->has_scalarized_args()) { + _instructions->relocate(call->instruction_address(), + relocInfo::static_call_type, Assembler::call32_operand,_oop_recorder->find_index(method())); + }else{ + _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand); + } + break; } case INVOKESPECIAL: { assert(!method->is_static(), "cannot call static method with invokespecial"); call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - _instructions->relocate(call->instruction_address(), + + // attach the target method only for scalarized args to avoid null check on receiver if receiver was optimized from non-scalarized to scalarized + // attach only for scalarized args otherwise assert(attached_method->has_scalarized_args(), "invalid use of attached method"); will trigger + if (method()->has_scalarized_args()) { + _instructions->relocate(call->instruction_address(), + relocInfo::opt_virtual_call_type, Assembler::call32_operand, _oop_recorder->find_index(method())); + } else { + _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand); + } + break; } default: From 2a56481552f26e9cfc2b98a592ef82e9cd486f3d Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 3 Feb 2025 10:01:10 +0100 Subject: [PATCH 50/98] Enable inlining of methods with scalarized parameters again. Use the outer declaring class for flat fields during constant folding. Remove assertion checking for inline klass and just return false instead. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 2 +- .../ci/hotspot/HotSpotObjectConstantImpl.java | 2 +- .../hotspot/HotSpotResolvedJavaFieldImpl.java | 18 ++++++++++++++++++ .../hotspot/HotSpotResolvedJavaMethodImpl.java | 16 ++++++++-------- .../hotspot/HotSpotResolvedObjectTypeImpl.java | 1 + .../jdk/vm/ci/meta/ResolvedJavaField.java | 10 ++++++++++ 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 82c9cae965f..cb4319bd4e5 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -382,7 +382,7 @@ C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) Method* method = UNPACK_PAIR(Method, method); Klass* klass = UNPACK_PAIR(Klass, klass); - assert(klass->is_inline_klass(), "Klass should be inline type"); + if(!klass->is_inline_klass()) return false; InlineKlass* inlineKlass = InlineKlass::cast(klass); return !method->is_native() && inlineKlass->can_be_returned_as_fields(); C2V_END diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index cf3ac0f994a..625bc47aca1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -200,7 +200,7 @@ public JavaConstant readFieldValue(HotSpotResolvedJavaField field) { if (field.isStatic()) { return null; } - HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getDeclaringClass(); + HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getOuterDeclaringClass(); char typeChar = field.getType().getJavaKind().getTypeChar(); return runtime().compilerToVm.readFieldValue(this, declaringClass, field.getOffset(), typeChar); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 94503721b42..12158bac92a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -42,6 +42,9 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { private final HotSpotResolvedObjectTypeImpl holder; + + private HotSpotResolvedObjectTypeImpl outerHolder; + private JavaType type; /** @@ -171,6 +174,21 @@ public HotSpotResolvedObjectTypeImpl getDeclaringClass() { return holder; } + @Override + public HotSpotResolvedObjectTypeImpl getOuterDeclaringClass() { + if (outerHolder == null) { + return holder; + } + return outerHolder; + } + + @Override + public ResolvedJavaField setOuterDeclaringClass(HotSpotResolvedObjectType outerHolder) { + HotSpotResolvedJavaFieldImpl field = new HotSpotResolvedJavaFieldImpl(holder, type, offset, classfileFlags, internalFlags, index); + field.outerHolder = (HotSpotResolvedObjectTypeImpl) outerHolder; + return field; + } + @Override public String getName() { return holder.getFieldInfo(index).getName(holder); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 6f7b4b55622..ff7c172c728 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -570,14 +570,13 @@ public Type[] getGenericParameterTypes() { @Override public boolean canBeInlined() { -// if (isForceInline()) { -// return true; -// } -// if (hasNeverInlineDirective()) { -// return false; -// } -// return compilerToVM().isCompilable(this); - return false; + if (isForceInline()) { + return true; + } + if (hasNeverInlineDirective()) { + return false; + } + return compilerToVM().isCompilable(this); } @Override @@ -864,6 +863,7 @@ private boolean returnsInlineType() { // check if the method returns an object if (returnType instanceof HotSpotResolvedObjectType type) { // check if the returned value is an inline type + // TODO: is correct otherwise just use return true? return !type.isInterface() && !type.isAbstract() && !type.isIdentity(); } return false; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 0381e947d24..37b93855a32 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -957,6 +957,7 @@ private HotSpotResolvedJavaField[] getFlattenedFields(HotSpotResolvedJavaField[] // holder has no header so remove the header offset int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.firstFieldOffset()); HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; + innerField.setOuterDeclaringClass(this); resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset)); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index bd74d7d50b0..b0d1db789df 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -22,6 +22,8 @@ */ package jdk.vm.ci.meta; +import jdk.vm.ci.hotspot.HotSpotResolvedObjectType; + import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Modifier; @@ -114,6 +116,14 @@ default int getNullMarkerOffset() { @Override ResolvedJavaType getDeclaringClass(); + default ResolvedJavaType getOuterDeclaringClass() { + throw new UnsupportedOperationException(); + } + + default ResolvedJavaField setOuterDeclaringClass(HotSpotResolvedObjectType outerHolder) { + throw new UnsupportedOperationException(); + } + /** * Gets the value of the {@code ConstantValue} attribute ({@jvms 4.7.2}) associated with this * field. From 7bb56bae76d652a21bc76e4ca757d3f02abadc55 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 8 Feb 2025 16:13:21 +0100 Subject: [PATCH 51/98] Refactored interface for calling convention --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 10 + src/hotspot/share/jvmci/jvmciEnv.hpp | 1 + .../jdk/vm/ci/hotspot/CompilerToVM.java | 11 ++ .../HotSpotResolvedJavaMethodImpl.java | 136 ++++++------- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 185 ++++++++++++++++-- 5 files changed, 255 insertions(+), 88 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index cb4319bd4e5..4b62829846e 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -374,6 +374,15 @@ C2V_VMENTRY_0(jboolean, isScalarizedParameter, (JNIEnv* env, jobject, ARGUMENT_P return method->is_scalarized_arg(idx); C2V_END +C2V_VMENTRY_0(jbooleanArray, getScalarizedParametersInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jint len)) + Method* method = UNPACK_PAIR(Method, method); + JVMCIPrimitiveArray result = JVMCIENV->new_booleanArray(len, JVMCI_CHECK_NULL); + for(int i=0; iput_bool_at(result, i, method->is_scalarized_arg(i)); + } + return JVMCIENV->get_jbooleanArray(result); +C2V_END + C2V_VMENTRY_0(jboolean, hasScalarizedParameters, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) Method* method = UNPACK_PAIR(Method, method); return method->has_scalarized_args(); @@ -3319,6 +3328,7 @@ C2V_VMENTRY_0(jint, getCompilationActivityMode, (JNIEnv* env, jobject)) JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, {CC "isScalarizedParameter", CC "(" HS_METHOD2 "I)Z", FN_PTR(isScalarizedParameter)}, + {CC "getScalarizedParametersInfo", CC "(" HS_METHOD2 "I)[Z", FN_PTR(getScalarizedParametersInfo)}, {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index 69f6647b0d6..f48fa19cd49 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -328,6 +328,7 @@ class JVMCIEnv : public ResourceObj { jarray get_jarray(JVMCIArray array) { assert(array.as_jobject() == nullptr || is_hotspot() == array.is_hotspot(), "mismatch"); return array.as_jobject(); } jobjectArray get_jobjectArray(JVMCIObjectArray objectArray) { assert(objectArray.as_jobject() == nullptr || is_hotspot() == objectArray.is_hotspot(), "mismatch"); return objectArray.as_jobject(); } jbyteArray get_jbyteArray(JVMCIPrimitiveArray primitiveArray) { assert(primitiveArray.as_jobject() == nullptr || is_hotspot() == primitiveArray.is_hotspot(), "mismatch"); return primitiveArray.as_jbyteArray(); } + jbooleanArray get_jbooleanArray(JVMCIPrimitiveArray primitiveArray) { assert(primitiveArray.as_jobject() == nullptr || is_hotspot() == primitiveArray.is_hotspot(), "mismatch"); return primitiveArray.as_jbooleanArray(); } JVMCIObject wrap(jobject obj); JVMCIObjectArray wrap(jobjectArray obj) { return (JVMCIObjectArray) wrap((jobject) obj); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index ecbecde08a7..3408165db6c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -140,6 +140,17 @@ boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, int index) { private native boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, long methodPointer, int index); + /** + * Delivers information about scalaraized parameters in the signature of the {@code method} + * + * @return a boolean array with the value true at index i if the parameter is scalarized, false otherwise + */ + boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method) { + return getScalarizedParametersInfo(method, method.getMethodPointer(), method.getSignature().getParameterCount(!method.isStatic())); + } + + private native boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method, long methodPointer, int parameterLength); + /** * Determines if any parameter in the {@code method} is scalarized. * diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index ff7c172c728..1796058ce11 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -39,7 +39,6 @@ import java.util.BitSet; import java.util.Collections; import java.util.List; -import java.util.Objects; import jdk.internal.vm.VMSupport; import jdk.vm.ci.common.JVMCIError; @@ -778,51 +777,61 @@ public BitSet getOopMapAt(int bci) { return BitSet.valueOf(oopMap); } + private boolean[] scalarizedParametersInfo; + @Override // see ciMethod::is_scalarized_arg - public boolean isScalarizedParameter(int index) { + public boolean isScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + if (scalarizedParametersInfo == null) { + scalarizedParametersInfo = compilerToVM().getScalarizedParametersInfo(this); + } // if method is non-static index 0 refers to receiver, therefore adapt the index - return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); + return scalarizedParametersInfo[index + ((isStatic() || indexIncludesReceiverIfExists) ? 0 : 1)]; } - @Override - public boolean isScalarizedParameter(int index, boolean withReceiver) { - if (withReceiver) { - return compilerToVM().isScalarizedParameter(this, index); - } else { - return compilerToVM().isScalarizedParameter(this, index + (isStatic() ? 0 : 1)); - } - } @Override - public boolean isParameterNullFree(int index) { + public boolean isParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { // maybe for the future - return false; - } - - @Override - public boolean isParameterNullFree(int index, boolean withReceiver) { - // maybe for the future - if (!withReceiver) return false; + if (!indexIncludesReceiverIfExists) return false; if (!isStatic() && index == 0) return true; return false; } + private TriState hasScalarizedParameters = TriState.UNKNOWN; + @Override // see ciMethod::has_scalarized_args public boolean hasScalarizedParameters() { - return compilerToVM().hasScalarizedParameters(this); + if (hasScalarizedParameters.isKnown()) return hasScalarizedParameters.toBoolean(); + boolean result = compilerToVM().hasScalarizedParameters(this); + hasScalarizedParameters = TriState.get(result); + return result; } + private TriState hasScalarizedReturn = TriState.UNKNOWN; + @Override public boolean hasScalarizedReturn() { - if (!returnsInlineType()) return false; - return compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); + if (hasScalarizedReturn.isKnown()) return hasScalarizedReturn.toBoolean(); + boolean result; + if (!returnsInlineType()) { + result = false; + } else { + result = compilerToVM().hasScalarizedReturn(this, getReturnedInlineType()); + } + hasScalarizedReturn = TriState.get(result); + return result; } + private TriState hasScalarizedReceiver = TriState.UNKNOWN; + @Override public boolean hasScalarizedReceiver() { - return !isStatic() && compilerToVM().isScalarizedParameter(this, 0); + if (hasScalarizedReceiver.isKnown()) return hasScalarizedReceiver.toBoolean(); + boolean result = !isStatic() && compilerToVM().isScalarizedParameter(this, 0); + hasScalarizedReceiver = TriState.get(result); + return result; } @Override @@ -831,27 +840,21 @@ public HotSpotSignature getScalarizedSignature() { return compilerToVM().getScalarizedSignature(this); } - public boolean needsStackRepair() { - return getScalarizedParameters(true).length > getSignature().getParameterCount(true) || getScalarizedParameters(true).length > getScalarizedParameters(false).length; - } - - @Override /* * * see TypeTuple::make_range in opto/type.cpp */ - public ResolvedJavaType[] getScalarizedReturn() { + public JavaType[] getScalarizedReturn() { assert hasScalarizedReturn() : "Scalarized return presumed"; HotSpotResolvedObjectType returnType = getReturnedInlineType(); ResolvedJavaField[] fields = returnType.getInstanceFields(true); - // one extra field for oop (for already allocated buffer) - ResolvedJavaType[] types = new ResolvedJavaType[fields.length + 1]; + // one extra field for oop or hub + JavaType[] types = new JavaType[fields.length + 1]; types[0] = returnType; for (int i = 1; i < types.length; i++) { - JavaType type = fields[i - 1].getType(); - types[i] = type.resolve(getDeclaringClass()); + types[i] = fields[i - 1].getType(); } return types; } @@ -874,21 +877,19 @@ private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { } - // ignore the next funtions for the moment - @Override - public ResolvedJavaType[] getScalarizedParameter(int index) { - assert isScalarizedParameter(index) : "Scalarized parameter presumed"; - JavaType type = signature.getParameterType(index, getDeclaringClass()); - ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); - assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, false); + public JavaType[] getScalarizedParameterNullFree(int index) { + return getScalarizedParameter(index, false, true); } @Override - public ResolvedJavaType[] getScalarizedParameter(int index, boolean withReceiver) { - assert isScalarizedParameter(index, withReceiver) : "Scalarized parameter presumed"; - boolean includeReceiver = withReceiver && !isStatic(); + public JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + return getScalarizedParameter(index, indexIncludesReceiverIfExists, isParameterNullFree(index, indexIncludesReceiverIfExists)); + } + + private JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists, boolean nullFree) { + assert isScalarizedParameter(index, indexIncludesReceiverIfExists) : "Scalarized parameter presumed"; + boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); if (includeReceiver) { if (index == 0) { return getScalarizedReceiver(); @@ -899,13 +900,13 @@ public ResolvedJavaType[] getScalarizedParameter(int index, boolean withReceiver JavaType type = signature.getParameterType(index, getDeclaringClass()); ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, !isParameterNullFree(index)); + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterIsNotNullType(index, indexIncludesReceiverIfExists)); } @Override - public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withReceiver) { - boolean includeReceiver = withReceiver && !isStatic(); + public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); if (includeReceiver) { if (index == 0) { return getDeclaringClass().getInstanceFields(true); @@ -917,16 +918,18 @@ public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withR } @Override - public ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { - assert isScalarizedParameter(index) && !isParameterNullFree(index) : "Scalarized nullable parameter presumed"; - return HotSpotResolvedPrimitiveType.forKind(JavaKind.Byte); + public JavaType getScalarizedParameterIsNotNullType(int index, boolean indexIncludesReceiverIfExists) { + assert isScalarizedParameter(index, indexIncludesReceiverIfExists) && !isParameterNullFree(index, indexIncludesReceiverIfExists) : "Scalarized nullable parameter presumed"; + return HotSpotResolvedPrimitiveType.forKind(IS_NOT_NULL_KIND); } + private static final JavaKind IS_NOT_NULL_KIND = JavaKind.Byte; + @Override - public ResolvedJavaType[] getScalarizedReceiver() { + public JavaType[] getScalarizedReceiver() { assert hasScalarizedReceiver() : "Scalarized receiver presumed"; - return getFieldsArray(getDeclaringClass(), false); + return getFieldsArray(getDeclaringClass(), true, null); } @Override @@ -934,23 +937,24 @@ public ResolvedJavaType[] getScalarizedReceiver() { * * see TypeTuple::make_domain in opto/type.cpp */ - public ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver) { + public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { assert hasScalarizedParameters() : "Any scalarized parameters presumed"; - ArrayList types = new ArrayList<>(); + ArrayList types = new ArrayList<>(); if (hasScalarizedReceiver() && scalarizeReceiver) { - types.addAll(getFields(getDeclaringClass(), false)); + types.addAll(getFields(getDeclaringClass(), true, null)); } else if (!isStatic()) { types.add(getDeclaringClass()); } for (int i = 0; i < signature.getParameterCount(false); i++) { JavaType type = signature.getParameterType(i, getDeclaringClass()); - ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); if (isScalarizedParameter(i)) { + ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, !isParameterNullFree(i))); + boolean nullFree = isParameterNullFree(i); + types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterIsNotNullType(i))); } else { - types.add(resolvedType); + types.add(type); } } @@ -958,20 +962,18 @@ public ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver) { } - private static ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { + private ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType isNotNullType) { ResolvedJavaField[] fields = holder.getInstanceFields(true); - ArrayList types = new ArrayList<>(fields.length + (isInit ? 1 : 0)); - if (isInit) types.add(HotSpotResolvedPrimitiveType.forKind(JavaKind.Byte)); + ArrayList types = new ArrayList<>(fields.length + (!nullFree ? 1 : 0)); + if (!nullFree) types.add(isNotNullType); for (int i = 0; i < fields.length; i++) { - JavaType type = fields[i].getType(); - ResolvedJavaType resolvedType = type.resolve(holder); - types.add(resolvedType); + types.add(fields[i].getType()); } return types; } - private static ResolvedJavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean isInit) { - ArrayList list = getFields(holder, isInit); - return list.toArray(new ResolvedJavaType[list.size()]); + private JavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType isNotNullType) { + ArrayList list = getFields(holder, nullFree, isNotNullType); + return list.toArray(new JavaType[list.size()]); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index ed0fdceb8b1..ad72a550f83 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -30,7 +30,6 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; -import java.util.BitSet; /** * Represents a resolved Java method. Methods, like fields and types, are resolved through @@ -483,48 +482,192 @@ default boolean isScoped() { */ SpeculationLog getSpeculationLog(); - boolean isScalarizedParameter(int index); + /** + * Same as {@link #isScalarizedParameter(int, boolean)} but implicitly excluding the receiver from the index. + * + * @param index the index of a formal parameter in the signature excluding the receiver if it exists + * @return true if the parameter is scalarized, false otherwise + */ + default boolean isScalarizedParameter(int index) { + return isScalarizedParameter(index, false); + } - default boolean isScalarizedParameter(int index, boolean withReceiver) { - throw new UnsupportedOperationException("isScalarizedParameter not implemented yet"); + /** + * Gets the information if a parameter at a certain position in the method signature is scalarized. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return true if the parameter is scalarized, false otherwise + */ + default boolean isScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + return false; } + /** + * Counts the number of scalarized parameters of a method. + * + * @return the number of scalarized parameters in this method + */ + default int getScalarizedParametersCount() { + int count = 0; + for (int i = 0; i < getSignature().getParameterCount(!isStatic()); i++) { + if (isScalarizedParameter(i, true)) count++; + } + return count; + } + + /** + * Same as {@link #isParameterNullFree(int, boolean)} but implicitly excluding the receiver from the index. + * + * @param index the index of a formal parameter in the signature excluding the receiver if it exists + * @return true if the parameter is null free, false otherwise + */ default boolean isParameterNullFree(int index) { - throw new UnsupportedOperationException("isParameterNullFree not implemented yet"); + return isParameterNullFree(index, false); } - default boolean isParameterNullFree(int index, boolean withReceiver) { - throw new UnsupportedOperationException("isParameterNullFree not implemented yet"); + /** + * Gets the information if a parameter at a certain position in the method signature is non free. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return true if the parameter is null free, false otherwise + */ + default boolean isParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + return false; } - boolean hasScalarizedParameters(); + /** + * Finds out if this method has scalarized parameters. + * + * @return true if the method has scalarized parameters, false otherwise + */ + default boolean hasScalarizedParameters() { + return false; + } - boolean hasScalarizedReturn(); + /** + * Finds out if this method has a scalarized return. + * + * @return true if this method returns it's return value in a scalarized form, false otherwise + */ + default boolean hasScalarizedReturn() { + return false; + } - boolean hasScalarizedReceiver(); + /** + * Finds out if this method has a sclarized receiver. + * + * @return true if this method's receiver is passed scalarized, false otherwise + */ + default boolean hasScalarizedReceiver() { + return false; + } - HotSpotSignature getScalarizedSignature(); + default HotSpotSignature getScalarizedSignature() { + throw new UnsupportedOperationException("scalarized signature not yet implemented"); + } - ResolvedJavaType[] getScalarizedReturn(); + /** + * Gets the type information of the method's scalarized return. + * + * @return the scalarized return type which consists of the oopOrHub type as well as the instance fields of the return type + */ + default JavaType[] getScalarizedReturn() { + throw new UnsupportedOperationException("scalarized return not yet implemented"); + } - ResolvedJavaType[] getScalarizedParameters(boolean scalarizeReceiver); + /** + * Gets the scalarized method signature. + * + * @param scalarizeReceiver true if the receiver should be scalarized as well, false otherwise + * @return the types representing the scalarized method signature + */ + default JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { + throw new UnsupportedOperationException("scalarized parameters not yet implemented"); + } + + /** + * Same as {@link #getScalarizedParameter(int)} but implicitly excluding the receiver from the index. + * + * @param index the index of a formal parameter in the signature + * @return the instance fields as types including the is not null type + */ + default JavaType[] getScalarizedParameter(int index) { + return getScalarizedParameter(index, false); + } + + /** + * Same as {@link #getScalarizedParameterNullFree(int)} but implicitly excluding the receiver from the index. + * + * @param index the index of a formal parameter in the signature + * @return the instance fields as types + */ + default JavaType[] getScalarizedParameterNullFree(int index) { + return getScalarizedParameterNullFree(index, false); + } - ResolvedJavaType[] getScalarizedParameter(int index); + /** + * Similar to as {@link #getScalarizedParameterNullFree(int, boolean)} but also includes the is not null type if the parameter is not null free. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return the instance fields as types including the is not null type + */ + default JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("scalarized parameter not yet implemented"); + } - ResolvedJavaType[] getScalarizedParameter(int index, boolean withReceiver); + /** + * Gets the instance fields of a scalarized parameter as types. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return the instance fields as types + */ + default JavaType[] getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("scalarized parameter not yet implemented"); + } - default ResolvedJavaField[] getScalarizedParameterFields(int index, boolean withReceiver) { + /** + * Gets the instance fields of a scalarized parameter. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return the instance fields of a scalarized parameter + */ + default ResolvedJavaField[] getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { throw new UnsupportedOperationException("getParameterFields is not supported"); } - default ResolvedJavaType getScalarizedParameterIsNotNullType(int index) { - throw new UnsupportedOperationException("getScalarizedParameterIsNotNull is not supported"); + /** + * Same as {@link #getScalarizedParameterIsNotNullType(int)} but implicitly excluding the receiver from the index. + * + * @param index the index of a formal parameter in the signature + * @return the type representing the is not null information + */ + default JavaType getScalarizedParameterIsNotNullType(int index) { + return getScalarizedParameterIsNotNullType(index, false); } - default JavaKind getScalarizedParameterIsNotNullKind() { - return JavaKind.Byte; + /** + * Gets the type used for a scalarized parameter to represent it's is not null information. + * + * @param index the index of a formal parameter in the signature + * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise + * @return the type representing the is not null information + */ + default JavaType getScalarizedParameterIsNotNullType(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("getScalarizedParameterIsNotNull is not supported"); } - ResolvedJavaType[] getScalarizedReceiver(); + /** + * Gets the type information of the method's scalarized receiver. + * + * @return the scalarized receiver type which consists of the instance fields. + */ + default JavaType[] getScalarizedReceiver() { + throw new UnsupportedOperationException("getScalarizedReceiver is not yet implemented"); + } } From 98000f56aabb8264689ba740f21347cee9e13e31 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 12 Feb 2025 16:23:27 +0100 Subject: [PATCH 52/98] Fixed bug in calling convention interface after refactoring. --- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 1796058ce11..3836711ad2a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -890,6 +890,7 @@ public JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceive private JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists, boolean nullFree) { assert isScalarizedParameter(index, indexIncludesReceiverIfExists) : "Scalarized parameter presumed"; boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); + int previousIndex = index; if (includeReceiver) { if (index == 0) { return getScalarizedReceiver(); @@ -900,7 +901,7 @@ private JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiv JavaType type = signature.getParameterType(index, getDeclaringClass()); ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterIsNotNullType(index, indexIncludesReceiverIfExists)); + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterIsNotNullType(previousIndex, indexIncludesReceiverIfExists)); } @@ -919,7 +920,7 @@ public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean index @Override public JavaType getScalarizedParameterIsNotNullType(int index, boolean indexIncludesReceiverIfExists) { - assert isScalarizedParameter(index, indexIncludesReceiverIfExists) && !isParameterNullFree(index, indexIncludesReceiverIfExists) : "Scalarized nullable parameter presumed"; + assert isScalarizedParameter(index, indexIncludesReceiverIfExists) /*&& !isParameterNullFree(index, indexIncludesReceiverIfExists)*/ : "Scalarized nullable parameter presumed"; return HotSpotResolvedPrimitiveType.forKind(IS_NOT_NULL_KIND); } From db70238e893c8c9808b5878e79035a47145d6844 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 20 Feb 2025 15:29:52 +0100 Subject: [PATCH 53/98] Make SharedRuntime::store_inline_type_fields_to_buf accessible for Graal. --- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 97c6ab21345..ebf73d00895 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -857,6 +857,7 @@ declare_function(SharedRuntime::enable_stack_reserved_zone) \ declare_function(SharedRuntime::frem) \ declare_function(SharedRuntime::drem) \ + declare_function(SharedRuntime::store_inline_type_fields_to_buf) \ JVMTI_ONLY(declare_function(SharedRuntime::notify_jvmti_vthread_start)) \ JVMTI_ONLY(declare_function(SharedRuntime::notify_jvmti_vthread_end)) \ JVMTI_ONLY(declare_function(SharedRuntime::notify_jvmti_vthread_mount)) \ From df0442ead945dbcfba2ad98fa111a2779a50d79e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 20 Feb 2025 16:10:07 +0100 Subject: [PATCH 54/98] Set return_scalarized in debug recorder. --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 57a5a0663a6..dcef7c89164 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -41,6 +41,9 @@ #include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/align.hpp" +#include "ci/ciSignature.hpp" +#include "oops/inlineKlass.hpp" +#include "runtime/globals.hpp" // frequently used constants // Allocate them with new so they are never destroyed (otherwise, a @@ -1138,6 +1141,17 @@ int CodeInstaller::map_jvmci_bci(int bci) { return bci; } +bool has_scalarized_return(methodHandle& methodHandle){ + if(!InlineTypeReturnedAsFields) return false; + Method* method = methodHandle(); + InlineKlass* klass = method->returns_inline_type(Thread::current()); + bool has_scalar_ret = false; + if(klass != nullptr) { + has_scalar_ret = !method->is_native() && klass->can_be_returned_as_fields(); + } + return has_scalar_ret; +} + void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS) { if (full_info) { read_virtual_objects(stream, JVMCI_CHECK); @@ -1179,7 +1193,8 @@ void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stre } // has_ea_local_in_scope and arg_escape should be added to JVMCI - const bool return_scalarized = false; + const bool return_scalarized = has_scalarized_return(method); + return_oop |= has_scalarized_return(method); const bool has_ea_local_in_scope = false; const bool arg_escape = false; _debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, is_mh_invoke, return_oop, From 834b80472a2b570c9c7c12656188a3fc7d27ec3a Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 20 Feb 2025 18:22:33 +0100 Subject: [PATCH 55/98] Commit before rebase. --- .../hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java | 3 ++- .../jtreg/compiler/valhalla/inlinetypes/InlineTypes.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 07b8de3fd63..af88e68738b 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -270,6 +270,7 @@ public TestFramework addFlags(String... flags) { public TestFramework setCompileOnlyTestMethods(Class clazz) { //addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::test*", "-XX:InlineFieldMaxFlatSize=-1", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); addFlags("-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::test*"); + addFlags("-DIgnoreCompilerControls=true"); return this; } @@ -334,7 +335,7 @@ public TestFramework addScenarios(Scenario... scenarios) { this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); - addFlags("-XX:-InlineTypePassFieldsAsArgs", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); + addFlags(/*"-XX:-InlineTypePassFieldsAsArgs", */"-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-DIgnoreCompilerControls=false"/*, "-DPreferCommandLineFlags=true"*/); return this; } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java index 89812f65f58..0b1e60576f2 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/InlineTypes.java @@ -129,7 +129,7 @@ public class InlineTypes { public static TestFramework getFramework() { StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE); TestFramework framework = new TestFramework(walker.getCallerClass()).setDefaultWarmup(251); - framework.addFlags("-XX:-InlineTypePassFieldsAsArgs", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363"); + framework.addFlags(/*"-XX:-InlineTypePassFieldsAsArgs", */"-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363"); return framework; } } From 2558e9951a6b655db0d2740615bafc1079828535 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 22 Feb 2025 18:44:37 +0100 Subject: [PATCH 56/98] Fixed bugs after rebasing. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 9 ++++++++- src/hotspot/share/jvmci/jvmciEnv.cpp | 2 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 7 +++---- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 7 +++---- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 3 ++- .../share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 5 ++--- 6 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 4b62829846e..865cef5c038 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -51,6 +51,7 @@ #include "oops/method.inline.hpp" #include "oops/objArrayKlass.inline.hpp" #include "oops/typeArrayOop.inline.hpp" +#include "oops/layoutKind.hpp" #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" @@ -719,8 +720,14 @@ C2V_VMENTRY_NULL(jobject, getFlatArrayType, (JNIEnv* env, jobject, jchar type_ch if(klass->is_inline_klass()){ InlineKlass* inline_klass = InlineKlass::cast(klass); + ArrayKlass* flat_array_klass; + if(inline_klass->flat_array()){ + flat_array_klass = (ArrayKlass*)inline_klass->flat_array_klass(LayoutKind::NON_ATOMIC_FLAT, CHECK_NULL); + }else{ + flat_array_klass = (ArrayKlass*)inline_klass->null_free_reference_array(CHECK_NULL); + } // Request a flat array, but we might not actually get it...either way "null-free" are the aaload/aastore semantics - ArrayKlass* flat_array_klass = (ArrayKlass*)inline_klass->value_array_klass(CHECK_NULL); + //ArrayKlass* flat_array_klass = (ArrayKlass*)inline_klass->flat_array_klass(LayoutKind::NON_ATOMIC_FLAT, CHECK_NULL); array_klass = flat_array_klass; assert(array_klass->is_null_free_array_klass(), "Expect a null-free array class here"); //assert(array_klass->is_flatArray_klass, "Expect a flat array class here"); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 45289bdcc8b..a38a6ff91a8 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1714,7 +1714,7 @@ BasicType JVMCIEnv::typeCharToBasicType(jchar ch, JVMCI_TRAPS) { case 'J': return T_LONG; case 'D': return T_DOUBLE; case 'A': return T_OBJECT; - case 'Q': return T_PRIMITIVE_OBJECT; + case 'Q': return T_OBJECT; case '-': return T_ILLEGAL; default: JVMCI_ERROR_(T_ILLEGAL, "unexpected type char: %c", ch); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 42d0d659e28..9d45742ee19 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -445,14 +445,13 @@ JRT_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArray assert(array->klass()->is_flatArray_klass(), "should not be called"); assert(array->length() > 0 && index < array->length(), "already checked"); - flatArrayHandle vah(current, array); - oop obj = flatArrayOopDesc::value_alloc_copy_from_index(vah, index, CHECK); + oop obj = array->read_value_from_flat_array(index, THREAD); current->set_vm_result(obj); JRT_END -JRT_LEAF(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index, oopDesc* value)) +JRT_ENTRY(void, JVMCIRuntime::store_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index, oopDesc* value)) assert(array->klass()->is_flatArray_klass(), "should not be called"); - array->value_copy_to_index(value, index); + array->write_value_to_flat_array(value, index, THREAD); JRT_END // Object.notifyAll() fast path, caller does slow path diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index ebf73d00895..30f7f35f2db 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -268,8 +268,8 @@ nonstatic_field(Klass, _super, Klass*) \ nonstatic_field(Klass, _super_check_offset, juint) \ nonstatic_field(InstanceKlass, _adr_inlineklass_fixed_block, InlineKlassFixedBlock const *) \ - nonstatic_field(InlineKlassFixedBlock, _first_field_offset, int) \ - nonstatic_field(InlineKlassFixedBlock, _internal_null_marker_offset, int) \ + nonstatic_field(InlineKlassFixedBlock, _payload_offset, int) \ + nonstatic_field(InlineKlassFixedBlock, _null_marker_offset, int) \ nonstatic_field(FieldInfo, _null_marker_offset, u4) \ volatile_nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ @@ -498,7 +498,6 @@ declare_constant(FieldInfo::FieldFlags::_ff_flat) \ declare_constant(FieldInfo::FieldFlags::_ff_null_free_inline_type) \ declare_constant(FieldInfo::FieldFlags::_ff_null_marker) \ - declare_constant(FieldInfo::FieldFlags::_ff_internal_null_marker) \ declare_preprocessor_constant("JVM_ACC_VARARGS", JVM_ACC_VARARGS) \ declare_preprocessor_constant("JVM_ACC_BRIDGE", JVM_ACC_BRIDGE) \ declare_preprocessor_constant("JVM_ACC_ANNOTATION", JVM_ACC_ANNOTATION) \ @@ -840,7 +839,7 @@ declare_constant(markWord::inline_type_pattern) \ declare_constant(markWord::inline_type_mask_in_place) \ declare_constant(markWord::inline_type_bit_in_place) \ - declare_constant(markWord::flat_array_pattern) \ + declare_constant(markWord::null_free_flat_array_pattern) \ declare_constant(markWord::flat_array_mask_in_place) \ declare_constant(markWord::null_free_array_pattern) \ declare_constant(markWord::null_free_array_mask_in_place) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 37b93855a32..252bd6ea2ba 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -834,7 +834,8 @@ private boolean hasNullMarker() { } private boolean hasInternalNullMarker() { - return (getInternalFlags() & (1 << config().jvmFieldFlagInternalNullMarkerShift)) != 0; + return true; + //return (getInternalFlags() & (1 << config().jvmFieldFlagInternalNullMarkerShift)) != 0; } // private int internalNullMarkerOffset() { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 3e6d2b18d78..f6a15a21c3a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -77,8 +77,7 @@ static String getHostArchitectureName() { final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*"); final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint"); final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*"); - final int firstFieldOffset = getFieldOffset("InlineKlassFixedBlock::_first_field_offset", Integer.class, "int"); - final int internalNullMarkerOffset = getFieldOffset("InlineKlassFixedBlock::_internal_null_marker_offset", Integer.class, "int"); + final int firstFieldOffset = getFieldOffset("InlineKlassFixedBlock::_payload_offset", Integer.class, "int"); final int nullMarkerOffset = getFieldOffset("FieldInfo::_null_marker_offset", Integer.class, "u4"); final int inlineKlassFixedBlockAdr = getFieldOffset("InstanceKlass::_adr_inlineklass_fixed_block", Integer.class, "InlineKlassFixedBlock const *"); @@ -129,7 +128,7 @@ static String getHostArchitectureName() { final int jvmFieldFlagFlatShift = getConstant("FieldInfo::FieldFlags::_ff_flat", Integer.class); final int jvmFieldFlagNullFreeInlineTypeShift = getConstant("FieldInfo::FieldFlags::_ff_null_free_inline_type", Integer.class); final int jvmFieldFlagNullMarkerShift = getConstant("FieldInfo::FieldFlags::_ff_null_marker", Integer.class); - final int jvmFieldFlagInternalNullMarkerShift = getConstant("FieldInfo::FieldFlags::_ff_internal_null_marker", Integer.class); + //final int jvmFieldFlagInternalNullMarkerShift = getConstant("FieldInfo::FieldFlags::_ff_internal_null_marker", Integer.class); final int jvmAccIsCloneableFast = getConstant("KlassFlags::_misc_is_cloneable_fast", Integer.class); From 00d454f0d21a6c6367bb6ee8492a2dda225405a3 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 25 Feb 2025 07:23:06 +0100 Subject: [PATCH 57/98] Set outer declaring class for flat fields correctly. --- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 252bd6ea2ba..e689f4061ec 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -958,8 +958,7 @@ private HotSpotResolvedJavaField[] getFlattenedFields(HotSpotResolvedJavaField[] // holder has no header so remove the header offset int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.firstFieldOffset()); HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; - innerField.setOuterDeclaringClass(this); - resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset)); + resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset).setOuterDeclaringClass((HotSpotResolvedObjectType) resolvedJavaField.getDeclaringClass())); } } From 48c2442065de3be2d81ba9c3618bfd8613820af7 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 25 Feb 2025 11:07:50 +0100 Subject: [PATCH 58/98] Adaptions on jtreg test case scenarios. --- .../lib/ir_framework/TestFramework.java | 7 +++++++ .../inlinetypes/TestArrayCopyWithOops.java | 9 +++++++- .../TestDeoptimizationWhenBuffering.java | 14 ++++++------- .../inlinetypes/TestFlatArrayThreshold.java | 2 +- .../TestInlineFieldNonFlattened.java | 1 - .../valhalla/inlinetypes/TestLWorld.java | 21 ++++++++++++++++++- .../inlinetypes/TestMethodHandles.java | 1 + 7 files changed, 44 insertions(+), 11 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index af88e68738b..390f2226871 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -274,6 +274,13 @@ public TestFramework setCompileOnlyTestMethods(Class clazz) { return this; } + public TestFramework setCompileOnlyClass(Class clazz) { + //addFlags("-XX:-InlineTypePassFieldsAsArgs", "-XX:-InlineTypeReturnedAsFields", "-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::test*", "-XX:InlineFieldMaxFlatSize=-1", "-DIgnoreCompilerControls=true"/*, "-DPreferCommandLineFlags=true"*/); + addFlags("-XX:CompileCommand=compileonly," + clazz.getCanonicalName() + "::putVal*"); + addFlags("-DIgnoreCompilerControls=true"); + return this; + } + public TestFramework setGraalLog() { addFlags("-Djdk.graal.CompilationFailureAction=Diagnose", "-Djdk.graal.LogFile=/home/michael/projects/logs/log.txt"); return this; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java index 3b72f348bd5..51a4272e4e0 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestArrayCopyWithOops.java @@ -31,13 +31,20 @@ * java.base/jdk.internal.vm.annotation * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* * * compiler.valhalla.inlinetypes.TestArrayCopyWithOops * @run main/othervm -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* * -XX:-UseArrayFlattening + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* * compiler.valhalla.inlinetypes.TestArrayCopyWithOops - * @run main/othervm compiler.valhalla.inlinetypes.TestArrayCopyWithOops + * @run main/othervm + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::test* + * -XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestArrayCopyWithOops::create* + * compiler.valhalla.inlinetypes.TestArrayCopyWithOops */ package compiler.valhalla.inlinetypes; diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java index a458a14a2b2..1b2340145ec 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestDeoptimizationWhenBuffering.java @@ -50,35 +50,35 @@ * -XX:+DeoptimizeALot -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering C1 * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch + * -XX:+DeoptimizeALot -XX:-UseTLAB * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline * -XX:-InlineTypePassFieldsAsArgs -XX:-InlineTypeReturnedAsFields -XX:+UseArrayFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline * -XX:-InlineTypePassFieldsAsArgs -XX:-InlineTypeReturnedAsFields -XX:+UseArrayFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline * -XX:+InlineTypePassFieldsAsArgs -XX:+InlineTypeReturnedAsFields -XX:+UseArrayFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline * -XX:+InlineTypePassFieldsAsArgs -XX:+InlineTypeReturnedAsFields -XX:+UseArrayFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:-AlwaysIncrementalInline * -XX:+InlineTypePassFieldsAsArgs -XX:+InlineTypeReturnedAsFields -XX:+UseArrayFlattening -XX:-UseFieldFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:+DeoptimizeALot -XX:-UseTLAB -Xbatch -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline + * -XX:+DeoptimizeALot -XX:-UseTLAB -XX:-MonomorphicArrayCheck -XX:+AlwaysIncrementalInline * -XX:+InlineTypePassFieldsAsArgs -XX:+InlineTypeReturnedAsFields -XX:+UseArrayFlattening -XX:-UseFieldFlattening * -XX:CompileCommand=dontinline,compiler.valhalla.inlinetypes.*::test* * compiler.valhalla.inlinetypes.TestDeoptimizationWhenBuffering diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java index 8dcf0d1a4b9..ebd91627ece 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java @@ -36,7 +36,7 @@ * TestFlatArrayThreshold * @run main/othervm -XX:FlatArrayElementMaxOops=1 * TestFlatArrayThreshold - * @run main/othervm -XX:FlatArrayElementMaxSize=1 + * @run main/othervm -XX:+UseArrayFlattening * TestFlatArrayThreshold */ diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java index ed2ec6caf06..d0be61d9d9e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java @@ -99,7 +99,6 @@ public static void main(String[] args) { "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", "-XX:-TieredCompilation", "-XX:-UseFieldFlattening") - "-XX:InlineFieldMaxFlatSize=0") .setCompileOnlyTestMethods(TestInlineFieldNonFlattened.class).setGraalLog() .start(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java index 0b5df74e282..9dedd5176fc 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestLWorld.java @@ -72,7 +72,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) - .setCompileOnlyTestMethods(TestLWorld.class).setGraalLog() + .setCompileOnlyTestMethods(TestLWorld.class).setCompileOnlyClass(java.util.HashMap.class).setGraalLog() //.addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestLWorld::test*") .addHelperClasses(MyValue1.class, MyValue2.class, @@ -4655,4 +4655,23 @@ static void runFlatArrayInexactLoadAndStore() { Asserts.assertEQ(subValueClassWithInt, testFlatArrayInexactAbstractValueClassLoad(true)); Asserts.assertEQ(subValueClassWithDouble, testFlatArrayInexactAbstractValueClassLoad(false)); } + + @Test + public MyValue3 testMyValue3(MyValue3 value, MyValue3 value2, MyValue3 value3){ + return value3; + } + + @Run(test = "testMyValue3") + public void testMyValue3_verifier() throws Exception { + java.util.HashMap a = new java.util.HashMap<>(); + for(int i = 0;i<100_000;i++){ + a.put(1,2); + } + Method helper_m = getClass().getDeclaredMethod("testMyValue3", MyValue3.class, MyValue3.class,MyValue3.class); + TestFramework.compile(helper_m, CompLevel.C2); + TestFramework.assertCompiledByC2(helper_m); + //testMyValue3(MyValue3.create(),MyValue3.create(),MyValue3.create()); + } + + } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java index 33742d7669f..a39b5ece83f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMethodHandles.java @@ -152,6 +152,7 @@ public static void main(String[] args) { MyValue2Inline.class, MyValue3.class, MyValue3Inline.class) + .setCompileOnlyTestMethods(TestMethodHandles.class).setGraalLog() .start(); } From 3f5b908434daffc18c28e70078b391bb52dd71e7 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 5 Mar 2025 08:02:36 +0100 Subject: [PATCH 59/98] Pull-request review. --- .../cpu/x86/jvmciCodeInstaller_x86.cpp | 4 +-- .../share/interpreter/linkResolver.hpp | 2 -- .../share/jvmci/jvmciCodeInstaller.cpp | 12 ++++----- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 12 +++------ .../jdk/vm/ci/code/RegisterConfig.java | 16 +++++++++--- .../classes/jdk/vm/ci/code/VirtualObject.java | 9 +++++++ .../jdk/vm/ci/hotspot/ACmpDataAccessor.java | 13 ++++++++-- .../jdk/vm/ci/hotspot/CompilerToVM.java | 18 +++---------- .../jdk/vm/ci/hotspot/HotSpotMethodData.java | 26 +------------------ .../HotSpotResolvedJavaMethodImpl.java | 12 ++------- .../jdk/vm/ci/hotspot/SingleTypeEntry.java | 23 +++++++++++++--- .../amd64/AMD64HotSpotRegisterConfig.java | 9 +++---- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 12 +++------ .../jdk/vm/ci/meta/ResolvedJavaType.java | 5 +++- 14 files changed, 83 insertions(+), 90 deletions(-) diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 11c4050497e..5848e22e113 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -164,7 +164,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - if(method()->has_scalarized_args()) { + if (method()->has_scalarized_args()) { _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc, _oop_recorder->find_index(method())), Assembler::call32_operand); @@ -180,7 +180,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - if(method()->has_scalarized_args()) { + if (method()->has_scalarized_args()) { _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand,_oop_recorder->find_index(method())); }else{ diff --git a/src/hotspot/share/interpreter/linkResolver.hpp b/src/hotspot/share/interpreter/linkResolver.hpp index 8fab5a703f3..2d3f8832592 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -359,8 +359,6 @@ class LinkResolver: AllStatic { const methodHandle& attached_method, Bytecodes::Code byte, bool check_null_or_abstract, TRAPS); - static void resolve_invoke_jvmci(CallInfo& result, Handle recv, const constantPoolHandle& pool, int index, Bytecodes::Code byte, bool check_null_or_abstract, TRAPS); - // Only resolved method known. static void throw_abstract_method_error(const methodHandle& resolved_method, TRAPS) { throw_abstract_method_error(resolved_method, methodHandle(), nullptr, CHECK); diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index dcef7c89164..10ca3e53921 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1142,14 +1142,15 @@ int CodeInstaller::map_jvmci_bci(int bci) { } bool has_scalarized_return(methodHandle& methodHandle){ - if(!InlineTypeReturnedAsFields) return false; + if (!InlineTypeReturnedAsFields) { + return false; + } Method* method = methodHandle(); InlineKlass* klass = method->returns_inline_type(Thread::current()); - bool has_scalar_ret = false; - if(klass != nullptr) { - has_scalar_ret = !method->is_native() && klass->can_be_returned_as_fields(); + if (klass != nullptr) { + return !method->is_native() && klass->can_be_returned_as_fields(); } - return has_scalar_ret; + return false; } void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS) { @@ -1194,7 +1195,6 @@ void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stre // has_ea_local_in_scope and arg_escape should be added to JVMCI const bool return_scalarized = has_scalarized_return(method); - return_oop |= has_scalarized_return(method); const bool has_ea_local_in_scope = false; const bool arg_escape = false; _debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, is_mh_invoke, return_oop, diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 865cef5c038..11cce3059ad 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -370,14 +370,9 @@ C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, ARGUMENT_PAIR(m return JVMCIENV->get_jbyteArray(result); C2V_END -C2V_VMENTRY_0(jboolean, isScalarizedParameter, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jint idx)) +C2V_VMENTRY_0(jbooleanArray, getScalarizedParametersInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jbooleanArray infoArray, jint len)) Method* method = UNPACK_PAIR(Method, method); - return method->is_scalarized_arg(idx); -C2V_END - -C2V_VMENTRY_0(jbooleanArray, getScalarizedParametersInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jint len)) - Method* method = UNPACK_PAIR(Method, method); - JVMCIPrimitiveArray result = JVMCIENV->new_booleanArray(len, JVMCI_CHECK_NULL); + JVMCIPrimitiveArray result = JVMCIENV->wrap(infoArray); for(int i=0; iput_bool_at(result, i, method->is_scalarized_arg(i)); } @@ -3334,8 +3329,7 @@ C2V_VMENTRY_0(jint, getCompilationActivityMode, (JNIEnv* env, jobject)) JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, - {CC "isScalarizedParameter", CC "(" HS_METHOD2 "I)Z", FN_PTR(isScalarizedParameter)}, - {CC "getScalarizedParametersInfo", CC "(" HS_METHOD2 "I)[Z", FN_PTR(getScalarizedParametersInfo)}, + {CC "getScalarizedParametersInfo", CC "(" HS_METHOD2 "[ZI)[Z", FN_PTR(getScalarizedParametersInfo)}, {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java index 87fcfe76cc7..d7e666b03a2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java @@ -37,9 +37,11 @@ public interface RegisterConfig { Register getReturnRegister(JavaKind kind); /** - * Gets the registers to be used for returning multiple values e.g. used for a scalarized inline object. + * Gets the registers to be used for returning multiple values e.g. used for a scalarized inline object. Same procedure as with {@link #getReturnRegister(JavaKind)}. + * @param kinds the kinds used to decide if a value will be returned in a general or float register. + * @param includeFirstGeneralRegister determines if the first general register, which will contain the oop or tagged hub, should be skipped */ - default Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { + default Register[] getReturnRegisters(JavaKind[] kinds, boolean includeFirstGeneralRegister) { throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); } @@ -66,7 +68,15 @@ default int getMaximumFrameSize() { */ CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory valueKindFactory); - default AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeRax) { + /** + * Gets the ordered set of registers that are used to return a nullable scalarized inline object according to the return convention. + * The first register contains an oop or tagged hub, while the rest contains the field values. + * + * @param returnTypes types of the values being returned + * @param valueKindFactory the factory to create custom {@link ValueKind ValueKinds} + * @param includeFirstGeneralRegister determines if the first general register, which will contain the oop or tagged hub, should be skipped + */ + default AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); } /** diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java index 7fe999b0fef..0b2396db97a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java @@ -241,6 +241,10 @@ public JavaValue[] getValues() { return values; } + /** + * Virtual objects can also be null. Returns an array containing one value indicating if the virtual object is non-null. + */ + @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "`values` is intentional mutable") public JavaValue[] getIsNotNull() { return isNotNull; } @@ -284,6 +288,11 @@ public void setValues(JavaValue[] values, JavaKind[] slotKinds) { this.slotKinds = slotKinds; } + /** + * Overwrites the current value with a new one. + * + * @param isNotNull an array containing one value indicating if the virtual object is non-null. + */ public void setIsNotNull(JavaValue[] isNotNull) { this.isNotNull = isNotNull; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java index 2e2622e5bd9..bd6caddc8b7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java @@ -1,10 +1,19 @@ package jdk.vm.ci.hotspot; +/** + * The acmp comparison compares two objects for equality. Due to Valhalla, profiling data is now attached to this comparison. + * This class represents the profiled type information of both operands. + * Corresponds to {@code ciACmpData} + */ public interface ACmpDataAccessor { + /** + * @return the profiled type information of the left operand + */ SingleTypeEntry getLeft(); + /** + * @return the profiled type information of the right operand + */ SingleTypeEntry getRight(); - void setDeoptClassCheck(); - void setDeoptNullCheck(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 3408165db6c..93e52e0b0f6 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -130,26 +130,16 @@ byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) { private native byte[] getBytecode(HotSpotResolvedJavaMethodImpl method, long methodPointer); /** - * Determines if the parameter {@code index} in the {@code method} is scalarized. - * - * @return true if the parameter is scalarized - */ - boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, int index) { - return isScalarizedParameter(method, method.getMethodPointer(), index); - } - - private native boolean isScalarizedParameter(HotSpotResolvedJavaMethodImpl method, long methodPointer, int index); - - /** - * Delivers information about scalaraized parameters in the signature of the {@code method} + * Delivers information about scalarized parameters in the signature of the {@code method} * * @return a boolean array with the value true at index i if the parameter is scalarized, false otherwise */ boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method) { - return getScalarizedParametersInfo(method, method.getMethodPointer(), method.getSignature().getParameterCount(!method.isStatic())); + int len = method.getSignature().getParameterCount(!method.isStatic()); + return getScalarizedParametersInfo(method, method.getMethodPointer(), new boolean[len], len); } - private native boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method, long methodPointer, int parameterLength); + private native boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method, long methodPointer, boolean[] infoArray, int len); /** * Determines if any parameter in the {@code method} is scalarized. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java index fbcab80058e..b8efccd4fc4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMethodData.java @@ -79,7 +79,7 @@ static final class VMState { // inherits from branch and two cells for types final int acmpDataSize = branchDataSize + cellsToBytes(1)*2; - // TODO: get values from VM + final int leftOperandOffset = cellIndexToOffset(3); final int rightOperandOffset = cellIndexToOffset(4); final int leftInlineTypeFlag = 1 << config.leftInlineTypeFlag; @@ -821,18 +821,6 @@ public boolean inlineType(){ return inlineType; } - @Override - public void setDeoptClassCheck(){ - this.validType=null; - this.inlineType=true; - } - - @Override - public void setDeoptNullCheck(){ - this.alwaysNull=false; - this.neverNull=false; - this.maybeNull=false; - } } @@ -889,18 +877,6 @@ public SingleTypeEntry getLeft() { public SingleTypeEntry getRight() { return right; } - - @Override - public void setDeoptClassCheck() { - left.setDeoptClassCheck(); - right.setDeoptClassCheck(); - } - - @Override - public void setDeoptNullCheck() { - left.setDeoptNullCheck(); - right.setDeoptNullCheck(); - } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 3836711ad2a..5b11f24d3c0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -829,22 +829,14 @@ public boolean hasScalarizedReturn() { @Override public boolean hasScalarizedReceiver() { if (hasScalarizedReceiver.isKnown()) return hasScalarizedReceiver.toBoolean(); - boolean result = !isStatic() && compilerToVM().isScalarizedParameter(this, 0); + boolean result = !isStatic() && isScalarizedParameter(0, true); hasScalarizedReceiver = TriState.get(result); return result; } - @Override - // see ciMethod::get_sig_cc() - public HotSpotSignature getScalarizedSignature() { - return compilerToVM().getScalarizedSignature(this); - } @Override - /* - * - * see TypeTuple::make_range in opto/type.cpp - */ + // see TypeTuple::make_range in opto/type.cpp public JavaType[] getScalarizedReturn() { assert hasScalarizedReturn() : "Scalarized return presumed"; HotSpotResolvedObjectType returnType = getReturnedInlineType(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java index 6a2ad9dcca7..ac1d6d35813 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java @@ -1,19 +1,36 @@ package jdk.vm.ci.hotspot; +/** + * The acmp comparison compares two objects for equality. Due to Valhalla, profiling data is now attached to this comparison. + * This class represents the profiled type information of one operand. + * Corresponds to {@code ciSingleTypeEntry} + */ public interface SingleTypeEntry{ + /** + * @return returns the profiled type, null if multiple types have been seen + */ HotSpotResolvedObjectType getValidType(); + /** + * @return whether the operand was seen to be null, false otherwise + */ boolean maybeNull(); + /** + * @return whether the operand was never null, false otherwise + */ boolean neverNull(); + /** + * @return whether the operand was always null, false otherwise + */ boolean alwaysNull(); + /** + * @return whether the operand was seen to be an inline type, false otherwise + */ boolean inlineType(); - void setDeoptClassCheck(); - void setDeoptNullCheck(); - } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 53969b6ac79..43e647c94b7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -45,7 +45,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Stream; import jdk.vm.ci.code.Architecture; import jdk.vm.ci.code.CallingConvention; @@ -206,12 +205,12 @@ public CallingConvention getCallingConvention(Type type, JavaType returnType, Ja } @Override - public AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeRax) { + public AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { JavaKind[] kinds = new JavaKind[returnTypes.length]; for (int i = 0; i < returnTypes.length; i++) { kinds[i] = returnTypes[i].getJavaKind().getStackKind(); } - return getReturnLocations(getReturnRegisters(kinds, includeRax), returnTypes, valueKindFactory); + return getReturnLocations(getReturnRegisters(kinds, includeFirstGeneralRegister), returnTypes, valueKindFactory); } @Override @@ -324,12 +323,12 @@ public Register getReturnRegister(JavaKind kind) { } @Override - public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeRax) { + public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeFirstGeneralRegister) { Register[] registers = new Register[kinds.length]; RegisterArray generalReturnRegisters = javaGeneralReturnRegisters; RegisterArray xmmReturnRegisters = javaXMMParameterRegisters; - int currentGeneral = includeRax ? 0 : 1; + int currentGeneral = includeFirstGeneralRegister ? 0 : 1; int currentXMM = 0; Register register; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index ad72a550f83..fb49668eafe 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -22,7 +22,6 @@ */ package jdk.vm.ci.meta; -import jdk.vm.ci.hotspot.HotSpotSignature; import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; @@ -556,7 +555,7 @@ default boolean hasScalarizedReturn() { } /** - * Finds out if this method has a sclarized receiver. + * Finds out if this method has a scalarized receiver. * * @return true if this method's receiver is passed scalarized, false otherwise */ @@ -564,9 +563,6 @@ default boolean hasScalarizedReceiver() { return false; } - default HotSpotSignature getScalarizedSignature() { - throw new UnsupportedOperationException("scalarized signature not yet implemented"); - } /** * Gets the type information of the method's scalarized return. @@ -652,7 +648,7 @@ default JavaType getScalarizedParameterIsNotNullType(int index) { } /** - * Gets the type used for a scalarized parameter to represent it's is not null information. + * Gets the type used for a scalarized parameter to represent its is not null information. * * @param index the index of a formal parameter in the signature * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise @@ -663,9 +659,9 @@ default JavaType getScalarizedParameterIsNotNullType(int index, boolean indexInc } /** - * Gets the type information of the method's scalarized receiver. + * Gets the ordered type information of each field according to {@link ResolvedJavaType#getInstanceFields(boolean)} of the method's scalarized receiver. * - * @return the scalarized receiver type which consists of the instance fields. + * @return the scalarized receiver which consists of its instance fields. */ default JavaType[] getScalarizedReceiver() { throw new UnsupportedOperationException("getScalarizedReceiver is not yet implemented"); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index 684619be7c8..f0788573182 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -237,6 +237,9 @@ default ResolvedJavaType getElementalType() { @Override ResolvedJavaType getArrayClass(); + /** + * Gets the array class type used when creating an array with {@link jdk.internal.value.ValueClass#newNullRestrictedArray(Class, int)} + */ default ResolvedJavaType getFlatArrayClass() { throw new UnsupportedOperationException(); } @@ -413,7 +416,7 @@ default boolean isConcrete() { } /** - * Checks whether this type has an identity. + * Checks whether this type has an identity. See {@link Class#isIdentity()}. * * @return {@code true} if this type has an identity */ From 2d41b6f6893ed30db6455b25b3ba9f384595cd07 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 5 Mar 2025 08:53:48 +0100 Subject: [PATCH 60/98] Correct identity check. --- .../vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 11 +++++------ .../classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index e689f4061ec..1ef0485f273 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -450,7 +450,10 @@ public boolean isInterface() { @Override public boolean isIdentity() { - return (getAccessFlags() & config().jvmAccIdentity) != 0; + if (!config().valhallaEnabled) { + return !isInterface(); + } + return isArray() || (getAccessFlags() & config().jvmAccIdentity) != 0; } @Override @@ -1284,9 +1287,5 @@ private List getAnnotationData0(ResolvedJavaType... filter) { byte[] encoded = compilerToVM().getEncodedClassAnnotationData(this, filter); return VMSupport.decodeAnnotations(encoded, AnnotationDataDecoder.INSTANCE); } - - public boolean canBePassedAsFields() { - if (isStatic() || isInterface() || !isIdentity()) return false; - return compilerToVM().canBePassedAsFields(this); - } + } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index f6a15a21c3a..01b5a15ba9d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -71,6 +71,7 @@ static String getHostArchitectureName() { final int objectAlignment = getFlag("ObjectAlignmentInBytes", Integer.class); final int klassOffsetInBytes = getFieldValue("CompilerToVM::Data::oopDesc_klass_offset_in_bytes", Integer.class, "int"); + public final boolean valhallaEnabled = getFlag("EnableValhalla", Boolean.class); final int subklassOffset = getFieldOffset("Klass::_subklass", Integer.class, "Klass*"); final int superOffset = getFieldOffset("Klass::_super", Integer.class, "Klass*"); From 53fd54f1e7e84cc0323359e9f3155033590f7e3e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 7 Mar 2025 09:45:31 +0100 Subject: [PATCH 61/98] Provide a runtime function for the identity exception. --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 10 ++++++++++ src/hotspot/share/jvmci/jvmciRuntime.hpp | 1 + src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 + 3 files changed, 12 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 9d45742ee19..3e9853a5c00 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -494,6 +494,16 @@ JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_class_cast_exception(JavaThread* curren return caller_is_deopted(); JRT_END +JRT_BLOCK_ENTRY(int, JVMCIRuntime::throw_identity_exception(JavaThread* current, const char* exception, Klass* klass)) + JRT_BLOCK; + ResourceMark rm(current); + char* message = SharedRuntime::generate_identity_exception_message(current, klass); + TempNewSymbol symbol = SymbolTable::new_symbol(exception); + SharedRuntime::throw_and_post_jvmti_exception(current, symbol, message); + JRT_BLOCK_END; + return caller_is_deopted(); +JRT_END + class ArgumentPusher : public SignatureIterator { protected: JavaCallArguments* _jca; diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index abf93288ac3..55c95a62025 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -555,6 +555,7 @@ class JVMCIRuntime: public CHeapObj { // helper methods to throw exception with complex messages static int throw_klass_external_name_exception(JavaThread* current, const char* exception, Klass* klass); static int throw_class_cast_exception(JavaThread* current, const char* exception, Klass* caster_klass, Klass* target_klass); + static int throw_identity_exception(JavaThread* current, const char* exception, Klass* klass); // A helper to allow invocation of an arbitrary Java method. For simplicity the method is // restricted to a static method that takes at most one argument. For calling convention diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 30f7f35f2db..9f91ce26793 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -905,6 +905,7 @@ declare_function(JVMCIRuntime::throw_and_post_jvmti_exception) \ declare_function(JVMCIRuntime::throw_klass_external_name_exception) \ declare_function(JVMCIRuntime::throw_class_cast_exception) \ + declare_function(JVMCIRuntime::throw_identity_exception) \ declare_function(JVMCIRuntime::log_primitive) \ declare_function(JVMCIRuntime::log_object) \ declare_function(JVMCIRuntime::log_printf) \ From 13e6ba350f9ef1e0a732f39a0074b13226c17509 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 7 Mar 2025 09:49:46 +0100 Subject: [PATCH 62/98] The base offset of flat arrays is now the same as that used for object arrays. --- src/hotspot/share/jvmci/jvmciEnv.cpp | 1 - .../share/classes/jdk/vm/ci/hotspot/CompilerToVM.java | 2 -- .../classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java | 8 -------- .../jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java | 4 ---- .../share/classes/jdk/vm/ci/meta/MetaAccessProvider.java | 4 ---- 5 files changed, 19 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index a38a6ff91a8..526482a85d4 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1714,7 +1714,6 @@ BasicType JVMCIEnv::typeCharToBasicType(jchar ch, JVMCI_TRAPS) { case 'J': return T_LONG; case 'D': return T_DOUBLE; case 'A': return T_OBJECT; - case 'Q': return T_OBJECT; case '-': return T_ILLEGAL; default: JVMCI_ERROR_(T_ILLEGAL, "unexpected type char: %c", ch); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 93e52e0b0f6..7fc60e31769 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -69,7 +69,6 @@ final class CompilerToVM { final int ARRAY_FLOAT_BASE_OFFSET; final int ARRAY_DOUBLE_BASE_OFFSET; final int ARRAY_OBJECT_BASE_OFFSET; - final int ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET; final int ARRAY_BOOLEAN_INDEX_SCALE; final int ARRAY_BYTE_INDEX_SCALE; final int ARRAY_SHORT_INDEX_SCALE; @@ -93,7 +92,6 @@ final class CompilerToVM { ARRAY_FLOAT_BASE_OFFSET = arrayBaseOffset(JavaKind.Float.getTypeChar()); ARRAY_DOUBLE_BASE_OFFSET = arrayBaseOffset(JavaKind.Double.getTypeChar()); ARRAY_OBJECT_BASE_OFFSET = arrayBaseOffset(JavaKind.Object.getTypeChar()); - ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET = arrayBaseOffset('Q'); ARRAY_BOOLEAN_INDEX_SCALE = arrayIndexScale(JavaKind.Boolean.getTypeChar()); ARRAY_BYTE_INDEX_SCALE = arrayIndexScale(JavaKind.Byte.getTypeChar()); ARRAY_SHORT_INDEX_SCALE = arrayIndexScale(JavaKind.Short.getTypeChar()); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 9c7d2bee2e1..5ad4d857715 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -1163,14 +1163,6 @@ public int getArrayBaseOffset(JavaKind kind) { } - /** - * The offset from the origin of a flat array to the first element. - * - * @return the offset in bytes - */ - public int getFlatArrayBaseOffset() { - return compilerToVm.ARRAY_PRIMITIVE_OBJECT_BASE_OFFSET; - } /** * The scale used for the index when accessing elements of an array of this kind. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 8728a485d58..5dfc75e9f57 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -340,10 +340,6 @@ public int getArrayBaseOffset(JavaKind kind) { return runtime.getArrayBaseOffset(kind); } - @Override - public int getFlatArrayBaseOffset() { - return runtime.getFlatArrayBaseOffset(); - } @Override public int getArrayIndexScale(JavaKind kind) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java index e3ea36fdb89..33db3705afa 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java @@ -123,9 +123,5 @@ default ResolvedJavaType[] lookupJavaTypes(Class[] classes) { int getArrayBaseOffset(JavaKind elementKind); - default int getFlatArrayBaseOffset() { - throw new UnsupportedOperationException(); - } - int getArrayIndexScale(JavaKind elementKind); } From ef79f273a3c83a30476ae22323516d811afa2514 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 7 Mar 2025 12:22:56 +0100 Subject: [PATCH 63/98] Renamed calling convention function. --- .../share/classes/jdk/vm/ci/code/CodeUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java index 67cf35e4d14..1caf3d69fbd 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java @@ -439,11 +439,11 @@ public static CallingConvention getCallingConvention(CodeCacheProvider codeCache } /** - * Create a calling convention from a {@link ResolvedJavaMethod} with the parameters scalarized. + * Create a calling convention from a {@link ResolvedJavaMethod} with scalarized inline type parameters . * - * @param scalarizeReceiver decides if also the receiver should be scalarized + * @param scalarizeReceiver true if the receiver should be scalarized, false otherwise */ - public static CallingConvention getScalarizedCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory valueKindFactory, boolean scalarizeReceiver) { + public static CallingConvention getValhallaCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory valueKindFactory, boolean scalarizeReceiver) { if (!method.hasScalarizedParameters()) return getCallingConvention(codeCache, type, method, valueKindFactory); Signature sig = method.getSignature(); JavaType[] argTypes = method.getScalarizedParameters(scalarizeReceiver); From 16399db35121ea851e67ca441ecaa229c359620c Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sun, 9 Mar 2025 12:03:34 +0100 Subject: [PATCH 64/98] Adapted isIdentity implementation. --- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 6 +++--- .../jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java | 5 ----- .../share/classes/jdk/vm/ci/meta/ResolvedJavaType.java | 5 ++++- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 1ef0485f273..3f4b25a6d9b 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -450,10 +450,10 @@ public boolean isInterface() { @Override public boolean isIdentity() { - if (!config().valhallaEnabled) { - return !isInterface(); + if (config().valhallaEnabled) { + return isArray() || (getAccessFlags() & config().jvmAccIdentity) != 0; } - return isArray() || (getAccessFlags() & config().jvmAccIdentity) != 0; + return !isInterface(); } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java index b989772da43..ed4851213d4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType.java @@ -183,11 +183,6 @@ public boolean isInterface() { return false; } - @Override - public boolean isIdentity() { - return false; - } - @Override public boolean isAssignableFrom(ResolvedJavaType other) { assert other != null; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index f0788573182..da6c4887581 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -421,6 +421,9 @@ default boolean isConcrete() { * @return {@code true} if this type has an identity */ default boolean isIdentity(){ - throw new UnsupportedOperationException("isIdentity is unsupported"); + if (isPrimitive()) { + return false; + } + return !isInterface(); } } From 193044227951066a0fe53bd52e58df5520ca1b2a Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 10 Mar 2025 07:44:52 +0100 Subject: [PATCH 65/98] Fix bug causing Graal annotation processor to fail. --- .../classes/com/sun/tools/javac/jvm/ClassReader.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 2d6b1a45048..61b2cb568b5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -596,11 +596,9 @@ Type classSigToType() { sbp - startSbp)); try { - if (outer == Type.noType) { - ClassType et = (ClassType) t.erasure(types); - return new ClassType(et.getEnclosingType(), List.nil(), et.tsym, et.getMetadata()); - } - return new ClassType(outer, List.nil(), t, List.nil()); + return (outer == Type.noType) ? + t.erasure(types) : + new ClassType(outer, List.nil(), t); } finally { sbp = startSbp; } From ced28d6f617b633e31be0b46b4d2539f54ac92a1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 10 Mar 2025 07:45:45 +0100 Subject: [PATCH 66/98] Reinstall old Field constructor in reflection for libgraal. --- .../classes/java/lang/reflect/Field.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/java.base/share/classes/java/lang/reflect/Field.java b/src/java.base/share/classes/java/lang/reflect/Field.java index 61d9b8fd6b8..ccd373c3c68 100644 --- a/src/java.base/share/classes/java/lang/reflect/Field.java +++ b/src/java.base/share/classes/java/lang/reflect/Field.java @@ -77,6 +77,7 @@ class Field extends AccessibleObject implements Member { // Generics and annotations support private final transient String signature; private final byte[] annotations; + private final boolean trustedFinal; /** * Fields are mutable due to {@link AccessibleObject#setAccessible(boolean)}. @@ -136,6 +137,30 @@ private FieldRepository getGenericInfo() { this.slot = slot; this.signature = signature; this.annotations = annotations; + this.trustedFinal = isTrustedFinal(); + } + + /** + * Package-private constructor + */ + @SuppressWarnings("deprecation") + Field(Class declaringClass, + String name, + Class type, + int modifiers, + boolean trustedFinal, + int slot, + String signature, + byte[] annotations) { + this.clazz = declaringClass; + this.name = name; + this.type = type; + this.modifiers = modifiers; + this.trustedFinal = trustedFinal; + this.slot = slot; + this.signature = signature; + this.annotations = annotations; + this.flags = this.trustedFinal ? TRUST_FINAL : 0; } /** From fdb16900fb1ff1efd78ac11097a1e698853eb703 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 11 Mar 2025 11:14:10 +0100 Subject: [PATCH 67/98] Use the valhalla enabled option when retrieving instance fields. --- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 3f4b25a6d9b..2f91b176526 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -860,10 +860,10 @@ public int compare(ResolvedJavaField a, ResolvedJavaField b) { @Override public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { - return getInstanceFields(includeSuperclasses, true); + return getInstanceFields(includeSuperclasses, config().valhallaEnabled); } - public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses, boolean flat) { + public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses, boolean valhallaEnabled) { if (instanceFields == null) { if (isArray() || isInterface()) { instanceFields = NO_FIELDS; @@ -872,7 +872,7 @@ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses, boolea if (getSuperclass() != null) { prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); } - if (flat) { + if (valhallaEnabled) { instanceFields = getFlattenedFields(prepend); } else { instanceFields = getFields(false, prepend); From 7c00b05e76ba56aa5dedfe58c935a88b32c7df6f Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 11 Mar 2025 15:51:26 +0100 Subject: [PATCH 68/98] Renamed isNotNull to nonNull. --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 2 +- .../classes/jdk/vm/ci/code/VirtualObject.java | 12 ++++++------ .../vm/ci/hotspot/HotSpotCompiledCodeStream.java | 6 +++--- .../ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 14 +++++++------- .../classes/jdk/vm/ci/meta/ResolvedJavaMethod.java | 10 +++++----- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 10ca3e53921..730d1434c2f 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1102,7 +1102,7 @@ void CodeInstaller::read_virtual_objects(HotSpotCompiledCodeStream* stream, JVMC _has_auto_box = true; } // see code in output.cpp line 812 (PhaseOutput::FillLocArray line) - bool check_is_not_null = stream->read_bool("isNotNull"); + bool check_is_not_null = stream->read_bool("nonNull"); ScopeValue *is_init = nullptr; if (check_is_not_null) { ScopeValue* cur_second = nullptr; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java index 0b2396db97a..224e70de4af 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/VirtualObject.java @@ -44,7 +44,7 @@ public final class VirtualObject implements JavaValue { private JavaKind[] slotKinds; private final int id; private boolean isAutoBox; - private JavaValue[] isNotNull; + private JavaValue[] nonNull; /** * Creates a new {@link VirtualObject} for the given type, with the given fields. If @@ -245,8 +245,8 @@ public JavaValue[] getValues() { * Virtual objects can also be null. Returns an array containing one value indicating if the virtual object is non-null. */ @SuppressFBWarnings(value = "EI_EXPOSE_REP", justification = "`values` is intentional mutable") - public JavaValue[] getIsNotNull() { - return isNotNull; + public JavaValue[] getNonNull() { + return nonNull; } /** @@ -291,10 +291,10 @@ public void setValues(JavaValue[] values, JavaKind[] slotKinds) { /** * Overwrites the current value with a new one. * - * @param isNotNull an array containing one value indicating if the virtual object is non-null. + * @param nonNull an array containing one value indicating if the virtual object is non-null. */ - public void setIsNotNull(JavaValue[] isNotNull) { - this.isNotNull = isNotNull; + public void setNonNull(JavaValue[] nonNull) { + this.nonNull = nonNull; } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 6f84050633d..b50a8a79295 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java @@ -985,10 +985,10 @@ private void writeVirtualObjects(VirtualObject[] virtualObjects) { writeBoolean("isAutoBox", vo.isAutoBox()); // if virtual object can be nullable e.g. framestate of invoke with scalarized return values, also insert null indication - writeBoolean("isNotNull", vo.getIsNotNull() != null); - if (vo.getIsNotNull() != null) { + writeBoolean("nonNull", vo.getNonNull() != null); + if (vo.getNonNull() != null) { writeBasicType(JavaKind.Int); - JavaValue jv = vo.getIsNotNull()[0]; + JavaValue jv = vo.getNonNull()[0]; writeJavaValue(jv, JavaKind.Int); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 5b11f24d3c0..091f20feff8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -893,7 +893,7 @@ private JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiv JavaType type = signature.getParameterType(index, getDeclaringClass()); ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterIsNotNullType(previousIndex, indexIncludesReceiverIfExists)); + return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterNonNullType(previousIndex, indexIncludesReceiverIfExists)); } @@ -911,7 +911,7 @@ public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean index } @Override - public JavaType getScalarizedParameterIsNotNullType(int index, boolean indexIncludesReceiverIfExists) { + public JavaType getScalarizedParameterNonNullType(int index, boolean indexIncludesReceiverIfExists) { assert isScalarizedParameter(index, indexIncludesReceiverIfExists) /*&& !isParameterNullFree(index, indexIncludesReceiverIfExists)*/ : "Scalarized nullable parameter presumed"; return HotSpotResolvedPrimitiveType.forKind(IS_NOT_NULL_KIND); } @@ -945,7 +945,7 @@ public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; boolean nullFree = isParameterNullFree(i); - types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterIsNotNullType(i))); + types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterNonNullType(i))); } else { types.add(type); } @@ -955,18 +955,18 @@ public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { } - private ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType isNotNullType) { + private ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { ResolvedJavaField[] fields = holder.getInstanceFields(true); ArrayList types = new ArrayList<>(fields.length + (!nullFree ? 1 : 0)); - if (!nullFree) types.add(isNotNullType); + if (!nullFree) types.add(nonNullType); for (int i = 0; i < fields.length; i++) { types.add(fields[i].getType()); } return types; } - private JavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType isNotNullType) { - ArrayList list = getFields(holder, nullFree, isNotNullType); + private JavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { + ArrayList list = getFields(holder, nullFree, nonNullType); return list.toArray(new JavaType[list.size()]); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index fb49668eafe..ca1e2b491f0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -638,13 +638,13 @@ default ResolvedJavaField[] getScalarizedParameterFields(int index, boolean inde /** - * Same as {@link #getScalarizedParameterIsNotNullType(int)} but implicitly excluding the receiver from the index. + * Same as {@link #getScalarizedParameterNonNullType(int)} but implicitly excluding the receiver from the index. * * @param index the index of a formal parameter in the signature * @return the type representing the is not null information */ - default JavaType getScalarizedParameterIsNotNullType(int index) { - return getScalarizedParameterIsNotNullType(index, false); + default JavaType getScalarizedParameterNonNullType(int index) { + return getScalarizedParameterNonNullType(index, false); } /** @@ -654,8 +654,8 @@ default JavaType getScalarizedParameterIsNotNullType(int index) { * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise * @return the type representing the is not null information */ - default JavaType getScalarizedParameterIsNotNullType(int index, boolean indexIncludesReceiverIfExists) { - throw new UnsupportedOperationException("getScalarizedParameterIsNotNull is not supported"); + default JavaType getScalarizedParameterNonNullType(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("getScalarizedParameterNonNull is not supported"); } /** From 22cdaddc458f4f3061fd1a9b61d724a917f40004 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 11 Mar 2025 17:24:07 +0100 Subject: [PATCH 69/98] Added comments in jvmciCodeInstaller. --- src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp | 3 +++ src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp index 3015206dadc..caa7b6c8bb8 100644 --- a/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp @@ -133,6 +133,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, methodHandle& metho case INVOKEINTERFACE: { assert(!method->is_static(), "cannot call static method with invokeinterface"); call = nativeCall_at(_instructions->start() + pc_offset); + // TODO: attach method for valhalla calling convention see jvmciCodeInstaller_x86.cpp _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc)); call->trampoline_jump(cbuf, SharedRuntime::get_resolve_virtual_call_stub(), JVMCI_CHECK); break; @@ -140,6 +141,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, methodHandle& metho case INVOKESTATIC: { assert(method->is_static(), "cannot call non-static method with invokestatic"); call = nativeCall_at(_instructions->start() + pc_offset); + // TODO: attach method for valhalla calling convention see jvmciCodeInstaller_x86.cpp _instructions->relocate(call->instruction_address(), relocInfo::static_call_type); call->trampoline_jump(cbuf, SharedRuntime::get_resolve_static_call_stub(), JVMCI_CHECK); break; @@ -147,6 +149,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &cbuf, methodHandle& metho case INVOKESPECIAL: { assert(!method->is_static(), "cannot call static method with invokespecial"); call = nativeCall_at(_instructions->start() + pc_offset); + // TODO: attach method for valhalla calling convention see jvmciCodeInstaller_x86.cpp _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type); call->trampoline_jump(cbuf, SharedRuntime::get_resolve_opt_virtual_call_stub(), JVMCI_CHECK); break; diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 5848e22e113..d25769b1d8b 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -195,8 +195,9 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_opt_virtual_call_stub()); - // attach the target method only for scalarized args to avoid null check on receiver if receiver was optimized from non-scalarized to scalarized + // attach the target method only for scalarized args to avoid a null check on the receiver if receiver was optimized from non-scalarized to scalarized // attach only for scalarized args otherwise assert(attached_method->has_scalarized_args(), "invalid use of attached method"); will trigger + // see resolved_method_index in machnode.hpp if (method()->has_scalarized_args()) { _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand, _oop_recorder->find_index(method())); From 8da680444d321f246a619e8f89daad812d0ff831 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 20 Mar 2025 20:15:59 +0100 Subject: [PATCH 70/98] Don't scalarize parameters if there is a mismatch. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 11cce3059ad..256b48f4e3a 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -373,15 +373,16 @@ C2V_END C2V_VMENTRY_0(jbooleanArray, getScalarizedParametersInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jbooleanArray infoArray, jint len)) Method* method = UNPACK_PAIR(Method, method); JVMCIPrimitiveArray result = JVMCIENV->wrap(infoArray); + bool mismatch = method->mismatch(); for(int i=0; iput_bool_at(result, i, method->is_scalarized_arg(i)); + JVMCIENV->put_bool_at(result, i, !mismatch && method->is_scalarized_arg(i)); } return JVMCIENV->get_jbooleanArray(result); C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedParameters, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) Method* method = UNPACK_PAIR(Method, method); - return method->has_scalarized_args(); + return !method->mismatch() && method->has_scalarized_args(); C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) From 9446b94c4c9b93105c8b47c8d172ad61ec892728 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 24 Mar 2025 22:21:25 +0100 Subject: [PATCH 71/98] Include the outer declaring class in the equals method of the ResolvedJavaField to avoid 'GraphProtocol: toString mismatch for' error. --- .../classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 12158bac92a..435102bf6ba 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -86,7 +86,7 @@ public boolean equals(Object obj) { HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; if (that.offset != this.offset || that.isStatic() != this.isStatic()) { return false; - } else if (this.holder.equals(that.holder)) { + } else if (this.holder.equals(that.holder) && this.getOuterDeclaringClass().equals(that.getOuterDeclaringClass())) { return true; } } From 8d5a1fec3758f13e383fcf6ae20b43ff9703ceed Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sat, 29 Mar 2025 18:43:43 +0100 Subject: [PATCH 72/98] Fixed bug during constant folding of load field. Sanity check for an object part of a flat field fails. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 28 +++++++++++-------- .../jdk/vm/ci/hotspot/CompilerToVM.java | 8 ++++-- .../ci/hotspot/HotSpotObjectConstantImpl.java | 2 +- .../ci/hotspot/HotSpotResolvedObjectType.java | 2 ++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 256b48f4e3a..5fd6b8d723f 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2306,7 +2306,7 @@ C2V_VMENTRY_NULL(jobjectArray, getDeclaredFieldsInfo, (JNIEnv* env, jobject, ARG return array.as_jobject(); C2V_END -static jobject read_field_value(Handle obj, long displacement, jchar type_char, bool is_static, Thread* THREAD, JVMCIEnv* JVMCIENV) { +static jobject read_field_value(Handle obj, long displacement, jchar type_char, bool is_static, jboolean is_flat, Thread* THREAD, JVMCIEnv* JVMCIENV) { BasicType basic_type = JVMCIENV->typeCharToBasicType(type_char, JVMCI_CHECK_NULL); int basic_type_elemsize = type2aelembytes(basic_type); @@ -2335,12 +2335,18 @@ static jobject read_field_value(Handle obj, long displacement, jchar type_char, } else if (obj->is_instance()) { InstanceKlass* klass = InstanceKlass::cast(is_static ? java_lang_Class::as_Klass(obj()) : obj->klass()); fieldDescriptor fd; - if (!klass->find_field_from_offset(displacement, is_static, &fd)) { - JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Can't find field at displacement %d in object of type %s", (int) displacement, klass->external_name())); - } - if (fd.field_type() != T_OBJECT && fd.field_type() != T_ARRAY) { - JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Field at displacement %d in object of type %s is %s but expected %s", (int) displacement, - klass->external_name(), type2name(fd.field_type()), type2name(basic_type))); + if(is_flat) { + // TODO: correct sanity check for flat fields, for flat fields the container klass is not klass the field was originally defined in. + // that's why !klass->find_field_from_offset(displacement, is_static, &fd) will fail, so skip it for now. + // use TestLWorld#run1, MyValue1.o embedded in TestLWorld at offset 144 fails + } else{ + if (!klass->find_field_from_offset(displacement, is_static, &fd)) { + JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Can't find field at displacement %d in object of type %s", (int) displacement, klass->external_name())); + } + if (fd.field_type() != T_OBJECT && fd.field_type() != T_ARRAY) { + JVMCI_THROW_MSG_NULL(IllegalArgumentException, err_msg("Field at displacement %d in object of type %s is %s but expected %s", (int) displacement, + klass->external_name(), type2name(fd.field_type()), type2name(basic_type))); + } } } else if (obj->is_typeArray()) { JVMCI_THROW_MSG_NULL(IllegalArgumentException, "Can't read objects from primitive array"); @@ -2412,10 +2418,10 @@ static jobject read_field_value(Handle obj, long displacement, jchar type_char, C2V_VMENTRY_NULL(jobject, readStaticFieldValue, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), long displacement, jchar type_char)) Klass* klass = UNPACK_PAIR(Klass, klass); Handle obj(THREAD, klass->java_mirror()); - return read_field_value(obj, displacement, type_char, true, THREAD, JVMCIENV); + return read_field_value(obj, displacement, type_char, true, false, THREAD, JVMCIENV); C2V_END -C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, ARGUMENT_PAIR(expected_type), long displacement, jchar type_char)) +C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, ARGUMENT_PAIR(expected_type), long displacement, jchar type_char, jboolean is_flat)) if (object == nullptr) { JVMCI_THROW_NULL(NullPointerException); } @@ -2432,7 +2438,7 @@ C2V_VMENTRY_NULL(jobject, readFieldValue, (JNIEnv* env, jobject, jobject object, } } bool is_static = expected_klass == nullptr && java_lang_Class::is_instance(obj()) && displacement >= InstanceMirrorKlass::offset_of_static_fields(); - return read_field_value(obj, displacement, type_char, is_static, THREAD, JVMCIENV); + return read_field_value(obj, displacement, type_char, is_static, is_flat, THREAD, JVMCIENV); C2V_END C2V_VMENTRY_0(jboolean, isInstance, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jobject object)) @@ -3420,7 +3426,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getDeclaredMethods", CC "(" HS_KLASS2 ")[" RESOLVED_METHOD, FN_PTR(getDeclaredMethods)}, {CC "getDeclaredFieldsInfo", CC "(" HS_KLASS2 ")[" FIELDINFO, FN_PTR(getDeclaredFieldsInfo)}, {CC "readStaticFieldValue", CC "(" HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readStaticFieldValue)}, - {CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JC)" JAVACONSTANT, FN_PTR(readFieldValue)}, + {CC "readFieldValue", CC "(" OBJECTCONSTANT HS_KLASS2 "JCZ)" JAVACONSTANT, FN_PTR(readFieldValue)}, {CC "isInstance", CC "(" HS_KLASS2 OBJECTCONSTANT ")Z", FN_PTR(isInstance)}, {CC "isAssignableFrom", CC "(" HS_KLASS2 HS_KLASS2 ")Z", FN_PTR(isAssignableFrom)}, {CC "isTrustedForIntrinsics", CC "(" HS_KLASS2 ")Z", FN_PTR(isTrustedForIntrinsics)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 7fc60e31769..2c5fad41964 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1259,11 +1259,15 @@ JavaConstant readStaticFieldValue(HotSpotResolvedObjectTypeImpl declaringKlass, * @throws IllegalArgumentException if any of the sanity checks fail */ JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedObjectTypeImpl expectedType, long offset, char typeChar) { + return readFieldValue(object, expectedType, offset, typeChar, false); + } + + JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedObjectTypeImpl expectedType, long offset, char typeChar, boolean isFlat) { long expectedTypePointer = expectedType != null ? expectedType.getKlassPointer() : 0L; - return readFieldValue(object, expectedType, expectedTypePointer, offset, typeChar); + return readFieldValue(object, expectedType, expectedTypePointer, offset, typeChar, isFlat); } - native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedObjectTypeImpl expectedType, long expectedTypePointer, long offset, char typeChar); + native JavaConstant readFieldValue(HotSpotObjectConstantImpl object, HotSpotResolvedObjectTypeImpl expectedType, long expectedTypePointer, long offset, char typeChar, boolean isFlat); /** * @see ResolvedJavaType#isInstance(JavaConstant) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index 625bc47aca1..8d4a374ef47 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -202,7 +202,7 @@ public JavaConstant readFieldValue(HotSpotResolvedJavaField field) { } HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getOuterDeclaringClass(); char typeChar = field.getType().getJavaKind().getTypeChar(); - return runtime().compilerToVm.readFieldValue(this, declaringClass, field.getOffset(), typeChar); + return runtime().compilerToVm.readFieldValue(this, declaringClass, field.getOffset(), typeChar, declaringClass != field.getDeclaringClass()); } public ResolvedJavaType asJavaType() { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 996f8da1fde..2152d551da5 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -111,6 +111,8 @@ default JavaKind getJavaKind() { boolean isPrimaryType(); int superCheckOffset(); + + // TODO: rename to payloadOffset int firstFieldOffset(); long prototypeMarkWord(); From a8af251f0e26ac7da8fc9a1ea2ca652ba363c12e Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Sun, 30 Mar 2025 13:23:11 +0200 Subject: [PATCH 73/98] Use a JavaType array to avoid error, some types may not be resolved. --- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 091f20feff8..790193a582a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -951,7 +951,7 @@ public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { } } - return types.toArray(new ResolvedJavaType[types.size()]); + return types.toArray(new JavaType[types.size()]); } From 8b96ff36a7065ea905e9808c7bad13e79bce1210 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 8 Apr 2025 19:58:22 +0200 Subject: [PATCH 74/98] Added jdk internal exports to microbenchmark makefile, to get master thesis prototype benchmark running. --- make/test/BuildMicrobenchmark.gmk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 757ac593dfd..fcf3183426d 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -99,14 +99,20 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ --add-exports java.base/sun.security.util=ALL-UNNAMED \ --add-exports java.base/sun.security.util.math=ALL-UNNAMED \ --add-exports java.base/sun.security.util.math.intpoly=ALL-UNNAMED \ + --add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED \ --enable-preview \ + --patch-module java.base=/home/michael/projects/valhalla/build/linux-x86_64-server-release/images/jdk/lib/valueclasses/java.base-valueclasses.jar \ + --add-exports java.base/jdk.internal.value=ALL-UNNAMED \ -XDsuppressNotes \ -processor org.openjdk.jmh.generators.BenchmarkProcessor \ -s $(MICROBENCHMARK_GENSRC), \ JAVA_FLAGS := \ --add-exports java.base/jdk.internal.vm=ALL-UNNAMED \ --add-modules jdk.unsupported \ + --add-modules java.base \ + --add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED \ --enable-preview \ + --add-exports java.base/jdk.internal.value=ALL-UNNAMED \ --limit-modules java.management, \ )) From 484646a94dffbcb592ed54c48db1131bced092db Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 8 Apr 2025 20:00:25 +0200 Subject: [PATCH 75/98] Started with some prototype benchmarks for the master thesis. --- .../thesis_benchmarks/CallingConvention.java | 56 ++ .../thesis_benchmarks/CompareValue1.java | 23 + .../thesis_benchmarks/CompareValue2.java | 6 + .../thesis_benchmarks/Inline64long.java | 477 ++++++++++++++++++ .../thesis_benchmarks/MyInterface1.java | 12 + .../valhalla/thesis_benchmarks/MyObject.java | 23 + .../valhalla/thesis_benchmarks/MyValue1.java | 19 + .../valhalla/thesis_benchmarks/MyValue2.java | 19 + .../valhalla/thesis_benchmarks/MyValue3.java | 26 + .../valhalla/thesis_benchmarks/MyValue4.java | 26 + .../thesis_benchmarks/NBodySimulation.java | 50 ++ .../valhalla/thesis_benchmarks/OtherVal.java | 9 + .../valhalla/thesis_benchmarks/Particle.java | 18 + .../SubstitutabilityCheck.java | 60 +++ 14 files changed, 824 insertions(+) create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CallingConvention.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue1.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue2.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Inline64long.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyInterface1.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyObject.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue1.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue2.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue3.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue4.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/NBodySimulation.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/OtherVal.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Particle.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/SubstitutabilityCheck.java diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CallingConvention.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CallingConvention.java new file mode 100644 index 00000000000..6dad1ba2ed2 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CallingConvention.java @@ -0,0 +1,56 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyInterface1; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyObject; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyValue1; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyValue2; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyValue3; +import org.openjdk.bench.valhalla.thesis_benchmarks.MyValue4; +import org.openjdk.bench.valhalla.thesis_benchmarks.OtherVal; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.CompilerControl; + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class CallingConvention { + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public static int test21(MyInterface1 intf, MyValue4 v, int y) { + return intf.test10(v, y, y, y, y, y, y).getValue(); + } + + public static final int rI = 1; + + @Benchmark + @OperationsPerInvocation(1) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void testFunc() { + MyValue1 val1 = new MyValue1(rI); + MyValue2 val2 = new MyValue2(rI + 1); + MyValue3 val3 = new MyValue3(rI + 2); + MyValue4 val4 = new MyValue4(rI + 3); + OtherVal other = new OtherVal(rI + 4); + MyObject obj = new MyObject(rI + 5); + test21(val1, val4, rI); + test21(val2, val4, rI); + test21(val3, val4, rI); + test21(val4, val4, rI); + test21(obj, val4, rI); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue1.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue1.java new file mode 100644 index 00000000000..88cd094a03c --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue1.java @@ -0,0 +1,23 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + + +public class CompareValue1 { + int i; + long l; + Object o; + CompareValue2 myValue2; + + public CompareValue1() { + this.i = 3; + this.l = 4; + this.o = 5; + this.myValue2 = new CompareValue2(); + } + + public CompareValue1(long l) { + this.i = 3; + this.l = l; + this.o = 5; + this.myValue2 = new CompareValue2(); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue2.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue2.java new file mode 100644 index 00000000000..c1f1d3a7000 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/CompareValue2.java @@ -0,0 +1,6 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +public class CompareValue2 { + float f = 5.0f; + double d = 6.0; +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Inline64long.java new file mode 100644 index 00000000000..174f81662cb --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Inline64long.java @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Fork(value = 1, + jvmArgsAppend = {"--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED", + "--enable-preview"}) +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +//@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) +public class Inline64long { + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public interface ByLong { + + public long longSum(); + + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public interface Int64 { + + public long longValue(); + + public int intValue(); + + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public value class Q64long implements Int64, ByLong { + + public final long v0; + + public Q64long() { + this(0); + } + + public Q64long(long v0) { + this.v0 = v0; + } + + @Override + public long longValue() { + return v0; + } + + @Override + public int intValue() { + return (int)v0; + } + + @Override + public long longSum() { + return v0; + } + + } + + // must be divisible by 2 and 3 and around 100 + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public abstract static class InvocationLogic { + //@CompilerControl(CompilerControl.Mode.DONT_INLINE) + public abstract Q64long compute(Q64long v1); + + //@CompilerControl(CompilerControl.Mode.DONT_INLINE) + public abstract Q64long compute(Q64long v1, Q64long v2); + + //@CompilerControl(CompilerControl.Mode.DONT_INLINE) + public abstract Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4); + + //@CompilerControl(CompilerControl.Mode.DONT_INLINE) + public abstract Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8); + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class InvokeImpl1 extends InvocationLogic { + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2) { + return v1; + } + + @Override + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { + return v1; + } + + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class InvokeImpl2 extends InvocationLogic { + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { + return v1; + } + + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class InvokeImpl3 extends InvocationLogic { + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4) { + return v1; + } + + @Override + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public Q64long compute(Q64long v1, Q64long v2, Q64long v3, Q64long v4, Q64long v5, Q64long v6, Q64long v7, Q64long v8) { + return v1; + } + + } + + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + private static InvocationLogic getImpl(int i, int targets) { + switch (i % targets) { + case 0: + return new InvokeImpl1(); + case 1: + return new InvokeImpl2(); + case 2: + return new InvokeImpl3(); + } + return null; + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + @State(Scope.Thread) + public static class StateTargets0 { + InvokeImpl1[] arr; + + @Setup + public void setup() { + arr = new InvokeImpl1[96]; + for (int i = 0; i < arr.length; i++) { + arr[i] = new InvokeImpl1(); + } + } + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + @State(Scope.Thread) + public static abstract class StateTargets { + InvocationLogic[] arr; + + public void init(int targets) { + arr = new InvocationLogic[96]; + for (int i = 0; i < arr.length; i++) { + arr[i] = getImpl(i, targets); + } + } + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class StateTargets1 extends StateTargets { + @Setup + public void setup() { + init(1); + } + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class StateTargets2 extends StateTargets { + @Setup + public void setup() { + init(2); + } + } + + //@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) + public static class StateTargets3 extends StateTargets { + @Setup + public void setup() { + init(3); + } + } + + Q64long a0 = new Q64long(42); + Q64long a1 = new Q64long(43); + Q64long a2 = new Q64long(44); + Q64long a3 = new Q64long(45); + Q64long a4 = new Q64long(46); + Q64long a5 = new Q64long(47); + Q64long a6 = new Q64long(48); + Q64long a7 = new Q64long(49); + + @CompilerControl(CompilerControl.Mode.INLINE) + public long args1(InvocationLogic[] logic) { + Q64long a0 = new Q64long(42); + long r = 0; + for (InvocationLogic t : logic) { + r += t.compute(a0).longValue(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public long args2(InvocationLogic[] logic) { + Q64long a0 = new Q64long(42); + Q64long a1 = new Q64long(43); + long r = 0; + for (InvocationLogic t : logic) { + r += t.compute(a0, a1).longValue(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public long args4(InvocationLogic[] logic) { + Q64long a0 = new Q64long(42); + Q64long a1 = new Q64long(43); + Q64long a2 = new Q64long(44); + Q64long a3 = new Q64long(45); + long r = 0; + for (InvocationLogic t : logic) { + r += t.compute(a0, a1, a2, a3).longValue(); + } + return r; + } + + @CompilerControl(CompilerControl.Mode.INLINE) + public long args8(InvocationLogic[] logic) { + Q64long a0 = new Q64long(42); + Q64long a1 = new Q64long(43); + Q64long a2 = new Q64long(44); + Q64long a3 = new Q64long(45); + Q64long a4 = new Q64long(46); + Q64long a5 = new Q64long(47); + Q64long a6 = new Q64long(48); + Q64long a7 = new Q64long(49); + long r = 0; + for (InvocationLogic t : logic) { + r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args1_targets0(StateTargets0 st) { + + InvokeImpl1[] arr = st.arr; + long r = 0; + for (InvocationLogic t : arr) { + Q64long a0 = new Q64long(r); + r += t.compute(a0).longValue(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args2_targets0(StateTargets0 st) { + + InvokeImpl1[] arr = st.arr; + long r = 0; + for (InvocationLogic t : arr) { + Q64long a0 = new Q64long(r); + Q64long a1 = new Q64long(r+1); + r += t.compute(a0, a1).longValue(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args4_targets0(StateTargets0 st) { + + InvokeImpl1[] arr = st.arr; + long r = 0; + for (InvocationLogic t : arr) { + Q64long a0 = new Q64long(r); + Q64long a1 = new Q64long(r+1); + Q64long a2 = new Q64long(r+2); + Q64long a3 = new Q64long(r+3); + r += t.compute(a0, a1, a2, a3).longValue(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args8_targets0(StateTargets0 st) { + + InvokeImpl1[] arr = st.arr; + long r = 0; + for (InvocationLogic t : arr) { + Q64long a0 = new Q64long(r); + Q64long a1 = new Q64long(r+1); + Q64long a2 = new Q64long(r+2); + Q64long a3 = new Q64long(r+3); + Q64long a4 = new Q64long(r+4); + Q64long a5 = new Q64long(r+5); + Q64long a6 = new Q64long(r+6); + Q64long a7 = new Q64long(r+7); + r += t.compute(a0, a1, a2, a3, a4, a5, a6, a7).longValue(); + } + return r; + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args1_targets1(StateTargets1 st) { + return args1(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args2_targets1(StateTargets1 st) { + return args2(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args4_targets1(StateTargets1 st) { + return args4(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args8_targets1(StateTargets1 st) { + return args8(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args1_targets2(StateTargets2 st) { + return args1(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args2_targets2(StateTargets2 st) { + return args2(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args4_targets2(StateTargets2 st) { + return args4(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args8_targets2(StateTargets2 st) { + return args8(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args1_targets3(StateTargets3 st) { + return args1(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args2_targets3(StateTargets3 st) { + return args2(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args4_targets3(StateTargets3 st) { + return args4(st.arr); + } + + @Benchmark + @OperationsPerInvocation(96) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public long Q64long_args8_targets3(StateTargets3 st) { + return args8(st.arr); + } + + +} diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyInterface1.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyInterface1.java new file mode 100644 index 00000000000..f1902200dd8 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyInterface1.java @@ -0,0 +1,12 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import org.openjdk.jmh.annotations.CompilerControl; + +interface MyInterface1 { + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyInterface1 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6); + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public int getValue(); +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyObject.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyObject.java new file mode 100644 index 00000000000..e3debe9526a --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyObject.java @@ -0,0 +1,23 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import org.openjdk.jmh.annotations.CompilerControl; + +class MyObject implements MyInterface1 { + private final int x; + + public MyObject(int x) { + this.x = x; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Override + public int getValue() { + return x; + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyObject test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) { + return new MyObject(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue1.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue1.java new file mode 100644 index 00000000000..cf60e8be081 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue1.java @@ -0,0 +1,19 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; +import org.openjdk.jmh.annotations.CompilerControl; +value class MyValue1 implements MyInterface1 { + public int x; + + public MyValue1(int x) { + this.x = x; + } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Override + public int getValue() { + return x; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyValue1 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) { + return new MyValue1(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue2.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue2.java new file mode 100644 index 00000000000..f4d82f1240d --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue2.java @@ -0,0 +1,19 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; +import org.openjdk.jmh.annotations.CompilerControl; +value class MyValue2 implements MyInterface1 { + public int x; + + public MyValue2(int x) { + this.x = x; + } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Override + public int getValue() { + return x; + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyValue2 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) { + return new MyValue2(x + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue3.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue3.java new file mode 100644 index 00000000000..6970b830a25 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue3.java @@ -0,0 +1,26 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; +import org.openjdk.jmh.annotations.CompilerControl; +value class MyValue3 implements MyInterface1 { + public double d1; + public double d2; + public double d3; + public double d4; + + public MyValue3(double d) { + this.d1 = d; + this.d2 = d; + this.d3 = d; + this.d4 = d; + } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Override + public int getValue() { + return (int)d4; + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyValue3 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) { + return new MyValue3(d1 + d2 + d3 + d4 + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue4.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue4.java new file mode 100644 index 00000000000..65d5cad54e7 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/MyValue4.java @@ -0,0 +1,26 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; +import org.openjdk.jmh.annotations.CompilerControl; +value class MyValue4 implements MyInterface1 { + public int x1; + public int x2; + public int x3; + public int x4; + + public MyValue4(int i) { + this.x1 = i; + this.x2 = i; + this.x3 = i; + this.x4 = i; + } + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + @Override + public int getValue() { + return x4; + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public MyValue4 test10(MyValue4 other, int i1, int i2, int i3, int i4, int i5, int i6) { + return new MyValue4(x1 + x2 + x3 + x4 + other.x1 + other.x2 + other.x3 + other.x4 + i1 + i2 + i3 + i4 + i5 + i6); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/NBodySimulation.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/NBodySimulation.java new file mode 100644 index 00000000000..01421726306 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/NBodySimulation.java @@ -0,0 +1,50 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.ImplicitlyConstructible; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class NBodySimulation { + + + static final int N = 1_000_000; + static Particle[] particles = /*new Particle[N];*/(Particle[]) ValueClass.newNullRestrictedArray(Particle.class, N); + + static { + initialize(); + } + + static void initialize() { + for (int i = 0; i < N; i++) + particles[i] = new Particle(Math.random(), Math.random(), Math.random(), 0.01, 0.01, 0.01); + } + + @Benchmark + @OperationsPerInvocation(N) + //@CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void simulate() { + for (int i = 0; i < N; i++) + particles[i] = particles[i].update(); + } + +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/OtherVal.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/OtherVal.java new file mode 100644 index 00000000000..071883648be --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/OtherVal.java @@ -0,0 +1,9 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +value class OtherVal { + public int x; + + public OtherVal(int x) { + this.x = x; + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Particle.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Particle.java new file mode 100644 index 00000000000..fd01e09b828 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Particle.java @@ -0,0 +1,18 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; +import jdk.internal.vm.annotation.ImplicitlyConstructible; +import jdk.internal.vm.annotation.LooselyConsistentValue; + +@ImplicitlyConstructible +@LooselyConsistentValue +value class Particle { + private final double x, y, z, vx, vy, vz; + + public Particle(double x, double y, double z, double vx, double vy, double vz) { + this.x = x; this.y = y; this.z = z; + this.vx = vx; this.vy = vy; this.vz = vz; + } + + public Particle update() { + return new Particle(x + vx, y + vy, z + vz, vx, vy, vz); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/SubstitutabilityCheck.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/SubstitutabilityCheck.java new file mode 100644 index 00000000000..6caa475ce80 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/SubstitutabilityCheck.java @@ -0,0 +1,60 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +//import org.openjdk.bench.valhalla.thesis_benchmarks.CompareValue1; +//import org.openjdk.bench.valhalla.thesis_benchmarks.CompareValue2; + +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.CompilerControl; + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +//@Fork(value = 1, +// jvmArgsAppend = {"--add-opens", "java.base/jdk.internal.misc=ALL-UNNAMED", +// "--enable-preview"}) +@Fork(1) +//@CompilerControl(CompilerControl.Mode.COMPILE_ONLY) +public class SubstitutabilityCheck { + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean compareFunc(CompareValue1 a, Object b) { + return a == b; + } + + @Benchmark + @OperationsPerInvocation(1) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public boolean compare() { + compareFunc(new CompareValue1(), new CompareValue1(6)); + return compareFunc(new CompareValue1(), new Object()); + } + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + private static boolean compareFuncPEA() { + CompareValue1 a = new CompareValue1(); + CompareValue1 b = new CompareValue1(7); + return a == b; + } + + @Benchmark + @OperationsPerInvocation(1) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public boolean comparePEA() { + return compareFuncPEA(); + } + + +} \ No newline at end of file From 9e690d4469657c624172835c5fe2c99afb37699b Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Apr 2025 03:56:03 +0200 Subject: [PATCH 76/98] Additional verified entry points for the calling convention are initialized with -1. In case they haven't been set before method registration, set them. --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 730d1434c2f..338f51f26c0 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -780,6 +780,14 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, if (_nmethod_entry_patch_offset == -1) { JVMCI_THROW_MSG_(IllegalArgumentException, "nmethod entry barrier is missing", JVMCI::ok); } + + if(_offsets.value(CodeOffsets::Verified_Inline_Entry) == -1) { + _offsets.set_value(CodeOffsets::Verified_Inline_Entry, _offsets.value(CodeOffsets::Verified_Entry)); + } + + if(_offsets.value(CodeOffsets::Verified_Inline_Entry_RO) == -1) { + _offsets.set_value(CodeOffsets::Verified_Inline_Entry_RO, _offsets.value(CodeOffsets::Verified_Entry)); + } JVMCIObject mirror = installed_code; nmethod* nm = nullptr; // nm is an out parameter of register_method From 2a72f893700bad9543cd03b1547dc536647682a1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Apr 2025 04:01:05 +0200 Subject: [PATCH 77/98] Avoid sanity check when computing hash code in libgraal. --- src/hotspot/share/runtime/synchronizer.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 34f2610613c..543fd595f5f 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1033,7 +1033,8 @@ static intptr_t install_hash_code(Thread* current, oop obj) { } intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { - if (EnableValhalla && obj->klass()->is_inline_klass()) { +// TODO: libgraal uses this function to compute the hash code, but does not understand value objects yet, ignore the sanity check for now. + if (EnableValhalla && obj->klass()->is_inline_klass() && !EnableJVMCI) { // VM should be calling bootstrap method ShouldNotReachHere(); } From 373cf952f77e879fbbe69b06026c0c0016478d58 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Apr 2025 04:02:57 +0200 Subject: [PATCH 78/98] Primitive type of void class is not found, avoid an error for the moment. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 5fd6b8d723f..753944094cf 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2478,6 +2478,10 @@ C2V_VMENTRY_NULL(jobject, asJavaType, (JNIEnv* env, jobject, jobject object)) Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL); if (java_lang_Class::is_instance(obj())) { if (java_lang_Class::is_primitive(obj())) { + // TODO: primitive type of void class is not found + if(java_lang_Class::primitive_type(obj()) == BasicType::T_VOID){ + return nullptr; + } JVMCIObject type = JVMCIENV->get_jvmci_primitive_type(java_lang_Class::primitive_type(obj())); return JVMCIENV->get_jobject(type); } From 8f895ce0f2f6516a6e0da6964bbdc93661d0c994 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Apr 2025 13:06:12 +0200 Subject: [PATCH 79/98] Adapted implementation of getIdentityHashCode in compilerToVm to also consider value objects. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 8 ++++++++ src/hotspot/share/runtime/synchronizer.cpp | 3 +-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 753944094cf..8c26299b630 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2161,6 +2161,14 @@ C2V_END C2V_VMENTRY_0(jint, getIdentityHashCode, (JNIEnv* env, jobject, jobject object)) Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0); + if(obj->is_inline_type()){ + + // cannot call to Java library due to guarantee(thread->can_call_java()) failed: cannot make java calls from the native compiler + //return JVMCIRuntime::value_object_hashCode(THREAD, obj()); + + // from JvmtiEnv::GetObjectHashCode + return (jint)((int64_t)obj->klass() >> 3); + } return obj->identity_hash(); C2V_END diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 543fd595f5f..34f2610613c 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1033,8 +1033,7 @@ static intptr_t install_hash_code(Thread* current, oop obj) { } intptr_t ObjectSynchronizer::FastHashCode(Thread* current, oop obj) { -// TODO: libgraal uses this function to compute the hash code, but does not understand value objects yet, ignore the sanity check for now. - if (EnableValhalla && obj->klass()->is_inline_klass() && !EnableJVMCI) { + if (EnableValhalla && obj->klass()->is_inline_klass()) { // VM should be calling bootstrap method ShouldNotReachHere(); } From 0fe0119a981d2dfeabbefdc3e02d7bef99a85f1c Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Fri, 11 Apr 2025 17:53:41 +0200 Subject: [PATCH 80/98] Valhalla extended the BasicType by T_FLAT_ELEMENT, which has the value 14. T_VOID originally had the value 14, but now 15, so we need to adapt its JavaKind. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 4 ---- .../share/classes/jdk/vm/ci/meta/JavaKind.java | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 8c26299b630..40f44d9aad9 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2486,10 +2486,6 @@ C2V_VMENTRY_NULL(jobject, asJavaType, (JNIEnv* env, jobject, jobject object)) Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_NULL); if (java_lang_Class::is_instance(obj())) { if (java_lang_Class::is_primitive(obj())) { - // TODO: primitive type of void class is not found - if(java_lang_Class::primitive_type(obj()) == BasicType::T_VOID){ - return nullptr; - } JVMCIObject type = JVMCIENV->get_jvmci_primitive_type(java_lang_Class::primitive_type(obj())); return JVMCIENV->get_jobject(type); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/JavaKind.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/JavaKind.java index baa7e295d32..1f371f729ef 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/JavaKind.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/JavaKind.java @@ -60,7 +60,7 @@ public enum JavaKind { Object('A', 12, "Object", 1, false, null, null), /** The void kind. */ - Void('V', 14, "void", 0, false, java.lang.Void.TYPE, java.lang.Void.class), + Void('V', 15, "void", 0, false, java.lang.Void.TYPE, java.lang.Void.class), /** The non-type. */ Illegal('-', 99, "illegal", 0, false, null, null); From 9b64c8fd51e0a55794b6ad98063111cbe1883348 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 15 Apr 2025 12:05:37 +0200 Subject: [PATCH 81/98] Use the object handle to compute a hashcode for hotspot objects in libgraal. --- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 8 ------- src/hotspot/share/jvmci/jvmciEnv.cpp | 2 +- src/hotspot/share/jvmci/jvmciJavaClasses.hpp | 2 +- .../DirectHotSpotObjectConstantImpl.java | 5 +++++ .../vm/ci/hotspot/HotSpotObjectConstant.java | 2 ++ .../IndirectHotSpotObjectConstantImpl.java | 22 ++++++++++++++++--- 6 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 40f44d9aad9..5fd6b8d723f 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -2161,14 +2161,6 @@ C2V_END C2V_VMENTRY_0(jint, getIdentityHashCode, (JNIEnv* env, jobject, jobject object)) Handle obj = JVMCIENV->asConstant(JVMCIENV->wrap(object), JVMCI_CHECK_0); - if(obj->is_inline_type()){ - - // cannot call to Java library due to guarantee(thread->can_call_java()) failed: cannot make java calls from the native compiler - //return JVMCIRuntime::value_object_hashCode(THREAD, obj()); - - // from JvmtiEnv::GetObjectHashCode - return (jint)((int64_t)obj->klass() >> 3); - } return obj->identity_hash(); C2V_END diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 526482a85d4..9de83e43a8b 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -1629,7 +1629,7 @@ JVMCIObject JVMCIEnv::get_object_constant(oop objOop, bool compressed, bool dont JNIAccessMark jni(this, THREAD); jobject result = jni()->NewObject(JNIJVMCI::IndirectHotSpotObjectConstantImpl::clazz(), JNIJVMCI::IndirectHotSpotObjectConstantImpl::constructor(), - handle, compressed, dont_register); + handle, compressed, dont_register, obj->is_inline_type()); return wrap(result); } } diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index fe1bf265c26..5f9e1985a2c 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -178,7 +178,7 @@ end_class \ start_class(IndirectHotSpotObjectConstantImpl, jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl) \ long_field(IndirectHotSpotObjectConstantImpl, objectHandle) \ - jvmci_constructor(IndirectHotSpotObjectConstantImpl, "(JZZ)V") \ + jvmci_constructor(IndirectHotSpotObjectConstantImpl, "(JZZZ)V") \ end_class \ start_class(JavaKind, jdk_vm_ci_meta_JavaKind) \ char_field(JavaKind, typeChar) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java index c241af0348a..2f5e0114426 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl.java @@ -69,4 +69,9 @@ public JavaConstant uncompress() { public int getIdentityHashCode() { return System.identityHashCode(object); } + + @Override + public boolean objectIsInlineType() { + return !getType().isIdentity(); + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java index 227fcb731a9..9c33451eed8 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java @@ -94,4 +94,6 @@ public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VM @Override String toValueString(); + + boolean objectIsInlineType(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java index 2b8f717840e..b5b479dc2c1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl.java @@ -23,7 +23,6 @@ package jdk.vm.ci.hotspot; import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime; -import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -51,6 +50,8 @@ final class IndirectHotSpotObjectConstantImpl extends HotSpotObjectConstantImpl final IndirectHotSpotObjectConstantImpl base; + private final boolean objectIsInlineType; + private static class Audit { final Object scope; final long handle; @@ -71,11 +72,12 @@ private static class Audit { private Object rawAudit; @VMEntryPoint - private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister) { + private IndirectHotSpotObjectConstantImpl(long objectHandle, boolean compressed, boolean skipRegister, boolean objectIsInlineType) { super(compressed); assert objectHandle != 0 && UnsafeAccess.UNSAFE.getLong(objectHandle) != 0; this.objectHandle = objectHandle; this.base = null; + this.objectIsInlineType = objectIsInlineType; if (!skipRegister) { HotSpotObjectConstantScope scope = HotSpotObjectConstantScope.CURRENT.get(); if (scope != null && !scope.isGlobal()) { @@ -102,6 +104,7 @@ private IndirectHotSpotObjectConstantImpl(IndirectHotSpotObjectConstantImpl base // There should only be one level of indirection to the base object. assert base.base == null || base.base.base == null; this.base = base.base != null ? base.base : base; + this.objectIsInlineType = base.objectIsInlineType; } long getHandle() { @@ -182,7 +185,15 @@ public int getIdentityHashCode() { checkHandle(); int hash = hashCode; if (hash == 0) { - hash = runtime().compilerToVm.getIdentityHashCode(this); + if (objectIsInlineType) { + // The method ValueObjectMethods:valueObjectHashCode is private, we would need to go into the VM. + // This is not allowed though, because Java calls are disabled when libjvmci enters + // the VM via a C2V (i.e. CompilerToVM) native method. + // guarantee(thread->can_call_java(), "cannot make java calls from the native compiler"); triggers + hash = Long.hashCode(objectHandle); + } else { + hash = runtime().compilerToVm.getIdentityHashCode(this); + } if (hash == 0) { hash = 31; } @@ -190,4 +201,9 @@ public int getIdentityHashCode() { } return hash; } + + @Override + public boolean objectIsInlineType() { + return objectIsInlineType; + } } From a69010b32e8edab1f53bd390a28c51f767f8ab11 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 15 Apr 2025 19:49:35 +0200 Subject: [PATCH 82/98] Search for an existing inline type oop during handle creation. --- src/hotspot/share/jvmci/jvmciRuntime.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 3e9853a5c00..359acf79146 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -905,6 +905,17 @@ jlong JVMCIRuntime::make_oop_handle(const Handle& obj) { assert(oopDesc::is_oop(obj()), "not an oop"); oop* ptr = OopHandle(object_handles(), obj()).ptr_raw(); + if (obj()->is_inline_type()) { + int index = _oop_handles.find(ptr); + if (index != -1) { + // Satisfy OopHandles::release precondition that all + // handles being released are null. + NativeAccess<>::oop_store(ptr, (oop) nullptr); + object_handles()->release(ptr); + ptr = _oop_handles.at(index); + return reinterpret_cast(ptr); + } + } MutexLocker ml(_lock); _oop_handles.append(ptr); return reinterpret_cast(ptr); From 86a557d500e79afd8a5b32b7668d69da4418c479 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 22 Apr 2025 14:14:56 +0200 Subject: [PATCH 83/98] Made acmp profiling method default. --- .../share/classes/jdk/vm/ci/meta/ProfilingInfo.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java index 0092a66746c..008eec15d19 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java @@ -83,7 +83,9 @@ public interface ProfilingInfo { * * @return Returns a AcmpData object, or null if not available. */ - ACmpDataAccessor getACmpData(int bci); + default ACmpDataAccessor getACmpData(int bci) { + return null; + } /** * Returns information if null was ever seen for the given BCI. This information is collected From f296c790f36bb9420c4c47f70336b1535a92139a Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 22 Apr 2025 14:15:15 +0200 Subject: [PATCH 84/98] Jtreg test case adaptions. --- .../jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java | 1 + .../compiler/valhalla/inlinetypes/TestNullableInlineTypes.java | 1 + 2 files changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java index 3385d05a4b4..79617c330ca 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableArrays.java @@ -63,6 +63,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestNullableArrays.class) .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class) diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java index e650a3aa4e0..84dd1f2881a 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestNullableInlineTypes.java @@ -66,6 +66,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestNullableInlineTypes.class).setGraalLog() .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, From 5ae4805f33ef0cb1a86ef55dca0a8678aa5bff99 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 22 Apr 2025 14:16:01 +0200 Subject: [PATCH 85/98] Benchmark adaptions. --- .../valhalla/ackermann/Inline64long.java | 16 ++ .../valhalla/thesis_benchmarks/Equality.java | 87 ++++++++++ .../valhalla/thesis_benchmarks/Sorting.java | 149 ++++++++++++++++++ .../openjdk/bench/valhalla/types/Q32int.java | 3 + 4 files changed, 255 insertions(+) create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java diff --git a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java b/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java index b075e928747..3c15c81b7c1 100644 --- a/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java +++ b/test/micro/org/openjdk/bench/valhalla/ackermann/Inline64long.java @@ -77,4 +77,20 @@ public long ack_Int() { + ack_inter(new Q64long(X3), new Q64long(Y3)).longValue(); } + static value class CompareValue{ + int a = 3; + long l = 4; + Object u = 5; + } + + private static boolean testFunc(CompareValue a, CompareValue b){ + return a == b; + } + + @Benchmark + @OperationsPerInvocation(1) + public boolean testFunc_Ref() { + return testFunc(new CompareValue(), new CompareValue()); + } + } diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java new file mode 100644 index 00000000000..6fff057fa1f --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java @@ -0,0 +1,87 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import java.util.Random; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.ImplicitlyConstructible; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.bench.valhalla.types.Q32int; + + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Equality { + + public static value class Line { + @NullRestricted + Point p1; + @NullRestricted + Point p2; + + public Line(Point p1, Point p2) { + this.p1 = p1; + this.p2 = p2; + } + } + + @ImplicitlyConstructible + public static value class Point { + int x; + int y; + + public Point(int x, int y) { + this.x = x; + this.y = y; + } + } + + static final int N = 100; + static Line[] lineArray = new Line[N]; + + public static void initialize() { + // initialize randomly + Random rand = new Random(); + for (int i = 0; i < lineArray.length; i++) { + Point p1 = new Point(rand.nextInt(), rand.nextInt()); + Point p2 = new Point(rand.nextInt(), rand.nextInt()); + lineArray[i] = new Line(p1, p2); + } + } + + public static int findDuplicates() { + int count = 0; + for (int i = 0; i < lineArray.length; i++) { + for (int j = i + 1; j < lineArray.length; j++) { + if (lineArray[i] == lineArray[j]) { + count++; + } + } + } + return count; + } + + + @Benchmark + @OperationsPerInvocation(100) + public void benchmark() { + initialize(); + findDuplicates(); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java new file mode 100644 index 00000000000..ebca23edfbe --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java @@ -0,0 +1,149 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import java.util.Random; + +import jdk.internal.value.ValueClass; +import jdk.internal.vm.annotation.ImplicitlyConstructible; +import jdk.internal.vm.annotation.LooselyConsistentValue; +import jdk.internal.vm.annotation.NullRestricted; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.OperationsPerInvocation; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.annotations.CompilerControl; +import org.openjdk.bench.valhalla.types.Q32int; + + +import java.util.concurrent.TimeUnit; + +@Warmup(iterations = 5, time = 1) +@Measurement(iterations = 5, time = 1) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@BenchmarkMode(Mode.AverageTime) +@State(Scope.Thread) +public class Sorting { + + + static final int N = 1_000; + static Q32int[] array = (Q32int[]) ValueClass.newNullRestrictedArray(Q32int.class, N); + + public static void initialize() { + // initialize randomly + Random rand = new Random(); + for (int i = 0; i < array.length; i++) { + array[i] = new Q32int(rand.nextInt()); + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public static int bubblesort(Q32int[] array) { + Q32int temp; +// for (int i = 1; i < array.length; i++) { +// for (int j = 0; j < array.length - i; j++) { + return array[1].intValue(); +// if (array[j].intValue() > array[j + 1].intValue()) { +// temp = array[j]; +// array[j] = array[j + 1]; +// array[j + 1] = temp; +// } +// } +// } + //return array; + } + + public static Q32int[] fill() { + int N = 1_000_000; + Q32int[] array = (Q32int[]) ValueClass.newNullRestrictedArray(Q32int.class, N); + // initialize randomly + Random rand = new Random(); + for (int i = 0; i < array.length; i++) { + array[i] = new Q32int(rand.nextInt()); + } + return array; + } + + public static Q32int getMax() { + int N = 1_000_000; + Q32int max = new Q32int(Integer.MIN_VALUE); + Q32int[] array = (Q32int[]) ValueClass.newNullRestrictedArray(Q32int.class, N); + // initialize randomly + for (int i = 0; i < array.length; i++) { + if (max.intValue() < array[i].intValue()) { + max = array[i]; + } + } + return max; + } + + public static Q32int[] selectionSort(Q32int[] array) { + for (int i = 0; i < array.length - 1; i++) { + int minIndex = i; + for (int j = i + 1; j < array.length; j++) { + if (array[j].intValue() < array[minIndex].intValue()) { + minIndex = j; + } + } + Q32int temp = array[i]; + array[i] = array[minIndex]; + array[minIndex] = temp; + } + return array; + } + + public static Q32int[] insertionSort(Q32int[] array) { + for (int i = 1; i < array.length; i++) { + Q32int key = array[i]; + int j = i - 1; + while (j >= 0 && array[j].intValue() > key.intValue()) { + array[j + 1] = array[j]; + j--; + } + array[j + 1] = key; + } + return array; + } + +// @Benchmark +// @OperationsPerInvocation(1_000_000) +// public void benchmark_max() { +// getMax(); +// //initialize(); +// //bubblesort(array); +// //initialize(); +// //selectionSort(array); +// //initialize(); +// //insertionSort(array); +// } +// +// @Benchmark +// @OperationsPerInvocation(1_000_000) +// public void benchmark_fill() { +// fill(); +// //initialize(); +// //bubblesort(array); +// //initialize(); +// //selectionSort(array); +// //initialize(); +// //insertionSort(array); +// } + + @Benchmark + @OperationsPerInvocation(1_000) + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + public void benchmark_sorting() { + //fill(); + //initialize(); + bubblesort(array); + //initialize(); + //selectionSort(array); + //initialize(); + //insertionSort(array); + } +} \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/types/Q32int.java b/test/micro/org/openjdk/bench/valhalla/types/Q32int.java index 6cee8dbad25..1115d899232 100644 --- a/test/micro/org/openjdk/bench/valhalla/types/Q32int.java +++ b/test/micro/org/openjdk/bench/valhalla/types/Q32int.java @@ -22,6 +22,9 @@ */ package org.openjdk.bench.valhalla.types; +import jdk.internal.vm.annotation.ImplicitlyConstructible; + +@ImplicitlyConstructible public value class Q32int implements Int32, ByInt { public final int v0; From a70d96f9992c0a60015c572d9cf9e7af6ac1dcfb Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 22 Apr 2025 20:31:00 +0200 Subject: [PATCH 86/98] Use default methods in JVMCI. --- .../vm/ci/hotspot/HotSpotObjectConstant.java | 4 ++- .../ci/hotspot/HotSpotResolvedObjectType.java | 26 +++++++++++++------ 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java index 9c33451eed8..d065409bc3f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java @@ -95,5 +95,7 @@ public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VM @Override String toValueString(); - boolean objectIsInlineType(); + default boolean objectIsInlineType(){ + return false; + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 2152d551da5..91246639e0a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -40,11 +40,17 @@ public interface HotSpotResolvedObjectType extends ResolvedJavaType { HotSpotResolvedObjectType getArrayClass(); @Override - HotSpotResolvedObjectType getFlatArrayClass(); + default HotSpotResolvedObjectType getFlatArrayClass(){ + return null; + } - HotSpotResolvedObjectType convertToFlatArray(); + default HotSpotResolvedObjectType convertToFlatArray(){ + return null; + } - JavaConstant getDefaultInlineTypeInstance(); + default JavaConstant getDefaultInlineTypeInstance(){ + return null; + } @Override ResolvedJavaType getComponentType(); @@ -85,9 +91,13 @@ default JavaKind getJavaKind() { /** * Gets the component size in an array */ - int getLog2ComponentSize(); + default int getLog2ComponentSize(){ + return -1; + } - boolean isFlatArray(); + default boolean isFlatArray(){ + return false; + } int getVtableLength(); @@ -113,9 +123,9 @@ default JavaKind getJavaKind() { int superCheckOffset(); // TODO: rename to payloadOffset - int firstFieldOffset(); - - long prototypeMarkWord(); + default int firstFieldOffset(){ + return -1; + } int layoutHelper(); From de5a48d633f29e9777f4dd68d09a32661da3c3c0 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 22 Apr 2025 20:31:39 +0200 Subject: [PATCH 87/98] Updated location of value class jar. --- make/test/BuildMicrobenchmark.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index fcf3183426d..ddab7e0f44a 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -101,7 +101,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ --add-exports java.base/sun.security.util.math.intpoly=ALL-UNNAMED \ --add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED \ --enable-preview \ - --patch-module java.base=/home/michael/projects/valhalla/build/linux-x86_64-server-release/images/jdk/lib/valueclasses/java.base-valueclasses.jar \ + --patch-module java.base=/home/michael/work/git/oracle/valhalla/build/linux-x86_64-server-release/images/jdk/lib/valueclasses/java.base-valueclasses.jar \ --add-exports java.base/jdk.internal.value=ALL-UNNAMED \ -XDsuppressNotes \ -processor org.openjdk.jmh.generators.BenchmarkProcessor \ From 0d10821c9291123bc14c19ae6f7ac2443e8fdf22 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 23 Apr 2025 10:19:28 +0200 Subject: [PATCH 88/98] Restore deleted JVMCI method. --- .../classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index 91246639e0a..cd8c439d390 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -127,6 +127,8 @@ default int firstFieldOffset(){ return -1; } + long prototypeMarkWord(); + int layoutHelper(); @Override From 052d130670b3174ad153b59a3bb84fc56264c2ba Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 29 Apr 2025 12:06:52 +0200 Subject: [PATCH 89/98] Don't constant fold the equality comparison of two value objects in libgraal. --- .../HotSpotConstantReflectionProvider.java | 3 +++ .../vm/ci/hotspot/HotSpotJVMCIReflection.java | 4 +++ .../ci/hotspot/HotSpotObjectConstantImpl.java | 10 +++++++ .../hotspot/SharedLibraryJVMCIReflection.java | 27 +++++++++++++++++++ 4 files changed, 44 insertions(+) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java index 9e1cd287527..4d2ba4ce03a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java @@ -66,6 +66,9 @@ public Boolean constantEquals(Constant x, Constant y) { if (x == y) { return true; } else if (x instanceof HotSpotObjectConstantImpl) { + if (runtime.getConfig().valhallaEnabled) { + return y instanceof HotSpotObjectConstantImpl && ((HotSpotObjectConstantImpl) x).valhallaEquals(y); + } return y instanceof HotSpotObjectConstantImpl && x.equals(y); } else { return Objects.equals(x, y); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java index 3211e0ab409..60fbbbb554f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIReflection.java @@ -52,6 +52,10 @@ abstract class HotSpotJVMCIReflection { abstract boolean equals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that); + Boolean valhallaEquals(HotSpotObjectConstantImpl hotSpotResolvedJavaType, HotSpotObjectConstantImpl that) { + return equals(hotSpotResolvedJavaType, that); + } + abstract ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod); abstract Annotation[][] getParameterAnnotations(HotSpotResolvedJavaMethodImpl javaMethod); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index 8d4a374ef47..f3e8bde473e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -172,6 +172,16 @@ public boolean equals(Object o) { return false; } + public Boolean valhallaEquals(Object o) { + if (o == this) { + return true; + } else if (o instanceof HotSpotObjectConstantImpl) { + HotSpotObjectConstantImpl other = (HotSpotObjectConstantImpl) o; + return runtime().reflection.valhallaEquals(this, other); + } + return false; + } + @Override public int hashCode() { return getIdentityHashCode(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java index d7e8fd37ab2..cbc94969390 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SharedLibraryJVMCIReflection.java @@ -93,6 +93,33 @@ boolean equals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) { return runtime().compilerToVm.equals(x, indirectX.getHandle(), y, indirectY.getHandle()); } + @Override + Boolean valhallaEquals(HotSpotObjectConstantImpl x, HotSpotObjectConstantImpl y) { + if (x == y) { + return true; + } + if (x.compressed != y.compressed) { + return false; + } + if (x instanceof DirectHotSpotObjectConstantImpl && y instanceof DirectHotSpotObjectConstantImpl) { + DirectHotSpotObjectConstantImpl xd = (DirectHotSpotObjectConstantImpl) x; + DirectHotSpotObjectConstantImpl yd = (DirectHotSpotObjectConstantImpl) y; + return (xd.object == yd.object); + } + if (x instanceof DirectHotSpotObjectConstantImpl || y instanceof DirectHotSpotObjectConstantImpl) { + // Mixing of constant types is always inequal + return false; + } + IndirectHotSpotObjectConstantImpl indirectX = (IndirectHotSpotObjectConstantImpl) x; + IndirectHotSpotObjectConstantImpl indirectY = (IndirectHotSpotObjectConstantImpl) y; + boolean result = runtime().compilerToVm.equals(x, indirectX.getHandle(), y, indirectY.getHandle()); + if (!result && indirectX.objectIsInlineType() && indirectY.objectIsInlineType()) { + // reference comparison of oops falsified, doesn't mean that the two inline objects are not equal + return null; + } + return result; + } + @Override ResolvedJavaMethod.Parameter[] getParameters(HotSpotResolvedJavaMethodImpl javaMethod) { // ResolvedJavaMethod.getParameters allows a return value of null From caa844407937bbd8fbb93697c975ebbf112ab6a1 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 29 Apr 2025 22:03:54 +0200 Subject: [PATCH 90/98] Benchmark updates for master thesis. --- .../valhalla/thesis_benchmarks/Equality.java | 11 +-- .../valhalla/thesis_benchmarks/Q32int.java | 45 ++++++++++++ .../valhalla/thesis_benchmarks/Sorting.java | 72 ++++++++++--------- 3 files changed, 92 insertions(+), 36 deletions(-) create mode 100644 test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Q32int.java diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java index 6fff057fa1f..237cd06cab9 100644 --- a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java @@ -18,6 +18,8 @@ import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.annotations.CompilerControl; import org.openjdk.bench.valhalla.types.Q32int; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.Level; import java.util.concurrent.TimeUnit; @@ -42,6 +44,7 @@ public Line(Point p1, Point p2) { } @ImplicitlyConstructible + @LooselyConsistentValue public static value class Point { int x; int y; @@ -55,7 +58,8 @@ public Point(int x, int y) { static final int N = 100; static Line[] lineArray = new Line[N]; - public static void initialize() { + @Setup(Level.Invocation) + public void setUp() { // initialize randomly Random rand = new Random(); for (int i = 0; i < lineArray.length; i++) { @@ -68,7 +72,7 @@ public static void initialize() { public static int findDuplicates() { int count = 0; for (int i = 0; i < lineArray.length; i++) { - for (int j = i + 1; j < lineArray.length; j++) { + for (int j = 0; j < lineArray.length; j++) { if (lineArray[i] == lineArray[j]) { count++; } @@ -79,9 +83,8 @@ public static int findDuplicates() { @Benchmark - @OperationsPerInvocation(100) + @OperationsPerInvocation(1) public void benchmark() { - initialize(); findDuplicates(); } } \ No newline at end of file diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Q32int.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Q32int.java new file mode 100644 index 00000000000..a1b24f1ef8d --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Q32int.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, 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. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import jdk.internal.vm.annotation.*; + +@ImplicitlyConstructible +@LooselyConsistentValue +public value class Q32int{ + + public final int v0; + + public Q32int() { + v0 = 0; + } + + public Q32int(int val) { + this.v0 = val; + } + + public int intValue() { + return v0; + } + +} diff --git a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java index ebca23edfbe..9ea1242f9f4 100644 --- a/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java @@ -3,21 +3,8 @@ import java.util.Random; import jdk.internal.value.ValueClass; -import jdk.internal.vm.annotation.ImplicitlyConstructible; -import jdk.internal.vm.annotation.LooselyConsistentValue; -import jdk.internal.vm.annotation.NullRestricted; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OperationsPerInvocation; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.bench.valhalla.types.Q32int; +import org.openjdk.bench.valhalla.thesis_benchmarks.Q32int; +import org.openjdk.jmh.annotations.*; import java.util.concurrent.TimeUnit; @@ -35,27 +22,26 @@ public class Sorting { public static void initialize() { // initialize randomly - Random rand = new Random(); for (int i = 0; i < array.length; i++) { - array[i] = new Q32int(rand.nextInt()); + array[i] = new Q32int(array.length-1-i); } } @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public static int bubblesort(Q32int[] array) { + public static Q32int[] bubblesort(Q32int[] array) { Q32int temp; -// for (int i = 1; i < array.length; i++) { -// for (int j = 0; j < array.length - i; j++) { - return array[1].intValue(); -// if (array[j].intValue() > array[j + 1].intValue()) { -// temp = array[j]; -// array[j] = array[j + 1]; -// array[j + 1] = temp; -// } -// } -// } - //return array; + for (int i = 1; i < array.length; i++) { + for (int j = 0; j < array.length - i; j++) { + //return array[1].intValue(); + if (array[j].intValue() > array[j + 1].intValue()) { + temp = array[j]; + array[j] = array[j + 1]; + array[j + 1] = temp; + } + } + } + return array; } public static Q32int[] fill() { @@ -134,10 +120,14 @@ public static Q32int[] insertionSort(Q32int[] array) { // //insertionSort(array); // } + @Setup(Level.Invocation) + public void setUp() { + initialize(); + } + @Benchmark - @OperationsPerInvocation(1_000) - @CompilerControl(CompilerControl.Mode.DONT_INLINE) - public void benchmark_sorting() { + @OperationsPerInvocation(1) + public void benchmark_sorting_bubblesort() { //fill(); //initialize(); bubblesort(array); @@ -146,4 +136,22 @@ public void benchmark_sorting() { //initialize(); //insertionSort(array); } + + @Benchmark + @OperationsPerInvocation(1) + public void benchmark_sorting_selectionsort() { + selectionSort(array); + } + + @Benchmark + @OperationsPerInvocation(1) + public void benchmark_sorting_insertionsort() { + insertionSort(array); + } + + @Benchmark + @OperationsPerInvocation(1) + public void benchmark_sorting_fill() { + initialize(); + } } \ No newline at end of file From 74a45229c8790d224f391f8e4e1d0f3cf01b3417 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 27 May 2025 09:09:03 +0200 Subject: [PATCH 91/98] Provide functionality to check for mismatches on the calling convention. --- src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp | 6 +++--- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 11 ++++++++--- .../share/classes/jdk/vm/ci/hotspot/CompilerToVM.java | 11 +++++++++++ .../vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java | 10 ++++++++++ .../classes/jdk/vm/ci/meta/ResolvedJavaMethod.java | 9 +++++++++ 5 files changed, 41 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index d25769b1d8b..999b361dd02 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -164,7 +164,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_virtual_call_stub()); - if (method()->has_scalarized_args()) { + if (method->has_scalarized_args() && !method->mismatch()) { _instructions->relocate(call->instruction_address(), virtual_call_Relocation::spec(_invoke_mark_pc, _oop_recorder->find_index(method())), Assembler::call32_operand); @@ -180,7 +180,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - if (method()->has_scalarized_args()) { + if (method->has_scalarized_args()) { _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand,_oop_recorder->find_index(method())); }else{ @@ -198,7 +198,7 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j // attach the target method only for scalarized args to avoid a null check on the receiver if receiver was optimized from non-scalarized to scalarized // attach only for scalarized args otherwise assert(attached_method->has_scalarized_args(), "invalid use of attached method"); will trigger // see resolved_method_index in machnode.hpp - if (method()->has_scalarized_args()) { + if (method->has_scalarized_args() && !method->mismatch()) { _instructions->relocate(call->instruction_address(), relocInfo::opt_virtual_call_type, Assembler::call32_operand, _oop_recorder->find_index(method())); } else { diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 5fd6b8d723f..b6c8acbf224 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -373,16 +373,15 @@ C2V_END C2V_VMENTRY_0(jbooleanArray, getScalarizedParametersInfo, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), jbooleanArray infoArray, jint len)) Method* method = UNPACK_PAIR(Method, method); JVMCIPrimitiveArray result = JVMCIENV->wrap(infoArray); - bool mismatch = method->mismatch(); for(int i=0; iput_bool_at(result, i, !mismatch && method->is_scalarized_arg(i)); + JVMCIENV->put_bool_at(result, i, method->is_scalarized_arg(i)); } return JVMCIENV->get_jbooleanArray(result); C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedParameters, (JNIEnv* env, jobject, ARGUMENT_PAIR(method))) Method* method = UNPACK_PAIR(Method, method); - return !method->mismatch() && method->has_scalarized_args(); + return method->has_scalarized_args(); C2V_END C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) @@ -393,6 +392,11 @@ C2V_VMENTRY_0(jboolean, hasScalarizedReturn, (JNIEnv* env, jobject, ARGUMENT_PAI return !method->is_native() && inlineKlass->can_be_returned_as_fields(); C2V_END +C2V_VMENTRY_0(jboolean, hasCallingConventionMismatch, (JNIEnv* env, jobject, ARGUMENT_PAIR(method), ARGUMENT_PAIR(klass))) + Method* method = UNPACK_PAIR(Method, method); + return method->mismatch(); +C2V_END + C2V_VMENTRY_0(jboolean, canBePassedAsFields, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass))) Klass* klass = UNPACK_PAIR(Klass, klass); assert(klass->is_inline_klass(), "Klass should be an inline type"); @@ -3339,6 +3343,7 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getScalarizedParametersInfo", CC "(" HS_METHOD2 "[ZI)[Z", FN_PTR(getScalarizedParametersInfo)}, {CC "hasScalarizedParameters", CC "(" HS_METHOD2 ")Z", FN_PTR(hasScalarizedParameters)}, {CC "hasScalarizedReturn", CC "(" HS_METHOD2 HS_KLASS2 ")Z", FN_PTR(hasScalarizedReturn)}, + {CC "hasCallingConventionMismatch", CC "(" HS_METHOD2 ")Z", FN_PTR(hasCallingConventionMismatch)}, {CC "canBePassedAsFields", CC "(" HS_KLASS2 ")Z", FN_PTR(canBePassedAsFields)}, {CC "getExceptionTableStart", CC "(" HS_METHOD2 ")J", FN_PTR(getExceptionTableStart)}, {CC "getExceptionTableLength", CC "(" HS_METHOD2 ")I", FN_PTR(getExceptionTableLength)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 2c5fad41964..d614fe4b716 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -150,6 +150,17 @@ boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method) { private native boolean hasScalarizedParameters(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** + * Determines if the scalarized calling convention of the {@code method} does not match that of a subclass. + * + * @return true if there is a mismatch + */ + boolean hasCallingConventionMismatch(HotSpotResolvedJavaMethodImpl method) { + return hasCallingConventionMismatch(method, method.getMethodPointer()); + } + + private native boolean hasCallingConventionMismatch(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** * Determines if the return value of the {@code method} is scalarized. * diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 790193a582a..dbc033f9b09 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -834,6 +834,16 @@ public boolean hasScalarizedReceiver() { return result; } + private TriState hasCallingConventionMismatch = TriState.UNKNOWN; + + @Override + public boolean hasCallingConventionMismatch() { + if (hasCallingConventionMismatch.isKnown()) return hasCallingConventionMismatch.toBoolean(); + boolean result = compilerToVM().hasCallingConventionMismatch(this); + hasCallingConventionMismatch = TriState.get(result); + return result; + } + @Override // see TypeTuple::make_range in opto/type.cpp diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index ca1e2b491f0..f9a52f30108 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -563,6 +563,15 @@ default boolean hasScalarizedReceiver() { return false; } + /** + * Finds out if the scalarized calling convention of a method does not match that of a subclass. + * See CompiledEntrySignature::compute_calling_conventions which detects these mismatches. + * + * @return true if there is a mismatch + */ + default boolean hasCallingConventionMismatch() { + return false; + } /** * Gets the type information of the method's scalarized return. From 30acc74e740cbcc9cc8aae5e3dbbdccbea8c2c82 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 28 May 2025 09:29:38 +0200 Subject: [PATCH 92/98] Replace raw arrays with List in JVMCI. Refactored JVMCI of calling and return convention. --- .../classes/jdk/vm/ci/code/CodeUtil.java | 5 +- .../jdk/vm/ci/code/RegisterConfig.java | 4 +- .../HotSpotResolvedJavaMethodImpl.java | 101 ++++++++---------- .../amd64/AMD64HotSpotRegisterConfig.java | 18 ++-- .../jdk/vm/ci/meta/ResolvedJavaMethod.java | 77 +++---------- 5 files changed, 78 insertions(+), 127 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java index 1caf3d69fbd..51509b37862 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/CodeUtil.java @@ -25,6 +25,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.List; import java.util.Map; import jdk.vm.ci.meta.JavaType; @@ -446,10 +447,10 @@ public static CallingConvention getCallingConvention(CodeCacheProvider codeCache public static CallingConvention getValhallaCallingConvention(CodeCacheProvider codeCache, CallingConvention.Type type, ResolvedJavaMethod method, ValueKindFactory valueKindFactory, boolean scalarizeReceiver) { if (!method.hasScalarizedParameters()) return getCallingConvention(codeCache, type, method, valueKindFactory); Signature sig = method.getSignature(); - JavaType[] argTypes = method.getScalarizedParameters(scalarizeReceiver); + List argTypes = method.getScalarizedParameters(scalarizeReceiver); JavaType retType = sig.getReturnType(null); RegisterConfig registerConfig = codeCache.getRegisterConfig(); - return registerConfig.getCallingConvention(type, retType, argTypes, valueKindFactory); + return registerConfig.getCallingConvention(type, retType, argTypes.toArray(new JavaType[argTypes.size()]), valueKindFactory); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java index d7e666b03a2..c3cb2d20ea2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/code/RegisterConfig.java @@ -25,6 +25,8 @@ import jdk.vm.ci.code.CallingConvention.Type; import jdk.vm.ci.meta.*; +import java.util.List; + /** * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical * registers. @@ -76,7 +78,7 @@ default int getMaximumFrameSize() { * @param valueKindFactory the factory to create custom {@link ValueKind ValueKinds} * @param includeFirstGeneralRegister determines if the first general register, which will contain the oop or tagged hub, should be skipped */ - default AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { + default List getReturnConvention(List returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); } /** diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index dbc033f9b09..6debc45ace1 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java @@ -780,8 +780,8 @@ public BitSet getOopMapAt(int bci) { private boolean[] scalarizedParametersInfo; @Override - // see ciMethod::is_scalarized_arg public boolean isScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + // see ciMethod::is_scalarized_arg if (scalarizedParametersInfo == null) { scalarizedParametersInfo = compilerToVM().getScalarizedParametersInfo(this); } @@ -801,8 +801,8 @@ public boolean isParameterNullFree(int index, boolean indexIncludesReceiverIfExi private TriState hasScalarizedParameters = TriState.UNKNOWN; @Override - // see ciMethod::has_scalarized_args public boolean hasScalarizedParameters() { + // see ciMethod::has_scalarized_args if (hasScalarizedParameters.isKnown()) return hasScalarizedParameters.toBoolean(); boolean result = compilerToVM().hasScalarizedParameters(this); hasScalarizedParameters = TriState.get(result); @@ -844,31 +844,31 @@ public boolean hasCallingConventionMismatch() { return result; } - @Override - // see TypeTuple::make_range in opto/type.cpp - public JavaType[] getScalarizedReturn() { + public List getScalarizedReturn() { assert hasScalarizedReturn() : "Scalarized return presumed"; - HotSpotResolvedObjectType returnType = getReturnedInlineType(); - ResolvedJavaField[] fields = returnType.getInstanceFields(true); + JavaType type = signature.getReturnType(getDeclaringClass()); + assert type instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + ResolvedJavaField[] fields = resolvedType.getInstanceFields(true); // one extra field for oop or hub - JavaType[] types = new JavaType[fields.length + 1]; - types[0] = returnType; - for (int i = 1; i < types.length; i++) { - types[i] = fields[i - 1].getType(); + int length = fields.length + 1; + List types = new ArrayList<>(length); + types.add(resolvedType); + for (int i = 1; i < length; i++) { + types.add(fields[i - 1].getType()); } - return types; + return List.copyOf(types); } - private boolean returnsInlineType() { JavaType returnType = signature.getReturnType(getDeclaringClass()); // check if the method returns an object + // the type is not expected to be resolved if (returnType instanceof HotSpotResolvedObjectType type) { // check if the returned value is an inline type - // TODO: is correct otherwise just use return true? return !type.isInterface() && !type.isAbstract() && !type.isIdentity(); } return false; @@ -880,69 +880,65 @@ private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { @Override - public JavaType[] getScalarizedParameterNullFree(int index) { - return getScalarizedParameter(index, false, true); + public List getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + return getScalarizedParameter(index, indexIncludesReceiverIfExists, true); } @Override - public JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + public List getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { return getScalarizedParameter(index, indexIncludesReceiverIfExists, isParameterNullFree(index, indexIncludesReceiverIfExists)); } - private JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists, boolean nullFree) { + private List getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists, boolean nullFree) { assert isScalarizedParameter(index, indexIncludesReceiverIfExists) : "Scalarized parameter presumed"; boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); int previousIndex = index; if (includeReceiver) { if (index == 0) { - return getScalarizedReceiver(); + assert nullFree : "receiver should be null-free"; + return getFields(getDeclaringClass(), true, null); } else { index--; } } JavaType type = signature.getParameterType(index, getDeclaringClass()); - ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); - assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - return getFieldsArray((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, getScalarizedParameterNonNullType(previousIndex, indexIncludesReceiverIfExists)); + assert type instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + return getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterNonNullType(previousIndex, indexIncludesReceiverIfExists)); } @Override - public ResolvedJavaField[] getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + public List getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + assert isScalarizedParameter(index, indexIncludesReceiverIfExists) : "Scalarized parameter presumed"; boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); if (includeReceiver) { if (index == 0) { - return getDeclaringClass().getInstanceFields(true); + return List.of(getDeclaringClass().getInstanceFields(true)); } else { index--; } } - return getSignature().getParameterType(index, getDeclaringClass()).resolve(getDeclaringClass()).getInstanceFields(true); + JavaType type = signature.getParameterType(index, getDeclaringClass()); + assert type instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + return List.of(resolvedType.getInstanceFields(true)); } @Override public JavaType getScalarizedParameterNonNullType(int index, boolean indexIncludesReceiverIfExists) { assert isScalarizedParameter(index, indexIncludesReceiverIfExists) /*&& !isParameterNullFree(index, indexIncludesReceiverIfExists)*/ : "Scalarized nullable parameter presumed"; - return HotSpotResolvedPrimitiveType.forKind(IS_NOT_NULL_KIND); + return HotSpotResolvedPrimitiveType.forKind(NON_NULL_KIND); } - private static final JavaKind IS_NOT_NULL_KIND = JavaKind.Byte; - + private static final JavaKind NON_NULL_KIND = JavaKind.Byte; - @Override - public JavaType[] getScalarizedReceiver() { - assert hasScalarizedReceiver() : "Scalarized receiver presumed"; - return getFieldsArray(getDeclaringClass(), true, null); - } @Override - /* - * - * see TypeTuple::make_domain in opto/type.cpp - */ - public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { + public List getScalarizedParameters(boolean scalarizeReceiver) { + // see TypeTuple::make_domain in opto/type.cpp assert hasScalarizedParameters() : "Any scalarized parameters presumed"; - ArrayList types = new ArrayList<>(); + List types = new ArrayList<>(); if (hasScalarizedReceiver() && scalarizeReceiver) { types.addAll(getFields(getDeclaringClass(), true, null)); } else if (!isStatic()) { @@ -951,32 +947,29 @@ public JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { for (int i = 0; i < signature.getParameterCount(false); i++) { JavaType type = signature.getParameterType(i, getDeclaringClass()); - if (isScalarizedParameter(i)) { - ResolvedJavaType resolvedType = type.resolve(getDeclaringClass()); - assert resolvedType instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; - boolean nullFree = isParameterNullFree(i); - types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterNonNullType(i))); + if (isScalarizedParameter(i, false)) { + assert type instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + boolean nullFree = isParameterNullFree(i, false); + types.addAll(getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterNonNullType(i, false))); } else { types.add(type); } } - return types.toArray(new JavaType[types.size()]); + return List.copyOf(types); } - private ArrayList getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { + private List getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { ResolvedJavaField[] fields = holder.getInstanceFields(true); - ArrayList types = new ArrayList<>(fields.length + (!nullFree ? 1 : 0)); - if (!nullFree) types.add(nonNullType); + List types = new ArrayList<>(fields.length + (!nullFree ? 1 : 0)); + if (!nullFree) { + types.add(nonNullType); + } for (int i = 0; i < fields.length; i++) { types.add(fields[i].getType()); } - return types; - } - - private JavaType[] getFieldsArray(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { - ArrayList list = getFields(holder, nullFree, nonNullType); - return list.toArray(new JavaType[list.size()]); + return List.copyOf(types); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java index 43e647c94b7..4288d4c5774 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotRegisterConfig.java @@ -205,10 +205,10 @@ public CallingConvention getCallingConvention(Type type, JavaType returnType, Ja } @Override - public AllocatableValue[] getReturnConvention(JavaType[] returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { - JavaKind[] kinds = new JavaKind[returnTypes.length]; - for (int i = 0; i < returnTypes.length; i++) { - kinds[i] = returnTypes[i].getJavaKind().getStackKind(); + public List getReturnConvention(List returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { + JavaKind[] kinds = new JavaKind[returnTypes.size()]; + for (int i = 0; i < returnTypes.size(); i++) { + kinds[i] = returnTypes.get(i).getJavaKind().getStackKind(); } return getReturnLocations(getReturnRegisters(kinds, includeFirstGeneralRegister), returnTypes, valueKindFactory); } @@ -361,13 +361,13 @@ public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeFirstGener return registers; } - public AllocatableValue[] getReturnLocations(Register[] registers, JavaType[] returnTypes, ValueKindFactory valueKindFactory) { - AllocatableValue[] locations = new AllocatableValue[returnTypes.length]; + public List getReturnLocations(Register[] registers, List returnTypes, ValueKindFactory valueKindFactory) { + List locations = new ArrayList<>(returnTypes.size()); for (int i = 0; i < registers.length; i++) { - final JavaKind kind = returnTypes[i].getJavaKind().getStackKind(); - locations[i] = registers[i].asValue(valueKindFactory.getValueKind(kind)); + final JavaKind kind = returnTypes.get(i).getJavaKind().getStackKind(); + locations.add(registers[i].asValue(valueKindFactory.getValueKind(kind))); } - return locations; + return List.copyOf(locations); } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java index f9a52f30108..726ddb0d1f2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaMethod.java @@ -29,6 +29,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; +import java.util.List; /** * Represents a resolved Java method. Methods, like fields and types, are resolved through @@ -481,18 +482,10 @@ default boolean isScoped() { */ SpeculationLog getSpeculationLog(); - /** - * Same as {@link #isScalarizedParameter(int, boolean)} but implicitly excluding the receiver from the index. - * - * @param index the index of a formal parameter in the signature excluding the receiver if it exists - * @return true if the parameter is scalarized, false otherwise - */ - default boolean isScalarizedParameter(int index) { - return isScalarizedParameter(index, false); - } - /** * Gets the information if a parameter at a certain position in the method signature is scalarized. + * Inline type arguments may not be passed by reference, but in scalarized form. + * We get an argument per field of the inline type. * * @param index the index of a formal parameter in the signature * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise @@ -510,21 +503,13 @@ default boolean isScalarizedParameter(int index, boolean indexIncludesReceiverIf default int getScalarizedParametersCount() { int count = 0; for (int i = 0; i < getSignature().getParameterCount(!isStatic()); i++) { - if (isScalarizedParameter(i, true)) count++; + if (isScalarizedParameter(i, true)) { + count++; + } } return count; } - /** - * Same as {@link #isParameterNullFree(int, boolean)} but implicitly excluding the receiver from the index. - * - * @param index the index of a formal parameter in the signature excluding the receiver if it exists - * @return true if the parameter is null free, false otherwise - */ - default boolean isParameterNullFree(int index) { - return isParameterNullFree(index, false); - } - /** * Gets the information if a parameter at a certain position in the method signature is non free. * @@ -576,9 +561,9 @@ default boolean hasCallingConventionMismatch() { /** * Gets the type information of the method's scalarized return. * - * @return the scalarized return type which consists of the oopOrHub type as well as the instance fields of the return type + * @return the scalarized return type which consists of the return type as well as the instance fields of the return type */ - default JavaType[] getScalarizedReturn() { + default List getScalarizedReturn() { throw new UnsupportedOperationException("scalarized return not yet implemented"); } @@ -588,38 +573,18 @@ default JavaType[] getScalarizedReturn() { * @param scalarizeReceiver true if the receiver should be scalarized as well, false otherwise * @return the types representing the scalarized method signature */ - default JavaType[] getScalarizedParameters(boolean scalarizeReceiver) { + default List getScalarizedParameters(boolean scalarizeReceiver) { throw new UnsupportedOperationException("scalarized parameters not yet implemented"); } - /** - * Same as {@link #getScalarizedParameter(int)} but implicitly excluding the receiver from the index. - * - * @param index the index of a formal parameter in the signature - * @return the instance fields as types including the is not null type - */ - default JavaType[] getScalarizedParameter(int index) { - return getScalarizedParameter(index, false); - } - - /** - * Same as {@link #getScalarizedParameterNullFree(int)} but implicitly excluding the receiver from the index. - * - * @param index the index of a formal parameter in the signature - * @return the instance fields as types - */ - default JavaType[] getScalarizedParameterNullFree(int index) { - return getScalarizedParameterNullFree(index, false); - } - /** * Similar to as {@link #getScalarizedParameterNullFree(int, boolean)} but also includes the is not null type if the parameter is not null free. * - * @param index the index of a formal parameter in the signature + * @param index the index of a formal parameter in the signature * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise * @return the instance fields as types including the is not null type */ - default JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + default List getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { throw new UnsupportedOperationException("scalarized parameter not yet implemented"); } @@ -630,7 +595,7 @@ default JavaType[] getScalarizedParameter(int index, boolean indexIncludesReceiv * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise * @return the instance fields as types */ - default JavaType[] getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + default List getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { throw new UnsupportedOperationException("scalarized parameter not yet implemented"); } @@ -641,21 +606,10 @@ default JavaType[] getScalarizedParameterNullFree(int index, boolean indexInclud * @param indexIncludesReceiverIfExists true if the receiver is included in the {@code index}, false otherwise * @return the instance fields of a scalarized parameter */ - default ResolvedJavaField[] getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + default List getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { throw new UnsupportedOperationException("getParameterFields is not supported"); } - - /** - * Same as {@link #getScalarizedParameterNonNullType(int)} but implicitly excluding the receiver from the index. - * - * @param index the index of a formal parameter in the signature - * @return the type representing the is not null information - */ - default JavaType getScalarizedParameterNonNullType(int index) { - return getScalarizedParameterNonNullType(index, false); - } - /** * Gets the type used for a scalarized parameter to represent its is not null information. * @@ -672,7 +626,8 @@ default JavaType getScalarizedParameterNonNullType(int index, boolean indexInclu * * @return the scalarized receiver which consists of its instance fields. */ - default JavaType[] getScalarizedReceiver() { - throw new UnsupportedOperationException("getScalarizedReceiver is not yet implemented"); + default List getScalarizedReceiver() { + assert hasScalarizedReceiver() : "Scalarized receiver presumed"; + return getScalarizedParameter(0, true); } } From a39472ec3a6606914de40269796fbbd11a497a38 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Wed, 28 May 2025 10:58:28 +0200 Subject: [PATCH 93/98] Renamed firstFieldOffset to payloadOffset. --- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java | 3 +-- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 6 +++--- .../share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java | 2 +- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index cd8c439d390..d6c1a943cb3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -122,8 +122,7 @@ default boolean isFlatArray(){ int superCheckOffset(); - // TODO: rename to payloadOffset - default int firstFieldOffset(){ + default int payloadOffset() { return -1; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 2f91b176526..303884336ed 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -959,7 +959,7 @@ private HotSpotResolvedJavaField[] getFlattenedFields(HotSpotResolvedJavaField[] // compute all flattened fields recursively for (int i = 0; i < innerFields.length; ++i) { // holder has no header so remove the header offset - int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.firstFieldOffset()); + int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.payloadOffset()); HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset).setOuterDeclaringClass((HotSpotResolvedObjectType) resolvedJavaField.getDeclaringClass())); } @@ -1140,10 +1140,10 @@ public int superCheckOffset() { } @Override - public int firstFieldOffset() { + public int payloadOffset() { HotSpotVMConfig config = config(); long fixedBlockPointer = UNSAFE.getAddress(getKlassPointer() + config.inlineKlassFixedBlockAdr); - return UNSAFE.getInt(fixedBlockPointer + config.firstFieldOffset); + return UNSAFE.getInt(fixedBlockPointer + config.payloadOffset); } @Override diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 01b5a15ba9d..70af7b92743 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -78,7 +78,7 @@ static String getHostArchitectureName() { final int nextSiblingOffset = getFieldOffset("Klass::_next_sibling", Integer.class, "Klass*"); final int superCheckOffsetOffset = getFieldOffset("Klass::_super_check_offset", Integer.class, "juint"); final int secondarySuperCacheOffset = getFieldOffset("Klass::_secondary_super_cache", Integer.class, "Klass*"); - final int firstFieldOffset = getFieldOffset("InlineKlassFixedBlock::_payload_offset", Integer.class, "int"); + final int payloadOffset = getFieldOffset("InlineKlassFixedBlock::_payload_offset", Integer.class, "int"); final int nullMarkerOffset = getFieldOffset("FieldInfo::_null_marker_offset", Integer.class, "u4"); final int inlineKlassFixedBlockAdr = getFieldOffset("InstanceKlass::_adr_inlineklass_fixed_block", Integer.class, "InlineKlassFixedBlock const *"); From d987be76c8da575418e161ba53570b474dcedfcc Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Mon, 2 Jun 2025 08:27:33 +0200 Subject: [PATCH 94/98] Renamed outerDeclaringClass to containerClass. --- .../jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java | 2 +- .../jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 6 +++--- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 2 +- .../share/classes/jdk/vm/ci/meta/ResolvedJavaField.java | 8 ++++++-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java index f3e8bde473e..52703a79aa0 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstantImpl.java @@ -210,7 +210,7 @@ public JavaConstant readFieldValue(HotSpotResolvedJavaField field) { if (field.isStatic()) { return null; } - HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getOuterDeclaringClass(); + HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getContainerClass(); char typeChar = field.getType().getJavaKind().getTypeChar(); return runtime().compilerToVm.readFieldValue(this, declaringClass, field.getOffset(), typeChar, declaringClass != field.getDeclaringClass()); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 435102bf6ba..d2584d24c54 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -86,7 +86,7 @@ public boolean equals(Object obj) { HotSpotResolvedJavaFieldImpl that = (HotSpotResolvedJavaFieldImpl) obj; if (that.offset != this.offset || that.isStatic() != this.isStatic()) { return false; - } else if (this.holder.equals(that.holder) && this.getOuterDeclaringClass().equals(that.getOuterDeclaringClass())) { + } else if (this.holder.equals(that.holder) && this.getContainerClass().equals(that.getContainerClass())) { return true; } } @@ -175,7 +175,7 @@ public HotSpotResolvedObjectTypeImpl getDeclaringClass() { } @Override - public HotSpotResolvedObjectTypeImpl getOuterDeclaringClass() { + public HotSpotResolvedObjectTypeImpl getContainerClass() { if (outerHolder == null) { return holder; } @@ -183,7 +183,7 @@ public HotSpotResolvedObjectTypeImpl getOuterDeclaringClass() { } @Override - public ResolvedJavaField setOuterDeclaringClass(HotSpotResolvedObjectType outerHolder) { + public ResolvedJavaField setContainerClass(HotSpotResolvedObjectType outerHolder) { HotSpotResolvedJavaFieldImpl field = new HotSpotResolvedJavaFieldImpl(holder, type, offset, classfileFlags, internalFlags, index); field.outerHolder = (HotSpotResolvedObjectTypeImpl) outerHolder; return field; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index 303884336ed..f5bc40648f3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -961,7 +961,7 @@ private HotSpotResolvedJavaField[] getFlattenedFields(HotSpotResolvedJavaField[] // holder has no header so remove the header offset int offset = fieldOffset + (innerFields[i].getOffset() - resolvedFieldType.payloadOffset()); HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; - resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset).setOuterDeclaringClass((HotSpotResolvedObjectType) resolvedJavaField.getDeclaringClass())); + resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset).setContainerClass((HotSpotResolvedObjectType) resolvedJavaField.getDeclaringClass())); } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index b0d1db789df..5efa11f583e 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -116,11 +116,15 @@ default int getNullMarkerOffset() { @Override ResolvedJavaType getDeclaringClass(); - default ResolvedJavaType getOuterDeclaringClass() { + /** + * Returns the {@link ResolvedJavaType} object that represents the class in which an inline object (to which the field belongs) is embedded. + * This differs to {@link #getDeclaringClass} if the inline object is flattened. + */ + default ResolvedJavaType getContainerClass() { throw new UnsupportedOperationException(); } - default ResolvedJavaField setOuterDeclaringClass(HotSpotResolvedObjectType outerHolder) { + default ResolvedJavaField setContainerClass(HotSpotResolvedObjectType outerHolder) { throw new UnsupportedOperationException(); } From b9c697b2e21bfca832790a19ee74aa5f542d2b28 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 3 Jun 2025 08:22:06 +0200 Subject: [PATCH 95/98] Refactored JVMCI changes. --- .../jdk/vm/ci/hotspot/HotSpotProfilingInfo.java | 2 +- .../vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java | 11 +++++------ .../jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java | 3 +++ .../classes/jdk/vm/ci/meta/DefaultProfilingInfo.java | 4 +--- .../share/classes/jdk/vm/ci/meta/ProfilingInfo.java | 7 ++++--- .../classes/jdk/vm/ci/meta/ResolvedJavaField.java | 2 +- .../classes/jdk/vm/ci/meta/ResolvedJavaType.java | 12 ++++++++++++ 7 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index dca9e4d4e67..6507b36dd1d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java @@ -125,7 +125,7 @@ public TriState getExceptionSeen(int bci) { } @Override - public ACmpDataAccessor getACmpData(int bci) { + public Object getACmpData(int bci) { if (!isMature) { return null; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index d2584d24c54..24e87aa6e3c 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java @@ -26,7 +26,6 @@ import jdk.vm.ci.meta.*; import java.lang.annotation.Annotation; -import java.lang.reflect.Field; import java.util.Collections; import java.util.List; @@ -43,7 +42,7 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { private final HotSpotResolvedObjectTypeImpl holder; - private HotSpotResolvedObjectTypeImpl outerHolder; + private HotSpotResolvedObjectTypeImpl containerClass; private JavaType type; @@ -176,16 +175,16 @@ public HotSpotResolvedObjectTypeImpl getDeclaringClass() { @Override public HotSpotResolvedObjectTypeImpl getContainerClass() { - if (outerHolder == null) { + if (containerClass == null) { return holder; } - return outerHolder; + return containerClass; } @Override - public ResolvedJavaField setContainerClass(HotSpotResolvedObjectType outerHolder) { + public ResolvedJavaField setContainerClass(ResolvedJavaType containerClass) { HotSpotResolvedJavaFieldImpl field = new HotSpotResolvedJavaFieldImpl(holder, type, offset, classfileFlags, internalFlags, index); - field.outerHolder = (HotSpotResolvedObjectTypeImpl) outerHolder; + field.containerClass = (HotSpotResolvedObjectTypeImpl) containerClass; return field; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java index d6c1a943cb3..24695a33460 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectType.java @@ -44,10 +44,12 @@ default HotSpotResolvedObjectType getFlatArrayClass(){ return null; } + @Override default HotSpotResolvedObjectType convertToFlatArray(){ return null; } + @Override default JavaConstant getDefaultInlineTypeInstance(){ return null; } @@ -95,6 +97,7 @@ default int getLog2ComponentSize(){ return -1; } + @Override default boolean isFlatArray(){ return false; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java index 72fcc122d55..c254748b368 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/DefaultProfilingInfo.java @@ -22,8 +22,6 @@ */ package jdk.vm.ci.meta; -import jdk.vm.ci.hotspot.ACmpDataAccessor; - /** * An implementation of {@link ProfilingInfo} that can used in the absence of real profile * information. @@ -70,7 +68,7 @@ public TriState getExceptionSeen(int bci) { } @Override - public ACmpDataAccessor getACmpData(int bci) { + public Object getACmpData(int bci) { return null; } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java index 008eec15d19..35f50628d52 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ProfilingInfo.java @@ -83,7 +83,7 @@ public interface ProfilingInfo { * * @return Returns a AcmpData object, or null if not available. */ - default ACmpDataAccessor getACmpData(int bci) { + default Object getACmpData(int bci) { return null; } @@ -183,11 +183,12 @@ default String toString(ResolvedJavaMethod method, String sep) { buf.append(String.format("nullSeen@%d: %s%s", i, getNullSeen(i).name(), sep)); } + ACmpDataAccessor aCmpData = (ACmpDataAccessor) getACmpData(i); if (getACmpData(i) != null) { - SingleTypeEntry left = getACmpData(i).getLeft(); + SingleTypeEntry left = aCmpData.getLeft(); String formatString = "ACmpType@%d: %s alwaysNull:%b inlineType:%b%s"; buf.append(String.format(formatString, i, left.getValidType(), left.alwaysNull(), left.inlineType(), sep)); - SingleTypeEntry right = getACmpData(i).getRight(); + SingleTypeEntry right = aCmpData.getRight(); buf.append(String.format(formatString, i, right.getValidType(), right.alwaysNull(), right.inlineType(), sep)); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java index 5efa11f583e..909ec248d07 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaField.java @@ -124,7 +124,7 @@ default ResolvedJavaType getContainerClass() { throw new UnsupportedOperationException(); } - default ResolvedJavaField setContainerClass(HotSpotResolvedObjectType outerHolder) { + default ResolvedJavaField setContainerClass(ResolvedJavaType containerClass) { throw new UnsupportedOperationException(); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java index da6c4887581..922c673d618 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/ResolvedJavaType.java @@ -244,6 +244,18 @@ default ResolvedJavaType getFlatArrayClass() { throw new UnsupportedOperationException(); } + default ResolvedJavaType convertToFlatArray() { + throw new UnsupportedOperationException(); + } + + default boolean isFlatArray() { + return false; + } + + default JavaConstant getDefaultInlineTypeInstance() { + throw new UnsupportedOperationException(); + } + /** * Resolves the method implementation for virtual dispatches on objects of this dynamic type. * This resolution process only searches "up" the class hierarchy of this type. A broader search From 3823b2a4a8bd96e3104cc0518a4076a937a80fcf Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Thu, 26 Jun 2025 15:22:51 +0200 Subject: [PATCH 96/98] Provide access to the ValueObjectMethods class over JVMCI. --- .../cpu/x86/jvmciCodeInstaller_x86.cpp | 3 ++- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 16 ++++++++++++++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 4 ++++ .../ci/hotspot/HotSpotMetaAccessProvider.java | 22 +++++++++++++++++++ .../jdk/vm/ci/meta/MetaAccessProvider.java | 8 +++++++ 5 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp index 999b361dd02..e90a8f68d1d 100644 --- a/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp +++ b/src/hotspot/cpu/x86/jvmciCodeInstaller_x86.cpp @@ -180,7 +180,8 @@ void CodeInstaller::pd_relocate_JavaMethod(CodeBuffer &, methodHandle& method, j call = nativeCall_at(_instructions->start() + pc_offset); call->set_destination(SharedRuntime::get_resolve_static_call_stub()); - if (method->has_scalarized_args()) { + // calls to the ValueObjectMethods class do not exist in bytecode, need to attach them + if (method->has_scalarized_args() || method() == Universe::is_substitutable_method() || method() == Universe::value_object_hash_code_method()) { _instructions->relocate(call->instruction_address(), relocInfo::static_call_type, Assembler::call32_operand,_oop_recorder->find_index(method())); }else{ diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index b6c8acbf224..31bfec33b19 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -463,6 +463,20 @@ C2V_VMENTRY_NULL(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject return JVMCIENV->get_jobject(result); } +C2V_VMENTRY_NULL(jobject, getIsSubstitutableMethod, (JNIEnv* env)) + // class will be initialized in SharedRuntime::find_callee_info_helper if necessary + methodHandle method(THREAD, Universe::is_substitutable_method()); + JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL); + return JVMCIENV->get_jobject(result); +} + +C2V_VMENTRY_NULL(jobject, getValueObjectHashCodeMethod, (JNIEnv* env)) + // TODO: do we need to initialize here? + methodHandle method(THREAD, Universe::value_object_hash_code_method()); + JVMCIObject result = JVMCIENV->get_jvmci_method(method, JVMCI_CHECK_NULL); + return JVMCIENV->get_jobject(result); +} + C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass_or_method), jboolean is_klass)) ConstantPool* cp = nullptr; if (UNPACK_PAIR(address, klass_or_method) == nullptr) { @@ -3388,6 +3402,8 @@ JNINativeMethod CompilerToVM::methods[] = { {CC "getMaxCallTargetOffset", CC "(J)J", FN_PTR(getMaxCallTargetOffset)}, {CC "asResolvedJavaMethod", CC "(" EXECUTABLE ")" HS_METHOD, FN_PTR(asResolvedJavaMethod)}, {CC "getResolvedJavaMethod", CC "(" OBJECTCONSTANT "J)" HS_METHOD, FN_PTR(getResolvedJavaMethod)}, + {CC "getIsSubstitutableMethod", CC "()" HS_METHOD, FN_PTR(getIsSubstitutableMethod)}, + {CC "getValueObjectHashCodeMethod", CC "()" HS_METHOD, FN_PTR(getValueObjectHashCodeMethod)}, {CC "getConstantPool", CC "(" OBJECT "JZ)" HS_CONSTANT_POOL, FN_PTR(getConstantPool)}, {CC "getResolvedJavaType0", CC "(Ljava/lang/Object;JZ)" HS_KLASS, FN_PTR(getResolvedJavaType0)}, {CC "readConfiguration", CC "()[" OBJECT, FN_PTR(readConfiguration)}, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index d614fe4b716..f7fae8c5595 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1019,6 +1019,10 @@ int getVtableIndexForInterfaceMethod(HotSpotResolvedObjectTypeImpl type, HotSpot */ native HotSpotResolvedJavaMethodImpl getResolvedJavaMethod(HotSpotObjectConstantImpl base, long displacement); + native HotSpotResolvedJavaMethodImpl getIsSubstitutableMethod(); + + native HotSpotResolvedJavaMethodImpl getValueObjectHashCodeMethod(); + /** * Gets the {@code ConstantPool*} associated with {@code object} and returns a * {@link HotSpotConstantPool} wrapping it. diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 5dfc75e9f57..ee816319437 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -81,6 +81,28 @@ public ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod) { return runtime.getCompilerToVM().asResolvedJavaMethod(Objects.requireNonNull(reflectionMethod)); } + private ResolvedJavaMethod isSubstitutableMethod; + + @Override + public ResolvedJavaMethod getIsSubstitutableMethod() { + if (isSubstitutableMethod != null) { + return isSubstitutableMethod; + } + isSubstitutableMethod = runtime.getCompilerToVM().getIsSubstitutableMethod(); + return isSubstitutableMethod; + } + + private ResolvedJavaMethod valueObjectHashCodeMethod; + + @Override + public ResolvedJavaMethod getValueObjectHashCodeMethod() { + if (valueObjectHashCodeMethod != null) { + return valueObjectHashCodeMethod; + } + valueObjectHashCodeMethod = runtime.getCompilerToVM().getValueObjectHashCodeMethod(); + return valueObjectHashCodeMethod; + } + @Override public ResolvedJavaField lookupJavaField(Field reflectionField) { Class fieldHolder = reflectionField.getDeclaringClass(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java index 33db3705afa..00543c212e2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/meta/MetaAccessProvider.java @@ -62,6 +62,14 @@ default ResolvedJavaType[] lookupJavaTypes(Class[] classes) { */ ResolvedJavaMethod lookupJavaMethod(Executable reflectionMethod); + default ResolvedJavaMethod getIsSubstitutableMethod() { + return null; + } + + default ResolvedJavaMethod getValueObjectHashCodeMethod() { + return null; + } + /** * Provides the {@link ResolvedJavaField} for a {@link Field} obtained via reflection. */ From 1728fe5ce18e60a6e6e55364bd2a60539b779954 Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 1 Jul 2025 11:39:24 +0200 Subject: [PATCH 97/98] Changed absolute to relative path. --- make/test/BuildMicrobenchmark.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index ddab7e0f44a..66a393f6329 100644 --- a/make/test/BuildMicrobenchmark.gmk +++ b/make/test/BuildMicrobenchmark.gmk @@ -101,7 +101,7 @@ $(eval $(call SetupJavaCompilation, BUILD_JDK_MICROBENCHMARK, \ --add-exports java.base/sun.security.util.math.intpoly=ALL-UNNAMED \ --add-exports java.base/jdk.internal.vm.annotation=ALL-UNNAMED \ --enable-preview \ - --patch-module java.base=/home/michael/work/git/oracle/valhalla/build/linux-x86_64-server-release/images/jdk/lib/valueclasses/java.base-valueclasses.jar \ + --patch-module java.base=$(JAVA_HOME)/lib/valueclasses/java.base-valueclasses.jar \ --add-exports java.base/jdk.internal.value=ALL-UNNAMED \ -XDsuppressNotes \ -processor org.openjdk.jmh.generators.BenchmarkProcessor \ From 4bf3091eb5ad53f9d1fb7e09b0c3098d8bd2155f Mon Sep 17 00:00:00 2001 From: MichaelHaas99 Date: Tue, 1 Jul 2025 11:52:22 +0200 Subject: [PATCH 98/98] Fixed trailing whitespace. --- src/hotspot/share/jvmci/jvmciCodeInstaller.cpp | 2 +- .../jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 338f51f26c0..cbdc3f55686 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -780,7 +780,7 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, if (_nmethod_entry_patch_offset == -1) { JVMCI_THROW_MSG_(IllegalArgumentException, "nmethod entry barrier is missing", JVMCI::ok); } - + if(_offsets.value(CodeOffsets::Verified_Inline_Entry) == -1) { _offsets.set_value(CodeOffsets::Verified_Inline_Entry, _offsets.value(CodeOffsets::Verified_Entry)); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java index f5bc40648f3..fc47cf5c8a4 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl.java @@ -1287,5 +1287,4 @@ private List getAnnotationData0(ResolvedJavaType... filter) { byte[] encoded = compilerToVM().getEncodedClassAnnotationData(this, filter); return VMSupport.decodeAnnotations(encoded, AnnotationDataDecoder.INSTANCE); } - }