diff --git a/make/test/BuildMicrobenchmark.gmk b/make/test/BuildMicrobenchmark.gmk index 757ac593dfd..66a393f6329 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=$(JAVA_HOME)/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, \ )) 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 9e6a4789dc2..e90a8f68d1d 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() && !method->mismatch()) { _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,33 @@ 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(), + // 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{ + _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 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() && !method->mismatch()) { + _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: 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); 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; diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 0811a71c5c1..b1cdc2cfb0b 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -1769,7 +1769,7 @@ void LinkResolver::resolve_invokevirtual(CallInfo& result, Handle recv, 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, true, 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 f7463aa6d03..2d3f8832592 100644 --- a/src/hotspot/share/interpreter/linkResolver.hpp +++ b/src/hotspot/share/interpreter/linkResolver.hpp @@ -357,7 +357,7 @@ 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); // Only resolved method known. static void throw_abstract_method_error(const methodHandle& resolved_method, TRAPS) { diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 24515d3ff9b..cbdc3f55686 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 @@ -778,6 +781,14 @@ JVMCI::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, 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 result = runtime()->register_method(jvmci_env(), @@ -1098,9 +1109,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_is_not_null = stream->read_bool("nonNull"); + ScopeValue *is_init = nullptr; + if (check_is_not_null) { + 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 @@ -1128,6 +1149,18 @@ 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()); + if (klass != nullptr) { + return !method->is_native() && klass->can_be_returned_as_fields(); + } + 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) { if (full_info) { read_virtual_objects(stream, JVMCI_CHECK); @@ -1169,7 +1202,7 @@ 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); 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, @@ -1315,9 +1348,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/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index 7fdfc9ce3a2..31bfec33b19 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -47,9 +47,11 @@ #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" +#include "oops/layoutKind.hpp" #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" @@ -368,6 +370,40 @@ C2V_VMENTRY_NULL(jbyteArray, getBytecode, (JNIEnv* env, jobject, ARGUMENT_PAIR(m return JVMCIENV->get_jbyteArray(result); 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); + 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(); +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); + if(!klass->is_inline_klass()) return false; + InlineKlass* inlineKlass = InlineKlass::cast(klass); + 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"); + 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(); @@ -427,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) { @@ -505,7 +555,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)); + intptr_t temp = (intptr_t) *((Klass**) (intptr_t) (base_address + offset)); + + // 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; @@ -675,6 +728,39 @@ 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); + 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->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"); + }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, 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) { @@ -2238,7 +2324,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); @@ -2267,12 +2353,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"); @@ -2344,10 +2436,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); } @@ -2364,7 +2456,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)) @@ -3262,6 +3354,11 @@ C2V_VMENTRY_0(jint, getCompilationActivityMode, (JNIEnv* env, jobject)) JNINativeMethod CompilerToVM::methods[] = { {CC "getBytecode", CC "(" HS_METHOD2 ")[B", FN_PTR(getBytecode)}, + {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)}, {CC "findUniqueConcreteMethod", CC "(" HS_KLASS2 HS_METHOD2 ")" HS_METHOD, FN_PTR(findUniqueConcreteMethod)}, @@ -3276,6 +3373,8 @@ 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 "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)}, @@ -3303,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)}, @@ -3346,7 +3447,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/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 78f5bca4769..9de83e43a8b 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); } @@ -1627,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); } } @@ -1740,7 +1742,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/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/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index d5fcd2aaaba..5f9e1985a2c 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) \ @@ -177,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/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index c88a4390590..359acf79146 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" @@ -413,6 +416,44 @@ 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 + +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 + +JRT_ENTRY(void, JVMCIRuntime::load_unknown_inline(JavaThread* current, flatArrayOopDesc* array, jint index)) + assert(array->klass()->is_flatArray_klass(), "should not be called"); + + assert(array->length() > 0 && index < array->length(), "already checked"); + oop obj = array->read_value_from_flat_array(index, THREAD); + current->set_vm_result(obj); +JRT_END + +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->write_value_to_flat_array(value, index, THREAD); +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"); @@ -453,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; @@ -854,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); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index 884d11f792e..55c95a62025 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" @@ -521,11 +524,16 @@ 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 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); static void log_printf(JavaThread* thread, const char* format, jlong v1, jlong v2, jlong v3); @@ -547,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 cfefd0cf967..9f91ce26793 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -267,12 +267,18 @@ 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 const *) \ + 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) \ + nonstatic_field(Klass, _prototype_header, markWord) \ nonstatic_field(Klass, _name, Symbol*) \ 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) \ @@ -295,6 +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_ro_entry, address) \ \ nonstatic_field(MethodCounters, _invoke_mask, int) \ nonstatic_field(MethodCounters, _backedge_mask, int) \ @@ -488,12 +495,16 @@ \ 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_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) \ 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) \ @@ -532,6 +543,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()) \ @@ -539,7 +552,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) \ @@ -759,6 +775,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) \ @@ -766,6 +783,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) \ \ @@ -817,6 +836,13 @@ \ 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) \ + 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) \ // Helper macro to support ZGC pattern where the function itself isn't exported #define DECLARE_FUNCTION_FROM_ADDR(declare_function_with_value, name) \ @@ -830,6 +856,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)) \ @@ -869,11 +896,16 @@ declare_function(JVMCIRuntime::exception_handler_for_pc) \ declare_function(JVMCIRuntime::monitorenter) \ 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) \ 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) \ 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/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/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; } /** 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; } 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..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; @@ -437,4 +438,19 @@ 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 scalarized inline type parameters . + * + * @param scalarizeReceiver true if the receiver should be scalarized, false otherwise + */ + 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(); + List argTypes = method.getScalarizedParameters(scalarizeReceiver); + JavaType retType = sig.getReturnType(null); + RegisterConfig registerConfig = codeCache.getRegisterConfig(); + 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 09360885c0b..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 @@ -23,10 +23,9 @@ 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.*; + +import java.util.List; /** * A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical @@ -39,6 +38,15 @@ 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. 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 includeFirstGeneralRegister) { + throw new UnsupportedOperationException("config for multiple register usage on return not implemented yet"); + } + /** * Gets the maximum allowed size of the frame. */ @@ -62,6 +70,17 @@ default int getMaximumFrameSize() { */ CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, ValueKindFactory valueKindFactory); + /** + * 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 List getReturnConvention(List returnTypes, ValueKindFactory valueKindFactory, boolean includeFirstGeneralRegister) { + 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..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,6 +44,7 @@ public final class VirtualObject implements JavaValue { private JavaKind[] slotKinds; private final int id; private boolean isAutoBox; + private JavaValue[] nonNull; /** * Creates a new {@link VirtualObject} for the given type, with the given fields. If @@ -240,6 +241,14 @@ 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[] getNonNull() { + return nonNull; + } + /** * Returns the kind of the value at {@code index}. */ @@ -279,6 +288,15 @@ public void setValues(JavaValue[] values, JavaKind[] slotKinds) { this.slotKinds = slotKinds; } + /** + * Overwrites the current value with a new one. + * + * @param nonNull an array containing one value indicating if the virtual object is non-null. + */ + public void setNonNull(JavaValue[] nonNull) { + this.nonNull = nonNull; + } + @Override public int hashCode() { return 42 + type.hashCode(); 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..bd6caddc8b7 --- /dev/null +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/ACmpDataAccessor.java @@ -0,0 +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(); + +} 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..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 @@ -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 @@ -132,6 +127,74 @@ byte[] getBytecode(HotSpotResolvedJavaMethodImpl method) { private native byte[] getBytecode(HotSpotResolvedJavaMethodImpl method, long methodPointer); + /** + * 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) { + int len = method.getSignature().getParameterCount(!method.isStatic()); + return getScalarizedParametersInfo(method, method.getMethodPointer(), new boolean[len], len); + } + + private native boolean[] getScalarizedParametersInfo(HotSpotResolvedJavaMethodImpl method, long methodPointer, boolean[] infoArray, int len); + + /** + * 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 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. + * + * @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. @@ -427,11 +490,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 @@ -467,10 +530,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 @@ -591,7 +654,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}. @@ -636,13 +699,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 @@ -697,8 +760,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}. @@ -956,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. @@ -992,8 +1059,13 @@ 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); + HotSpotResolvedObjectTypeImpl getResolvedJavaType(Object base, long displacement){ + return getResolvedJavaType0(base, displacement, false); + } + HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotConstantPool base, long displacement) { return getResolvedJavaType0(base, displacement, false); } @@ -1099,6 +1171,20 @@ 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); + + JavaConstant getDefaultInlineTypeInstance(HotSpotResolvedObjectTypeImpl nonPrimitiveKlass) { + long nonPrimitiveKlassPointer = nonPrimitiveKlass.getKlassPointer(); + return getDefaultInlineTypeInstance(nonPrimitiveKlass, nonPrimitiveKlassPointer); + } + + native JavaConstant getDefaultInlineTypeInstance(HotSpotResolvedObjectTypeImpl klass, long klassPointer); + /** * Forces initialization of {@code klass}. */ @@ -1188,11 +1274,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) @@ -1419,7 +1509,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 @@ -1428,12 +1518,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 @@ -1442,12 +1532,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 @@ -1456,12 +1546,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/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/HotSpotCompiledCodeStream.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotCompiledCodeStream.java index 49dfdcea5a2..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 @@ -983,6 +983,15 @@ 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("nonNull", vo.getNonNull() != null); + if (vo.getNonNull() != null) { + writeBasicType(JavaKind.Int); + JavaValue jv = vo.getNonNull()[0]; + writeJavaValue(jv, JavaKind.Int); + } + } 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/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/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 0943b0f8162..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,6 +1163,7 @@ public int getArrayBaseOffset(JavaKind kind) { } + /** * 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..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(); @@ -340,6 +362,7 @@ public int getArrayBaseOffset(JavaKind kind) { return runtime.getArrayBaseOffset(kind); } + @Override public int getArrayIndexScale(JavaKind kind) { return runtime.getArrayIndexScale(kind); 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..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 @@ -77,6 +77,14 @@ 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 << config.leftInlineTypeFlag; + final int rightInlineTypeFlag = 1 << config.rightInlineTypeFlag; + final int arrayDataLengthOffset = cellIndexToOffset(config.arrayDataArrayLenOffset); final int arrayDataStartOffset = cellIndexToOffset(config.arrayDataArrayStartOffset); @@ -107,7 +115,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 +299,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 +706,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 +734,170 @@ public StringBuilder appendTo(StringBuilder sb, HotSpotMethodData data, int pos) } } + static class ACmpData extends BranchData { + + abstract static class SingleTypeEntryImpl implements SingleTypeEntry { + 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; + + SingleTypeEntryImpl(ACmpData aCmpData, HotSpotMethodData data, int position) { + this.state = aCmpData.state; + this.value = data.readPointer(position, getOperandOffset()); + + int offset = state.computeFullOffset(position, getOperandOffset()); + this.validType = computeValidType(this.value, data, offset); + + if(!wasNullSeen(this.value)){ + this.neverNull = true; + }else if(isTypeNone(this.value)){ + this.alwaysNull = true; + }else{ + this.maybeNull = true; + } + + int flags = aCmpData.getFlags(data, position); + this.inlineType =(flags & getInlineFlag()) !=0; + } + + abstract int getOperandOffset(); + abstract int getInlineFlag(); + + protected VMState getState(){ + return state; + } + + private static boolean isTypeNone(long value){ + return (value & typeMask) == 0; + } + + private static boolean isTypeUnknown(long value){ + return (value & typeUnknown) != 0; + } + + private static boolean wasNullSeen(long value){ + return (value & nullSeen) != 0; + } + + private HotSpotResolvedObjectType computeValidType(long value, HotSpotMethodData data, int offset){ + if(!isTypeNone(value) && ! isTypeUnknown(value)){ + return compilerToVM().getResolvedJavaType(data, offset); + }else{ + return null; + } + + } + + @Override + public HotSpotResolvedObjectType getValidType(){ + return validType; + } + + @Override + public boolean maybeNull(){ + return maybeNull; + } + + @Override + public boolean neverNull(){ + return neverNull; + } + + @Override + public boolean alwaysNull(){ + return alwaysNull; + } + + @Override + public boolean inlineType(){ + return inlineType; + } + + + } + + static class LeftSingleTypeEntryImpl extends SingleTypeEntryImpl { + + LeftSingleTypeEntryImpl(ACmpData aCmpData,HotSpotMethodData data, int position) { + super(aCmpData, data, position); + } + + @Override + int getOperandOffset(){ + return getState().leftOperandOffset; + } + + @Override + int getInlineFlag(){ + return getState().leftInlineTypeFlag; + } + } + + static class RightSingleTypeEntryImpl extends SingleTypeEntryImpl { + + RightSingleTypeEntryImpl(ACmpData aCmpData, HotSpotMethodData data, int position) { + super(aCmpData, data, position); + } + + @Override + int getOperandOffset(){ + return getState().rightOperandOffset; + } + + @Override + int getInlineFlag(){ + return getState().rightInlineTypeFlag; + } + } + + static class ACmpDataAccessorImpl implements ACmpDataAccessor{ + + private final SingleTypeEntry left; + private final SingleTypeEntry right; + + ACmpDataAccessorImpl(ACmpData aCmpData, HotSpotMethodData data, int position){ + left = aCmpData.getLeft(aCmpData, data, position); + right = aCmpData.getRight(aCmpData, data, position); + } + + @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(ACmpData aCmpData, HotSpotMethodData data, int position) { + return new LeftSingleTypeEntryImpl(aCmpData, data, position); + } + + private SingleTypeEntry getRight(ACmpData aCmpData, HotSpotMethodData data, int position) { + return new RightSingleTypeEntryImpl(aCmpData, data, position); + } + + 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/HotSpotObjectConstant.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotObjectConstant.java index 227fcb731a9..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 @@ -94,4 +94,8 @@ public interface HotSpotObjectConstant extends JavaConstant, HotSpotConstant, VM @Override String toValueString(); + + default boolean objectIsInlineType(){ + return false; + } } 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..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 @@ -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(); @@ -200,9 +210,9 @@ public JavaConstant readFieldValue(HotSpotResolvedJavaField field) { if (field.isStatic()) { return null; } - HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getDeclaringClass(); + HotSpotResolvedObjectTypeImpl declaringClass = (HotSpotResolvedObjectTypeImpl) field.getContainerClass(); 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/HotSpotProfilingInfo.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotProfilingInfo.java index 97deccf0dcf..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 @@ -124,6 +124,18 @@ public TriState getExceptionSeen(int bci) { return dataAccessor.getExceptionSeen(methodData, position); } + @Override + public Object 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/HotSpotResolvedJavaFieldImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl.java index 6eb4dfb9b02..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 @@ -22,22 +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.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 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. @@ -45,13 +41,16 @@ class HotSpotResolvedJavaFieldImpl implements HotSpotResolvedJavaField { private final HotSpotResolvedObjectTypeImpl holder; + + private HotSpotResolvedObjectTypeImpl containerClass; + private JavaType type; /** * 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()}. @@ -86,7 +85,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.getContainerClass().equals(that.getContainerClass())) { return true; } } @@ -108,11 +107,57 @@ 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; + } + + @Override + public boolean isInitialized() { + assert isStatic() : "should only be called on static fields"; + if (getDeclaringClass().isInitialized()) { + return !runtime().getCompilerToVM().readStaticFieldValue(getDeclaringClass(), getOffset(), JavaKind.Object.getTypeChar()).isNull(); + } + return false; + } + + @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) { @@ -128,6 +173,21 @@ public HotSpotResolvedObjectTypeImpl getDeclaringClass() { return holder; } + @Override + public HotSpotResolvedObjectTypeImpl getContainerClass() { + if (containerClass == null) { + return holder; + } + return containerClass; + } + + @Override + public ResolvedJavaField setContainerClass(ResolvedJavaType containerClass) { + HotSpotResolvedJavaFieldImpl field = new HotSpotResolvedJavaFieldImpl(holder, type, offset, classfileFlags, internalFlags, index); + field.containerClass = (HotSpotResolvedObjectTypeImpl) containerClass; + return field; + } + @Override public String getName() { return holder.getFieldInfo(index).getName(holder); @@ -159,6 +219,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. @@ -184,7 +249,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/HotSpotResolvedJavaMethodImpl.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotResolvedJavaMethodImpl.java index 4fbd4796024..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 @@ -35,29 +35,15 @@ 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; -import java.util.Objects; 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 +776,200 @@ public BitSet getOopMapAt(int bci) { compilerToVM().getOopMapAt(this, bci, oopMap); return BitSet.valueOf(oopMap); } + + private boolean[] scalarizedParametersInfo; + + @Override + public boolean isScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + // see ciMethod::is_scalarized_arg + if (scalarizedParametersInfo == null) { + scalarizedParametersInfo = compilerToVM().getScalarizedParametersInfo(this); + } + // if method is non-static index 0 refers to receiver, therefore adapt the index + return scalarizedParametersInfo[index + ((isStatic() || indexIncludesReceiverIfExists) ? 0 : 1)]; + } + + + @Override + public boolean isParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + // maybe for the future + if (!indexIncludesReceiverIfExists) return false; + if (!isStatic() && index == 0) return true; + return false; + } + + private TriState hasScalarizedParameters = TriState.UNKNOWN; + + @Override + public boolean hasScalarizedParameters() { + // see ciMethod::has_scalarized_args + 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 (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() { + if (hasScalarizedReceiver.isKnown()) return hasScalarizedReceiver.toBoolean(); + boolean result = !isStatic() && isScalarizedParameter(0, true); + hasScalarizedReceiver = TriState.get(result); + 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 + public List getScalarizedReturn() { + assert hasScalarizedReturn() : "Scalarized return presumed"; + 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 + 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 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 + return !type.isInterface() && !type.isAbstract() && !type.isIdentity(); + } + return false; + } + + private HotSpotResolvedObjectTypeImpl getReturnedInlineType() { + return (HotSpotResolvedObjectTypeImpl) signature.getReturnType(getDeclaringClass()); + } + + + @Override + public List getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + return getScalarizedParameter(index, indexIncludesReceiverIfExists, true); + } + + @Override + public List getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + return getScalarizedParameter(index, indexIncludesReceiverIfExists, isParameterNullFree(index, indexIncludesReceiverIfExists)); + } + + 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) { + assert nullFree : "receiver should be null-free"; + return getFields(getDeclaringClass(), true, null); + } else { + index--; + } + } + JavaType type = signature.getParameterType(index, getDeclaringClass()); + assert type instanceof HotSpotResolvedObjectType : "HotSpotResolvedObjectType expected"; + ResolvedJavaType resolvedType = (ResolvedJavaType) type; + return getFields((HotSpotResolvedObjectTypeImpl) resolvedType, nullFree, nullFree ? null : getScalarizedParameterNonNullType(previousIndex, indexIncludesReceiverIfExists)); + + } + + @Override + public List getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + assert isScalarizedParameter(index, indexIncludesReceiverIfExists) : "Scalarized parameter presumed"; + boolean includeReceiver = indexIncludesReceiverIfExists && !isStatic(); + if (includeReceiver) { + if (index == 0) { + return List.of(getDeclaringClass().getInstanceFields(true)); + } else { + index--; + } + } + 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(NON_NULL_KIND); + } + + private static final JavaKind NON_NULL_KIND = JavaKind.Byte; + + + @Override + public List getScalarizedParameters(boolean scalarizeReceiver) { + // see TypeTuple::make_domain in opto/type.cpp + assert hasScalarizedParameters() : "Any scalarized parameters presumed"; + List types = new ArrayList<>(); + if (hasScalarizedReceiver() && scalarizeReceiver) { + 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()); + + 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 List.copyOf(types); + } + + + private List getFields(HotSpotResolvedObjectTypeImpl holder, boolean nullFree, JavaType nonNullType) { + ResolvedJavaField[] fields = holder.getInstanceFields(true); + 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 List.copyOf(types); + } } 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 0417a761fc4..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 @@ -39,6 +39,21 @@ public interface HotSpotResolvedObjectType extends ResolvedJavaType { @Override HotSpotResolvedObjectType getArrayClass(); + @Override + default HotSpotResolvedObjectType getFlatArrayClass(){ + return null; + } + + @Override + default HotSpotResolvedObjectType convertToFlatArray(){ + return null; + } + + @Override + default JavaConstant getDefaultInlineTypeInstance(){ + return null; + } + @Override ResolvedJavaType getComponentType(); @@ -75,6 +90,18 @@ default JavaKind getJavaKind() { */ int instanceSize(); + /** + * Gets the component size in an array + */ + default int getLog2ComponentSize(){ + return -1; + } + + @Override + default boolean isFlatArray(){ + return false; + } + int getVtableLength(); @Override @@ -98,6 +125,10 @@ default JavaKind getJavaKind() { int superCheckOffset(); + default int payloadOffset() { + return -1; + } + long prototypeMarkWord(); int layoutHelper(); 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..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 @@ -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* @@ -465,6 +448,14 @@ public boolean isInterface() { return (getAccessFlags() & config().jvmAccInterface) != 0; } + @Override + public boolean isIdentity() { + if (config().valhallaEnabled) { + return isArray() || (getAccessFlags() & config().jvmAccIdentity) != 0; + } + return !isInterface(); + } + @Override public boolean isAssignableFrom(ResolvedJavaType other) { assert other != null; @@ -545,6 +536,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(); @@ -682,6 +693,25 @@ 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); + } + + @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. @@ -694,24 +724,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() { @@ -738,9 +779,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) { @@ -750,6 +796,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) { @@ -777,6 +824,29 @@ 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 true; + //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()); } @@ -790,6 +860,10 @@ public int compare(ResolvedJavaField a, ResolvedJavaField b) { @Override public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { + return getInstanceFields(includeSuperclasses, config().valhallaEnabled); + } + + public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses, boolean valhallaEnabled) { if (instanceFields == null) { if (isArray() || isInterface()) { instanceFields = NO_FIELDS; @@ -798,7 +872,12 @@ public ResolvedJavaField[] getInstanceFields(boolean includeSuperclasses) { if (getSuperclass() != null) { prepend = (HotSpotResolvedJavaField[]) getSuperclass().getInstanceFields(true); } - instanceFields = getFields(false, prepend); + if (valhallaEnabled) { + instanceFields = getFlattenedFields(prepend); + } else { + instanceFields = getFields(false, prepend); + } + } } if (!includeSuperclasses && getSuperclass() != null) { @@ -835,12 +914,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.payloadOffset()); + HotSpotResolvedJavaField innerField = (HotSpotResolvedJavaField) innerFields[i]; + resultList.add((HotSpotResolvedJavaField) innerField.changeOffset(offset).setContainerClass((HotSpotResolvedObjectType) resolvedJavaField.getDeclaringClass())); + } + } + + } 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; @@ -966,7 +1108,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 @@ -997,6 +1139,13 @@ public int superCheckOffset() { return UNSAFE.getInt(getKlassPointer() + config.superCheckOffsetOffset); } + @Override + public int payloadOffset() { + HotSpotVMConfig config = config(); + long fixedBlockPointer = UNSAFE.getAddress(getKlassPointer() + config.inlineKlassFixedBlockAdr); + return UNSAFE.getInt(fixedBlockPointer + config.payloadOffset); + } + @Override public long prototypeMarkWord() { HotSpotVMConfig config = config(); 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..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 @@ -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; @@ -92,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/hotspot/HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 7205b453e40..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 @@ -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(); } } @@ -70,12 +71,16 @@ 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*"); 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 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 *"); final int classLoaderDataOffset = getFieldOffset("Klass::_class_loader_data", Integer.class, "ClassLoaderData*"); @@ -89,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*"); @@ -117,6 +126,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. @@ -126,6 +140,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); @@ -388,4 +403,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); } 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; + } } 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 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..ac1d6d35813 --- /dev/null +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/SingleTypeEntry.java @@ -0,0 +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(); + +} 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..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 @@ -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,15 @@ public CallingConvention getCallingConvention(Type type, JavaType returnType, Ja return callingConvention(javaGeneralParameterRegisters, javaXMMParameterRegisters, false, returnType, parameterTypes, hotspotType, valueKindFactory); } + @Override + 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); + } + @Override public RegisterArray getCallingConventionRegisters(Type type, JavaKind kind) { HotSpotCallingConventionType hotspotType = (HotSpotCallingConventionType) type; @@ -309,6 +322,54 @@ public Register getReturnRegister(JavaKind kind) { } } + @Override + public Register[] getReturnRegisters(JavaKind[] kinds, boolean includeFirstGeneralRegister) { + Register[] registers = new Register[kinds.length]; + RegisterArray generalReturnRegisters = javaGeneralReturnRegisters; + RegisterArray xmmReturnRegisters = javaXMMParameterRegisters; + + int currentGeneral = includeFirstGeneralRegister ? 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: + assert currentXMM < xmmReturnRegisters.size() : "return values can only be stored in registers"; + 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 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.get(i).getJavaKind().getStackKind(); + locations.add(registers[i].asValue(valueKindFactory.getValueKind(kind))); + } + return List.copyOf(locations); + } + @Override public Register getFrameRegister() { return rsp; 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..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 @@ -67,6 +67,11 @@ public TriState getExceptionSeen(int bci) { return exceptionSeen; } + @Override + public Object getACmpData(int bci) { + 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/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); 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..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 @@ -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. */ @@ -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. */ 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..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 @@ -22,6 +22,9 @@ */ 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 * returns the information that is available at the time of invocation. If a method is invoked @@ -75,6 +78,15 @@ public interface ProfilingInfo { */ TriState getExceptionSeen(int bci); + /** + * Returns the AcmpProfile for the given BCI. + * + * @return Returns a AcmpData object, or null if not available. + */ + default Object getACmpData(int bci) { + return null; + } + /** * Returns information if null was ever seen for the given BCI. This information is collected * for the aastore, checkcast and instanceof bytecodes. @@ -171,6 +183,15 @@ 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 = 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 = aCmpData.getRight(); + buf.append(String.format(formatString, i, right.getValidType(), right.alwaysNull(), right.inlineType(), sep)); + } + JavaTypeProfile typeProfile = getTypeProfile(i); MetaUtil.appendProfile(buf, typeProfile, i, "types", 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 cb891ab2e1b..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 @@ -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; @@ -46,6 +48,20 @@ 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(); + } + + /** + * 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(); } @@ -56,6 +72,38 @@ 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 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. + */ + 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. */ @@ -68,6 +116,18 @@ default boolean isFinal() { @Override ResolvedJavaType getDeclaringClass(); + /** + * 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 setContainerClass(ResolvedJavaType containerClass) { + throw new UnsupportedOperationException(); + } + /** * Gets the value of the {@code ConstantValue} attribute ({@jvms 4.7.2}) associated with this * field. 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..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 @@ -22,13 +22,14 @@ */ package jdk.vm.ci.meta; + import java.lang.annotation.Annotation; import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Type; -import java.util.BitSet; +import java.util.List; /** * Represents a resolved Java method. Methods, like fields and types, are resolved through @@ -480,4 +481,153 @@ default boolean isScoped() { * responsibility to ensure the same speculation log is used throughout a compilation. */ SpeculationLog getSpeculationLog(); + + /** + * 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 + * @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; + } + + /** + * 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; + } + + /** + * Finds out if this method has scalarized parameters. + * + * @return true if the method has scalarized parameters, false otherwise + */ + default boolean hasScalarizedParameters() { + return false; + } + + /** + * 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; + } + + /** + * Finds out if this method has a scalarized receiver. + * + * @return true if this method's receiver is passed scalarized, false otherwise + */ + 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. + * + * @return the scalarized return type which consists of the return type as well as the instance fields of the return type + */ + default List getScalarizedReturn() { + throw new UnsupportedOperationException("scalarized return not yet implemented"); + } + + /** + * 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 List getScalarizedParameters(boolean scalarizeReceiver) { + throw new UnsupportedOperationException("scalarized parameters not yet implemented"); + } + + /** + * 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 List getScalarizedParameter(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("scalarized parameter not yet implemented"); + } + + /** + * 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 List getScalarizedParameterNullFree(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("scalarized parameter not yet implemented"); + } + + /** + * 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 List getScalarizedParameterFields(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("getParameterFields is not supported"); + } + + /** + * 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 + * @return the type representing the is not null information + */ + default JavaType getScalarizedParameterNonNullType(int index, boolean indexIncludesReceiverIfExists) { + throw new UnsupportedOperationException("getScalarizedParameterNonNull is not supported"); + } + + /** + * Gets the ordered type information of each field according to {@link ResolvedJavaType#getInstanceFields(boolean)} of the method's scalarized receiver. + * + * @return the scalarized receiver which consists of its instance fields. + */ + default List getScalarizedReceiver() { + assert hasScalarizedReceiver() : "Scalarized receiver presumed"; + return getScalarizedParameter(0, true); + } } 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..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 @@ -237,6 +237,25 @@ 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(); + } + + 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 @@ -407,4 +426,16 @@ default ResolvedJavaField resolveField(UnresolvedJavaField unresolvedJavaField, default boolean isConcrete() { return isArray() || !isAbstract(); } + + /** + * Checks whether this type has an identity. See {@link Class#isIdentity()}. + * + * @return {@code true} if this type has an identity + */ + default boolean isIdentity(){ + if (isPrimitive()) { + return false; + } + return !isInterface(); + } } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 2bf29580977..390f2226871 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -267,6 +267,25 @@ 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*"); + addFlags("-DIgnoreCompilerControls=true"); + 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; + } + /** * 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 +342,7 @@ public TestFramework addScenarios(Scenario... scenarios) { this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); + addFlags(/*"-XX:-InlineTypePassFieldsAsArgs", */"-DVerifyIR=false", "-Djdk.test.lib.random.seed=-8514275799831337363", "-DIgnoreCompilerControls=false"/*, "-DPreferCommandLineFlags=true"*/); return this; } @@ -721,7 +741,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 853475ced1e..0b1e60576f2 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", @@ -126,6 +128,8 @@ public class InlineTypes { 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", */"-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 b52ca86bd46..7ff92270ac4 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestAllocationMergeAndFolding.java @@ -45,6 +45,7 @@ public static void main(String[] args) { .addScenarios(InlineTypes.DEFAULT_SCENARIOS) .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..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* - * -Xbatch + * -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* - * -Xbatch -XX:-UseArrayFlattening + * -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/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 582b5d670bb..1e460ad9eff 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC1.java @@ -60,8 +60,8 @@ public static void main(String[] args) { 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") +// // Xcomp Only C2. +// new Scenario(4, "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-Xcomp") }; InlineTypes.getFramework() @@ -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/TestC2CCalls.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java index 3184c2b9d44..f2f618bc61e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestC2CCalls.java @@ -29,30 +29,34 @@ * @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:-UseBimorphicInlining * -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 -XX:-ProfileInterpreter * -XX:CompileCommand=compileonly,TestC2CCalls*::test* * -XX:CompileCommand=dontinline,TestC2CCalls*::test* * TestC2CCalls * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI - * -XX:-UseBimorphicInlining -Xbatch + * -XX:-UseBimorphicInlining * -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 -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, diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java index 80a0584295b..38537de5a1e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestCallingConventionC1.java @@ -57,7 +57,7 @@ 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", @@ -81,6 +81,7 @@ public static void main(String[] args) { "-XX:+TieredCompilation", "-XX:+IgnoreUnrecognizedVMOptions", "-XX:-PatchALot"), + // Only C2. new Scenario(4, "--enable-preview", @@ -92,6 +93,7 @@ public static void main(String[] args) { InlineTypes.getFramework() .addScenarios(scenarios) + .setCompileOnlyTestMethods(TestCallingConventionC1.class).setGraalLog() .start(); } 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/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 eb6b99e1e79..ebd91627ece 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestFlatArrayThreshold.java @@ -28,13 +28,16 @@ * @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 + * @run main/othervm -XX:FlatArrayElementMaxOops=1 + * TestFlatArrayThreshold + * @run main/othervm -XX:+UseArrayFlattening * 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 b163ecb2eef..f9ba55febeb 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestGenerated.java @@ -28,9 +28,10 @@ * @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..bcb549bc9cb 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"), @@ -97,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", @@ -108,7 +113,7 @@ public static void main(String[] args) { "-XX:TieredStopAtLevel=4", "-XX:-TieredCompilation", "-XX:-OmitStackTraceInFastThrow", - "-Xcomp") + "-Xcomp") */ }; InlineTypes.getFramework() @@ -116,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..d0be61d9d9e 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestInlineFieldNonFlattened.java @@ -99,6 +99,7 @@ public static void main(String[] args) { "--add-exports", "java.base/jdk.internal.value=ALL-UNNAMED", "-XX:-TieredCompilation", "-XX:-UseFieldFlattening") + .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..9dedd5176fc 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).setCompileOnlyClass(java.util.HashMap.class).setGraalLog() + //.addFlags("-XX:CompileCommand=compileonly,compiler.valhalla.inlinetypes.TestLWorld::test*") .addHelperClasses(MyValue1.class, MyValue2.class, MyValue2Inline.class, @@ -4652,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/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/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(); } diff --git a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java index f2cabb1845d..6f57c729e0d 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestMismatchHandling.java @@ -35,30 +35,30 @@ * -XX:-Inline -XX:-InlineAccessors -XX:-UseBimorphicInlining -XX:-UseCHA -XX:-UseTypeProfile * -XX:CompileCommand=compileonly,TestMismatchHandling::test* * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch + * @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 -Xbatch + * @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 -Xbatch + * @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 -Xbatch + * @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 -Xbatch + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:+DeoptimizeNMethodBarriersALot * TestMismatchHandling - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -Xbatch + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions * -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/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, 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 1a65f7ef828..06d4a8b23c0 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestSafepointAtPollReturn.java @@ -25,7 +25,7 @@ * @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 + * @run main/othervm -XX:CompileCommand=compileonly,TestSafepointAtPollReturn::test* -XX:+UnlockDiagnosticVMOptions * -XX:+SafepointALot -XX:-TieredCompilation 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 617fedc59b4..7da68a29f8f 100644 --- a/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java +++ b/test/hotspot/jtreg/compiler/valhalla/inlinetypes/TestValueConstruction.java @@ -62,7 +62,7 @@ * @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=compileonly,*TestValueConstruction::test* * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -75,7 +75,7 @@ * @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 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:CompileCommand=dontinline,compiler*::helper* * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction @@ -89,7 +89,7 @@ * @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=dontinline,*MyValue*:: * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -102,7 +102,7 @@ * @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=dontinline,*Object:: * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -115,7 +115,7 @@ * @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:+DeoptimizeALot -XX:CompileCommand=dontinline,*Object:: * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -128,7 +128,7 @@ * @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=dontinline,*MyAbstract:: * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -140,7 +140,7 @@ * @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 + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt * compiler.valhalla.inlinetypes.TestValueConstruction @@ -156,7 +156,7 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=compileonly,*TestValueConstruction::test* -Xbatch + * -XX:CompileCommand=compileonly,*TestValueConstruction::test* * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -169,7 +169,7 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*MyValue*:: -Xbatch + * -XX:CompileCommand=dontinline,*MyValue*:: * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -183,7 +183,7 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*Object:: -Xbatch + * -XX:CompileCommand=dontinline,*Object:: * compiler.valhalla.inlinetypes.TestValueConstruction */ @@ -197,10 +197,11 @@ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI * -XX:-TieredCompilation -XX:+StressIncrementalInlining * -XX:CompileCommand=inline,TestValueConstruction::checkDeopt - * -XX:CompileCommand=dontinline,*MyAbstract:: -Xbatch + * -XX:CompileCommand=dontinline,*MyAbstract:: * 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"); 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/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/Equality.java b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java new file mode 100644 index 00000000000..237cd06cab9 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Equality.java @@ -0,0 +1,90 @@ +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 org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.Level; + + +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 + @LooselyConsistentValue + 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]; + + @Setup(Level.Invocation) + public void setUp() { + // 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 = 0; j < lineArray.length; j++) { + if (lineArray[i] == lineArray[j]) { + count++; + } + } + } + return count; + } + + + @Benchmark + @OperationsPerInvocation(1) + public void benchmark() { + findDuplicates(); + } +} \ 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/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 new file mode 100644 index 00000000000..9ea1242f9f4 --- /dev/null +++ b/test/micro/org/openjdk/bench/valhalla/thesis_benchmarks/Sorting.java @@ -0,0 +1,157 @@ +package org.openjdk.bench.valhalla.thesis_benchmarks; + +import java.util.Random; + +import jdk.internal.value.ValueClass; +import org.openjdk.bench.valhalla.thesis_benchmarks.Q32int; +import org.openjdk.jmh.annotations.*; + + +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 + for (int i = 0; i < array.length; i++) { + array[i] = new Q32int(array.length-1-i); + } + } + + + @CompilerControl(CompilerControl.Mode.DONT_INLINE) + 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; + } + + 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); +// } + + @Setup(Level.Invocation) + public void setUp() { + initialize(); + } + + @Benchmark + @OperationsPerInvocation(1) + public void benchmark_sorting_bubblesort() { + //fill(); + //initialize(); + bubblesort(array); + //initialize(); + //selectionSort(array); + //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 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 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;