From b95ac21cc681945069a76cf2d3dfebec525634e7 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 3 Apr 2025 07:51:04 +0530 Subject: [PATCH 01/16] 8352675: Support Intel AVX10 converged vector ISA feature detection --- src/hotspot/cpu/x86/vm_version_x86.cpp | 102 ++++++++++++++---- src/hotspot/cpu/x86/vm_version_x86.hpp | 57 +++++++++- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 6 +- .../share/runtime/abstract_vm_version.cpp | 4 +- .../share/runtime/abstract_vm_version.hpp | 7 +- .../share/classes/jdk/vm/ci/amd64/AMD64.java | 2 + .../hotspot/HotSpotJVMCIBackendFactory.java | 12 +++ .../AArch64HotSpotJVMCIBackendFactory.java | 2 +- .../AMD64HotSpotJVMCIBackendFactory.java | 3 +- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 3 + .../RISCV64HotSpotJVMCIBackendFactory.java | 2 +- .../jdk/test/whitebox/CPUInfoTest.java | 4 +- 12 files changed, 171 insertions(+), 33 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 4b9c1c3416a5d..209851f9321e1 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -51,6 +51,10 @@ VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_NAME)}; #undef DECLARE_CPU_FEATURE_FLAG +#define DECLARE_EXTRA_CPU_FEATURE_NAME(id, name, bit) name, +const char* VM_Version::_extra_features_names[] = { EXTRA_CPU_FEATURE_FLAGS(DECLARE_EXTRA_CPU_FEATURE_NAME)}; +#undef DECLARE_EXTRA_CPU_FEATURE_FLAG + // Address of instruction which causes SEGV address VM_Version::_cpuinfo_segv_addr = nullptr; // Address of instruction after the one which causes SEGV @@ -138,7 +142,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { const uint32_t CPU_FAMILY_486 = (4 << CPU_FAMILY_SHIFT); bool use_evex = FLAG_IS_DEFAULT(UseAVX) || (UseAVX > 2); - Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4; + Label detect_486, cpu486, detect_586, std_cpuid1, std_cpuid4, std_cpuid24; Label sef_cpuid, sefsl1_cpuid, ext_cpuid, ext_cpuid1, ext_cpuid5, ext_cpuid7; Label ext_cpuid8, done, wrapup, vector_save_restore, apx_save_restore_warning; Label legacy_setup, save_restore_except, legacy_save_restore, start_simd_check; @@ -341,6 +345,17 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movl(Address(rsi, 0), rax); __ movl(Address(rsi, 4), rdx); + // + // cpuid(0x24) Converged Vector ISA Main Leaf (EAX = 24H, ECX = 0). + // + __ bind(std_cpuid24); + __ movl(rax, 0x24); + __ movl(rcx, 0); + __ cpuid(); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid24_offset()))); + __ movl(Address(rsi, 0), rax); + __ movl(Address(rsi, 4), rbx); + // // Extended cpuid(0x80000000) // @@ -428,13 +443,11 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset()))); __ movl(rax, 0x200000); __ andl(rax, Address(rsi, 4)); - __ cmpl(rax, 0x200000); - __ jcc(Assembler::notEqual, vector_save_restore); + __ jcc(Assembler::equal, vector_save_restore); // check _cpuid_info.xem_xcr0_eax.bits.apx_f __ movl(rax, 0x80000); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits apx_f - __ cmpl(rax, 0x80000); - __ jcc(Assembler::notEqual, vector_save_restore); + __ jcc(Assembler::equal, vector_save_restore); #ifndef PRODUCT bool save_apx = UseAPX; @@ -463,13 +476,11 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); __ movl(rcx, 0x18000000); // cpuid1 bits osxsave | avx __ andl(rcx, Address(rsi, 8)); // cpuid1 bits osxsave | avx - __ cmpl(rcx, 0x18000000); - __ jccb(Assembler::notEqual, done); // jump if AVX is not supported + __ jccb(Assembler::equal, done); // jump if AVX is not supported __ movl(rax, 0x6); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ cmpl(rax, 0x6); - __ jccb(Assembler::equal, start_simd_check); // return if AVX is not supported + __ jccb(Assembler::notEqual, start_simd_check); // return if AVX is not supported // we need to bridge farther than imm8, so we use this island as a thunk __ bind(done); @@ -488,18 +499,21 @@ class VM_Version_StubGenerator: public StubCodeGenerator { // If UseAVX is uninitialized or is set by the user to include EVEX if (use_evex) { // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f + // OR check _cpuid_info.std_cpuid24_ebx.bits.avx10 __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ movl(rax, 0x10000); - __ andl(rax, Address(rsi, 4)); // xcr0 bits sse | ymm - __ cmpl(rax, 0x10000); - __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported + __ andl(rax, Address(rsi, 4)); + __ lea(rsi, Address(rbp, in_bytes(VM_Version::sefsl1_cpuid7_offset()))); + __ movl(rbx, 0x80000); + __ andl(rbx, Address(rsi, 4)); + __ orl(rax, rbx); + __ jccb(Assembler::equal, legacy_setup); // jump if EVEX is not supported // check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ cmpl(rax, 0xE0); - __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported + __ jccb(Assembler::equal, legacy_setup); // jump if EVEX is not supported if (FLAG_IS_DEFAULT(UseAVX)) { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); @@ -577,15 +591,13 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ movl(rax, 0x10000); __ andl(rax, Address(rsi, 4)); - __ cmpl(rax, 0x10000); - __ jcc(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::equal, legacy_save_restore); // check _cpuid_info.xem_xcr0_eax.bits.opmask // check _cpuid_info.xem_xcr0_eax.bits.zmm512 // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ cmpl(rax, 0xE0); - __ jcc(Assembler::notEqual, legacy_save_restore); + __ jcc(Assembler::equal, legacy_save_restore); if (FLAG_IS_DEFAULT(UseAVX)) { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); @@ -879,6 +891,7 @@ void VM_Version::get_processor_features() { if (cpu_family() > 4) { // it supports CPUID _features = _cpuid_info.feature_flags(); // These can be changed by VM settings + _extra_features = _cpuid_info.extra_feature_flags(); // These can be changed by VM settings _cpu_features = _features; // Preserve features // Logical processors are only available on P4s and above, // and only if hyperthreading is available. @@ -892,6 +905,7 @@ void VM_Version::get_processor_features() { LP64_ONLY(_supports_atomic_getset8 = true); LP64_ONLY(_supports_atomic_getadd8 = true); + #ifdef _LP64 // OS should support SSE for x64 and hardware should support at least SSE2. if (!VM_Version::supports_sse2()) { @@ -1018,6 +1032,8 @@ void VM_Version::get_processor_features() { _features &= ~CPU_AVX512DQ; _features &= ~CPU_AVX512CD; _features &= ~CPU_AVX512BW; + _features &= ~CPU_AVX512ER; + _features &= ~CPU_AVX512PF; _features &= ~CPU_AVX512VL; _features &= ~CPU_AVX512_VPOPCNTDQ; _features &= ~CPU_AVX512_VPCLMULQDQ; @@ -1029,6 +1045,8 @@ void VM_Version::get_processor_features() { _features &= ~CPU_AVX512_IFMA; _features &= ~CPU_APX_F; _features &= ~CPU_AVX512_FP16; + _features &= ~CPU_AVX10_1; + _features &= ~EXTRA_CPU_AVX10_2; } // Currently APX support is only enabled for targets supporting AVX512VL feature. @@ -1089,14 +1107,16 @@ void VM_Version::get_processor_features() { _has_intel_jcc_erratum = IntelJccErratumMitigation; } - char buf[1024]; + char buf[2048] = {'\0'}; int res = jio_snprintf( buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(res > 0, "not enough temporary space allocated"); - insert_features_names(buf + res, sizeof(buf) - res, _features_names); + insert_features_names(_features, buf + res, sizeof(buf) - res, _features_names); + res = (int)strlen(buf); + insert_features_names(_extra_features, buf + res, sizeof(buf) - res, _extra_features_names); _features_string = os::strdup(buf); @@ -2962,6 +2982,21 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) { return _max_qualified_cpu_frequency; } +uint64_t VM_Version::CpuidInfo::extra_feature_flags() const { + uint64_t result = 0; + if (is_intel()) { + if (sefsl1_cpuid7_edx.bits.avx10 != 0 && + std_cpuid24_ebx.bits.avx10_vlen_512 !=0 && + std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2 && + xem_xcr0_eax.bits.opmask != 0 && + xem_xcr0_eax.bits.zmm512 != 0 && + xem_xcr0_eax.bits.zmm32 != 0) { + result |= EXTRA_CPU_AVX10_2; + } + } + return result; +} + uint64_t VM_Version::CpuidInfo::feature_flags() const { uint64_t result = 0; if (std_cpuid1_edx.bits.cmpxchg8 != 0) @@ -3054,7 +3089,34 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0) result |= CPU_AVX512_VBMI2; } + if (is_intel()) { + if (sefsl1_cpuid7_edx.bits.avx10 != 0 && + std_cpuid24_ebx.bits.avx10_vlen_512 !=0 && + std_cpuid24_ebx.bits.avx10_converged_isa_version >= 1 && + xem_xcr0_eax.bits.opmask != 0 && + xem_xcr0_eax.bits.zmm512 != 0 && + xem_xcr0_eax.bits.zmm32 != 0) { + result |= CPU_AVX10_1; + result |= CPU_AVX_IFMA; + result |= CPU_AVX512F; + result |= CPU_AVX512CD; + result |= CPU_AVX512DQ; + result |= CPU_AVX512_IFMA; + result |= CPU_AVX512PF; + result |= CPU_AVX512ER; + result |= CPU_AVX512BW; + result |= CPU_AVX512VL; + result |= CPU_AVX512_VPOPCNTDQ; + result |= CPU_AVX512_VPCLMULQDQ; + result |= CPU_AVX512_VAES; + result |= CPU_AVX512_VNNI; + result |= CPU_AVX512_BITALG; + result |= CPU_AVX512_VBMI; + result |= CPU_AVX512_VBMI2; + } + } } + if (std_cpuid1_ecx.bits.hv != 0) result |= CPU_HV; if (sef_cpuid7_ebx.bits.bmi1 != 0) diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index cc5c6c1c63992..c9f56f63afb40 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -295,12 +295,32 @@ class VM_Version : public Abstract_VM_Version { union SefCpuid7SubLeaf1Edx { uint32_t value; struct { - uint32_t : 21, + uint32_t : 19, + avx10 : 1, + : 1, apx_f : 1, : 10; } bits; }; + union StdCpuid24MainLeafEax { + uint32_t value; + struct { + uint32_t sub_leaves_cnt : 31; + } bits; + }; + + union StdCpuid24MainLeafEbx { + uint32_t value; + struct { + uint32_t avx10_converged_isa_version : 8, + : 8, + : 2, + avx10_vlen_512 : 1, + : 13; + } bits; + }; + union ExtCpuid1EEbx { uint32_t value; struct { @@ -342,7 +362,7 @@ class VM_Version : public Abstract_VM_Version { /* * Update following files when declaring new flags: * test/lib-test/jdk/test/whitebox/CPUInfoTest.java - * src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java + * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java */ enum Feature_Flag : uint64_t { #define CPU_FEATURE_FLAGS(decl) \ @@ -420,14 +440,30 @@ class VM_Version : public Abstract_VM_Version { decl(AVX_IFMA, "avx_ifma", 59) /* 256-bit VEX-coded variant of AVX512-IFMA*/ \ decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ \ decl(SHA512, "sha512", 61) /* SHA512 instructions*/ \ - decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ + decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ \ + decl(AVX10_1, "avx10_1", 63) /* AVX10 512 bit vector ISA Version 1 support*/ #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1ULL << bit), CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) #undef DECLARE_CPU_FEATURE_FLAG }; + /* + * Update following files when declaring new flags: + * test/lib-test/jdk/test/whitebox/CPUInfoTest.java + * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java + */ + enum Extra_Feature_Flag : uint64_t { +#define EXTRA_CPU_FEATURE_FLAGS(decl) \ + decl(AVX10_2, "avx10_2", 0) /* AVX10 512 bit vector ISA Version 2 support*/ + +#define DECLARE_EXTRA_CPU_FEATURE_FLAG(id, name, bit) EXTRA_CPU_##id = (1ULL << bit), + EXTRA_CPU_FEATURE_FLAGS(DECLARE_EXTRA_CPU_FEATURE_FLAG) +#undef DECLARE_EXTRA_CPU_FEATURE_FLAG + }; + static const char* _features_names[]; + static const char* _extra_features_names[]; enum Extended_Family { // AMD @@ -492,6 +528,11 @@ class VM_Version : public Abstract_VM_Version { SefCpuid7SubLeaf1Eax sefsl1_cpuid7_eax; SefCpuid7SubLeaf1Edx sefsl1_cpuid7_edx; + // cpuid function 24 converged vector ISA main leaf + // eax = 24, ecx = 0 + StdCpuid24MainLeafEax std_cpuid24_eax; + StdCpuid24MainLeafEbx std_cpuid24_ebx; + // cpuid function 0xB (processor topology) // ecx = 0 uint32_t tpl_cpuidB0_eax; @@ -566,6 +607,7 @@ class VM_Version : public Abstract_VM_Version { jlong apx_save[2]; // Save r16 and r31 uint64_t feature_flags() const; + uint64_t extra_feature_flags() const; // Asserts void assert_is_initialized() const { @@ -611,6 +653,7 @@ class VM_Version : public Abstract_VM_Version { // Offsets for cpuid asm stub static ByteSize std_cpuid0_offset() { return byte_offset_of(CpuidInfo, std_max_function); } static ByteSize std_cpuid1_offset() { return byte_offset_of(CpuidInfo, std_cpuid1_eax); } + static ByteSize std_cpuid24_offset() { return byte_offset_of(CpuidInfo, std_cpuid24_eax); } static ByteSize dcp_cpuid4_offset() { return byte_offset_of(CpuidInfo, dcp_cpuid4_eax); } static ByteSize sef_cpuid7_offset() { return byte_offset_of(CpuidInfo, sef_cpuid7_eax); } static ByteSize sefsl1_cpuid7_offset() { return byte_offset_of(CpuidInfo, sefsl1_cpuid7_eax); } @@ -646,7 +689,7 @@ class VM_Version : public Abstract_VM_Version { static void clean_cpuFeatures() { _features = 0; } static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } - static void set_evex_cpuFeatures() { _features |= (CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } + static void set_evex_cpuFeatures() { _features |= (CPU_AVX10_1 | EXTRA_CPU_AVX10_2 | CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } static void set_apx_cpuFeatures() { _features |= CPU_APX_F; } static void set_bmi_cpuFeatures() { _features |= (CPU_BMI1 | CPU_BMI2 | CPU_LZCNT | CPU_POPCNT); } @@ -768,6 +811,12 @@ class VM_Version : public Abstract_VM_Version { static bool supports_cet_ibt() { return (_features & CPU_CET_IBT) != 0; } static bool supports_sha512() { return (_features & CPU_SHA512) != 0; } + // IntelĀ® AVX10 introduces a versioned approach for enumeration that is monotonically increasing, inclusive, + // and supporting all vector lengths. Feature set supported by an AVX10 vector ISA version is also supported + // by all the versions above it. + static bool supports_avx10_1() { return (_features & CPU_AVX10_1) != 0;} + static bool supports_avx10_2() { return (_extra_features & EXTRA_CPU_AVX10_2) != 0;} + // // Feature identification not affected by VM flags // diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 3cbb1512cd06a..d68e00196c4c8 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -147,6 +147,7 @@ JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ \ static_field(Abstract_VM_Version, _features, uint64_t) \ + static_field(Abstract_VM_Version, _extra_features, uint64_t) \ \ nonstatic_field(Annotations, _class_annotations, AnnotationArray*) \ nonstatic_field(Annotations, _fields_annotations, Array*) \ @@ -976,7 +977,10 @@ declare_constant(frame::interpreter_frame_last_sp_offset) #define DECLARE_LONG_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::CPU_##id) -#define VM_LONG_CPU_FEATURE_CONSTANTS CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) +#define DECLARE_LONG_EXTRA_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::EXTRA_CPU_##id) +#define VM_LONG_CPU_FEATURE_CONSTANTS \ + CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) \ + EXTRA_CPU_FEATURE_FLAGS(DECLARE_LONG_EXTRA_CPU_FEATURE_CONSTANT) #endif diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 763e441fe541e..4e98354045688 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -33,6 +33,7 @@ const char* Abstract_VM_Version::_s_vm_release = Abstract_VM_Version::vm_release const char* Abstract_VM_Version::_s_internal_vm_info_string = Abstract_VM_Version::internal_vm_info_string(); uint64_t Abstract_VM_Version::_features = 0; +uint64_t Abstract_VM_Version::_extra_features = 0; const char* Abstract_VM_Version::_features_string = ""; uint64_t Abstract_VM_Version::_cpu_features = 0; @@ -320,8 +321,7 @@ unsigned int Abstract_VM_Version::jvm_version() { (Abstract_VM_Version::vm_build_number() & 0xFF); } -void Abstract_VM_Version::insert_features_names(char* buf, size_t buflen, const char* features_names[]) { - uint64_t features = _features; +void Abstract_VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[]) { uint features_names_index = 0; while (features != 0) { diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 8cfc7031f97ae..52021e715bc61 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -56,6 +56,9 @@ class Abstract_VM_Version: AllStatic { // CPU feature flags, can be affected by VM settings. static uint64_t _features; + // Extra CPU feature flags used when all 64 bits of _features are exhausted for + // on a given target, currently only used for x86_64, can be affected by VM settings. + static uint64_t _extra_features; static const char* _features_string; // Original CPU feature flags, not affected by VM settings. @@ -127,8 +130,10 @@ class Abstract_VM_Version: AllStatic { static const char* printable_jdk_debug_level(); static uint64_t features() { return _features; } + static uint64_t extra_features() { return _extra_features; } static const char* features_string() { return _features_string; } - static void insert_features_names(char* buf, size_t buflen, const char* features_names[]); + + static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[]); static VirtualizationType get_detected_virtualization() { return _detected_virtualization; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java index d25f7e7199056..c75b3d9f9ce85 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java @@ -258,6 +258,8 @@ public enum CPUFeature implements CPUFeatureName { APX_F, SHA512, AVX512_FP16, + AVX10_1, + AVX10_2 } private final EnumSet features; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 27fd3d23980de..1a3adae7b5300 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -57,6 +57,7 @@ static > EnumSet con Class enumType, Map constants, long features, + long extra_features, Map renaming) { EnumSet outFeatures = EnumSet.noneOf(enumType); List missing = new ArrayList<>(); @@ -74,6 +75,17 @@ static > EnumSet con missing.add(name); } } + if (key.startsWith("VM_Version::EXTRA_CPU_")) { + String name = key.substring("VM_Version::EXTRA_CPU_".length()); + try { + CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name)); + if ((extra_features & bitMask) != 0) { + outFeatures.add(feature); + } + } catch (IllegalArgumentException iae) { + missing.add(name); + } + } } if (!missing.isEmpty()) { throw new JVMCIError("Missing CPU feature constants: %s", missing); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java index 890a335767842..0c8f4a5d44ade 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java @@ -49,7 +49,7 @@ public class AArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac private static EnumSet computeFeatures(AArch64HotSpotVMConfig config) { // Configure the feature set using the HotSpot flag settings. Map constants = config.getStore().getConstants(); - return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap()); + return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, 0L, emptyMap()); } private static EnumSet computeFlags(AArch64HotSpotVMConfig config) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 821bd9371b2d7..bd9b60574dcfb 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -50,7 +50,8 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map constants = config.getStore().getConstants(); Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; - EnumSet features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, renaming); + EnumSet features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, + config.vmVersionExtraFeatures, renaming); features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE2); return features; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index b0e2f425dae4f..67241fffddd80 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -47,6 +47,7 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final int useAVX = getFlag("UseAVX", Integer.class); final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t"); + final long vmVersionExtraFeatures = getFieldValue("Abstract_VM_Version::_extra_features", Long.class, "uint64_t"); // CPU feature flags final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class); @@ -88,4 +89,6 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long amd64OSPKE = getConstant("VM_Version::CPU_OSPKE", Long.class); final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class); final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class); + final long avx10_1 = getConstant("VM_Version::CPU_AVX10_1", Long.class); + final long avx10_2 = getConstant("VM_Version::EXTRA_CPU_AVX10_2", Long.class); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java index 6e0eac91d6100..881cbf983e096 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java @@ -49,7 +49,7 @@ public class RISCV64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac private static EnumSet computeFeatures(RISCV64HotSpotVMConfig config) { // Configure the feature set using the HotSpot flag settings. Map constants = config.getStore().getConstants(); - return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap()); + return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, 0L, emptyMap()); } private static EnumSet computeFlags(RISCV64HotSpotVMConfig config) { diff --git a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java index 54a9ef872f5f2..4a68333aa9278 100644 --- a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java +++ b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,7 +66,7 @@ public class CPUInfoTest { "hv", "fsrm", "avx512_bitalg", "gfni", "f16c", "pku", "ospke", "cet_ibt", "cet_ss", "avx512_ifma", "serialize", "avx_ifma", - "apx_f" + "apx_f", "avx10_1", "avx10_2" ); // @formatter:on // Checkstyle: resume From 6a02fe93f1620824152f23143c686d430f732e4e Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 17 Apr 2025 08:00:44 +0530 Subject: [PATCH 02/16] dropping unneeded feature enabling/checks --- src/hotspot/cpu/x86/vm_version_x86.cpp | 1 - src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 209851f9321e1..4b3c3e0d32fc0 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -3101,7 +3101,6 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { result |= CPU_AVX512F; result |= CPU_AVX512CD; result |= CPU_AVX512DQ; - result |= CPU_AVX512_IFMA; result |= CPU_AVX512PF; result |= CPU_AVX512ER; result |= CPU_AVX512BW; diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index c9f56f63afb40..c39d186a05429 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -689,7 +689,7 @@ class VM_Version : public Abstract_VM_Version { static void clean_cpuFeatures() { _features = 0; } static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } - static void set_evex_cpuFeatures() { _features |= (CPU_AVX10_1 | EXTRA_CPU_AVX10_2 | CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } + static void set_evex_cpuFeatures() { _features |= (CPU_AVX10_1 | CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } static void set_apx_cpuFeatures() { _features |= CPU_APX_F; } static void set_bmi_cpuFeatures() { _features |= (CPU_BMI1 | CPU_BMI2 | CPU_LZCNT | CPU_POPCNT); } From 5d09adb384caa673c446938047b32a72b14d6221 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 23 Apr 2025 10:28:43 +0530 Subject: [PATCH 03/16] Add dynamic sized feature vectors --- .../cpu/aarch64/vm_version_aarch64.cpp | 2 + .../cpu/aarch64/vm_version_aarch64.hpp | 1 + src/hotspot/cpu/arm/vm_version_arm.hpp | 1 + src/hotspot/cpu/arm/vm_version_arm_32.cpp | 2 + src/hotspot/cpu/ppc/vm_version_ppc.cpp | 2 + src/hotspot/cpu/ppc/vm_version_ppc.hpp | 1 + src/hotspot/cpu/riscv/vm_version_riscv.cpp | 2 + src/hotspot/cpu/riscv/vm_version_riscv.hpp | 1 + src/hotspot/cpu/s390/vm_version_s390.cpp | 2 + src/hotspot/cpu/s390/vm_version_s390.hpp | 1 + src/hotspot/cpu/x86/vm_version_x86.cpp | 320 +++++++++--------- src/hotspot/cpu/x86/vm_version_x86.hpp | 184 +++++----- src/hotspot/cpu/zero/vm_version_zero.cpp | 2 + src/hotspot/cpu/zero/vm_version_zero.hpp | 1 + src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 10 +- .../share/runtime/abstract_vm_version.cpp | 11 +- .../share/runtime/abstract_vm_version.hpp | 69 +++- src/hotspot/share/runtime/init.cpp | 2 + src/hotspot/share/runtime/vmStructs.cpp | 3 + src/hotspot/share/runtime/vm_version.cpp | 4 + .../hotspot/HotSpotJVMCIBackendFactory.java | 53 ++- .../AArch64HotSpotJVMCIBackendFactory.java | 2 +- .../AMD64HotSpotJVMCIBackendFactory.java | 7 +- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 7 +- .../RISCV64HotSpotJVMCIBackendFactory.java | 2 +- .../serviceability/sa/ClhsdbLongConstant.java | 2 +- 26 files changed, 411 insertions(+), 283 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index b2d3455348791..0b08ad3b4b749 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -702,6 +702,8 @@ void VM_Version::print_platform_virtualization_info(outputStream* st) { #endif } +void VM_Version::pre_initialize() {} + void VM_Version::initialize_cpu_information(void) { // do nothing if cpu info has been initialized if (_initialized) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 04cf9c9c2a07c..c2d0bceec9562 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -63,6 +63,7 @@ class VM_Version : public Abstract_VM_Version { public: // Initialization + static void pre_initialize(); static void initialize(); static void check_virtualizations(); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 11c89da200538..8e6949603d7b8 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -39,6 +39,7 @@ class VM_Version: public Abstract_VM_Version { static bool _is_initialized; public: + static void pre_initialize(); static void initialize(); static bool is_initialized() { return _is_initialized; } diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp index 148786a55da41..0f8813f19fd8c 100644 --- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp +++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp @@ -353,6 +353,8 @@ void VM_Version::initialize() { _is_initialized = true; } +void VM_Version::pre_initialize() {} + void VM_Version::initialize_cpu_information(void) { // do nothing if cpu info has been initialized if (_initialized) { diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 8ec69bffe15ea..3af717494ebac 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -53,6 +53,8 @@ uint64_t VM_Version::_dscr_val = 0; "warning: -XX:+" #flag " requires -XX:+UseSIGTRAP\n" \ " -XX:+" #flag " will be disabled!\n"); +void VM_Version::pre_initialize() {} + void VM_Version::initialize() { // Test which instructions are supported and measure cache line size. diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index 6096f8e4fd113..c3b86094a1261 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -85,6 +85,7 @@ class VM_Version: public Abstract_VM_Version { public: // Initialization + static void pre_initialize(); static void initialize(); static void check_virtualizations(); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 8dcffc9c646fc..34150a66ba883 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -64,6 +64,8 @@ void VM_Version::initialize() { #endif // COMPILER2 } +void VM_Version::pre_initialize() {} + void VM_Version::common_initialize() { _supports_atomic_getset4 = true; _supports_atomic_getadd4 = true; diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 4214d6c53dc95..0582e8414891c 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -305,6 +305,7 @@ class VM_Version : public Abstract_VM_Version { public: // Initialization + static void pre_initialize(); static void initialize(); static void initialize_cpu_information(); diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 157b945e6e1a4..58bc1b2e70845 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -88,6 +88,8 @@ static const char* z_features[] = {" ", "bear_enh, sort_enh, nnpa_assist, storage_key_removal, vpack_decimal_enh" }; +void VM_Version::pre_initialize() {} + void VM_Version::initialize() { determine_features(); // Get processor capabilities. set_features_string(); // Set a descriptive feature indication. diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 49e6f5686f60a..b777308b64f0d 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -411,6 +411,7 @@ class VM_Version: public Abstract_VM_Version { }; // Initialization + static void pre_initialize(); static void initialize(); static void print_features(); static bool is_determine_features_test_running() { return _is_determine_features_test_running; } diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index f360d60de9a8a..2fa552ef7174f 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -51,10 +51,6 @@ VM_Version::CpuidInfo VM_Version::_cpuid_info = { 0, }; const char* VM_Version::_features_names[] = { CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_NAME)}; #undef DECLARE_CPU_FEATURE_FLAG -#define DECLARE_EXTRA_CPU_FEATURE_NAME(id, name, bit) name, -const char* VM_Version::_extra_features_names[] = { EXTRA_CPU_FEATURE_FLAGS(DECLARE_EXTRA_CPU_FEATURE_NAME)}; -#undef DECLARE_EXTRA_CPU_FEATURE_FLAG - // Address of instruction which causes SEGV address VM_Version::_cpuinfo_segv_addr = nullptr; // Address of instruction after the one which causes SEGV @@ -88,7 +84,7 @@ bool VM_Version::supports_clflush() { // up. Assembler::flush calls this routine to check that clflush // is allowed. So, we give the caller a free pass if Universe init // is still in progress. - assert ((!Universe::is_fully_initialized() || (_features & CPU_FLUSH) != 0), "clflush should be available"); + assert ((!Universe::is_fully_initialized() || SUPPORTS_CPU_FEATURE(CPU_FLUSH)), "clflush should be available"); return true; } #endif @@ -875,7 +871,6 @@ void VM_Version::get_processor_features() { _cpu = 4; // 486 by default _model = 0; _stepping = 0; - _features = 0; _logical_processors_per_package = 1; // i486 internal cache is both I&D and has a 16-byte line size _L1_data_cache_line_size = 16; @@ -890,9 +885,8 @@ void VM_Version::get_processor_features() { _stepping = cpu_stepping(); if (cpu_family() > 4) { // it supports CPUID - _features = _cpuid_info.feature_flags(); // These can be changed by VM settings - _extra_features = _cpuid_info.extra_feature_flags(); // These can be changed by VM settings - _cpu_features = _features; // Preserve features + _cpuid_info.feature_flags(); // These can be changed by VM settings + memcpy(_dynamic_cpu_features_vector, _dynamic_features_vector, sizeof(uint64_t) * _dynamic_features_vector_size); // Preserve features // Logical processors are only available on P4s and above, // and only if hyperthreading is available. _logical_processors_per_package = logical_processor_count(); @@ -948,21 +942,21 @@ void VM_Version::get_processor_features() { } if (UseSSE < 4) { - _features &= ~CPU_SSE4_1; - _features &= ~CPU_SSE4_2; + CLEAR_CPU_FEATURE(CPU_SSE4_1); + CLEAR_CPU_FEATURE(CPU_SSE4_2); } if (UseSSE < 3) { - _features &= ~CPU_SSE3; - _features &= ~CPU_SSSE3; - _features &= ~CPU_SSE4A; + CLEAR_CPU_FEATURE(CPU_SSE3); + CLEAR_CPU_FEATURE(CPU_SSSE3); + CLEAR_CPU_FEATURE(CPU_SSE4A); } if (UseSSE < 2) - _features &= ~CPU_SSE2; + CLEAR_CPU_FEATURE(CPU_SSE2); if (UseSSE < 1) - _features &= ~CPU_SSE; + CLEAR_CPU_FEATURE(CPU_SSE); //since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0. if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) { @@ -1028,25 +1022,25 @@ void VM_Version::get_processor_features() { } if (UseAVX < 3) { - _features &= ~CPU_AVX512F; - _features &= ~CPU_AVX512DQ; - _features &= ~CPU_AVX512CD; - _features &= ~CPU_AVX512BW; - _features &= ~CPU_AVX512ER; - _features &= ~CPU_AVX512PF; - _features &= ~CPU_AVX512VL; - _features &= ~CPU_AVX512_VPOPCNTDQ; - _features &= ~CPU_AVX512_VPCLMULQDQ; - _features &= ~CPU_AVX512_VAES; - _features &= ~CPU_AVX512_VNNI; - _features &= ~CPU_AVX512_VBMI; - _features &= ~CPU_AVX512_VBMI2; - _features &= ~CPU_AVX512_BITALG; - _features &= ~CPU_AVX512_IFMA; - _features &= ~CPU_APX_F; - _features &= ~CPU_AVX512_FP16; - _features &= ~CPU_AVX10_1; - _features &= ~EXTRA_CPU_AVX10_2; + CLEAR_CPU_FEATURE(CPU_AVX512F); + CLEAR_CPU_FEATURE(CPU_AVX512DQ); + CLEAR_CPU_FEATURE(CPU_AVX512CD); + CLEAR_CPU_FEATURE(CPU_AVX512BW); + CLEAR_CPU_FEATURE(CPU_AVX512ER); + CLEAR_CPU_FEATURE(CPU_AVX512PF); + CLEAR_CPU_FEATURE(CPU_AVX512VL); + CLEAR_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); + CLEAR_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); + CLEAR_CPU_FEATURE(CPU_AVX512_VAES); + CLEAR_CPU_FEATURE(CPU_AVX512_VNNI); + CLEAR_CPU_FEATURE(CPU_AVX512_VBMI); + CLEAR_CPU_FEATURE(CPU_AVX512_VBMI2); + CLEAR_CPU_FEATURE(CPU_AVX512_BITALG); + CLEAR_CPU_FEATURE(CPU_AVX512_IFMA); + CLEAR_CPU_FEATURE(CPU_APX_F); + CLEAR_CPU_FEATURE(CPU_AVX512_FP16); + CLEAR_CPU_FEATURE(CPU_AVX10_1); + CLEAR_CPU_FEATURE(CPU_AVX10_2); } // Currently APX support is only enabled for targets supporting AVX512VL feature. @@ -1059,45 +1053,45 @@ void VM_Version::get_processor_features() { } if (!UseAPX) { - _features &= ~CPU_APX_F; + CLEAR_CPU_FEATURE(CPU_APX_F); } if (UseAVX < 2) { - _features &= ~CPU_AVX2; - _features &= ~CPU_AVX_IFMA; + CLEAR_CPU_FEATURE(CPU_AVX2); + CLEAR_CPU_FEATURE(CPU_AVX_IFMA); } if (UseAVX < 1) { - _features &= ~CPU_AVX; - _features &= ~CPU_VZEROUPPER; - _features &= ~CPU_F16C; - _features &= ~CPU_SHA512; + CLEAR_CPU_FEATURE(CPU_AVX); + CLEAR_CPU_FEATURE(CPU_VZEROUPPER); + CLEAR_CPU_FEATURE(CPU_F16C); + CLEAR_CPU_FEATURE(CPU_SHA512); } if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. - _features &= ~CPU_HT; + CLEAR_CPU_FEATURE(CPU_HT); } if (is_intel()) { // Intel cpus specific settings if (is_knights_family()) { - _features &= ~CPU_VZEROUPPER; - _features &= ~CPU_AVX512BW; - _features &= ~CPU_AVX512VL; - _features &= ~CPU_AVX512DQ; - _features &= ~CPU_AVX512_VNNI; - _features &= ~CPU_AVX512_VAES; - _features &= ~CPU_AVX512_VPOPCNTDQ; - _features &= ~CPU_AVX512_VPCLMULQDQ; - _features &= ~CPU_AVX512_VBMI; - _features &= ~CPU_AVX512_VBMI2; - _features &= ~CPU_CLWB; - _features &= ~CPU_FLUSHOPT; - _features &= ~CPU_GFNI; - _features &= ~CPU_AVX512_BITALG; - _features &= ~CPU_AVX512_IFMA; - _features &= ~CPU_AVX_IFMA; - _features &= ~CPU_AVX512_FP16; + CLEAR_CPU_FEATURE(CPU_VZEROUPPER); + CLEAR_CPU_FEATURE(CPU_AVX512BW); + CLEAR_CPU_FEATURE(CPU_AVX512VL); + CLEAR_CPU_FEATURE(CPU_AVX512DQ); + CLEAR_CPU_FEATURE(CPU_AVX512_VNNI); + CLEAR_CPU_FEATURE(CPU_AVX512_VAES); + CLEAR_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); + CLEAR_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); + CLEAR_CPU_FEATURE(CPU_AVX512_VBMI); + CLEAR_CPU_FEATURE(CPU_AVX512_VBMI2); + CLEAR_CPU_FEATURE(CPU_CLWB); + CLEAR_CPU_FEATURE(CPU_FLUSHOPT); + CLEAR_CPU_FEATURE(CPU_GFNI); + CLEAR_CPU_FEATURE(CPU_AVX512_BITALG); + CLEAR_CPU_FEATURE(CPU_AVX512_IFMA); + CLEAR_CPU_FEATURE(CPU_AVX_IFMA); + CLEAR_CPU_FEATURE(CPU_AVX512_FP16); } } @@ -1108,15 +1102,16 @@ void VM_Version::get_processor_features() { } char buf[2048] = {'\0'}; - int res = jio_snprintf( + size_t res = jio_snprintf( buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(res > 0, "not enough temporary space allocated"); - insert_features_names(_features, buf + res, sizeof(buf) - res, _features_names); - res = (int)strlen(buf); - insert_features_names(_extra_features, buf + res, sizeof(buf) - res, _extra_features_names); + for (uint64_t i = 0; i < _dynamic_features_vector_size; i++) { + insert_features_names(_dynamic_features_vector[i], buf + res, sizeof(buf) - res, _features_names, 64 * i); + res = strlen(buf); + } _features_string = os::strdup(buf); @@ -2199,6 +2194,15 @@ void VM_Version::clear_apx_test_state() { static bool _vm_version_initialized = false; +void VM_Version::pre_initialize() { + _dynamic_features_element_shift_count = 6; + _dynamic_features_vector_size = (MAX_CPU_FEATURES >> _dynamic_features_element_shift_count) + 1; + _dynamic_features_vector = NEW_C_HEAP_ARRAY(uint64_t, _dynamic_features_vector_size, mtInternal); + _dynamic_cpu_features_vector = NEW_C_HEAP_ARRAY(uint64_t, _dynamic_features_vector_size, mtInternal); + memset(_dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); + memset(_dynamic_cpu_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); +} + void VM_Version::initialize() { ResourceMark rm; // Making this stub must be FIRST use of assembler @@ -2979,112 +2983,96 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) { return _max_qualified_cpu_frequency; } -uint64_t VM_Version::CpuidInfo::extra_feature_flags() const { - uint64_t result = 0; - if (is_intel()) { - if (sefsl1_cpuid7_edx.bits.avx10 != 0 && - std_cpuid24_ebx.bits.avx10_vlen_512 !=0 && - std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2 && - xem_xcr0_eax.bits.opmask != 0 && - xem_xcr0_eax.bits.zmm512 != 0 && - xem_xcr0_eax.bits.zmm32 != 0) { - result |= EXTRA_CPU_AVX10_2; - } - } - return result; -} - -uint64_t VM_Version::CpuidInfo::feature_flags() const { - uint64_t result = 0; +void VM_Version::CpuidInfo::feature_flags() const { if (std_cpuid1_edx.bits.cmpxchg8 != 0) - result |= CPU_CX8; + SET_CPU_FEATURE(CPU_CX8); if (std_cpuid1_edx.bits.cmov != 0) - result |= CPU_CMOV; + SET_CPU_FEATURE(CPU_CMOV); if (std_cpuid1_edx.bits.clflush != 0) - result |= CPU_FLUSH; + SET_CPU_FEATURE(CPU_FLUSH); #ifdef _LP64 // clflush should always be available on x86_64 // if not we are in real trouble because we rely on it // to flush the code cache. - assert ((result & CPU_FLUSH) != 0, "clflush should be available"); + assert (SUPPORTS_CPU_FEATURE(CPU_FLUSH), "clflush should be available"); #endif if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() && ext_cpuid1_edx.bits.fxsr != 0)) - result |= CPU_FXSR; + SET_CPU_FEATURE(CPU_FXSR); // HT flag is set for multi-core processors also. if (threads_per_core() > 1) - result |= CPU_HT; + SET_CPU_FEATURE(CPU_HT); if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() && ext_cpuid1_edx.bits.mmx != 0)) - result |= CPU_MMX; + SET_CPU_FEATURE(CPU_MMX); if (std_cpuid1_edx.bits.sse != 0) - result |= CPU_SSE; + SET_CPU_FEATURE(CPU_SSE); if (std_cpuid1_edx.bits.sse2 != 0) - result |= CPU_SSE2; + SET_CPU_FEATURE(CPU_SSE2); if (std_cpuid1_ecx.bits.sse3 != 0) - result |= CPU_SSE3; + SET_CPU_FEATURE(CPU_SSE3); if (std_cpuid1_ecx.bits.ssse3 != 0) - result |= CPU_SSSE3; + SET_CPU_FEATURE(CPU_SSSE3); if (std_cpuid1_ecx.bits.sse4_1 != 0) - result |= CPU_SSE4_1; + SET_CPU_FEATURE(CPU_SSE4_1); if (std_cpuid1_ecx.bits.sse4_2 != 0) - result |= CPU_SSE4_2; + SET_CPU_FEATURE(CPU_SSE4_2); if (std_cpuid1_ecx.bits.popcnt != 0) - result |= CPU_POPCNT; + SET_CPU_FEATURE(CPU_POPCNT); if (sefsl1_cpuid7_edx.bits.apx_f != 0 && xem_xcr0_eax.bits.apx_f != 0) { - result |= CPU_APX_F; + SET_CPU_FEATURE(CPU_APX_F); } if (std_cpuid1_ecx.bits.avx != 0 && std_cpuid1_ecx.bits.osxsave != 0 && xem_xcr0_eax.bits.sse != 0 && xem_xcr0_eax.bits.ymm != 0) { - result |= CPU_AVX; - result |= CPU_VZEROUPPER; + SET_CPU_FEATURE(CPU_AVX); + SET_CPU_FEATURE(CPU_VZEROUPPER); if (sefsl1_cpuid7_eax.bits.sha512 != 0) - result |= CPU_SHA512; + SET_CPU_FEATURE(CPU_SHA512); if (std_cpuid1_ecx.bits.f16c != 0) - result |= CPU_F16C; + SET_CPU_FEATURE(CPU_F16C); if (sef_cpuid7_ebx.bits.avx2 != 0) { - result |= CPU_AVX2; + SET_CPU_FEATURE(CPU_AVX2); if (sefsl1_cpuid7_eax.bits.avx_ifma != 0) - result |= CPU_AVX_IFMA; + SET_CPU_FEATURE(CPU_AVX_IFMA); } if (sef_cpuid7_ecx.bits.gfni != 0) - result |= CPU_GFNI; + SET_CPU_FEATURE(CPU_GFNI); if (sef_cpuid7_ebx.bits.avx512f != 0 && xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - result |= CPU_AVX512F; + SET_CPU_FEATURE(CPU_AVX512F); if (sef_cpuid7_ebx.bits.avx512cd != 0) - result |= CPU_AVX512CD; + SET_CPU_FEATURE(CPU_AVX512CD); if (sef_cpuid7_ebx.bits.avx512dq != 0) - result |= CPU_AVX512DQ; + SET_CPU_FEATURE(CPU_AVX512DQ); if (sef_cpuid7_ebx.bits.avx512ifma != 0) - result |= CPU_AVX512_IFMA; + SET_CPU_FEATURE(CPU_AVX512_IFMA); if (sef_cpuid7_ebx.bits.avx512pf != 0) - result |= CPU_AVX512PF; + SET_CPU_FEATURE(CPU_AVX512PF); if (sef_cpuid7_ebx.bits.avx512er != 0) - result |= CPU_AVX512ER; + SET_CPU_FEATURE(CPU_AVX512ER); if (sef_cpuid7_ebx.bits.avx512bw != 0) - result |= CPU_AVX512BW; + SET_CPU_FEATURE(CPU_AVX512BW); if (sef_cpuid7_ebx.bits.avx512vl != 0) - result |= CPU_AVX512VL; + SET_CPU_FEATURE(CPU_AVX512VL); if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0) - result |= CPU_AVX512_VPOPCNTDQ; + SET_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0) - result |= CPU_AVX512_VPCLMULQDQ; + SET_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); if (sef_cpuid7_ecx.bits.vaes != 0) - result |= CPU_AVX512_VAES; + SET_CPU_FEATURE(CPU_AVX512_VAES); if (sef_cpuid7_ecx.bits.avx512_vnni != 0) - result |= CPU_AVX512_VNNI; + SET_CPU_FEATURE(CPU_AVX512_VNNI); if (sef_cpuid7_ecx.bits.avx512_bitalg != 0) - result |= CPU_AVX512_BITALG; + SET_CPU_FEATURE(CPU_AVX512_BITALG); if (sef_cpuid7_ecx.bits.avx512_vbmi != 0) - result |= CPU_AVX512_VBMI; + SET_CPU_FEATURE(CPU_AVX512_VBMI); if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0) - result |= CPU_AVX512_VBMI2; + SET_CPU_FEATURE(CPU_AVX512_VBMI2); } if (is_intel()) { if (sefsl1_cpuid7_edx.bits.avx10 != 0 && @@ -3093,114 +3081,114 @@ uint64_t VM_Version::CpuidInfo::feature_flags() const { xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - result |= CPU_AVX10_1; - result |= CPU_AVX_IFMA; - result |= CPU_AVX512F; - result |= CPU_AVX512CD; - result |= CPU_AVX512DQ; - result |= CPU_AVX512PF; - result |= CPU_AVX512ER; - result |= CPU_AVX512BW; - result |= CPU_AVX512VL; - result |= CPU_AVX512_VPOPCNTDQ; - result |= CPU_AVX512_VPCLMULQDQ; - result |= CPU_AVX512_VAES; - result |= CPU_AVX512_VNNI; - result |= CPU_AVX512_BITALG; - result |= CPU_AVX512_VBMI; - result |= CPU_AVX512_VBMI2; + SET_CPU_FEATURE(CPU_AVX10_1); + SET_CPU_FEATURE(CPU_AVX512F); + SET_CPU_FEATURE(CPU_AVX512CD); + SET_CPU_FEATURE(CPU_AVX512DQ); + SET_CPU_FEATURE(CPU_AVX512PF); + SET_CPU_FEATURE(CPU_AVX512ER); + SET_CPU_FEATURE(CPU_AVX512BW); + SET_CPU_FEATURE(CPU_AVX512VL); + SET_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); + SET_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); + SET_CPU_FEATURE(CPU_AVX512_VAES); + SET_CPU_FEATURE(CPU_AVX512_VNNI); + SET_CPU_FEATURE(CPU_AVX512_BITALG); + SET_CPU_FEATURE(CPU_AVX512_VBMI); + SET_CPU_FEATURE(CPU_AVX512_VBMI2); + if (std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2) { + SET_CPU_FEATURE(CPU_AVX10_2); + } } } } if (std_cpuid1_ecx.bits.hv != 0) - result |= CPU_HV; + SET_CPU_FEATURE(CPU_HV); if (sef_cpuid7_ebx.bits.bmi1 != 0) - result |= CPU_BMI1; + SET_CPU_FEATURE(CPU_BMI1); if (std_cpuid1_edx.bits.tsc != 0) - result |= CPU_TSC; + SET_CPU_FEATURE(CPU_TSC); if (ext_cpuid7_edx.bits.tsc_invariance != 0) - result |= CPU_TSCINV_BIT; + SET_CPU_FEATURE(CPU_TSCINV_BIT); if (std_cpuid1_ecx.bits.aes != 0) - result |= CPU_AES; + SET_CPU_FEATURE(CPU_AES); if (ext_cpuid1_ecx.bits.lzcnt != 0) - result |= CPU_LZCNT; + SET_CPU_FEATURE(CPU_LZCNT); if (ext_cpuid1_ecx.bits.prefetchw != 0) - result |= CPU_3DNOW_PREFETCH; + SET_CPU_FEATURE(CPU_3DNOW_PREFETCH); if (sef_cpuid7_ebx.bits.erms != 0) - result |= CPU_ERMS; + SET_CPU_FEATURE(CPU_ERMS); if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0) - result |= CPU_FSRM; + SET_CPU_FEATURE(CPU_FSRM); if (std_cpuid1_ecx.bits.clmul != 0) - result |= CPU_CLMUL; + SET_CPU_FEATURE(CPU_CLMUL); if (sef_cpuid7_ebx.bits.rtm != 0) - result |= CPU_RTM; + SET_CPU_FEATURE(CPU_RTM); if (sef_cpuid7_ebx.bits.adx != 0) - result |= CPU_ADX; + SET_CPU_FEATURE(CPU_ADX); if (sef_cpuid7_ebx.bits.bmi2 != 0) - result |= CPU_BMI2; + SET_CPU_FEATURE(CPU_BMI2); if (sef_cpuid7_ebx.bits.sha != 0) - result |= CPU_SHA; + SET_CPU_FEATURE(CPU_SHA); if (std_cpuid1_ecx.bits.fma != 0) - result |= CPU_FMA; + SET_CPU_FEATURE(CPU_FMA); if (sef_cpuid7_ebx.bits.clflushopt != 0) - result |= CPU_FLUSHOPT; + SET_CPU_FEATURE(CPU_FLUSHOPT); if (sef_cpuid7_ebx.bits.clwb != 0) - result |= CPU_CLWB; + SET_CPU_FEATURE(CPU_CLWB); if (ext_cpuid1_edx.bits.rdtscp != 0) - result |= CPU_RDTSCP; + SET_CPU_FEATURE(CPU_RDTSCP); if (sef_cpuid7_ecx.bits.rdpid != 0) - result |= CPU_RDPID; + SET_CPU_FEATURE(CPU_RDPID); // AMD|Hygon additional features. if (is_amd_family()) { // PREFETCHW was checked above, check TDNOW here. if ((ext_cpuid1_edx.bits.tdnow != 0)) - result |= CPU_3DNOW_PREFETCH; + SET_CPU_FEATURE(CPU_3DNOW_PREFETCH); if (ext_cpuid1_ecx.bits.sse4a != 0) - result |= CPU_SSE4A; + SET_CPU_FEATURE(CPU_SSE4A); } // Intel additional features. if (is_intel()) { if (sef_cpuid7_edx.bits.serialize != 0) - result |= CPU_SERIALIZE; + SET_CPU_FEATURE(CPU_SERIALIZE); if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0) - result |= CPU_AVX512_FP16; + SET_CPU_FEATURE(CPU_AVX512_FP16); } // ZX additional features. if (is_zx()) { // We do not know if these are supported by ZX, so we cannot trust // common CPUID bit for them. - assert((result & CPU_CLWB) == 0, "Check if it is supported?"); - result &= ~CPU_CLWB; + assert(SUPPORTS_CPU_FEATURE(CPU_CLWB), "Check if it is supported?"); + CLEAR_CPU_FEATURE(CPU_CLWB); } // Protection key features. if (sef_cpuid7_ecx.bits.pku != 0) { - result |= CPU_PKU; + SET_CPU_FEATURE(CPU_PKU); } if (sef_cpuid7_ecx.bits.ospke != 0) { - result |= CPU_OSPKE; + SET_CPU_FEATURE(CPU_OSPKE); } // Control flow enforcement (CET) features. if (sef_cpuid7_ecx.bits.cet_ss != 0) { - result |= CPU_CET_SS; + SET_CPU_FEATURE(CPU_CET_SS); } if (sef_cpuid7_edx.bits.cet_ibt != 0) { - result |= CPU_CET_IBT; + SET_CPU_FEATURE(CPU_CET_IBT); } // Composite features. if (supports_tscinv_bit() && ((is_amd_family() && !is_amd_Barcelona()) || is_intel_tsc_synched_at_init())) { - result |= CPU_TSCINV; + SET_CPU_FEATURE(CPU_TSCINV); } - - return result; } bool VM_Version::os_supports_avx_vectors() { diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index c39d186a05429..f91d276bfe8e7 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -364,7 +364,7 @@ class VM_Version : public Abstract_VM_Version { * test/lib-test/jdk/test/whitebox/CPUInfoTest.java * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java */ - enum Feature_Flag : uint64_t { + enum Feature_Flag : uint32_t { #define CPU_FEATURE_FLAGS(decl) \ decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \ decl(CMOV, "cmov", 1) \ @@ -441,29 +441,17 @@ class VM_Version : public Abstract_VM_Version { decl(APX_F, "apx_f", 60) /* Intel Advanced Performance Extensions*/ \ decl(SHA512, "sha512", 61) /* SHA512 instructions*/ \ decl(AVX512_FP16, "avx512_fp16", 62) /* AVX512 FP16 ISA support*/ \ - decl(AVX10_1, "avx10_1", 63) /* AVX10 512 bit vector ISA Version 1 support*/ + decl(AVX10_1, "avx10_1", 63) /* AVX10 512 bit vector ISA Version 1 support*/ \ + decl(AVX10_2, "avx10_2", 64) /* AVX10 512 bit vector ISA Version 2 support*/ -#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (1ULL << bit), +#define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (bit), CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) #undef DECLARE_CPU_FEATURE_FLAG }; - /* - * Update following files when declaring new flags: - * test/lib-test/jdk/test/whitebox/CPUInfoTest.java - * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java - */ - enum Extra_Feature_Flag : uint64_t { -#define EXTRA_CPU_FEATURE_FLAGS(decl) \ - decl(AVX10_2, "avx10_2", 0) /* AVX10 512 bit vector ISA Version 2 support*/ - -#define DECLARE_EXTRA_CPU_FEATURE_FLAG(id, name, bit) EXTRA_CPU_##id = (1ULL << bit), - EXTRA_CPU_FEATURE_FLAGS(DECLARE_EXTRA_CPU_FEATURE_FLAG) -#undef DECLARE_EXTRA_CPU_FEATURE_FLAG - }; +#define MAX_CPU_FEATURES 64 static const char* _features_names[]; - static const char* _extra_features_names[]; enum Extended_Family { // AMD @@ -606,8 +594,7 @@ class VM_Version : public Abstract_VM_Version { // Space to save apx registers after signal handle jlong apx_save[2]; // Save r16 and r31 - uint64_t feature_flags() const; - uint64_t extra_feature_flags() const; + void feature_flags() const; // Asserts void assert_is_initialized() const { @@ -687,13 +674,30 @@ class VM_Version : public Abstract_VM_Version { LP64_ONLY(static void clear_apx_test_state()); - static void clean_cpuFeatures() { _features = 0; } - static void set_avx_cpuFeatures() { _features |= (CPU_SSE | CPU_SSE2 | CPU_AVX | CPU_VZEROUPPER ); } - static void set_evex_cpuFeatures() { _features |= (CPU_AVX10_1 | CPU_AVX512F | CPU_SSE | CPU_SSE2 | CPU_VZEROUPPER ); } - static void set_apx_cpuFeatures() { _features |= CPU_APX_F; } - static void set_bmi_cpuFeatures() { _features |= (CPU_BMI1 | CPU_BMI2 | CPU_LZCNT | CPU_POPCNT); } + static void clean_cpuFeatures() { memset(_dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); } + static void set_avx_cpuFeatures() { + SET_CPU_FEATURE(CPU_SSE); + SET_CPU_FEATURE(CPU_SSE2); + SET_CPU_FEATURE(CPU_AVX); + SET_CPU_FEATURE(CPU_VZEROUPPER); + } + static void set_evex_cpuFeatures() { + SET_CPU_FEATURE(CPU_AVX10_1); + SET_CPU_FEATURE(CPU_AVX512F); + SET_CPU_FEATURE(CPU_SSE); + SET_CPU_FEATURE(CPU_SSE2); + SET_CPU_FEATURE(CPU_VZEROUPPER); + } + static void set_apx_cpuFeatures() { SET_CPU_FEATURE(CPU_APX_F); } + static void set_bmi_cpuFeatures() { + SET_CPU_FEATURE(CPU_BMI1); + SET_CPU_FEATURE(CPU_BMI2); + SET_CPU_FEATURE(CPU_LZCNT); + SET_CPU_FEATURE(CPU_POPCNT); + } // Initialization + static void pre_initialize(); static void initialize(); // Override Abstract_VM_Version implementation @@ -746,40 +750,40 @@ class VM_Version : public Abstract_VM_Version { // // Feature identification which can be affected by VM settings // - static bool supports_cpuid() { return _features != 0; } - static bool supports_cmov() { return (_features & CPU_CMOV) != 0; } - static bool supports_fxsr() { return (_features & CPU_FXSR) != 0; } - static bool supports_ht() { return (_features & CPU_HT) != 0; } - static bool supports_mmx() { return (_features & CPU_MMX) != 0; } - static bool supports_sse() { return (_features & CPU_SSE) != 0; } - static bool supports_sse2() { return (_features & CPU_SSE2) != 0; } - static bool supports_sse3() { return (_features & CPU_SSE3) != 0; } - static bool supports_ssse3() { return (_features & CPU_SSSE3)!= 0; } - static bool supports_sse4_1() { return (_features & CPU_SSE4_1) != 0; } - static bool supports_sse4_2() { return (_features & CPU_SSE4_2) != 0; } - static bool supports_popcnt() { return (_features & CPU_POPCNT) != 0; } - static bool supports_avx() { return (_features & CPU_AVX) != 0; } - static bool supports_avx2() { return (_features & CPU_AVX2) != 0; } - static bool supports_tsc() { return (_features & CPU_TSC) != 0; } - static bool supports_rdtscp() { return (_features & CPU_RDTSCP) != 0; } - static bool supports_rdpid() { return (_features & CPU_RDPID) != 0; } - static bool supports_aes() { return (_features & CPU_AES) != 0; } - static bool supports_erms() { return (_features & CPU_ERMS) != 0; } - static bool supports_fsrm() { return (_features & CPU_FSRM) != 0; } - static bool supports_clmul() { return (_features & CPU_CLMUL) != 0; } - static bool supports_rtm() { return (_features & CPU_RTM) != 0; } - static bool supports_bmi1() { return (_features & CPU_BMI1) != 0; } - static bool supports_bmi2() { return (_features & CPU_BMI2) != 0; } - static bool supports_adx() { return (_features & CPU_ADX) != 0; } - static bool supports_evex() { return (_features & CPU_AVX512F) != 0; } - static bool supports_avx512dq() { return (_features & CPU_AVX512DQ) != 0; } - static bool supports_avx512ifma() { return (_features & CPU_AVX512_IFMA) != 0; } - static bool supports_avxifma() { return (_features & CPU_AVX_IFMA) != 0; } - static bool supports_avx512pf() { return (_features & CPU_AVX512PF) != 0; } - static bool supports_avx512er() { return (_features & CPU_AVX512ER) != 0; } - static bool supports_avx512cd() { return (_features & CPU_AVX512CD) != 0; } - static bool supports_avx512bw() { return (_features & CPU_AVX512BW) != 0; } - static bool supports_avx512vl() { return (_features & CPU_AVX512VL) != 0; } + static bool supports_cpuid() { return _dynamic_features_vector != nullptr; } + static bool supports_cmov() { return SUPPORTS_CPU_FEATURE(CPU_CMOV); } + static bool supports_fxsr() { return SUPPORTS_CPU_FEATURE(CPU_FXSR); } + static bool supports_ht() { return SUPPORTS_CPU_FEATURE(CPU_HT); } + static bool supports_mmx() { return SUPPORTS_CPU_FEATURE(CPU_MMX); } + static bool supports_sse() { return SUPPORTS_CPU_FEATURE(CPU_SSE); } + static bool supports_sse2() { return SUPPORTS_CPU_FEATURE(CPU_SSE2); } + static bool supports_sse3() { return SUPPORTS_CPU_FEATURE(CPU_SSE3); } + static bool supports_ssse3() { return SUPPORTS_CPU_FEATURE(CPU_SSSE3); } + static bool supports_sse4_1() { return SUPPORTS_CPU_FEATURE(CPU_SSE4_1); } + static bool supports_sse4_2() { return SUPPORTS_CPU_FEATURE(CPU_SSE4_2); } + static bool supports_popcnt() { return SUPPORTS_CPU_FEATURE(CPU_POPCNT); } + static bool supports_avx() { return SUPPORTS_CPU_FEATURE(CPU_AVX); } + static bool supports_avx2() { return SUPPORTS_CPU_FEATURE(CPU_AVX2); } + static bool supports_tsc() { return SUPPORTS_CPU_FEATURE(CPU_TSC); } + static bool supports_rdtscp() { return SUPPORTS_CPU_FEATURE(CPU_RDTSCP); } + static bool supports_rdpid() { return SUPPORTS_CPU_FEATURE(CPU_RDPID); } + static bool supports_aes() { return SUPPORTS_CPU_FEATURE(CPU_AES); } + static bool supports_erms() { return SUPPORTS_CPU_FEATURE(CPU_ERMS); } + static bool supports_fsrm() { return SUPPORTS_CPU_FEATURE(CPU_FSRM); } + static bool supports_clmul() { return SUPPORTS_CPU_FEATURE(CPU_CLMUL); } + static bool supports_rtm() { return SUPPORTS_CPU_FEATURE(CPU_RTM); } + static bool supports_bmi1() { return SUPPORTS_CPU_FEATURE(CPU_BMI1); } + static bool supports_bmi2() { return SUPPORTS_CPU_FEATURE(CPU_BMI2); } + static bool supports_adx() { return SUPPORTS_CPU_FEATURE(CPU_ADX); } + static bool supports_evex() { return SUPPORTS_CPU_FEATURE(CPU_AVX512F); } + static bool supports_avx512dq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512DQ); } + static bool supports_avx512ifma() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_IFMA); } + static bool supports_avxifma() { return SUPPORTS_CPU_FEATURE(CPU_AVX_IFMA); } + static bool supports_avx512pf() { return SUPPORTS_CPU_FEATURE(CPU_AVX512PF); } + static bool supports_avx512er() { return SUPPORTS_CPU_FEATURE(CPU_AVX512ER); } + static bool supports_avx512cd() { return SUPPORTS_CPU_FEATURE(CPU_AVX512CD); } + static bool supports_avx512bw() { return SUPPORTS_CPU_FEATURE(CPU_AVX512BW); } + static bool supports_avx512vl() { return SUPPORTS_CPU_FEATURE(CPU_AVX512VL); } static bool supports_avx512vlbw() { return (supports_evex() && supports_avx512bw() && supports_avx512vl()); } static bool supports_avx512bwdq() { return (supports_evex() && supports_avx512bw() && supports_avx512dq()); } static bool supports_avx512vldq() { return (supports_evex() && supports_avx512dq() && supports_avx512vl()); } @@ -788,39 +792,39 @@ class VM_Version : public Abstract_VM_Version { static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } - static bool supports_apx_f() { return (_features & CPU_APX_F) != 0; } + static bool supports_apx_f() { return SUPPORTS_CPU_FEATURE(CPU_APX_F); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } - static bool supports_sha() { return (_features & CPU_SHA) != 0; } - static bool supports_fma() { return (_features & CPU_FMA) != 0 && supports_avx(); } - static bool supports_vzeroupper() { return (_features & CPU_VZEROUPPER) != 0; } - static bool supports_avx512_vpopcntdq() { return (_features & CPU_AVX512_VPOPCNTDQ) != 0; } - static bool supports_avx512_vpclmulqdq() { return (_features & CPU_AVX512_VPCLMULQDQ) != 0; } - static bool supports_avx512_vaes() { return (_features & CPU_AVX512_VAES) != 0; } - static bool supports_gfni() { return (_features & CPU_GFNI) != 0; } - static bool supports_avx512_vnni() { return (_features & CPU_AVX512_VNNI) != 0; } - static bool supports_avx512_bitalg() { return (_features & CPU_AVX512_BITALG) != 0; } - static bool supports_avx512_vbmi() { return (_features & CPU_AVX512_VBMI) != 0; } - static bool supports_avx512_vbmi2() { return (_features & CPU_AVX512_VBMI2) != 0; } - static bool supports_avx512_fp16() { return (_features & CPU_AVX512_FP16) != 0; } - static bool supports_hv() { return (_features & CPU_HV) != 0; } - static bool supports_serialize() { return (_features & CPU_SERIALIZE) != 0; } - static bool supports_f16c() { return (_features & CPU_F16C) != 0; } - static bool supports_pku() { return (_features & CPU_PKU) != 0; } - static bool supports_ospke() { return (_features & CPU_OSPKE) != 0; } - static bool supports_cet_ss() { return (_features & CPU_CET_SS) != 0; } - static bool supports_cet_ibt() { return (_features & CPU_CET_IBT) != 0; } - static bool supports_sha512() { return (_features & CPU_SHA512) != 0; } + static bool supports_sha() { return SUPPORTS_CPU_FEATURE(CPU_SHA); } + static bool supports_fma() { return SUPPORTS_CPU_FEATURE(CPU_FMA) && supports_avx(); } + static bool supports_vzeroupper() { return SUPPORTS_CPU_FEATURE(CPU_VZEROUPPER); } + static bool supports_avx512_vpopcntdq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); } + static bool supports_avx512_vpclmulqdq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); } + static bool supports_avx512_vaes() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VAES); } + static bool supports_gfni() { return SUPPORTS_CPU_FEATURE(CPU_GFNI); } + static bool supports_avx512_vnni() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VNNI); } + static bool supports_avx512_bitalg() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_BITALG); } + static bool supports_avx512_vbmi() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VBMI); } + static bool supports_avx512_vbmi2() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VBMI2); } + static bool supports_avx512_fp16() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_FP16); } + static bool supports_hv() { return SUPPORTS_CPU_FEATURE(CPU_HV); } + static bool supports_serialize() { return SUPPORTS_CPU_FEATURE(CPU_SERIALIZE); } + static bool supports_f16c() { return SUPPORTS_CPU_FEATURE(CPU_F16C); } + static bool supports_pku() { return SUPPORTS_CPU_FEATURE(CPU_PKU); } + static bool supports_ospke() { return SUPPORTS_CPU_FEATURE(CPU_OSPKE); } + static bool supports_cet_ss() { return SUPPORTS_CPU_FEATURE(CPU_CET_SS); } + static bool supports_cet_ibt() { return SUPPORTS_CPU_FEATURE(CPU_CET_IBT); } + static bool supports_sha512() { return SUPPORTS_CPU_FEATURE(CPU_SHA512); } // IntelĀ® AVX10 introduces a versioned approach for enumeration that is monotonically increasing, inclusive, // and supporting all vector lengths. Feature set supported by an AVX10 vector ISA version is also supported // by all the versions above it. - static bool supports_avx10_1() { return (_features & CPU_AVX10_1) != 0;} - static bool supports_avx10_2() { return (_extra_features & EXTRA_CPU_AVX10_2) != 0;} + static bool supports_avx10_1() { return SUPPORTS_CPU_FEATURE(CPU_AVX10_1);} + static bool supports_avx10_2() { return SUPPORTS_CPU_FEATURE(CPU_AVX10_2);} // // Feature identification not affected by VM flags // - static bool cpu_supports_evex() { return (_cpu_features & CPU_AVX512F) != 0; } + static bool cpu_supports_evex() { return SUPPORTS_CPU_FEATURE_AUX(CPU_AVX512F); } static bool supports_avx512_simd_sort() { if (supports_avx512dq()) { @@ -858,19 +862,19 @@ class VM_Version : public Abstract_VM_Version { static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; } // AMD features - static bool supports_3dnow_prefetch() { return (_features & CPU_3DNOW_PREFETCH) != 0; } - static bool supports_lzcnt() { return (_features & CPU_LZCNT) != 0; } - static bool supports_sse4a() { return (_features & CPU_SSE4A) != 0; } + static bool supports_3dnow_prefetch() { return SUPPORTS_CPU_FEATURE(CPU_3DNOW_PREFETCH); } + static bool supports_lzcnt() { return SUPPORTS_CPU_FEATURE(CPU_LZCNT); } + static bool supports_sse4a() { return SUPPORTS_CPU_FEATURE(CPU_SSE4A); } static bool is_amd_Barcelona() { return is_amd() && extended_cpu_family() == CPU_FAMILY_AMD_11H; } // Intel and AMD newer cores support fast timestamps well static bool supports_tscinv_bit() { - return (_features & CPU_TSCINV_BIT) != 0; + return SUPPORTS_CPU_FEATURE(CPU_TSCINV_BIT); } static bool supports_tscinv() { - return (_features & CPU_TSCINV) != 0; + return SUPPORTS_CPU_FEATURE(CPU_TSCINV); } // Intel Core and newer cpus have fast IDIV instruction (excluding Atom). @@ -931,12 +935,12 @@ class VM_Version : public Abstract_VM_Version { #ifdef _LP64 static bool supports_clflush(); // Can't inline due to header file conflict #else - static bool supports_clflush() { return ((_features & CPU_FLUSH) != 0); } + static bool supports_clflush() { return (SUPPORTS_CPU_FEATURE(CPU_FLUSH)); } #endif // _LP64 // Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit - static bool supports_clflushopt() { return ((_features & CPU_FLUSHOPT) != 0); } - static bool supports_clwb() { return ((_features & CPU_CLWB) != 0); } + static bool supports_clflushopt() { return (SUPPORTS_CPU_FEATURE(CPU_FLUSHOPT)); } + static bool supports_clwb() { return (SUPPORTS_CPU_FEATURE(CPU_CLWB)); } // Old CPUs perform lea on AGU which causes additional latency transferring the // value from/to ALU for other operations diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp index e38561e19c571..a79b2291d558a 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.cpp +++ b/src/hotspot/cpu/zero/vm_version_zero.cpp @@ -32,6 +32,8 @@ #include "runtime/vm_version.hpp" +void VM_Version::pre_initialize() {} + void VM_Version::initialize() { // This machine does not allow unaligned memory accesses if (! FLAG_IS_DEFAULT(UseUnalignedAccesses)) { diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 0b5476165a48b..2899a490c4d26 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -31,6 +31,7 @@ class VM_Version : public Abstract_VM_Version { public: + static void pre_initialize(); static void initialize(); constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 2bc484108d62f..a99221ce6f27e 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -144,10 +144,12 @@ \ static_field(CompilerToVM::Data, data_section_item_alignment, int) \ \ - JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ + JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ \ static_field(Abstract_VM_Version, _features, uint64_t) \ - static_field(Abstract_VM_Version, _extra_features, uint64_t) \ + static_field(Abstract_VM_Version, _dynamic_features_vector, uint64_t*) \ + static_field(Abstract_VM_Version, _dynamic_features_vector_size, uint64_t) \ + static_field(Abstract_VM_Version, _dynamic_features_element_shift_count, uint64_t) \ \ nonstatic_field(Annotations, _class_annotations, AnnotationArray*) \ nonstatic_field(Annotations, _fields_annotations, Array*) \ @@ -984,10 +986,8 @@ declare_constant(frame::interpreter_frame_last_sp_offset) #define DECLARE_LONG_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::CPU_##id) -#define DECLARE_LONG_EXTRA_CPU_FEATURE_CONSTANT(id, name, bit) GENERATE_VM_LONG_CONSTANT_ENTRY(VM_Version::EXTRA_CPU_##id) #define VM_LONG_CPU_FEATURE_CONSTANTS \ - CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) \ - EXTRA_CPU_FEATURE_FLAGS(DECLARE_LONG_EXTRA_CPU_FEATURE_CONSTANT) + CPU_FEATURE_FLAGS(DECLARE_LONG_CPU_FEATURE_CONSTANT) #endif diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 4ae08ab962a4f..ca118a5821f57 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -33,10 +33,14 @@ const char* Abstract_VM_Version::_s_vm_release = Abstract_VM_Version::vm_release const char* Abstract_VM_Version::_s_internal_vm_info_string = Abstract_VM_Version::internal_vm_info_string(); uint64_t Abstract_VM_Version::_features = 0; -uint64_t Abstract_VM_Version::_extra_features = 0; const char* Abstract_VM_Version::_features_string = ""; uint64_t Abstract_VM_Version::_cpu_features = 0; +uint64_t* Abstract_VM_Version::_dynamic_features_vector = nullptr; +uint64_t Abstract_VM_Version::_dynamic_features_vector_size = 0; +uint64_t Abstract_VM_Version::_dynamic_features_element_shift_count = 0; +uint64_t* Abstract_VM_Version::_dynamic_cpu_features_vector = nullptr; + #ifndef SUPPORTS_NATIVE_CX8 bool Abstract_VM_Version::_supports_cx8 = false; #endif @@ -325,9 +329,8 @@ unsigned int Abstract_VM_Version::jvm_version() { (Abstract_VM_Version::vm_build_number() & 0xFF); } -void Abstract_VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[]) { - uint features_names_index = 0; - +void Abstract_VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], + uint features_names_index) { while (features != 0) { if (features & 1) { int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]); diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 52021e715bc61..0ae6569c575f5 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -56,14 +56,19 @@ class Abstract_VM_Version: AllStatic { // CPU feature flags, can be affected by VM settings. static uint64_t _features; - // Extra CPU feature flags used when all 64 bits of _features are exhausted for - // on a given target, currently only used for x86_64, can be affected by VM settings. - static uint64_t _extra_features; + static const char* _features_string; // Original CPU feature flags, not affected by VM settings. static uint64_t _cpu_features; + // Dynamically sized feature flags currently only used by x86 backend, + // can be affected by VM settings. + static uint64_t* _dynamic_features_vector; + static uint64_t _dynamic_features_vector_size; + static uint64_t _dynamic_features_element_shift_count; + static uint64_t* _dynamic_cpu_features_vector; + // These are set by machine-dependent initializations #ifndef SUPPORTS_NATIVE_CX8 static bool _supports_cx8; @@ -129,11 +134,63 @@ class Abstract_VM_Version: AllStatic { static const char* jdk_debug_level(); static const char* printable_jdk_debug_level(); - static uint64_t features() { return _features; } - static uint64_t extra_features() { return _extra_features; } + static uint64_t features() { + return _features; + } + + static void set_dynamic_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + _dynamic_features_vector[index] |= (1ULL << (feature & index_mask)); + } + + static void clear_dynamic_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + _dynamic_features_vector[index] &= ~(1ULL << (feature & index_mask)); + } + + static bool supports_dynamic_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + return (_dynamic_features_vector[index] & (1ULL << (feature & index_mask))) != 0; + } + + static void set_cpu_feature_aux(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + _dynamic_cpu_features_vector[index] |= (1ULL << (feature & index_mask)); + } + + static bool supports_cpu_feature_aux(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + return (_dynamic_cpu_features_vector[index] & (1ULL << (feature & index_mask))) != 0; + } + +#define SET_CPU_FEATURE(feature) \ + Abstract_VM_Version::set_dynamic_feature(feature) + +#define CLEAR_CPU_FEATURE(feature) \ + Abstract_VM_Version::clear_dynamic_feature(feature) + +#define SUPPORTS_CPU_FEATURE(feature) \ + Abstract_VM_Version::supports_dynamic_feature(feature) + +#define SET_CPU_FEATURE_AUX(feature) \ + Abstract_VM_Version::set_cpu_feature_aux(feature) + +#define SUPPORTS_CPU_FEATURE_AUX(feature) \ + Abstract_VM_Version::supports_cpu_feature_aux(feature) + static const char* features_string() { return _features_string; } - static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[]); + static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0); static VirtualizationType get_detected_virtualization() { return _detected_virtualization; diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index 417bba6c3fa0b..d5bcff402c60c 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -65,6 +65,7 @@ void classLoader_init1(); void compilationPolicy_init(); void codeCache_init(); void VM_Version_init(); +void VM_Version_pre_init(); void initial_stubs_init(); jint universe_init(); // depends on codeCache_init and initial_stubs_init @@ -123,6 +124,7 @@ jint init_globals() { bytecodes_init(); classLoader_init1(); compilationPolicy_init(); + VM_Version_pre_init(); // allocate feature flags arrays codeCache_init(); VM_Version_init(); // depends on codeCache_init for emitting code // stub routines in initial blob are referenced by later generated code diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index f865380fdb7de..0cdc98902dcee 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -702,6 +702,9 @@ static_field(Abstract_VM_Version, _s_internal_vm_info_string, const char*) \ static_field(Abstract_VM_Version, _features, uint64_t) \ static_field(Abstract_VM_Version, _features_string, const char*) \ + static_field(Abstract_VM_Version, _dynamic_features_vector, uint64_t*) \ + static_field(Abstract_VM_Version, _dynamic_features_vector_size, uint64_t) \ + static_field(Abstract_VM_Version, _dynamic_features_element_shift_count, uint64_t) \ static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_security_version, int) \ diff --git a/src/hotspot/share/runtime/vm_version.cpp b/src/hotspot/share/runtime/vm_version.cpp index 7c5b7fe3f3e97..149f6f01f1321 100644 --- a/src/hotspot/share/runtime/vm_version.cpp +++ b/src/hotspot/share/runtime/vm_version.cpp @@ -27,6 +27,10 @@ #include "memory/resourceArea.hpp" #include "runtime/vm_version.hpp" +void VM_Version_pre_init() { + VM_Version::pre_initialize(); +} + void VM_Version_init() { VM_Version::initialize(); guarantee(VM_Version::supports_cx8(), "Support for 64-bit atomic operations is required"); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 1a3adae7b5300..44c2e21bd6617 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -30,6 +30,7 @@ import jdk.vm.ci.common.JVMCIError; import jdk.vm.ci.runtime.JVMCIBackend; +import static jdk.vm.ci.hotspot.UnsafeAccess.UNSAFE; public interface HotSpotJVMCIBackendFactory { @@ -57,7 +58,6 @@ static > EnumSet con Class enumType, Map constants, long features, - long extra_features, Map renaming) { EnumSet outFeatures = EnumSet.noneOf(enumType); List missing = new ArrayList<>(); @@ -75,11 +75,56 @@ static > EnumSet con missing.add(name); } } - if (key.startsWith("VM_Version::EXTRA_CPU_")) { - String name = key.substring("VM_Version::EXTRA_CPU_".length()); + } + if (!missing.isEmpty()) { + throw new JVMCIError("Missing CPU feature constants: %s", missing); + } + return outFeatures; + } + + /** + * Converts a dynamically sized CPU features vector into enum constants. + * + * @param CPU feature enum type + * @param enumType the class of {@code CPUFeatureType} + * @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"} + * specifies a CPU feature and its value is a mask for a bit in {@code features} + * @param dynamic_features_vector_pointer pointer to dyanmic feature vector specifying CPU features + * @param dynamic_features_vector_size dyanmic feature array size + * @param dynamic_features_element_shift_count log of dyanmic feature vector element size in bits + * @param renaming maps from VM feature names to enum constant names where the two differ + * @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an + * enum value + * @return the set of converted values + */ + static > EnumSet convertDynamicFeaturesVector( + Class enumType, + Map constants, + long dynamic_features_vector_pointer, + long dynamic_features_vector_size, + long dynamic_features_element_shift_count, + Map renaming) { + EnumSet outFeatures = EnumSet.noneOf(enumType); + List missing = new ArrayList<>(); + for (Entry e : constants.entrySet()) { + String key = e.getKey(); + long bitIndex = e.getValue(); + if (key.startsWith("VM_Version::CPU_")) { + String name = key.substring("VM_Version::CPU_".length()); try { CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name)); - if ((extra_features & bitMask) != 0) { + long dynamic_features_vector_index = bitIndex >>> dynamic_features_element_shift_count; + assert dynamic_features_vector_index < dynamic_features_vector_size; + + long dynamic_features_element_bitsize = (1L << dynamic_features_element_shift_count); + assert (dynamic_features_element_bitsize & (dynamic_features_element_bitsize - 1)) == 0; + + long dynamic_features_element_size = dynamic_features_element_bitsize / Byte.SIZE; + long features = UNSAFE.getLong(dynamic_features_vector_pointer + + dynamic_features_vector_index * dynamic_features_element_size); + + long effective_bitMask = 1L << (bitIndex & (dynamic_features_element_bitsize - 1)); + if ((features & effective_bitMask) != 0) { outFeatures.add(feature); } } catch (IllegalArgumentException iae) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java index 0c8f4a5d44ade..890a335767842 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/aarch64/AArch64HotSpotJVMCIBackendFactory.java @@ -49,7 +49,7 @@ public class AArch64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac private static EnumSet computeFeatures(AArch64HotSpotVMConfig config) { // Configure the feature set using the HotSpot flag settings. Map constants = config.getStore().getConstants(); - return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, 0L, emptyMap()); + return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap()); } private static EnumSet computeFlags(AArch64HotSpotVMConfig config) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index bd9b60574dcfb..39dc95feb8916 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -50,8 +50,11 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map constants = config.getStore().getConstants(); Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; - EnumSet features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, - config.vmVersionExtraFeatures, renaming); + EnumSet features = HotSpotJVMCIBackendFactory.convertDynamicFeaturesVector(CPUFeature.class, constants, + config.vmVersionFeaturesVector, + config.vmVersionFeaturesVectorSize, + config.vmVersionFeaturesElemShiftCnt, + renaming); features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE2); return features; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index 67241fffddd80..e4204f5e1c8e9 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -46,8 +46,9 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final int useSSE = getFlag("UseSSE", Integer.class); final int useAVX = getFlag("UseAVX", Integer.class); - final long vmVersionFeatures = getFieldValue("Abstract_VM_Version::_features", Long.class, "uint64_t"); - final long vmVersionExtraFeatures = getFieldValue("Abstract_VM_Version::_extra_features", Long.class, "uint64_t"); + final long vmVersionFeaturesVector = getFieldAddress("Abstract_VM_Version::_dynamic_features_vector", "uint64_t*"); + final long vmVersionFeaturesVectorSize = getFieldValue("Abstract_VM_Version::_dynamic_features_vector_size", Long.class, "uint64_t"); + final long vmVersionFeaturesElemShiftCnt = getFieldValue("Abstract_VM_Version::_dynamic_features_element_shift_count", Long.class, "uint64_t"); // CPU feature flags final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class); @@ -90,5 +91,5 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class); final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class); final long avx10_1 = getConstant("VM_Version::CPU_AVX10_1", Long.class); - final long avx10_2 = getConstant("VM_Version::EXTRA_CPU_AVX10_2", Long.class); + final long avx10_2 = getConstant("VM_Version::CPU_AVX10_2", Long.class); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java index 881cbf983e096..6e0eac91d6100 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/riscv64/RISCV64HotSpotJVMCIBackendFactory.java @@ -49,7 +49,7 @@ public class RISCV64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFac private static EnumSet computeFeatures(RISCV64HotSpotVMConfig config) { // Configure the feature set using the HotSpot flag settings. Map constants = config.getStore().getConstants(); - return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, 0L, emptyMap()); + return HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, constants, config.vmVersionFeatures, emptyMap()); } private static EnumSet computeFlags(RISCV64HotSpotVMConfig config) { diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index 1f039eb73b5e0..5a3336de64d3e 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -105,7 +105,7 @@ private static void checkForTruncation(String longConstantOutput) throws Excepti // Expected value obtained from the CPU_SHA definition in vm_version_x86.hpp checkLongValue("VM_Version::CPU_SHA ", longConstantOutput, - 17179869184L); + 34L); } } From f413e0e1158756c18184e9948f7a1069395ed4fb Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 25 Apr 2025 11:18:58 +0530 Subject: [PATCH 04/16] Fix windows build --- src/hotspot/cpu/x86/vm_version_x86.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index ed0bcb882aa14..ab351e69240bb 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -1126,7 +1126,7 @@ void VM_Version::get_processor_features() { } char buf[2048]; - int res = jio_snprintf( + size_t res = jio_snprintf( buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d microcode 0x%x", cores_per_cpu(), threads_per_core(), From a9258174b847e070b33d9216bb4cc7e95298e8b1 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 2 May 2025 04:27:20 -0700 Subject: [PATCH 05/16] Refactoring code to create a seperate VM_Features class --- src/hotspot/cpu/x86/vm_version_x86.cpp | 16 +-- src/hotspot/cpu/x86/vm_version_x86.hpp | 6 +- .../share/jvmci/jvmciCompilerToVMInit.cpp | 1 + src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 8 +- .../share/runtime/abstract_vm_version.cpp | 37 +++++- .../share/runtime/abstract_vm_version.hpp | 117 +++++++++--------- src/hotspot/share/runtime/vmStructs.cpp | 9 +- .../hotspot/HotSpotJVMCIBackendFactory.java | 20 ++- .../AMD64HotSpotJVMCIBackendFactory.java | 7 +- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 8 +- 10 files changed, 139 insertions(+), 90 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index b991b217bd637..5ede52b19853b 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -858,7 +858,7 @@ void VM_Version::get_processor_features() { if (cpu_family() > 4) { // it supports CPUID _cpuid_info.feature_flags(); // These can be changed by VM settings - memcpy(_dynamic_cpu_features_vector, _dynamic_features_vector, sizeof(uint64_t) * _dynamic_features_vector_size); // Preserve features + Abstract_VM_Version::sync_cpu_features(); // Preserve features // Logical processors are only available on P4s and above, // and only if hyperthreading is available. _logical_processors_per_package = logical_processor_count(); @@ -1097,9 +1097,10 @@ void VM_Version::get_processor_features() { cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(cpu_info_size > 0, "not enough temporary space allocated"); - for (uint64_t i = 0; i < _dynamic_features_vector_size; i++) { - insert_features_names(_dynamic_features_vector[i], buf + cpu_info_size, sizeof(buf) - cpu_info_size, _features_names, 64 * i); - cpu_info_size = strlen(buf); + size_t buf_iter = cpu_info_size; + for (uint64_t i = 0; i < dynamic_features_vector_size(); i++) { + insert_features_names(dynamic_features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i); + buf_iter = strlen(buf); } _cpu_info_string = os::strdup(buf); @@ -2101,12 +2102,7 @@ void VM_Version::clear_apx_test_state() { static bool _vm_version_initialized = false; void VM_Version::pre_initialize() { - _dynamic_features_element_shift_count = 6; - _dynamic_features_vector_size = (MAX_CPU_FEATURES >> _dynamic_features_element_shift_count) + 1; - _dynamic_features_vector = NEW_C_HEAP_ARRAY(uint64_t, _dynamic_features_vector_size, mtInternal); - _dynamic_cpu_features_vector = NEW_C_HEAP_ARRAY(uint64_t, _dynamic_features_vector_size, mtInternal); - memset(_dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); - memset(_dynamic_cpu_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); + Abstract_VM_Version::init_vm_features((MAX_CPU_FEATURES >> 6) + 1, 6); } void VM_Version::initialize() { diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 5559d45bf4419..ed8c621f88601 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -674,7 +674,9 @@ class VM_Version : public Abstract_VM_Version { static void clear_apx_test_state(); - static void clean_cpuFeatures() { memset(_dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features_vector_size); } + static void clean_cpuFeatures() { + Abstract_VM_Version::clear_cpu_features(); + } static void set_avx_cpuFeatures() { SET_CPU_FEATURE(CPU_SSE); SET_CPU_FEATURE(CPU_SSE2); @@ -750,7 +752,7 @@ class VM_Version : public Abstract_VM_Version { // // Feature identification which can be affected by VM settings // - static bool supports_cpuid() { return _dynamic_features_vector != nullptr; } + static bool supports_cpuid() { return Abstract_VM_Version::vm_features_exist(); } static bool supports_cmov() { return SUPPORTS_CPU_FEATURE(CPU_CMOV); } static bool supports_fxsr() { return SUPPORTS_CPU_FEATURE(CPU_FXSR); } static bool supports_ht() { return SUPPORTS_CPU_FEATURE(CPU_HT); } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index a729e34a2796b..005728db1d792 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -449,6 +449,7 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) { strcmp(vmField.typeString, "intptr_t") == 0 || strcmp(vmField.typeString, "uintptr_t") == 0 || strcmp(vmField.typeString, "OopHandle") == 0 || + strcmp(vmField.typeString, "VM_Features") == 0 || strcmp(vmField.typeString, "size_t") == 0 || // All foo* types are addresses. vmField.typeString[strlen(vmField.typeString) - 1] == '*') { diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index a99221ce6f27e..7c1d06d267597 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -147,9 +147,11 @@ JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ \ static_field(Abstract_VM_Version, _features, uint64_t) \ - static_field(Abstract_VM_Version, _dynamic_features_vector, uint64_t*) \ - static_field(Abstract_VM_Version, _dynamic_features_vector_size, uint64_t) \ - static_field(Abstract_VM_Version, _dynamic_features_element_shift_count, uint64_t) \ + static_field(Abstract_VM_Version, _dynamic_features, VM_Features) \ + \ + nonstatic_field(VM_Features, _dynamic_features_vector, uint64_t*) \ + nonstatic_field(VM_Features, _dynamic_features_vector_size, uint32_t) \ + nonstatic_field(VM_Features, _dynamic_features_element_shift_count, uint32_t) \ \ nonstatic_field(Annotations, _class_annotations, AnnotationArray*) \ nonstatic_field(Annotations, _fields_annotations, Array*) \ diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 44af6f428aba3..22ba99ac571d0 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -37,10 +37,8 @@ const char* Abstract_VM_Version::_features_string = ""; const char* Abstract_VM_Version::_cpu_info_string = ""; uint64_t Abstract_VM_Version::_cpu_features = 0; -uint64_t* Abstract_VM_Version::_dynamic_features_vector = nullptr; -uint64_t Abstract_VM_Version::_dynamic_features_vector_size = 0; -uint64_t Abstract_VM_Version::_dynamic_features_element_shift_count = 0; -uint64_t* Abstract_VM_Version::_dynamic_cpu_features_vector = nullptr; +VM_Features Abstract_VM_Version::_dynamic_features = {nullptr, 0, 0}; +VM_Features Abstract_VM_Version::_dynamic_cpu_features = {nullptr, 0, 0}; #ifndef SUPPORTS_NATIVE_CX8 bool Abstract_VM_Version::_supports_cx8 = false; @@ -421,3 +419,34 @@ const char* Abstract_VM_Version::cpu_description(void) { strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); return tmp; } + + +void VM_Features::init_vm_features(uint32_t size, uint32_t elem_shift_count) { + _dynamic_features_vector_size = size; + _dynamic_features_element_shift_count = elem_shift_count; + + uint64_t* features_memory = NEW_C_HEAP_ARRAY(uint64_t, size, mtInternal); + memset(features_memory, 0, sizeof(uint64_t*) * size); + _dynamic_features_vector = features_memory; + } + +void VM_Features::set_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + _dynamic_features_vector[index] |= (1ULL << (feature & index_mask)); +} + +void VM_Features::clear_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + _dynamic_features_vector[index] &= ~(1ULL << (feature & index_mask)); +} + +bool VM_Features::supports_feature(uint32_t feature) { + uint32_t index = feature >> _dynamic_features_element_shift_count; + uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; + assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); + return (_dynamic_features_vector[index] & (1ULL << (feature & index_mask))) != 0; +} diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 1b4818f680a69..384c760c2eb39 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -44,6 +44,23 @@ typedef enum { class outputStream; enum class vmIntrinsicID; +class VM_Features { + public: + // Dynamically sized feature flags currently only used by x86 backend, + // can be affected by VM settings. + uint64_t* _dynamic_features_vector; + uint32_t _dynamic_features_vector_size; + uint32_t _dynamic_features_element_shift_count; + + void init_vm_features(uint32_t size, uint32_t elem_shift_count); + + void set_feature(uint32_t feature); + + void clear_feature(uint32_t feature); + + bool supports_feature(uint32_t feature); +}; + // Abstract_VM_Version provides information about the VM. class Abstract_VM_Version: AllStatic { @@ -64,12 +81,50 @@ class Abstract_VM_Version: AllStatic { // Original CPU feature flags, not affected by VM settings. static uint64_t _cpu_features; - // Dynamically sized feature flags currently only used by x86 backend, - // can be affected by VM settings. - static uint64_t* _dynamic_features_vector; - static uint64_t _dynamic_features_vector_size; - static uint64_t _dynamic_features_element_shift_count; - static uint64_t* _dynamic_cpu_features_vector; + static VM_Features _dynamic_features; + + static VM_Features _dynamic_cpu_features; + +#define SET_CPU_FEATURE(feature) \ + _dynamic_features.set_feature(feature) + +#define CLEAR_CPU_FEATURE(feature) \ + _dynamic_features.clear_feature(feature) + +#define SUPPORTS_CPU_FEATURE(feature) \ + _dynamic_features.supports_feature(feature) + +#define SUPPORTS_CPU_FEATURE_AUX(feature) \ + _dynamic_cpu_features.supports_feature(feature) + + static void init_vm_features(uint32_t size, uint32_t elem_shift_count) { + _dynamic_features.init_vm_features(size, elem_shift_count); + _dynamic_cpu_features.init_vm_features(size, elem_shift_count); + } + + static void sync_cpu_features() { + assert(_dynamic_cpu_features._dynamic_features_vector_size == _dynamic_features._dynamic_features_vector_size, ""); + memcpy(_dynamic_cpu_features._dynamic_features_vector, _dynamic_features._dynamic_features_vector, + sizeof(uint64_t) * _dynamic_features._dynamic_features_vector_size); + } + + static void clear_cpu_features() { + memset(_dynamic_features._dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features._dynamic_features_vector_size); + } + + static bool vm_features_exist() { + return (_dynamic_features._dynamic_features_vector_size > 0) && + (_dynamic_features._dynamic_features_vector != nullptr); + } + + static uint32_t dynamic_features_vector_size() { + return _dynamic_features._dynamic_features_vector_size; + } + + static uint64_t dynamic_features_vector_elem(uint32_t elem) { + assert(elem < _dynamic_features._dynamic_features_vector_size, ""); + return _dynamic_features._dynamic_features_vector[elem]; + } // These are set by machine-dependent initializations #ifndef SUPPORTS_NATIVE_CX8 @@ -140,56 +195,6 @@ class Abstract_VM_Version: AllStatic { return _features; } - static void set_dynamic_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - _dynamic_features_vector[index] |= (1ULL << (feature & index_mask)); - } - - static void clear_dynamic_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - _dynamic_features_vector[index] &= ~(1ULL << (feature & index_mask)); - } - - static bool supports_dynamic_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - return (_dynamic_features_vector[index] & (1ULL << (feature & index_mask))) != 0; - } - - static void set_cpu_feature_aux(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - _dynamic_cpu_features_vector[index] |= (1ULL << (feature & index_mask)); - } - - static bool supports_cpu_feature_aux(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - return (_dynamic_cpu_features_vector[index] & (1ULL << (feature & index_mask))) != 0; - } - -#define SET_CPU_FEATURE(feature) \ - Abstract_VM_Version::set_dynamic_feature(feature) - -#define CLEAR_CPU_FEATURE(feature) \ - Abstract_VM_Version::clear_dynamic_feature(feature) - -#define SUPPORTS_CPU_FEATURE(feature) \ - Abstract_VM_Version::supports_dynamic_feature(feature) - -#define SET_CPU_FEATURE_AUX(feature) \ - Abstract_VM_Version::set_cpu_feature_aux(feature) - -#define SUPPORTS_CPU_FEATURE_AUX(feature) \ - Abstract_VM_Version::supports_cpu_feature_aux(feature) - static const char* features_string() { return _features_string; } static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index a6d3648f1d773..cb9d77ce1a1ce 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -703,13 +703,15 @@ static_field(Abstract_VM_Version, _features, uint64_t) \ static_field(Abstract_VM_Version, _features_string, const char*) \ static_field(Abstract_VM_Version, _cpu_info_string, const char*) \ - static_field(Abstract_VM_Version, _dynamic_features_vector, uint64_t*) \ - static_field(Abstract_VM_Version, _dynamic_features_vector_size, uint64_t) \ - static_field(Abstract_VM_Version, _dynamic_features_element_shift_count, uint64_t) \ static_field(Abstract_VM_Version, _vm_major_version, int) \ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_security_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ + static_field(Abstract_VM_Version, _dynamic_features, VM_Features) \ + \ + nonstatic_field(VM_Features, _dynamic_features_vector, uint64_t*) \ + nonstatic_field(VM_Features, _dynamic_features_vector_size, uint32_t) \ + nonstatic_field(VM_Features, _dynamic_features_element_shift_count, uint32_t) \ \ /*************************/ \ /* JVMTI */ \ @@ -1167,6 +1169,7 @@ /********************/ \ \ declare_toplevel_type(Abstract_VM_Version) \ + declare_toplevel_type(VM_Features) \ \ /*************/ \ /* Arguments */ \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 44c2e21bd6617..10fd84b34bb83 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -89,9 +89,11 @@ static > EnumSet con * @param enumType the class of {@code CPUFeatureType} * @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"} * specifies a CPU feature and its value is a mask for a bit in {@code features} - * @param dynamic_features_vector_pointer pointer to dyanmic feature vector specifying CPU features - * @param dynamic_features_vector_size dyanmic feature array size - * @param dynamic_features_element_shift_count log of dyanmic feature vector element size in bits + * @param dynamic_features_vector_pointer pointer to dynamic feature bit vector of CPU features + * @param dynamic_features_vector_offset offset of dynamic_feature_vector field in {@code VM_Features} + * @param dynamic_features_vector_size_offset offset of dynamic_feature_vector_size field in {@code VM_Features} + * @param dynamic_features_element_shift_count_offset offset of dynamic_features_element_shift_count field in {@code VM_Features} + * ,it holds the base2 logarithmic value of dynamic feature bit vector lanesize in bits. * @param renaming maps from VM feature names to enum constant names where the two differ * @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an * enum value @@ -100,12 +102,18 @@ static > EnumSet con static > EnumSet convertDynamicFeaturesVector( Class enumType, Map constants, - long dynamic_features_vector_pointer, - long dynamic_features_vector_size, - long dynamic_features_element_shift_count, + long dynamic_features_pointer, + long dynamic_features_vector_offset, + long dynamic_features_vector_size_offset, + long dynamic_features_element_shift_count_offset, Map renaming) { EnumSet outFeatures = EnumSet.noneOf(enumType); List missing = new ArrayList<>(); + + long dynamic_features_vector_pointer = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_vector_offset); + long dynamic_features_vector_size = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_vector_size_offset); + long dynamic_features_element_shift_count = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_element_shift_count_offset); + for (Entry e : constants.entrySet()) { String key = e.getKey(); long bitIndex = e.getValue(); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 39dc95feb8916..3a5501f5b18f2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -51,9 +51,10 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; EnumSet features = HotSpotJVMCIBackendFactory.convertDynamicFeaturesVector(CPUFeature.class, constants, - config.vmVersionFeaturesVector, - config.vmVersionFeaturesVectorSize, - config.vmVersionFeaturesElemShiftCnt, + config.vmVersionDynFeatures, + config.vmFeaturesDynFeaturesVecOffset, + config.vmFeaturesDynFeaturesVecSizeOffset, + config.vmFeaturesDynFeaturesElemShiftCntOffset, renaming); features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE2); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index e4204f5e1c8e9..f8107155902ea 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -42,13 +42,15 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); + // CPU capabilities final int useSSE = getFlag("UseSSE", Integer.class); final int useAVX = getFlag("UseAVX", Integer.class); - final long vmVersionFeaturesVector = getFieldAddress("Abstract_VM_Version::_dynamic_features_vector", "uint64_t*"); - final long vmVersionFeaturesVectorSize = getFieldValue("Abstract_VM_Version::_dynamic_features_vector_size", Long.class, "uint64_t"); - final long vmVersionFeaturesElemShiftCnt = getFieldValue("Abstract_VM_Version::_dynamic_features_element_shift_count", Long.class, "uint64_t"); + final long vmFeaturesDynFeaturesVecOffset = getFieldOffset("VM_Features::_dynamic_features_vector", Long.class, "uint64_t*"); + final long vmFeaturesDynFeaturesVecSizeOffset = getFieldOffset("VM_Features::_dynamic_features_vector_size", Long.class, "uint32_t"); + final long vmFeaturesDynFeaturesElemShiftCntOffset = getFieldOffset("VM_Features::_dynamic_features_element_shift_count", Long.class, "uint32_t"); + final long vmVersionDynFeatures = getFieldAddress("Abstract_VM_Version::_dynamic_features", "VM_Features"); // CPU feature flags final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class); From ccfa432ea2d8a086f80cd3bac37873fe67d1a977 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Mon, 5 May 2025 08:52:41 +0530 Subject: [PATCH 06/16] Review comments resolutions --- .../cpu/aarch64/vm_version_aarch64.cpp | 2 - .../cpu/aarch64/vm_version_aarch64.hpp | 1 - src/hotspot/cpu/arm/vm_version_arm.hpp | 1 - src/hotspot/cpu/arm/vm_version_arm_32.cpp | 2 - src/hotspot/cpu/ppc/vm_version_ppc.cpp | 2 - src/hotspot/cpu/ppc/vm_version_ppc.hpp | 1 - src/hotspot/cpu/riscv/vm_version_riscv.cpp | 2 - src/hotspot/cpu/riscv/vm_version_riscv.hpp | 1 - src/hotspot/cpu/s390/vm_version_s390.cpp | 2 - src/hotspot/cpu/s390/vm_version_s390.hpp | 1 - src/hotspot/cpu/x86/vm_version_x86.cpp | 284 +++++++++--------- src/hotspot/cpu/x86/vm_version_x86.hpp | 162 +++++----- src/hotspot/cpu/zero/vm_version_zero.cpp | 2 - src/hotspot/cpu/zero/vm_version_zero.hpp | 1 - src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 8 +- .../share/runtime/abstract_vm_version.cpp | 44 ++- .../share/runtime/abstract_vm_version.hpp | 65 ++-- src/hotspot/share/runtime/init.cpp | 1 - src/hotspot/share/runtime/vmStructs.cpp | 9 +- src/hotspot/share/runtime/vm_version.cpp | 4 - .../hotspot/HotSpotJVMCIBackendFactory.java | 41 ++- .../AMD64HotSpotJVMCIBackendFactory.java | 14 +- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 11 +- .../serviceability/sa/ClhsdbLongConstant.java | 2 +- 24 files changed, 308 insertions(+), 355 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index cededf592678f..6ed7a6be58552 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -707,8 +707,6 @@ void VM_Version::print_platform_virtualization_info(outputStream* st) { #endif } -void VM_Version::pre_initialize() {} - void VM_Version::initialize_cpu_information(void) { // do nothing if cpu info has been initialized if (_initialized) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 252a136a01675..373f8da540589 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -63,7 +63,6 @@ class VM_Version : public Abstract_VM_Version { public: // Initialization - static void pre_initialize(); static void initialize(); static void check_virtualizations(); diff --git a/src/hotspot/cpu/arm/vm_version_arm.hpp b/src/hotspot/cpu/arm/vm_version_arm.hpp index 8e6949603d7b8..11c89da200538 100644 --- a/src/hotspot/cpu/arm/vm_version_arm.hpp +++ b/src/hotspot/cpu/arm/vm_version_arm.hpp @@ -39,7 +39,6 @@ class VM_Version: public Abstract_VM_Version { static bool _is_initialized; public: - static void pre_initialize(); static void initialize(); static bool is_initialized() { return _is_initialized; } diff --git a/src/hotspot/cpu/arm/vm_version_arm_32.cpp b/src/hotspot/cpu/arm/vm_version_arm_32.cpp index 4f72fee538c0e..d094193603567 100644 --- a/src/hotspot/cpu/arm/vm_version_arm_32.cpp +++ b/src/hotspot/cpu/arm/vm_version_arm_32.cpp @@ -353,8 +353,6 @@ void VM_Version::initialize() { _is_initialized = true; } -void VM_Version::pre_initialize() {} - void VM_Version::initialize_cpu_information(void) { // do nothing if cpu info has been initialized if (_initialized) { diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 68da0b7207962..3cb0bf9bf720b 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -53,8 +53,6 @@ uint64_t VM_Version::_dscr_val = 0; "warning: -XX:+" #flag " requires -XX:+UseSIGTRAP\n" \ " -XX:+" #flag " will be disabled!\n"); -void VM_Version::pre_initialize() {} - void VM_Version::initialize() { // Test which instructions are supported and measure cache line size. diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.hpp b/src/hotspot/cpu/ppc/vm_version_ppc.hpp index c3b86094a1261..6096f8e4fd113 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.hpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.hpp @@ -85,7 +85,6 @@ class VM_Version: public Abstract_VM_Version { public: // Initialization - static void pre_initialize(); static void initialize(); static void check_virtualizations(); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 1c91e636fb61b..28c32ed33c824 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -64,8 +64,6 @@ void VM_Version::initialize() { #endif // COMPILER2 } -void VM_Version::pre_initialize() {} - void VM_Version::common_initialize() { _supports_atomic_getset4 = true; _supports_atomic_getadd4 = true; diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 0582e8414891c..4214d6c53dc95 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -305,7 +305,6 @@ class VM_Version : public Abstract_VM_Version { public: // Initialization - static void pre_initialize(); static void initialize(); static void initialize_cpu_information(); diff --git a/src/hotspot/cpu/s390/vm_version_s390.cpp b/src/hotspot/cpu/s390/vm_version_s390.cpp index 71228d4e95863..8261fbd083aae 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.cpp +++ b/src/hotspot/cpu/s390/vm_version_s390.cpp @@ -88,8 +88,6 @@ static const char* z_features[] = {" ", "bear_enh, sort_enh, nnpa_assist, storage_key_removal, vpack_decimal_enh" }; -void VM_Version::pre_initialize() {} - void VM_Version::initialize() { determine_features(); // Get processor capabilities. set_cpu_info_string(); // Set a descriptive feature indication. diff --git a/src/hotspot/cpu/s390/vm_version_s390.hpp b/src/hotspot/cpu/s390/vm_version_s390.hpp index 3bb47419a5e17..6c6eb76bf7b03 100644 --- a/src/hotspot/cpu/s390/vm_version_s390.hpp +++ b/src/hotspot/cpu/s390/vm_version_s390.hpp @@ -411,7 +411,6 @@ class VM_Version: public Abstract_VM_Version { }; // Initialization - static void pre_initialize(); static void initialize(); static void print_features(); static bool is_determine_features_test_running() { return _is_determine_features_test_running; } diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 5ede52b19853b..24f0729874e54 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -82,7 +82,7 @@ bool VM_Version::supports_clflush() { // up. Assembler::flush calls this routine to check that clflush // is allowed. So, we give the caller a free pass if Universe init // is still in progress. - assert ((!Universe::is_fully_initialized() || SUPPORTS_CPU_FEATURE(CPU_FLUSH)), "clflush should be available"); + assert ((!Universe::is_fully_initialized() || _vm_target_features.supports_feature(CPU_FLUSH)), "clflush should be available"); return true; } @@ -857,7 +857,7 @@ void VM_Version::get_processor_features() { _stepping = cpu_stepping(); if (cpu_family() > 4) { // it supports CPUID - _cpuid_info.feature_flags(); // These can be changed by VM settings + _cpuid_info.install_feature_flags(); // These can be changed by VM settings Abstract_VM_Version::sync_cpu_features(); // Preserve features // Logical processors are only available on P4s and above, // and only if hyperthreading is available. @@ -907,21 +907,21 @@ void VM_Version::get_processor_features() { } if (UseSSE < 4) { - CLEAR_CPU_FEATURE(CPU_SSE4_1); - CLEAR_CPU_FEATURE(CPU_SSE4_2); + _vm_target_features.clear_feature(CPU_SSE4_1); + _vm_target_features.clear_feature(CPU_SSE4_2); } if (UseSSE < 3) { - CLEAR_CPU_FEATURE(CPU_SSE3); - CLEAR_CPU_FEATURE(CPU_SSSE3); - CLEAR_CPU_FEATURE(CPU_SSE4A); + _vm_target_features.clear_feature(CPU_SSE3); + _vm_target_features.clear_feature(CPU_SSSE3); + _vm_target_features.clear_feature(CPU_SSE4A); } if (UseSSE < 2) - CLEAR_CPU_FEATURE(CPU_SSE2); + _vm_target_features.clear_feature(CPU_SSE2); if (UseSSE < 1) - CLEAR_CPU_FEATURE(CPU_SSE); + _vm_target_features.clear_feature(CPU_SSE); //since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0. if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) { @@ -987,25 +987,25 @@ void VM_Version::get_processor_features() { } if (UseAVX < 3) { - CLEAR_CPU_FEATURE(CPU_AVX512F); - CLEAR_CPU_FEATURE(CPU_AVX512DQ); - CLEAR_CPU_FEATURE(CPU_AVX512CD); - CLEAR_CPU_FEATURE(CPU_AVX512BW); - CLEAR_CPU_FEATURE(CPU_AVX512ER); - CLEAR_CPU_FEATURE(CPU_AVX512PF); - CLEAR_CPU_FEATURE(CPU_AVX512VL); - CLEAR_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); - CLEAR_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); - CLEAR_CPU_FEATURE(CPU_AVX512_VAES); - CLEAR_CPU_FEATURE(CPU_AVX512_VNNI); - CLEAR_CPU_FEATURE(CPU_AVX512_VBMI); - CLEAR_CPU_FEATURE(CPU_AVX512_VBMI2); - CLEAR_CPU_FEATURE(CPU_AVX512_BITALG); - CLEAR_CPU_FEATURE(CPU_AVX512_IFMA); - CLEAR_CPU_FEATURE(CPU_APX_F); - CLEAR_CPU_FEATURE(CPU_AVX512_FP16); - CLEAR_CPU_FEATURE(CPU_AVX10_1); - CLEAR_CPU_FEATURE(CPU_AVX10_2); + _vm_target_features.clear_feature(CPU_AVX512F); + _vm_target_features.clear_feature(CPU_AVX512DQ); + _vm_target_features.clear_feature(CPU_AVX512CD); + _vm_target_features.clear_feature(CPU_AVX512BW); + _vm_target_features.clear_feature(CPU_AVX512ER); + _vm_target_features.clear_feature(CPU_AVX512PF); + _vm_target_features.clear_feature(CPU_AVX512VL); + _vm_target_features.clear_feature(CPU_AVX512_VPOPCNTDQ); + _vm_target_features.clear_feature(CPU_AVX512_VPCLMULQDQ); + _vm_target_features.clear_feature(CPU_AVX512_VAES); + _vm_target_features.clear_feature(CPU_AVX512_VNNI); + _vm_target_features.clear_feature(CPU_AVX512_VBMI); + _vm_target_features.clear_feature(CPU_AVX512_VBMI2); + _vm_target_features.clear_feature(CPU_AVX512_BITALG); + _vm_target_features.clear_feature(CPU_AVX512_IFMA); + _vm_target_features.clear_feature(CPU_APX_F); + _vm_target_features.clear_feature(CPU_AVX512_FP16); + _vm_target_features.clear_feature(CPU_AVX10_1); + _vm_target_features.clear_feature(CPU_AVX10_2); } // Currently APX support is only enabled for targets supporting AVX512VL feature. @@ -1018,45 +1018,45 @@ void VM_Version::get_processor_features() { } if (!UseAPX) { - CLEAR_CPU_FEATURE(CPU_APX_F); + _vm_target_features.clear_feature(CPU_APX_F); } if (UseAVX < 2) { - CLEAR_CPU_FEATURE(CPU_AVX2); - CLEAR_CPU_FEATURE(CPU_AVX_IFMA); + _vm_target_features.clear_feature(CPU_AVX2); + _vm_target_features.clear_feature(CPU_AVX_IFMA); } if (UseAVX < 1) { - CLEAR_CPU_FEATURE(CPU_AVX); - CLEAR_CPU_FEATURE(CPU_VZEROUPPER); - CLEAR_CPU_FEATURE(CPU_F16C); - CLEAR_CPU_FEATURE(CPU_SHA512); + _vm_target_features.clear_feature(CPU_AVX); + _vm_target_features.clear_feature(CPU_VZEROUPPER); + _vm_target_features.clear_feature(CPU_F16C); + _vm_target_features.clear_feature(CPU_SHA512); } if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. - CLEAR_CPU_FEATURE(CPU_HT); + _vm_target_features.clear_feature(CPU_HT); } if (is_intel()) { // Intel cpus specific settings if (is_knights_family()) { - CLEAR_CPU_FEATURE(CPU_VZEROUPPER); - CLEAR_CPU_FEATURE(CPU_AVX512BW); - CLEAR_CPU_FEATURE(CPU_AVX512VL); - CLEAR_CPU_FEATURE(CPU_AVX512DQ); - CLEAR_CPU_FEATURE(CPU_AVX512_VNNI); - CLEAR_CPU_FEATURE(CPU_AVX512_VAES); - CLEAR_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); - CLEAR_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); - CLEAR_CPU_FEATURE(CPU_AVX512_VBMI); - CLEAR_CPU_FEATURE(CPU_AVX512_VBMI2); - CLEAR_CPU_FEATURE(CPU_CLWB); - CLEAR_CPU_FEATURE(CPU_FLUSHOPT); - CLEAR_CPU_FEATURE(CPU_GFNI); - CLEAR_CPU_FEATURE(CPU_AVX512_BITALG); - CLEAR_CPU_FEATURE(CPU_AVX512_IFMA); - CLEAR_CPU_FEATURE(CPU_AVX_IFMA); - CLEAR_CPU_FEATURE(CPU_AVX512_FP16); + _vm_target_features.clear_feature(CPU_VZEROUPPER); + _vm_target_features.clear_feature(CPU_AVX512BW); + _vm_target_features.clear_feature(CPU_AVX512VL); + _vm_target_features.clear_feature(CPU_AVX512DQ); + _vm_target_features.clear_feature(CPU_AVX512_VNNI); + _vm_target_features.clear_feature(CPU_AVX512_VAES); + _vm_target_features.clear_feature(CPU_AVX512_VPOPCNTDQ); + _vm_target_features.clear_feature(CPU_AVX512_VPCLMULQDQ); + _vm_target_features.clear_feature(CPU_AVX512_VBMI); + _vm_target_features.clear_feature(CPU_AVX512_VBMI2); + _vm_target_features.clear_feature(CPU_CLWB); + _vm_target_features.clear_feature(CPU_FLUSHOPT); + _vm_target_features.clear_feature(CPU_GFNI); + _vm_target_features.clear_feature(CPU_AVX512_BITALG); + _vm_target_features.clear_feature(CPU_AVX512_IFMA); + _vm_target_features.clear_feature(CPU_AVX_IFMA); + _vm_target_features.clear_feature(CPU_AVX512_FP16); } } @@ -1098,8 +1098,8 @@ void VM_Version::get_processor_features() { cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(cpu_info_size > 0, "not enough temporary space allocated"); size_t buf_iter = cpu_info_size; - for (uint64_t i = 0; i < dynamic_features_vector_size(); i++) { - insert_features_names(dynamic_features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i); + for (uint64_t i = 0; i < features_vector_size(); i++) { + insert_features_names(features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i); buf_iter = strlen(buf); } @@ -2101,12 +2101,10 @@ void VM_Version::clear_apx_test_state() { static bool _vm_version_initialized = false; -void VM_Version::pre_initialize() { - Abstract_VM_Version::init_vm_features((MAX_CPU_FEATURES >> 6) + 1, 6); -} - void VM_Version::initialize() { ResourceMark rm; + assert(VM_Features::is_within_feature_vector_bounds(MAX_CPU_FEATURES), "Feature out of vector bounds"); + // Making this stub must be FIRST use of assembler stub_blob = BufferBlob::create("VM_Version stub", stub_size); if (stub_blob == nullptr) { @@ -2882,94 +2880,94 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) { return _max_qualified_cpu_frequency; } -void VM_Version::CpuidInfo::feature_flags() const { +void VM_Version::CpuidInfo::install_feature_flags() const { if (std_cpuid1_edx.bits.cmpxchg8 != 0) - SET_CPU_FEATURE(CPU_CX8); + _vm_target_features.set_feature(CPU_CX8); if (std_cpuid1_edx.bits.cmov != 0) - SET_CPU_FEATURE(CPU_CMOV); + _vm_target_features.set_feature(CPU_CMOV); if (std_cpuid1_edx.bits.clflush != 0) - SET_CPU_FEATURE(CPU_FLUSH); + _vm_target_features.set_feature(CPU_FLUSH); // clflush should always be available on x86_64 // if not we are in real trouble because we rely on it // to flush the code cache. - assert (SUPPORTS_CPU_FEATURE(CPU_FLUSH), "clflush should be available"); + assert (_vm_target_features.supports_feature(CPU_FLUSH), "clflush should be available"); if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() && ext_cpuid1_edx.bits.fxsr != 0)) - SET_CPU_FEATURE(CPU_FXSR); + _vm_target_features.set_feature(CPU_FXSR); // HT flag is set for multi-core processors also. if (threads_per_core() > 1) - SET_CPU_FEATURE(CPU_HT); + _vm_target_features.set_feature(CPU_HT); if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() && ext_cpuid1_edx.bits.mmx != 0)) - SET_CPU_FEATURE(CPU_MMX); + _vm_target_features.set_feature(CPU_MMX); if (std_cpuid1_edx.bits.sse != 0) - SET_CPU_FEATURE(CPU_SSE); + _vm_target_features.set_feature(CPU_SSE); if (std_cpuid1_edx.bits.sse2 != 0) - SET_CPU_FEATURE(CPU_SSE2); + _vm_target_features.set_feature(CPU_SSE2); if (std_cpuid1_ecx.bits.sse3 != 0) - SET_CPU_FEATURE(CPU_SSE3); + _vm_target_features.set_feature(CPU_SSE3); if (std_cpuid1_ecx.bits.ssse3 != 0) - SET_CPU_FEATURE(CPU_SSSE3); + _vm_target_features.set_feature(CPU_SSSE3); if (std_cpuid1_ecx.bits.sse4_1 != 0) - SET_CPU_FEATURE(CPU_SSE4_1); + _vm_target_features.set_feature(CPU_SSE4_1); if (std_cpuid1_ecx.bits.sse4_2 != 0) - SET_CPU_FEATURE(CPU_SSE4_2); + _vm_target_features.set_feature(CPU_SSE4_2); if (std_cpuid1_ecx.bits.popcnt != 0) - SET_CPU_FEATURE(CPU_POPCNT); + _vm_target_features.set_feature(CPU_POPCNT); if (sefsl1_cpuid7_edx.bits.apx_f != 0 && xem_xcr0_eax.bits.apx_f != 0) { - SET_CPU_FEATURE(CPU_APX_F); + _vm_target_features.set_feature(CPU_APX_F); } if (std_cpuid1_ecx.bits.avx != 0 && std_cpuid1_ecx.bits.osxsave != 0 && xem_xcr0_eax.bits.sse != 0 && xem_xcr0_eax.bits.ymm != 0) { - SET_CPU_FEATURE(CPU_AVX); - SET_CPU_FEATURE(CPU_VZEROUPPER); + _vm_target_features.set_feature(CPU_AVX); + _vm_target_features.set_feature(CPU_VZEROUPPER); if (sefsl1_cpuid7_eax.bits.sha512 != 0) - SET_CPU_FEATURE(CPU_SHA512); + _vm_target_features.set_feature(CPU_SHA512); if (std_cpuid1_ecx.bits.f16c != 0) - SET_CPU_FEATURE(CPU_F16C); + _vm_target_features.set_feature(CPU_F16C); if (sef_cpuid7_ebx.bits.avx2 != 0) { - SET_CPU_FEATURE(CPU_AVX2); + _vm_target_features.set_feature(CPU_AVX2); if (sefsl1_cpuid7_eax.bits.avx_ifma != 0) - SET_CPU_FEATURE(CPU_AVX_IFMA); + _vm_target_features.set_feature(CPU_AVX_IFMA); } if (sef_cpuid7_ecx.bits.gfni != 0) - SET_CPU_FEATURE(CPU_GFNI); + _vm_target_features.set_feature(CPU_GFNI); if (sef_cpuid7_ebx.bits.avx512f != 0 && xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - SET_CPU_FEATURE(CPU_AVX512F); + _vm_target_features.set_feature(CPU_AVX512F); if (sef_cpuid7_ebx.bits.avx512cd != 0) - SET_CPU_FEATURE(CPU_AVX512CD); + _vm_target_features.set_feature(CPU_AVX512CD); if (sef_cpuid7_ebx.bits.avx512dq != 0) - SET_CPU_FEATURE(CPU_AVX512DQ); + _vm_target_features.set_feature(CPU_AVX512DQ); if (sef_cpuid7_ebx.bits.avx512ifma != 0) - SET_CPU_FEATURE(CPU_AVX512_IFMA); + _vm_target_features.set_feature(CPU_AVX512_IFMA); if (sef_cpuid7_ebx.bits.avx512pf != 0) - SET_CPU_FEATURE(CPU_AVX512PF); + _vm_target_features.set_feature(CPU_AVX512PF); if (sef_cpuid7_ebx.bits.avx512er != 0) - SET_CPU_FEATURE(CPU_AVX512ER); + _vm_target_features.set_feature(CPU_AVX512ER); if (sef_cpuid7_ebx.bits.avx512bw != 0) - SET_CPU_FEATURE(CPU_AVX512BW); + _vm_target_features.set_feature(CPU_AVX512BW); if (sef_cpuid7_ebx.bits.avx512vl != 0) - SET_CPU_FEATURE(CPU_AVX512VL); + _vm_target_features.set_feature(CPU_AVX512VL); if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0) - SET_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); + _vm_target_features.set_feature(CPU_AVX512_VPOPCNTDQ); if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0) - SET_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); + _vm_target_features.set_feature(CPU_AVX512_VPCLMULQDQ); if (sef_cpuid7_ecx.bits.vaes != 0) - SET_CPU_FEATURE(CPU_AVX512_VAES); + _vm_target_features.set_feature(CPU_AVX512_VAES); if (sef_cpuid7_ecx.bits.avx512_vnni != 0) - SET_CPU_FEATURE(CPU_AVX512_VNNI); + _vm_target_features.set_feature(CPU_AVX512_VNNI); if (sef_cpuid7_ecx.bits.avx512_bitalg != 0) - SET_CPU_FEATURE(CPU_AVX512_BITALG); + _vm_target_features.set_feature(CPU_AVX512_BITALG); if (sef_cpuid7_ecx.bits.avx512_vbmi != 0) - SET_CPU_FEATURE(CPU_AVX512_VBMI); + _vm_target_features.set_feature(CPU_AVX512_VBMI); if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0) - SET_CPU_FEATURE(CPU_AVX512_VBMI2); + _vm_target_features.set_feature(CPU_AVX512_VBMI2); } if (is_intel()) { if (sefsl1_cpuid7_edx.bits.avx10 != 0 && @@ -2978,113 +2976,113 @@ void VM_Version::CpuidInfo::feature_flags() const { xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - SET_CPU_FEATURE(CPU_AVX10_1); - SET_CPU_FEATURE(CPU_AVX512F); - SET_CPU_FEATURE(CPU_AVX512CD); - SET_CPU_FEATURE(CPU_AVX512DQ); - SET_CPU_FEATURE(CPU_AVX512PF); - SET_CPU_FEATURE(CPU_AVX512ER); - SET_CPU_FEATURE(CPU_AVX512BW); - SET_CPU_FEATURE(CPU_AVX512VL); - SET_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); - SET_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); - SET_CPU_FEATURE(CPU_AVX512_VAES); - SET_CPU_FEATURE(CPU_AVX512_VNNI); - SET_CPU_FEATURE(CPU_AVX512_BITALG); - SET_CPU_FEATURE(CPU_AVX512_VBMI); - SET_CPU_FEATURE(CPU_AVX512_VBMI2); + _vm_target_features.set_feature(CPU_AVX10_1); + _vm_target_features.set_feature(CPU_AVX512F); + _vm_target_features.set_feature(CPU_AVX512CD); + _vm_target_features.set_feature(CPU_AVX512DQ); + _vm_target_features.set_feature(CPU_AVX512PF); + _vm_target_features.set_feature(CPU_AVX512ER); + _vm_target_features.set_feature(CPU_AVX512BW); + _vm_target_features.set_feature(CPU_AVX512VL); + _vm_target_features.set_feature(CPU_AVX512_VPOPCNTDQ); + _vm_target_features.set_feature(CPU_AVX512_VPCLMULQDQ); + _vm_target_features.set_feature(CPU_AVX512_VAES); + _vm_target_features.set_feature(CPU_AVX512_VNNI); + _vm_target_features.set_feature(CPU_AVX512_BITALG); + _vm_target_features.set_feature(CPU_AVX512_VBMI); + _vm_target_features.set_feature(CPU_AVX512_VBMI2); if (std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2) { - SET_CPU_FEATURE(CPU_AVX10_2); + _vm_target_features.set_feature(CPU_AVX10_2); } } } } if (std_cpuid1_ecx.bits.hv != 0) - SET_CPU_FEATURE(CPU_HV); + _vm_target_features.set_feature(CPU_HV); if (sef_cpuid7_ebx.bits.bmi1 != 0) - SET_CPU_FEATURE(CPU_BMI1); + _vm_target_features.set_feature(CPU_BMI1); if (std_cpuid1_edx.bits.tsc != 0) - SET_CPU_FEATURE(CPU_TSC); + _vm_target_features.set_feature(CPU_TSC); if (ext_cpuid7_edx.bits.tsc_invariance != 0) - SET_CPU_FEATURE(CPU_TSCINV_BIT); + _vm_target_features.set_feature(CPU_TSCINV_BIT); if (std_cpuid1_ecx.bits.aes != 0) - SET_CPU_FEATURE(CPU_AES); + _vm_target_features.set_feature(CPU_AES); if (ext_cpuid1_ecx.bits.lzcnt != 0) - SET_CPU_FEATURE(CPU_LZCNT); + _vm_target_features.set_feature(CPU_LZCNT); if (ext_cpuid1_ecx.bits.prefetchw != 0) - SET_CPU_FEATURE(CPU_3DNOW_PREFETCH); + _vm_target_features.set_feature(CPU_3DNOW_PREFETCH); if (sef_cpuid7_ebx.bits.erms != 0) - SET_CPU_FEATURE(CPU_ERMS); + _vm_target_features.set_feature(CPU_ERMS); if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0) - SET_CPU_FEATURE(CPU_FSRM); + _vm_target_features.set_feature(CPU_FSRM); if (std_cpuid1_ecx.bits.clmul != 0) - SET_CPU_FEATURE(CPU_CLMUL); + _vm_target_features.set_feature(CPU_CLMUL); if (sef_cpuid7_ebx.bits.rtm != 0) - SET_CPU_FEATURE(CPU_RTM); + _vm_target_features.set_feature(CPU_RTM); if (sef_cpuid7_ebx.bits.adx != 0) - SET_CPU_FEATURE(CPU_ADX); + _vm_target_features.set_feature(CPU_ADX); if (sef_cpuid7_ebx.bits.bmi2 != 0) - SET_CPU_FEATURE(CPU_BMI2); + _vm_target_features.set_feature(CPU_BMI2); if (sef_cpuid7_ebx.bits.sha != 0) - SET_CPU_FEATURE(CPU_SHA); + _vm_target_features.set_feature(CPU_SHA); if (std_cpuid1_ecx.bits.fma != 0) - SET_CPU_FEATURE(CPU_FMA); + _vm_target_features.set_feature(CPU_FMA); if (sef_cpuid7_ebx.bits.clflushopt != 0) - SET_CPU_FEATURE(CPU_FLUSHOPT); + _vm_target_features.set_feature(CPU_FLUSHOPT); if (sef_cpuid7_ebx.bits.clwb != 0) - SET_CPU_FEATURE(CPU_CLWB); + _vm_target_features.set_feature(CPU_CLWB); if (ext_cpuid1_edx.bits.rdtscp != 0) - SET_CPU_FEATURE(CPU_RDTSCP); + _vm_target_features.set_feature(CPU_RDTSCP); if (sef_cpuid7_ecx.bits.rdpid != 0) - SET_CPU_FEATURE(CPU_RDPID); + _vm_target_features.set_feature(CPU_RDPID); // AMD|Hygon additional features. if (is_amd_family()) { // PREFETCHW was checked above, check TDNOW here. if ((ext_cpuid1_edx.bits.tdnow != 0)) - SET_CPU_FEATURE(CPU_3DNOW_PREFETCH); + _vm_target_features.set_feature(CPU_3DNOW_PREFETCH); if (ext_cpuid1_ecx.bits.sse4a != 0) - SET_CPU_FEATURE(CPU_SSE4A); + _vm_target_features.set_feature(CPU_SSE4A); } // Intel additional features. if (is_intel()) { if (sef_cpuid7_edx.bits.serialize != 0) - SET_CPU_FEATURE(CPU_SERIALIZE); + _vm_target_features.set_feature(CPU_SERIALIZE); if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0) - SET_CPU_FEATURE(CPU_AVX512_FP16); + _vm_target_features.set_feature(CPU_AVX512_FP16); } // ZX additional features. if (is_zx()) { // We do not know if these are supported by ZX, so we cannot trust // common CPUID bit for them. - assert(SUPPORTS_CPU_FEATURE(CPU_CLWB), "Check if it is supported?"); - CLEAR_CPU_FEATURE(CPU_CLWB); + assert(_vm_target_features.supports_feature(CPU_CLWB), "Check if it is supported?"); + _vm_target_features.clear_feature(CPU_CLWB); } // Protection key features. if (sef_cpuid7_ecx.bits.pku != 0) { - SET_CPU_FEATURE(CPU_PKU); + _vm_target_features.set_feature(CPU_PKU); } if (sef_cpuid7_ecx.bits.ospke != 0) { - SET_CPU_FEATURE(CPU_OSPKE); + _vm_target_features.set_feature(CPU_OSPKE); } // Control flow enforcement (CET) features. if (sef_cpuid7_ecx.bits.cet_ss != 0) { - SET_CPU_FEATURE(CPU_CET_SS); + _vm_target_features.set_feature(CPU_CET_SS); } if (sef_cpuid7_edx.bits.cet_ibt != 0) { - SET_CPU_FEATURE(CPU_CET_IBT); + _vm_target_features.set_feature(CPU_CET_IBT); } // Composite features. if (supports_tscinv_bit() && ((is_amd_family() && !is_amd_Barcelona()) || is_intel_tsc_synched_at_init())) { - SET_CPU_FEATURE(CPU_TSCINV); + _vm_target_features.set_feature(CPU_TSCINV); } } diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index ed8c621f88601..f823ae8639aa0 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -447,10 +447,9 @@ class VM_Version : public Abstract_VM_Version { #define DECLARE_CPU_FEATURE_FLAG(id, name, bit) CPU_##id = (bit), CPU_FEATURE_FLAGS(DECLARE_CPU_FEATURE_FLAG) #undef DECLARE_CPU_FEATURE_FLAG + MAX_CPU_FEATURES }; -#define MAX_CPU_FEATURES 64 - static const char* _features_names[]; enum Extended_Family { @@ -594,7 +593,7 @@ class VM_Version : public Abstract_VM_Version { // Space to save apx registers after signal handle jlong apx_save[2]; // Save r16 and r31 - void feature_flags() const; + void install_feature_flags() const; // Asserts void assert_is_initialized() const { @@ -678,28 +677,27 @@ class VM_Version : public Abstract_VM_Version { Abstract_VM_Version::clear_cpu_features(); } static void set_avx_cpuFeatures() { - SET_CPU_FEATURE(CPU_SSE); - SET_CPU_FEATURE(CPU_SSE2); - SET_CPU_FEATURE(CPU_AVX); - SET_CPU_FEATURE(CPU_VZEROUPPER); + _vm_target_features.set_feature(CPU_SSE); + _vm_target_features.set_feature(CPU_SSE2); + _vm_target_features.set_feature(CPU_AVX); + _vm_target_features.set_feature(CPU_VZEROUPPER); } static void set_evex_cpuFeatures() { - SET_CPU_FEATURE(CPU_AVX10_1); - SET_CPU_FEATURE(CPU_AVX512F); - SET_CPU_FEATURE(CPU_SSE); - SET_CPU_FEATURE(CPU_SSE2); - SET_CPU_FEATURE(CPU_VZEROUPPER); + _vm_target_features.set_feature(CPU_AVX10_1); + _vm_target_features.set_feature(CPU_AVX512F); + _vm_target_features.set_feature(CPU_SSE); + _vm_target_features.set_feature(CPU_SSE2); + _vm_target_features.set_feature(CPU_VZEROUPPER); } - static void set_apx_cpuFeatures() { SET_CPU_FEATURE(CPU_APX_F); } + static void set_apx_cpuFeatures() { _vm_target_features.set_feature(CPU_APX_F); } static void set_bmi_cpuFeatures() { - SET_CPU_FEATURE(CPU_BMI1); - SET_CPU_FEATURE(CPU_BMI2); - SET_CPU_FEATURE(CPU_LZCNT); - SET_CPU_FEATURE(CPU_POPCNT); + _vm_target_features.set_feature(CPU_BMI1); + _vm_target_features.set_feature(CPU_BMI2); + _vm_target_features.set_feature(CPU_LZCNT); + _vm_target_features.set_feature(CPU_POPCNT); } // Initialization - static void pre_initialize(); static void initialize(); // Override Abstract_VM_Version implementation @@ -753,39 +751,39 @@ class VM_Version : public Abstract_VM_Version { // Feature identification which can be affected by VM settings // static bool supports_cpuid() { return Abstract_VM_Version::vm_features_exist(); } - static bool supports_cmov() { return SUPPORTS_CPU_FEATURE(CPU_CMOV); } - static bool supports_fxsr() { return SUPPORTS_CPU_FEATURE(CPU_FXSR); } - static bool supports_ht() { return SUPPORTS_CPU_FEATURE(CPU_HT); } - static bool supports_mmx() { return SUPPORTS_CPU_FEATURE(CPU_MMX); } - static bool supports_sse() { return SUPPORTS_CPU_FEATURE(CPU_SSE); } - static bool supports_sse2() { return SUPPORTS_CPU_FEATURE(CPU_SSE2); } - static bool supports_sse3() { return SUPPORTS_CPU_FEATURE(CPU_SSE3); } - static bool supports_ssse3() { return SUPPORTS_CPU_FEATURE(CPU_SSSE3); } - static bool supports_sse4_1() { return SUPPORTS_CPU_FEATURE(CPU_SSE4_1); } - static bool supports_sse4_2() { return SUPPORTS_CPU_FEATURE(CPU_SSE4_2); } - static bool supports_popcnt() { return SUPPORTS_CPU_FEATURE(CPU_POPCNT); } - static bool supports_avx() { return SUPPORTS_CPU_FEATURE(CPU_AVX); } - static bool supports_avx2() { return SUPPORTS_CPU_FEATURE(CPU_AVX2); } - static bool supports_tsc() { return SUPPORTS_CPU_FEATURE(CPU_TSC); } - static bool supports_rdtscp() { return SUPPORTS_CPU_FEATURE(CPU_RDTSCP); } - static bool supports_rdpid() { return SUPPORTS_CPU_FEATURE(CPU_RDPID); } - static bool supports_aes() { return SUPPORTS_CPU_FEATURE(CPU_AES); } - static bool supports_erms() { return SUPPORTS_CPU_FEATURE(CPU_ERMS); } - static bool supports_fsrm() { return SUPPORTS_CPU_FEATURE(CPU_FSRM); } - static bool supports_clmul() { return SUPPORTS_CPU_FEATURE(CPU_CLMUL); } - static bool supports_rtm() { return SUPPORTS_CPU_FEATURE(CPU_RTM); } - static bool supports_bmi1() { return SUPPORTS_CPU_FEATURE(CPU_BMI1); } - static bool supports_bmi2() { return SUPPORTS_CPU_FEATURE(CPU_BMI2); } - static bool supports_adx() { return SUPPORTS_CPU_FEATURE(CPU_ADX); } - static bool supports_evex() { return SUPPORTS_CPU_FEATURE(CPU_AVX512F); } - static bool supports_avx512dq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512DQ); } - static bool supports_avx512ifma() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_IFMA); } - static bool supports_avxifma() { return SUPPORTS_CPU_FEATURE(CPU_AVX_IFMA); } - static bool supports_avx512pf() { return SUPPORTS_CPU_FEATURE(CPU_AVX512PF); } - static bool supports_avx512er() { return SUPPORTS_CPU_FEATURE(CPU_AVX512ER); } - static bool supports_avx512cd() { return SUPPORTS_CPU_FEATURE(CPU_AVX512CD); } - static bool supports_avx512bw() { return SUPPORTS_CPU_FEATURE(CPU_AVX512BW); } - static bool supports_avx512vl() { return SUPPORTS_CPU_FEATURE(CPU_AVX512VL); } + static bool supports_cmov() { return _vm_target_features.supports_feature(CPU_CMOV); } + static bool supports_fxsr() { return _vm_target_features.supports_feature(CPU_FXSR); } + static bool supports_ht() { return _vm_target_features.supports_feature(CPU_HT); } + static bool supports_mmx() { return _vm_target_features.supports_feature(CPU_MMX); } + static bool supports_sse() { return _vm_target_features.supports_feature(CPU_SSE); } + static bool supports_sse2() { return _vm_target_features.supports_feature(CPU_SSE2); } + static bool supports_sse3() { return _vm_target_features.supports_feature(CPU_SSE3); } + static bool supports_ssse3() { return _vm_target_features.supports_feature(CPU_SSSE3); } + static bool supports_sse4_1() { return _vm_target_features.supports_feature(CPU_SSE4_1); } + static bool supports_sse4_2() { return _vm_target_features.supports_feature(CPU_SSE4_2); } + static bool supports_popcnt() { return _vm_target_features.supports_feature(CPU_POPCNT); } + static bool supports_avx() { return _vm_target_features.supports_feature(CPU_AVX); } + static bool supports_avx2() { return _vm_target_features.supports_feature(CPU_AVX2); } + static bool supports_tsc() { return _vm_target_features.supports_feature(CPU_TSC); } + static bool supports_rdtscp() { return _vm_target_features.supports_feature(CPU_RDTSCP); } + static bool supports_rdpid() { return _vm_target_features.supports_feature(CPU_RDPID); } + static bool supports_aes() { return _vm_target_features.supports_feature(CPU_AES); } + static bool supports_erms() { return _vm_target_features.supports_feature(CPU_ERMS); } + static bool supports_fsrm() { return _vm_target_features.supports_feature(CPU_FSRM); } + static bool supports_clmul() { return _vm_target_features.supports_feature(CPU_CLMUL); } + static bool supports_rtm() { return _vm_target_features.supports_feature(CPU_RTM); } + static bool supports_bmi1() { return _vm_target_features.supports_feature(CPU_BMI1); } + static bool supports_bmi2() { return _vm_target_features.supports_feature(CPU_BMI2); } + static bool supports_adx() { return _vm_target_features.supports_feature(CPU_ADX); } + static bool supports_evex() { return _vm_target_features.supports_feature(CPU_AVX512F); } + static bool supports_avx512dq() { return _vm_target_features.supports_feature(CPU_AVX512DQ); } + static bool supports_avx512ifma() { return _vm_target_features.supports_feature(CPU_AVX512_IFMA); } + static bool supports_avxifma() { return _vm_target_features.supports_feature(CPU_AVX_IFMA); } + static bool supports_avx512pf() { return _vm_target_features.supports_feature(CPU_AVX512PF); } + static bool supports_avx512er() { return _vm_target_features.supports_feature(CPU_AVX512ER); } + static bool supports_avx512cd() { return _vm_target_features.supports_feature(CPU_AVX512CD); } + static bool supports_avx512bw() { return _vm_target_features.supports_feature(CPU_AVX512BW); } + static bool supports_avx512vl() { return _vm_target_features.supports_feature(CPU_AVX512VL); } static bool supports_avx512vlbw() { return (supports_evex() && supports_avx512bw() && supports_avx512vl()); } static bool supports_avx512bwdq() { return (supports_evex() && supports_avx512bw() && supports_avx512dq()); } static bool supports_avx512vldq() { return (supports_evex() && supports_avx512dq() && supports_avx512vl()); } @@ -794,39 +792,39 @@ class VM_Version : public Abstract_VM_Version { static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } - static bool supports_apx_f() { return SUPPORTS_CPU_FEATURE(CPU_APX_F); } + static bool supports_apx_f() { return _vm_target_features.supports_feature(CPU_APX_F); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } - static bool supports_sha() { return SUPPORTS_CPU_FEATURE(CPU_SHA); } - static bool supports_fma() { return SUPPORTS_CPU_FEATURE(CPU_FMA) && supports_avx(); } - static bool supports_vzeroupper() { return SUPPORTS_CPU_FEATURE(CPU_VZEROUPPER); } - static bool supports_avx512_vpopcntdq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VPOPCNTDQ); } - static bool supports_avx512_vpclmulqdq() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VPCLMULQDQ); } - static bool supports_avx512_vaes() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VAES); } - static bool supports_gfni() { return SUPPORTS_CPU_FEATURE(CPU_GFNI); } - static bool supports_avx512_vnni() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VNNI); } - static bool supports_avx512_bitalg() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_BITALG); } - static bool supports_avx512_vbmi() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VBMI); } - static bool supports_avx512_vbmi2() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_VBMI2); } - static bool supports_avx512_fp16() { return SUPPORTS_CPU_FEATURE(CPU_AVX512_FP16); } - static bool supports_hv() { return SUPPORTS_CPU_FEATURE(CPU_HV); } - static bool supports_serialize() { return SUPPORTS_CPU_FEATURE(CPU_SERIALIZE); } - static bool supports_f16c() { return SUPPORTS_CPU_FEATURE(CPU_F16C); } - static bool supports_pku() { return SUPPORTS_CPU_FEATURE(CPU_PKU); } - static bool supports_ospke() { return SUPPORTS_CPU_FEATURE(CPU_OSPKE); } - static bool supports_cet_ss() { return SUPPORTS_CPU_FEATURE(CPU_CET_SS); } - static bool supports_cet_ibt() { return SUPPORTS_CPU_FEATURE(CPU_CET_IBT); } - static bool supports_sha512() { return SUPPORTS_CPU_FEATURE(CPU_SHA512); } + static bool supports_sha() { return _vm_target_features.supports_feature(CPU_SHA); } + static bool supports_fma() { return _vm_target_features.supports_feature(CPU_FMA) && supports_avx(); } + static bool supports_vzeroupper() { return _vm_target_features.supports_feature(CPU_VZEROUPPER); } + static bool supports_avx512_vpopcntdq() { return _vm_target_features.supports_feature(CPU_AVX512_VPOPCNTDQ); } + static bool supports_avx512_vpclmulqdq() { return _vm_target_features.supports_feature(CPU_AVX512_VPCLMULQDQ); } + static bool supports_avx512_vaes() { return _vm_target_features.supports_feature(CPU_AVX512_VAES); } + static bool supports_gfni() { return _vm_target_features.supports_feature(CPU_GFNI); } + static bool supports_avx512_vnni() { return _vm_target_features.supports_feature(CPU_AVX512_VNNI); } + static bool supports_avx512_bitalg() { return _vm_target_features.supports_feature(CPU_AVX512_BITALG); } + static bool supports_avx512_vbmi() { return _vm_target_features.supports_feature(CPU_AVX512_VBMI); } + static bool supports_avx512_vbmi2() { return _vm_target_features.supports_feature(CPU_AVX512_VBMI2); } + static bool supports_avx512_fp16() { return _vm_target_features.supports_feature(CPU_AVX512_FP16); } + static bool supports_hv() { return _vm_target_features.supports_feature(CPU_HV); } + static bool supports_serialize() { return _vm_target_features.supports_feature(CPU_SERIALIZE); } + static bool supports_f16c() { return _vm_target_features.supports_feature(CPU_F16C); } + static bool supports_pku() { return _vm_target_features.supports_feature(CPU_PKU); } + static bool supports_ospke() { return _vm_target_features.supports_feature(CPU_OSPKE); } + static bool supports_cet_ss() { return _vm_target_features.supports_feature(CPU_CET_SS); } + static bool supports_cet_ibt() { return _vm_target_features.supports_feature(CPU_CET_IBT); } + static bool supports_sha512() { return _vm_target_features.supports_feature(CPU_SHA512); } // IntelĀ® AVX10 introduces a versioned approach for enumeration that is monotonically increasing, inclusive, // and supporting all vector lengths. Feature set supported by an AVX10 vector ISA version is also supported // by all the versions above it. - static bool supports_avx10_1() { return SUPPORTS_CPU_FEATURE(CPU_AVX10_1);} - static bool supports_avx10_2() { return SUPPORTS_CPU_FEATURE(CPU_AVX10_2);} + static bool supports_avx10_1() { return _vm_target_features.supports_feature(CPU_AVX10_1);} + static bool supports_avx10_2() { return _vm_target_features.supports_feature(CPU_AVX10_2);} // // Feature identification not affected by VM flags // - static bool cpu_supports_evex() { return SUPPORTS_CPU_FEATURE_AUX(CPU_AVX512F); } + static bool cpu_supports_evex() { return _cpu_target_features.supports_feature(CPU_AVX512F); } static bool supports_avx512_simd_sort() { if (supports_avx512dq()) { @@ -864,19 +862,19 @@ class VM_Version : public Abstract_VM_Version { static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; } // AMD features - static bool supports_3dnow_prefetch() { return SUPPORTS_CPU_FEATURE(CPU_3DNOW_PREFETCH); } - static bool supports_lzcnt() { return SUPPORTS_CPU_FEATURE(CPU_LZCNT); } - static bool supports_sse4a() { return SUPPORTS_CPU_FEATURE(CPU_SSE4A); } + static bool supports_3dnow_prefetch() { return _vm_target_features.supports_feature(CPU_3DNOW_PREFETCH); } + static bool supports_lzcnt() { return _vm_target_features.supports_feature(CPU_LZCNT); } + static bool supports_sse4a() { return _vm_target_features.supports_feature(CPU_SSE4A); } static bool is_amd_Barcelona() { return is_amd() && extended_cpu_family() == CPU_FAMILY_AMD_11H; } // Intel and AMD newer cores support fast timestamps well static bool supports_tscinv_bit() { - return SUPPORTS_CPU_FEATURE(CPU_TSCINV_BIT); + return _vm_target_features.supports_feature(CPU_TSCINV_BIT); } static bool supports_tscinv() { - return SUPPORTS_CPU_FEATURE(CPU_TSCINV); + return _vm_target_features.supports_feature(CPU_TSCINV); } // Intel Core and newer cpus have fast IDIV instruction (excluding Atom). @@ -937,8 +935,8 @@ class VM_Version : public Abstract_VM_Version { static bool supports_clflush(); // Can't inline due to header file conflict // Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit - static bool supports_clflushopt() { return (SUPPORTS_CPU_FEATURE(CPU_FLUSHOPT)); } - static bool supports_clwb() { return (SUPPORTS_CPU_FEATURE(CPU_CLWB)); } + static bool supports_clflushopt() { return (_vm_target_features.supports_feature(CPU_FLUSHOPT)); } + static bool supports_clwb() { return (_vm_target_features.supports_feature(CPU_CLWB)); } // Old CPUs perform lea on AGU which causes additional latency transferring the // value from/to ALU for other operations diff --git a/src/hotspot/cpu/zero/vm_version_zero.cpp b/src/hotspot/cpu/zero/vm_version_zero.cpp index f22d2d0d9dd29..3ce9227c1939c 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.cpp +++ b/src/hotspot/cpu/zero/vm_version_zero.cpp @@ -32,8 +32,6 @@ #include "runtime/vm_version.hpp" -void VM_Version::pre_initialize() {} - void VM_Version::initialize() { // This machine does not allow unaligned memory accesses if (! FLAG_IS_DEFAULT(UseUnalignedAccesses)) { diff --git a/src/hotspot/cpu/zero/vm_version_zero.hpp b/src/hotspot/cpu/zero/vm_version_zero.hpp index 2899a490c4d26..0b5476165a48b 100644 --- a/src/hotspot/cpu/zero/vm_version_zero.hpp +++ b/src/hotspot/cpu/zero/vm_version_zero.hpp @@ -31,7 +31,6 @@ class VM_Version : public Abstract_VM_Version { public: - static void pre_initialize(); static void initialize(); constexpr static bool supports_stack_watermark_barrier() { return true; } diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 7c1d06d267597..af747a0f98bea 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -147,11 +147,11 @@ JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ \ static_field(Abstract_VM_Version, _features, uint64_t) \ - static_field(Abstract_VM_Version, _dynamic_features, VM_Features) \ + static_field(Abstract_VM_Version, _vm_target_features, VM_Features) \ \ - nonstatic_field(VM_Features, _dynamic_features_vector, uint64_t*) \ - nonstatic_field(VM_Features, _dynamic_features_vector_size, uint32_t) \ - nonstatic_field(VM_Features, _dynamic_features_element_shift_count, uint32_t) \ + nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ + static_field(VM_Features, _features_vector_size, uint32_t) \ + static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ \ nonstatic_field(Annotations, _class_annotations, AnnotationArray*) \ nonstatic_field(Annotations, _fields_annotations, Array*) \ diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 22ba99ac571d0..7bd9cfdb357c4 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -37,8 +37,10 @@ const char* Abstract_VM_Version::_features_string = ""; const char* Abstract_VM_Version::_cpu_info_string = ""; uint64_t Abstract_VM_Version::_cpu_features = 0; -VM_Features Abstract_VM_Version::_dynamic_features = {nullptr, 0, 0}; -VM_Features Abstract_VM_Version::_dynamic_cpu_features = {nullptr, 0, 0}; +uint32_t VM_Features::_features_vector_element_shift_count = 6; +uint32_t VM_Features::_features_vector_size = MAX_FEATURE_VEC_SIZE; +VM_Features Abstract_VM_Version::_vm_target_features = {{0, 0, 0, 0}}; +VM_Features Abstract_VM_Version::_cpu_target_features = {{0, 0, 0, 0}}; #ifndef SUPPORTS_NATIVE_CX8 bool Abstract_VM_Version::_supports_cx8 = false; @@ -420,33 +422,27 @@ const char* Abstract_VM_Version::cpu_description(void) { return tmp; } - -void VM_Features::init_vm_features(uint32_t size, uint32_t elem_shift_count) { - _dynamic_features_vector_size = size; - _dynamic_features_element_shift_count = elem_shift_count; - - uint64_t* features_memory = NEW_C_HEAP_ARRAY(uint64_t, size, mtInternal); - memset(features_memory, 0, sizeof(uint64_t*) * size); - _dynamic_features_vector = features_memory; - } - void VM_Features::set_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - _dynamic_features_vector[index] |= (1ULL << (feature & index_mask)); + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + _features_vector[index] |= (1ULL << (feature & index_mask)); } void VM_Features::clear_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - _dynamic_features_vector[index] &= ~(1ULL << (feature & index_mask)); + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + _features_vector[index] &= ~(1ULL << (feature & index_mask)); } bool VM_Features::supports_feature(uint32_t feature) { - uint32_t index = feature >> _dynamic_features_element_shift_count; - uint32_t index_mask = (1 << _dynamic_features_element_shift_count) - 1; - assert(index < _dynamic_features_vector_size, "Features array index out of bounds"); - return (_dynamic_features_vector[index] & (1ULL << (feature & index_mask))) != 0; + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + return (_features_vector[index] & (1ULL << (feature & index_mask))) != 0; +} + +bool VM_Features::is_within_feature_vector_bounds(uint32_t num_features) { + return _features_vector_size >= ((num_features >> _features_vector_element_shift_count) + 1); } diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index 384c760c2eb39..c3411b22c4542 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -44,20 +44,26 @@ typedef enum { class outputStream; enum class vmIntrinsicID; +#define MAX_FEATURE_VEC_SIZE 4 + class VM_Features { public: - // Dynamically sized feature flags currently only used by x86 backend, - // can be affected by VM settings. - uint64_t* _dynamic_features_vector; - uint32_t _dynamic_features_vector_size; - uint32_t _dynamic_features_element_shift_count; + using FeatureVector = uint64_t [MAX_FEATURE_VEC_SIZE]; - void init_vm_features(uint32_t size, uint32_t elem_shift_count); + // Feature vector bitmap currently only used by x86 backend. + FeatureVector _features_vector; - void set_feature(uint32_t feature); + // Size of feature vector bitmap. + static uint32_t _features_vector_size; - void clear_feature(uint32_t feature); + // Log2 of feature vector element size in bits, used by JVMCI to check enabled feature bits. + // Refer HotSpotJVMCIBackendFactory::convertFeaturesVector. + static uint32_t _features_vector_element_shift_count; + static bool is_within_feature_vector_bounds(uint32_t num_features); + + void set_feature(uint32_t feature); + void clear_feature(uint32_t feature); bool supports_feature(uint32_t feature); }; @@ -81,49 +87,32 @@ class Abstract_VM_Version: AllStatic { // Original CPU feature flags, not affected by VM settings. static uint64_t _cpu_features; - static VM_Features _dynamic_features; + // CPU feature flags vector, can be affected by VM settings. + static VM_Features _vm_target_features; - static VM_Features _dynamic_cpu_features; - -#define SET_CPU_FEATURE(feature) \ - _dynamic_features.set_feature(feature) - -#define CLEAR_CPU_FEATURE(feature) \ - _dynamic_features.clear_feature(feature) - -#define SUPPORTS_CPU_FEATURE(feature) \ - _dynamic_features.supports_feature(feature) - -#define SUPPORTS_CPU_FEATURE_AUX(feature) \ - _dynamic_cpu_features.supports_feature(feature) - - static void init_vm_features(uint32_t size, uint32_t elem_shift_count) { - _dynamic_features.init_vm_features(size, elem_shift_count); - _dynamic_cpu_features.init_vm_features(size, elem_shift_count); - } + // Original CPU feature flags vector, not affected by VM settings. + static VM_Features _cpu_target_features; static void sync_cpu_features() { - assert(_dynamic_cpu_features._dynamic_features_vector_size == _dynamic_features._dynamic_features_vector_size, ""); - memcpy(_dynamic_cpu_features._dynamic_features_vector, _dynamic_features._dynamic_features_vector, - sizeof(uint64_t) * _dynamic_features._dynamic_features_vector_size); + memcpy(_cpu_target_features._features_vector, _vm_target_features._features_vector, + sizeof(uint64_t) * VM_Features::_features_vector_size); } static void clear_cpu_features() { - memset(_dynamic_features._dynamic_features_vector, 0, sizeof(uint64_t) * _dynamic_features._dynamic_features_vector_size); + memset(_vm_target_features._features_vector, 0, sizeof(uint64_t) * VM_Features::_features_vector_size); } static bool vm_features_exist() { - return (_dynamic_features._dynamic_features_vector_size > 0) && - (_dynamic_features._dynamic_features_vector != nullptr); + return VM_Features::_features_vector_size > 0; } - static uint32_t dynamic_features_vector_size() { - return _dynamic_features._dynamic_features_vector_size; + static uint32_t features_vector_size() { + return VM_Features::_features_vector_size; } - static uint64_t dynamic_features_vector_elem(uint32_t elem) { - assert(elem < _dynamic_features._dynamic_features_vector_size, ""); - return _dynamic_features._dynamic_features_vector[elem]; + static uint64_t features_vector_elem(uint32_t elem) { + assert(elem < VM_Features::_features_vector_size, ""); + return _vm_target_features._features_vector[elem]; } // These are set by machine-dependent initializations diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index 4c1f27627f6b9..da1d6ba564597 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -125,7 +125,6 @@ jint init_globals() { bytecodes_init(); classLoader_init1(); compilationPolicy_init(); - VM_Version_pre_init(); // allocate feature flags arrays codeCache_init(); VM_Version_init(); // depends on codeCache_init for emitting code icache_init2(); // depends on VM_Version for choosing the mechanism diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index cb9d77ce1a1ce..ff6ef7ed5661e 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -707,11 +707,11 @@ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_security_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ - static_field(Abstract_VM_Version, _dynamic_features, VM_Features) \ + static_field(Abstract_VM_Version, _vm_target_features, VM_Features) \ \ - nonstatic_field(VM_Features, _dynamic_features_vector, uint64_t*) \ - nonstatic_field(VM_Features, _dynamic_features_vector_size, uint32_t) \ - nonstatic_field(VM_Features, _dynamic_features_element_shift_count, uint32_t) \ + nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ + static_field(VM_Features, _features_vector_size, uint32_t) \ + static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ \ /*************************/ \ /* JVMTI */ \ @@ -1170,6 +1170,7 @@ \ declare_toplevel_type(Abstract_VM_Version) \ declare_toplevel_type(VM_Features) \ + declare_toplevel_type(VM_Features::FeatureVector) \ \ /*************/ \ /* Arguments */ \ diff --git a/src/hotspot/share/runtime/vm_version.cpp b/src/hotspot/share/runtime/vm_version.cpp index 149f6f01f1321..7c5b7fe3f3e97 100644 --- a/src/hotspot/share/runtime/vm_version.cpp +++ b/src/hotspot/share/runtime/vm_version.cpp @@ -27,10 +27,6 @@ #include "memory/resourceArea.hpp" #include "runtime/vm_version.hpp" -void VM_Version_pre_init() { - VM_Version::pre_initialize(); -} - void VM_Version_init() { VM_Version::initialize(); guarantee(VM_Version::supports_cx8(), "Support for 64-bit atomic operations is required"); diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 10fd84b34bb83..d33dfe115319f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,31 +89,26 @@ static > EnumSet con * @param enumType the class of {@code CPUFeatureType} * @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"} * specifies a CPU feature and its value is a mask for a bit in {@code features} - * @param dynamic_features_vector_pointer pointer to dynamic feature bit vector of CPU features - * @param dynamic_features_vector_offset offset of dynamic_feature_vector field in {@code VM_Features} - * @param dynamic_features_vector_size_offset offset of dynamic_feature_vector_size field in {@code VM_Features} - * @param dynamic_features_element_shift_count_offset offset of dynamic_features_element_shift_count field in {@code VM_Features} - * ,it holds the base2 logarithmic value of dynamic feature bit vector lanesize in bits. + * @param features_pointer pointer to {@code _vm_target_features} field of {@code Abstract_VM_Version} + * @param features_vector_offset offset of feature_vector field in {@code VM_Features} + * @param features_vector_size_offset offset of feature_vector_size field in {@code VM_Features} + * @param features_element_shift_count log2 of dynamic feature bit vector lanesize in bits. * @param renaming maps from VM feature names to enum constant names where the two differ * @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an * enum value * @return the set of converted values */ - static > EnumSet convertDynamicFeaturesVector( + static > EnumSet convertFeaturesVector( Class enumType, Map constants, - long dynamic_features_pointer, - long dynamic_features_vector_offset, - long dynamic_features_vector_size_offset, - long dynamic_features_element_shift_count_offset, + long features_pointer, + long features_vector_offset, + long features_vector_size, + long features_element_shift_count, Map renaming) { EnumSet outFeatures = EnumSet.noneOf(enumType); List missing = new ArrayList<>(); - long dynamic_features_vector_pointer = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_vector_offset); - long dynamic_features_vector_size = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_vector_size_offset); - long dynamic_features_element_shift_count = UNSAFE.getLong(dynamic_features_pointer + dynamic_features_element_shift_count_offset); - for (Entry e : constants.entrySet()) { String key = e.getKey(); long bitIndex = e.getValue(); @@ -121,17 +116,17 @@ static > EnumSet con String name = key.substring("VM_Version::CPU_".length()); try { CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name)); - long dynamic_features_vector_index = bitIndex >>> dynamic_features_element_shift_count; - assert dynamic_features_vector_index < dynamic_features_vector_size; + long features_vector_index = bitIndex >>> features_element_shift_count; + assert features_vector_index < features_vector_size; - long dynamic_features_element_bitsize = (1L << dynamic_features_element_shift_count); - assert (dynamic_features_element_bitsize & (dynamic_features_element_bitsize - 1)) == 0; + long features_element_bitsize = (1L << features_element_shift_count); + assert (features_element_bitsize & (features_element_bitsize - 1)) == 0; - long dynamic_features_element_size = dynamic_features_element_bitsize / Byte.SIZE; - long features = UNSAFE.getLong(dynamic_features_vector_pointer + - dynamic_features_vector_index * dynamic_features_element_size); + long features_element_size = features_element_bitsize / Byte.SIZE; + long features = UNSAFE.getLong(features_pointer + features_vector_offset + + features_vector_index * features_element_size); - long effective_bitMask = 1L << (bitIndex & (dynamic_features_element_bitsize - 1)); + long effective_bitMask = 1L << (bitIndex & (features_element_bitsize - 1)); if ((features & effective_bitMask) != 0) { outFeatures.add(feature); } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 3a5501f5b18f2..6d216af196101 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,12 +50,12 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map constants = config.getStore().getConstants(); Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; - EnumSet features = HotSpotJVMCIBackendFactory.convertDynamicFeaturesVector(CPUFeature.class, constants, - config.vmVersionDynFeatures, - config.vmFeaturesDynFeaturesVecOffset, - config.vmFeaturesDynFeaturesVecSizeOffset, - config.vmFeaturesDynFeaturesElemShiftCntOffset, - renaming); + EnumSet features = HotSpotJVMCIBackendFactory.convertFeaturesVector(CPUFeature.class, constants, + config.vmVersionTargetFeatures, + config.vmFeaturesFeaturesVecOffset, + config.vmFeaturesFeaturesVecSize, + config.vmFeaturesFeaturesElemShiftCnt, + renaming); features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE2); return features; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index f8107155902ea..ce6d94c30dc0f 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,16 +42,15 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); + final long vmVersionTargetFeatures = getFieldAddress("Abstract_VM_Version::_vm_target_features", "VM_Features"); + final long vmFeaturesFeaturesVecOffset = getFieldOffset("VM_Features::_features_vector", Long.class, "VM_Features::FeatureVector"); + final long vmFeaturesFeaturesVecSize = getFieldValue("VM_Features::_features_vector_size", Long.class, "uint32_t"); + final long vmFeaturesFeaturesElemShiftCnt = getFieldValue("VM_Features::_features_vector_element_shift_count", Long.class, "uint32_t"); // CPU capabilities final int useSSE = getFlag("UseSSE", Integer.class); final int useAVX = getFlag("UseAVX", Integer.class); - final long vmFeaturesDynFeaturesVecOffset = getFieldOffset("VM_Features::_dynamic_features_vector", Long.class, "uint64_t*"); - final long vmFeaturesDynFeaturesVecSizeOffset = getFieldOffset("VM_Features::_dynamic_features_vector_size", Long.class, "uint32_t"); - final long vmFeaturesDynFeaturesElemShiftCntOffset = getFieldOffset("VM_Features::_dynamic_features_element_shift_count", Long.class, "uint32_t"); - final long vmVersionDynFeatures = getFieldAddress("Abstract_VM_Version::_dynamic_features", "VM_Features"); - // CPU feature flags final long amd64CX8 = getConstant("VM_Version::CPU_CX8", Long.class); final long amd64CMOV = getConstant("VM_Version::CPU_CMOV", Long.class); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index 5a3336de64d3e..a35c7fc346014 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From 7b414b8ca0139ab8ea73426ffb2d68378d4e36cb Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Mon, 5 May 2025 08:55:32 +0530 Subject: [PATCH 07/16] Updating comment --- .../classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index d33dfe115319f..7763fe959ef68 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -91,7 +91,7 @@ static > EnumSet con * specifies a CPU feature and its value is a mask for a bit in {@code features} * @param features_pointer pointer to {@code _vm_target_features} field of {@code Abstract_VM_Version} * @param features_vector_offset offset of feature_vector field in {@code VM_Features} - * @param features_vector_size_offset offset of feature_vector_size field in {@code VM_Features} + * @param features_vector_size size of feature vector * @param features_element_shift_count log2 of dynamic feature bit vector lanesize in bits. * @param renaming maps from VM feature names to enum constant names where the two differ * @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an From b25cc7764f9f13d1296c74605b4620752821c478 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Tue, 6 May 2025 13:33:19 +0530 Subject: [PATCH 08/16] Review comments resolutions --- src/hotspot/cpu/x86/vm_version_x86.cpp | 331 ++++++++++-------- src/hotspot/cpu/x86/vm_version_x86.hpp | 208 ++++++----- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 12 +- .../share/runtime/abstract_vm_version.cpp | 44 --- .../share/runtime/abstract_vm_version.hpp | 56 +-- src/hotspot/share/runtime/init.cpp | 1 - src/hotspot/share/runtime/vmStructs.cpp | 13 +- .../AMD64HotSpotJVMCIBackendFactory.java | 2 +- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 2 +- 9 files changed, 334 insertions(+), 335 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 24f0729874e54..5ce31e7060bb1 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -63,6 +63,11 @@ address VM_Version::_cpuinfo_cont_addr_apx = nullptr; static BufferBlob* stub_blob; static const int stub_size = 2000; +uint32_t VM_Features::_features_vector_element_shift_count = 6; +uint32_t VM_Features::_features_vector_size = MAX_FEATURE_VEC_SIZE; +VM_Features VM_Version::_features; +VM_Features VM_Version::_cpu_features; + extern "C" { typedef void (*get_cpu_info_stub_t)(void*); typedef void (*detect_virt_stub_t)(uint32_t, uint32_t*); @@ -82,7 +87,7 @@ bool VM_Version::supports_clflush() { // up. Assembler::flush calls this routine to check that clflush // is allowed. So, we give the caller a free pass if Universe init // is still in progress. - assert ((!Universe::is_fully_initialized() || _vm_target_features.supports_feature(CPU_FLUSH)), "clflush should be available"); + assert ((!Universe::is_fully_initialized() || _features.supports_feature(CPU_FLUSH)), "clflush should be available"); return true; } @@ -857,8 +862,8 @@ void VM_Version::get_processor_features() { _stepping = cpu_stepping(); if (cpu_family() > 4) { // it supports CPUID - _cpuid_info.install_feature_flags(); // These can be changed by VM settings - Abstract_VM_Version::sync_cpu_features(); // Preserve features + _features = _cpuid_info.feature_flags(); // These can be changed by VM settings + _cpu_features = _features; // Preserve features // Logical processors are only available on P4s and above, // and only if hyperthreading is available. _logical_processors_per_package = logical_processor_count(); @@ -907,21 +912,21 @@ void VM_Version::get_processor_features() { } if (UseSSE < 4) { - _vm_target_features.clear_feature(CPU_SSE4_1); - _vm_target_features.clear_feature(CPU_SSE4_2); + _features.clear_feature(CPU_SSE4_1); + _features.clear_feature(CPU_SSE4_2); } if (UseSSE < 3) { - _vm_target_features.clear_feature(CPU_SSE3); - _vm_target_features.clear_feature(CPU_SSSE3); - _vm_target_features.clear_feature(CPU_SSE4A); + _features.clear_feature(CPU_SSE3); + _features.clear_feature(CPU_SSSE3); + _features.clear_feature(CPU_SSE4A); } if (UseSSE < 2) - _vm_target_features.clear_feature(CPU_SSE2); + _features.clear_feature(CPU_SSE2); if (UseSSE < 1) - _vm_target_features.clear_feature(CPU_SSE); + _features.clear_feature(CPU_SSE); //since AVX instructions is slower than SSE in some ZX cpus, force USEAVX=0. if (is_zx() && ((cpu_family() == 6) || (cpu_family() == 7))) { @@ -987,25 +992,25 @@ void VM_Version::get_processor_features() { } if (UseAVX < 3) { - _vm_target_features.clear_feature(CPU_AVX512F); - _vm_target_features.clear_feature(CPU_AVX512DQ); - _vm_target_features.clear_feature(CPU_AVX512CD); - _vm_target_features.clear_feature(CPU_AVX512BW); - _vm_target_features.clear_feature(CPU_AVX512ER); - _vm_target_features.clear_feature(CPU_AVX512PF); - _vm_target_features.clear_feature(CPU_AVX512VL); - _vm_target_features.clear_feature(CPU_AVX512_VPOPCNTDQ); - _vm_target_features.clear_feature(CPU_AVX512_VPCLMULQDQ); - _vm_target_features.clear_feature(CPU_AVX512_VAES); - _vm_target_features.clear_feature(CPU_AVX512_VNNI); - _vm_target_features.clear_feature(CPU_AVX512_VBMI); - _vm_target_features.clear_feature(CPU_AVX512_VBMI2); - _vm_target_features.clear_feature(CPU_AVX512_BITALG); - _vm_target_features.clear_feature(CPU_AVX512_IFMA); - _vm_target_features.clear_feature(CPU_APX_F); - _vm_target_features.clear_feature(CPU_AVX512_FP16); - _vm_target_features.clear_feature(CPU_AVX10_1); - _vm_target_features.clear_feature(CPU_AVX10_2); + _features.clear_feature(CPU_AVX512F); + _features.clear_feature(CPU_AVX512DQ); + _features.clear_feature(CPU_AVX512CD); + _features.clear_feature(CPU_AVX512BW); + _features.clear_feature(CPU_AVX512ER); + _features.clear_feature(CPU_AVX512PF); + _features.clear_feature(CPU_AVX512VL); + _features.clear_feature(CPU_AVX512_VPOPCNTDQ); + _features.clear_feature(CPU_AVX512_VPCLMULQDQ); + _features.clear_feature(CPU_AVX512_VAES); + _features.clear_feature(CPU_AVX512_VNNI); + _features.clear_feature(CPU_AVX512_VBMI); + _features.clear_feature(CPU_AVX512_VBMI2); + _features.clear_feature(CPU_AVX512_BITALG); + _features.clear_feature(CPU_AVX512_IFMA); + _features.clear_feature(CPU_APX_F); + _features.clear_feature(CPU_AVX512_FP16); + _features.clear_feature(CPU_AVX10_1); + _features.clear_feature(CPU_AVX10_2); } // Currently APX support is only enabled for targets supporting AVX512VL feature. @@ -1018,45 +1023,45 @@ void VM_Version::get_processor_features() { } if (!UseAPX) { - _vm_target_features.clear_feature(CPU_APX_F); + _features.clear_feature(CPU_APX_F); } if (UseAVX < 2) { - _vm_target_features.clear_feature(CPU_AVX2); - _vm_target_features.clear_feature(CPU_AVX_IFMA); + _features.clear_feature(CPU_AVX2); + _features.clear_feature(CPU_AVX_IFMA); } if (UseAVX < 1) { - _vm_target_features.clear_feature(CPU_AVX); - _vm_target_features.clear_feature(CPU_VZEROUPPER); - _vm_target_features.clear_feature(CPU_F16C); - _vm_target_features.clear_feature(CPU_SHA512); + _features.clear_feature(CPU_AVX); + _features.clear_feature(CPU_VZEROUPPER); + _features.clear_feature(CPU_F16C); + _features.clear_feature(CPU_SHA512); } if (logical_processors_per_package() == 1) { // HT processor could be installed on a system which doesn't support HT. - _vm_target_features.clear_feature(CPU_HT); + _features.clear_feature(CPU_HT); } if (is_intel()) { // Intel cpus specific settings if (is_knights_family()) { - _vm_target_features.clear_feature(CPU_VZEROUPPER); - _vm_target_features.clear_feature(CPU_AVX512BW); - _vm_target_features.clear_feature(CPU_AVX512VL); - _vm_target_features.clear_feature(CPU_AVX512DQ); - _vm_target_features.clear_feature(CPU_AVX512_VNNI); - _vm_target_features.clear_feature(CPU_AVX512_VAES); - _vm_target_features.clear_feature(CPU_AVX512_VPOPCNTDQ); - _vm_target_features.clear_feature(CPU_AVX512_VPCLMULQDQ); - _vm_target_features.clear_feature(CPU_AVX512_VBMI); - _vm_target_features.clear_feature(CPU_AVX512_VBMI2); - _vm_target_features.clear_feature(CPU_CLWB); - _vm_target_features.clear_feature(CPU_FLUSHOPT); - _vm_target_features.clear_feature(CPU_GFNI); - _vm_target_features.clear_feature(CPU_AVX512_BITALG); - _vm_target_features.clear_feature(CPU_AVX512_IFMA); - _vm_target_features.clear_feature(CPU_AVX_IFMA); - _vm_target_features.clear_feature(CPU_AVX512_FP16); + _features.clear_feature(CPU_VZEROUPPER); + _features.clear_feature(CPU_AVX512BW); + _features.clear_feature(CPU_AVX512VL); + _features.clear_feature(CPU_AVX512DQ); + _features.clear_feature(CPU_AVX512_VNNI); + _features.clear_feature(CPU_AVX512_VAES); + _features.clear_feature(CPU_AVX512_VPOPCNTDQ); + _features.clear_feature(CPU_AVX512_VPCLMULQDQ); + _features.clear_feature(CPU_AVX512_VBMI); + _features.clear_feature(CPU_AVX512_VBMI2); + _features.clear_feature(CPU_CLWB); + _features.clear_feature(CPU_FLUSHOPT); + _features.clear_feature(CPU_GFNI); + _features.clear_feature(CPU_AVX512_BITALG); + _features.clear_feature(CPU_AVX512_IFMA); + _features.clear_feature(CPU_AVX_IFMA); + _features.clear_feature(CPU_AVX512_FP16); } } @@ -1066,7 +1071,6 @@ void VM_Version::get_processor_features() { _has_intel_jcc_erratum = IntelJccErratumMitigation; } - assert(supports_cpuid(), "Always present"); assert(supports_clflush(), "Always present"); if (X86ICacheSync == -1) { // Auto-detect, choosing the best performant one that still flushes @@ -1098,7 +1102,7 @@ void VM_Version::get_processor_features() { cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(cpu_info_size > 0, "not enough temporary space allocated"); size_t buf_iter = cpu_info_size; - for (uint64_t i = 0; i < features_vector_size(); i++) { + for (uint64_t i = 0; i < VM_Features::features_vector_size(); i++) { insert_features_names(features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i); buf_iter = strlen(buf); } @@ -2880,94 +2884,95 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) { return _max_qualified_cpu_frequency; } -void VM_Version::CpuidInfo::install_feature_flags() const { +VM_Features VM_Version::CpuidInfo::feature_flags() const { + VM_Features vm_features; if (std_cpuid1_edx.bits.cmpxchg8 != 0) - _vm_target_features.set_feature(CPU_CX8); + vm_features.set_feature(CPU_CX8); if (std_cpuid1_edx.bits.cmov != 0) - _vm_target_features.set_feature(CPU_CMOV); + vm_features.set_feature(CPU_CMOV); if (std_cpuid1_edx.bits.clflush != 0) - _vm_target_features.set_feature(CPU_FLUSH); + vm_features.set_feature(CPU_FLUSH); // clflush should always be available on x86_64 // if not we are in real trouble because we rely on it // to flush the code cache. - assert (_vm_target_features.supports_feature(CPU_FLUSH), "clflush should be available"); + assert (vm_features.supports_feature(CPU_FLUSH), "clflush should be available"); if (std_cpuid1_edx.bits.fxsr != 0 || (is_amd_family() && ext_cpuid1_edx.bits.fxsr != 0)) - _vm_target_features.set_feature(CPU_FXSR); + vm_features.set_feature(CPU_FXSR); // HT flag is set for multi-core processors also. if (threads_per_core() > 1) - _vm_target_features.set_feature(CPU_HT); + vm_features.set_feature(CPU_HT); if (std_cpuid1_edx.bits.mmx != 0 || (is_amd_family() && ext_cpuid1_edx.bits.mmx != 0)) - _vm_target_features.set_feature(CPU_MMX); + vm_features.set_feature(CPU_MMX); if (std_cpuid1_edx.bits.sse != 0) - _vm_target_features.set_feature(CPU_SSE); + vm_features.set_feature(CPU_SSE); if (std_cpuid1_edx.bits.sse2 != 0) - _vm_target_features.set_feature(CPU_SSE2); + vm_features.set_feature(CPU_SSE2); if (std_cpuid1_ecx.bits.sse3 != 0) - _vm_target_features.set_feature(CPU_SSE3); + vm_features.set_feature(CPU_SSE3); if (std_cpuid1_ecx.bits.ssse3 != 0) - _vm_target_features.set_feature(CPU_SSSE3); + vm_features.set_feature(CPU_SSSE3); if (std_cpuid1_ecx.bits.sse4_1 != 0) - _vm_target_features.set_feature(CPU_SSE4_1); + vm_features.set_feature(CPU_SSE4_1); if (std_cpuid1_ecx.bits.sse4_2 != 0) - _vm_target_features.set_feature(CPU_SSE4_2); + vm_features.set_feature(CPU_SSE4_2); if (std_cpuid1_ecx.bits.popcnt != 0) - _vm_target_features.set_feature(CPU_POPCNT); + vm_features.set_feature(CPU_POPCNT); if (sefsl1_cpuid7_edx.bits.apx_f != 0 && xem_xcr0_eax.bits.apx_f != 0) { - _vm_target_features.set_feature(CPU_APX_F); + vm_features.set_feature(CPU_APX_F); } if (std_cpuid1_ecx.bits.avx != 0 && std_cpuid1_ecx.bits.osxsave != 0 && xem_xcr0_eax.bits.sse != 0 && xem_xcr0_eax.bits.ymm != 0) { - _vm_target_features.set_feature(CPU_AVX); - _vm_target_features.set_feature(CPU_VZEROUPPER); + vm_features.set_feature(CPU_AVX); + vm_features.set_feature(CPU_VZEROUPPER); if (sefsl1_cpuid7_eax.bits.sha512 != 0) - _vm_target_features.set_feature(CPU_SHA512); + vm_features.set_feature(CPU_SHA512); if (std_cpuid1_ecx.bits.f16c != 0) - _vm_target_features.set_feature(CPU_F16C); + vm_features.set_feature(CPU_F16C); if (sef_cpuid7_ebx.bits.avx2 != 0) { - _vm_target_features.set_feature(CPU_AVX2); + vm_features.set_feature(CPU_AVX2); if (sefsl1_cpuid7_eax.bits.avx_ifma != 0) - _vm_target_features.set_feature(CPU_AVX_IFMA); + vm_features.set_feature(CPU_AVX_IFMA); } if (sef_cpuid7_ecx.bits.gfni != 0) - _vm_target_features.set_feature(CPU_GFNI); + vm_features.set_feature(CPU_GFNI); if (sef_cpuid7_ebx.bits.avx512f != 0 && xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - _vm_target_features.set_feature(CPU_AVX512F); + vm_features.set_feature(CPU_AVX512F); if (sef_cpuid7_ebx.bits.avx512cd != 0) - _vm_target_features.set_feature(CPU_AVX512CD); + vm_features.set_feature(CPU_AVX512CD); if (sef_cpuid7_ebx.bits.avx512dq != 0) - _vm_target_features.set_feature(CPU_AVX512DQ); + vm_features.set_feature(CPU_AVX512DQ); if (sef_cpuid7_ebx.bits.avx512ifma != 0) - _vm_target_features.set_feature(CPU_AVX512_IFMA); + vm_features.set_feature(CPU_AVX512_IFMA); if (sef_cpuid7_ebx.bits.avx512pf != 0) - _vm_target_features.set_feature(CPU_AVX512PF); + vm_features.set_feature(CPU_AVX512PF); if (sef_cpuid7_ebx.bits.avx512er != 0) - _vm_target_features.set_feature(CPU_AVX512ER); + vm_features.set_feature(CPU_AVX512ER); if (sef_cpuid7_ebx.bits.avx512bw != 0) - _vm_target_features.set_feature(CPU_AVX512BW); + vm_features.set_feature(CPU_AVX512BW); if (sef_cpuid7_ebx.bits.avx512vl != 0) - _vm_target_features.set_feature(CPU_AVX512VL); + vm_features.set_feature(CPU_AVX512VL); if (sef_cpuid7_ecx.bits.avx512_vpopcntdq != 0) - _vm_target_features.set_feature(CPU_AVX512_VPOPCNTDQ); + vm_features.set_feature(CPU_AVX512_VPOPCNTDQ); if (sef_cpuid7_ecx.bits.avx512_vpclmulqdq != 0) - _vm_target_features.set_feature(CPU_AVX512_VPCLMULQDQ); + vm_features.set_feature(CPU_AVX512_VPCLMULQDQ); if (sef_cpuid7_ecx.bits.vaes != 0) - _vm_target_features.set_feature(CPU_AVX512_VAES); + vm_features.set_feature(CPU_AVX512_VAES); if (sef_cpuid7_ecx.bits.avx512_vnni != 0) - _vm_target_features.set_feature(CPU_AVX512_VNNI); + vm_features.set_feature(CPU_AVX512_VNNI); if (sef_cpuid7_ecx.bits.avx512_bitalg != 0) - _vm_target_features.set_feature(CPU_AVX512_BITALG); + vm_features.set_feature(CPU_AVX512_BITALG); if (sef_cpuid7_ecx.bits.avx512_vbmi != 0) - _vm_target_features.set_feature(CPU_AVX512_VBMI); + vm_features.set_feature(CPU_AVX512_VBMI); if (sef_cpuid7_ecx.bits.avx512_vbmi2 != 0) - _vm_target_features.set_feature(CPU_AVX512_VBMI2); + vm_features.set_feature(CPU_AVX512_VBMI2); } if (is_intel()) { if (sefsl1_cpuid7_edx.bits.avx10 != 0 && @@ -2976,114 +2981,115 @@ void VM_Version::CpuidInfo::install_feature_flags() const { xem_xcr0_eax.bits.opmask != 0 && xem_xcr0_eax.bits.zmm512 != 0 && xem_xcr0_eax.bits.zmm32 != 0) { - _vm_target_features.set_feature(CPU_AVX10_1); - _vm_target_features.set_feature(CPU_AVX512F); - _vm_target_features.set_feature(CPU_AVX512CD); - _vm_target_features.set_feature(CPU_AVX512DQ); - _vm_target_features.set_feature(CPU_AVX512PF); - _vm_target_features.set_feature(CPU_AVX512ER); - _vm_target_features.set_feature(CPU_AVX512BW); - _vm_target_features.set_feature(CPU_AVX512VL); - _vm_target_features.set_feature(CPU_AVX512_VPOPCNTDQ); - _vm_target_features.set_feature(CPU_AVX512_VPCLMULQDQ); - _vm_target_features.set_feature(CPU_AVX512_VAES); - _vm_target_features.set_feature(CPU_AVX512_VNNI); - _vm_target_features.set_feature(CPU_AVX512_BITALG); - _vm_target_features.set_feature(CPU_AVX512_VBMI); - _vm_target_features.set_feature(CPU_AVX512_VBMI2); + vm_features.set_feature(CPU_AVX10_1); + vm_features.set_feature(CPU_AVX512F); + vm_features.set_feature(CPU_AVX512CD); + vm_features.set_feature(CPU_AVX512DQ); + vm_features.set_feature(CPU_AVX512PF); + vm_features.set_feature(CPU_AVX512ER); + vm_features.set_feature(CPU_AVX512BW); + vm_features.set_feature(CPU_AVX512VL); + vm_features.set_feature(CPU_AVX512_VPOPCNTDQ); + vm_features.set_feature(CPU_AVX512_VPCLMULQDQ); + vm_features.set_feature(CPU_AVX512_VAES); + vm_features.set_feature(CPU_AVX512_VNNI); + vm_features.set_feature(CPU_AVX512_BITALG); + vm_features.set_feature(CPU_AVX512_VBMI); + vm_features.set_feature(CPU_AVX512_VBMI2); if (std_cpuid24_ebx.bits.avx10_converged_isa_version >= 2) { - _vm_target_features.set_feature(CPU_AVX10_2); + vm_features.set_feature(CPU_AVX10_2); } } } } if (std_cpuid1_ecx.bits.hv != 0) - _vm_target_features.set_feature(CPU_HV); + vm_features.set_feature(CPU_HV); if (sef_cpuid7_ebx.bits.bmi1 != 0) - _vm_target_features.set_feature(CPU_BMI1); + vm_features.set_feature(CPU_BMI1); if (std_cpuid1_edx.bits.tsc != 0) - _vm_target_features.set_feature(CPU_TSC); + vm_features.set_feature(CPU_TSC); if (ext_cpuid7_edx.bits.tsc_invariance != 0) - _vm_target_features.set_feature(CPU_TSCINV_BIT); + vm_features.set_feature(CPU_TSCINV_BIT); if (std_cpuid1_ecx.bits.aes != 0) - _vm_target_features.set_feature(CPU_AES); + vm_features.set_feature(CPU_AES); if (ext_cpuid1_ecx.bits.lzcnt != 0) - _vm_target_features.set_feature(CPU_LZCNT); + vm_features.set_feature(CPU_LZCNT); if (ext_cpuid1_ecx.bits.prefetchw != 0) - _vm_target_features.set_feature(CPU_3DNOW_PREFETCH); + vm_features.set_feature(CPU_3DNOW_PREFETCH); if (sef_cpuid7_ebx.bits.erms != 0) - _vm_target_features.set_feature(CPU_ERMS); + vm_features.set_feature(CPU_ERMS); if (sef_cpuid7_edx.bits.fast_short_rep_mov != 0) - _vm_target_features.set_feature(CPU_FSRM); + vm_features.set_feature(CPU_FSRM); if (std_cpuid1_ecx.bits.clmul != 0) - _vm_target_features.set_feature(CPU_CLMUL); + vm_features.set_feature(CPU_CLMUL); if (sef_cpuid7_ebx.bits.rtm != 0) - _vm_target_features.set_feature(CPU_RTM); + vm_features.set_feature(CPU_RTM); if (sef_cpuid7_ebx.bits.adx != 0) - _vm_target_features.set_feature(CPU_ADX); + vm_features.set_feature(CPU_ADX); if (sef_cpuid7_ebx.bits.bmi2 != 0) - _vm_target_features.set_feature(CPU_BMI2); + vm_features.set_feature(CPU_BMI2); if (sef_cpuid7_ebx.bits.sha != 0) - _vm_target_features.set_feature(CPU_SHA); + vm_features.set_feature(CPU_SHA); if (std_cpuid1_ecx.bits.fma != 0) - _vm_target_features.set_feature(CPU_FMA); + vm_features.set_feature(CPU_FMA); if (sef_cpuid7_ebx.bits.clflushopt != 0) - _vm_target_features.set_feature(CPU_FLUSHOPT); + vm_features.set_feature(CPU_FLUSHOPT); if (sef_cpuid7_ebx.bits.clwb != 0) - _vm_target_features.set_feature(CPU_CLWB); + vm_features.set_feature(CPU_CLWB); if (ext_cpuid1_edx.bits.rdtscp != 0) - _vm_target_features.set_feature(CPU_RDTSCP); + vm_features.set_feature(CPU_RDTSCP); if (sef_cpuid7_ecx.bits.rdpid != 0) - _vm_target_features.set_feature(CPU_RDPID); + vm_features.set_feature(CPU_RDPID); // AMD|Hygon additional features. if (is_amd_family()) { // PREFETCHW was checked above, check TDNOW here. if ((ext_cpuid1_edx.bits.tdnow != 0)) - _vm_target_features.set_feature(CPU_3DNOW_PREFETCH); + vm_features.set_feature(CPU_3DNOW_PREFETCH); if (ext_cpuid1_ecx.bits.sse4a != 0) - _vm_target_features.set_feature(CPU_SSE4A); + vm_features.set_feature(CPU_SSE4A); } // Intel additional features. if (is_intel()) { if (sef_cpuid7_edx.bits.serialize != 0) - _vm_target_features.set_feature(CPU_SERIALIZE); + vm_features.set_feature(CPU_SERIALIZE); if (_cpuid_info.sef_cpuid7_edx.bits.avx512_fp16 != 0) - _vm_target_features.set_feature(CPU_AVX512_FP16); + vm_features.set_feature(CPU_AVX512_FP16); } // ZX additional features. if (is_zx()) { // We do not know if these are supported by ZX, so we cannot trust // common CPUID bit for them. - assert(_vm_target_features.supports_feature(CPU_CLWB), "Check if it is supported?"); - _vm_target_features.clear_feature(CPU_CLWB); + assert(vm_features.supports_feature(CPU_CLWB), "Check if it is supported?"); + vm_features.clear_feature(CPU_CLWB); } // Protection key features. if (sef_cpuid7_ecx.bits.pku != 0) { - _vm_target_features.set_feature(CPU_PKU); + vm_features.set_feature(CPU_PKU); } if (sef_cpuid7_ecx.bits.ospke != 0) { - _vm_target_features.set_feature(CPU_OSPKE); + vm_features.set_feature(CPU_OSPKE); } // Control flow enforcement (CET) features. if (sef_cpuid7_ecx.bits.cet_ss != 0) { - _vm_target_features.set_feature(CPU_CET_SS); + vm_features.set_feature(CPU_CET_SS); } if (sef_cpuid7_edx.bits.cet_ibt != 0) { - _vm_target_features.set_feature(CPU_CET_IBT); + vm_features.set_feature(CPU_CET_IBT); } // Composite features. if (supports_tscinv_bit() && ((is_amd_family() && !is_amd_Barcelona()) || is_intel_tsc_synched_at_init())) { - _vm_target_features.set_feature(CPU_TSCINV); + vm_features.set_feature(CPU_TSCINV); } + return vm_features; } bool VM_Version::os_supports_avx_vectors() { @@ -3273,3 +3279,48 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) { } return true; } + +void VM_Features::set_feature(uint32_t feature) { + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + _features_vector[index] |= (1ULL << (feature & index_mask)); +} + +void VM_Features::clear_feature(uint32_t feature) { + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + _features_vector[index] &= ~(1ULL << (feature & index_mask)); +} + +void VM_Features::clear_features() { + for (uint32_t i = 0; i < _features_vector_size; i++) { + _features_vector[i] = 0; + } +} + +bool VM_Features::supports_feature(uint32_t feature) { + uint32_t index = feature >> _features_vector_element_shift_count; + uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; + assert(index < _features_vector_size, "Features array index out of bounds"); + return (_features_vector[index] & (1ULL << (feature & index_mask))) != 0; +} + +bool VM_Features::is_within_feature_vector_bounds(uint32_t num_features) { + return _features_vector_size >= ((num_features >> _features_vector_element_shift_count) + 1); +} + +void VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], + uint features_names_index) { + while (features != 0) { + if (features & 1) { + int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]); + assert(res > 0, "not enough temporary space allocated"); + buf += res; + buflen -= res; + } + features >>= 1; + ++features_names_index; + } +} diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index f823ae8639aa0..2b4b2bd6d9f5b 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -30,6 +30,35 @@ #include "utilities/macros.hpp" #include "utilities/sizes.hpp" +#define MAX_FEATURE_VEC_SIZE 4 + +class VM_Features { + public: + using FeatureVector = uint64_t [MAX_FEATURE_VEC_SIZE]; + + // Feature vector bitmap currently only used by x86 backend. + FeatureVector _features_vector; + + // log2 of feature vector element size in bits, used by JVMCI to check enabled feature bits. + // Refer HotSpotJVMCIBackendFactory::convertFeaturesVector. + static uint32_t _features_vector_element_shift_count; + + // Size of feature vector bitmap. + static uint32_t _features_vector_size; + + VM_Features() { + clear_features(); + } + + void set_feature(uint32_t feature); + void clear_feature(uint32_t feature); + bool supports_feature(uint32_t feature); + void clear_features(); + + static bool is_within_feature_vector_bounds(uint32_t num_features); + static uint32_t features_vector_size() { return _features_vector_size;} +}; + class VM_Version : public Abstract_VM_Version { friend class VMStructs; friend class JVMCIVMStructs; @@ -452,6 +481,22 @@ class VM_Version : public Abstract_VM_Version { static const char* _features_names[]; + // CPU feature flags vector, can be affected by VM settings. + static VM_Features _features; + + // Original CPU feature flags vector, not affected by VM settings. + static VM_Features _cpu_features; + + static void clear_cpu_features() { + _features.clear_features(); + _cpu_features.clear_features(); + } + + static uint64_t features_vector_elem(uint32_t elem) { + assert(elem < VM_Features::_features_vector_size, ""); + return _features._features_vector[elem]; + } + enum Extended_Family { // AMD CPU_FAMILY_AMD_11H = 0x11, @@ -593,7 +638,7 @@ class VM_Version : public Abstract_VM_Version { // Space to save apx registers after signal handle jlong apx_save[2]; // Save r16 and r31 - void install_feature_flags() const; + VM_Features feature_flags() const; // Asserts void assert_is_initialized() const { @@ -674,27 +719,27 @@ class VM_Version : public Abstract_VM_Version { static void clear_apx_test_state(); static void clean_cpuFeatures() { - Abstract_VM_Version::clear_cpu_features(); + VM_Version::clear_cpu_features(); } static void set_avx_cpuFeatures() { - _vm_target_features.set_feature(CPU_SSE); - _vm_target_features.set_feature(CPU_SSE2); - _vm_target_features.set_feature(CPU_AVX); - _vm_target_features.set_feature(CPU_VZEROUPPER); + _features.set_feature(CPU_SSE); + _features.set_feature(CPU_SSE2); + _features.set_feature(CPU_AVX); + _features.set_feature(CPU_VZEROUPPER); } static void set_evex_cpuFeatures() { - _vm_target_features.set_feature(CPU_AVX10_1); - _vm_target_features.set_feature(CPU_AVX512F); - _vm_target_features.set_feature(CPU_SSE); - _vm_target_features.set_feature(CPU_SSE2); - _vm_target_features.set_feature(CPU_VZEROUPPER); + _features.set_feature(CPU_AVX10_1); + _features.set_feature(CPU_AVX512F); + _features.set_feature(CPU_SSE); + _features.set_feature(CPU_SSE2); + _features.set_feature(CPU_VZEROUPPER); } - static void set_apx_cpuFeatures() { _vm_target_features.set_feature(CPU_APX_F); } + static void set_apx_cpuFeatures() { _features.set_feature(CPU_APX_F); } static void set_bmi_cpuFeatures() { - _vm_target_features.set_feature(CPU_BMI1); - _vm_target_features.set_feature(CPU_BMI2); - _vm_target_features.set_feature(CPU_LZCNT); - _vm_target_features.set_feature(CPU_POPCNT); + _features.set_feature(CPU_BMI1); + _features.set_feature(CPU_BMI2); + _features.set_feature(CPU_LZCNT); + _features.set_feature(CPU_POPCNT); } // Initialization @@ -750,40 +795,39 @@ class VM_Version : public Abstract_VM_Version { // // Feature identification which can be affected by VM settings // - static bool supports_cpuid() { return Abstract_VM_Version::vm_features_exist(); } - static bool supports_cmov() { return _vm_target_features.supports_feature(CPU_CMOV); } - static bool supports_fxsr() { return _vm_target_features.supports_feature(CPU_FXSR); } - static bool supports_ht() { return _vm_target_features.supports_feature(CPU_HT); } - static bool supports_mmx() { return _vm_target_features.supports_feature(CPU_MMX); } - static bool supports_sse() { return _vm_target_features.supports_feature(CPU_SSE); } - static bool supports_sse2() { return _vm_target_features.supports_feature(CPU_SSE2); } - static bool supports_sse3() { return _vm_target_features.supports_feature(CPU_SSE3); } - static bool supports_ssse3() { return _vm_target_features.supports_feature(CPU_SSSE3); } - static bool supports_sse4_1() { return _vm_target_features.supports_feature(CPU_SSE4_1); } - static bool supports_sse4_2() { return _vm_target_features.supports_feature(CPU_SSE4_2); } - static bool supports_popcnt() { return _vm_target_features.supports_feature(CPU_POPCNT); } - static bool supports_avx() { return _vm_target_features.supports_feature(CPU_AVX); } - static bool supports_avx2() { return _vm_target_features.supports_feature(CPU_AVX2); } - static bool supports_tsc() { return _vm_target_features.supports_feature(CPU_TSC); } - static bool supports_rdtscp() { return _vm_target_features.supports_feature(CPU_RDTSCP); } - static bool supports_rdpid() { return _vm_target_features.supports_feature(CPU_RDPID); } - static bool supports_aes() { return _vm_target_features.supports_feature(CPU_AES); } - static bool supports_erms() { return _vm_target_features.supports_feature(CPU_ERMS); } - static bool supports_fsrm() { return _vm_target_features.supports_feature(CPU_FSRM); } - static bool supports_clmul() { return _vm_target_features.supports_feature(CPU_CLMUL); } - static bool supports_rtm() { return _vm_target_features.supports_feature(CPU_RTM); } - static bool supports_bmi1() { return _vm_target_features.supports_feature(CPU_BMI1); } - static bool supports_bmi2() { return _vm_target_features.supports_feature(CPU_BMI2); } - static bool supports_adx() { return _vm_target_features.supports_feature(CPU_ADX); } - static bool supports_evex() { return _vm_target_features.supports_feature(CPU_AVX512F); } - static bool supports_avx512dq() { return _vm_target_features.supports_feature(CPU_AVX512DQ); } - static bool supports_avx512ifma() { return _vm_target_features.supports_feature(CPU_AVX512_IFMA); } - static bool supports_avxifma() { return _vm_target_features.supports_feature(CPU_AVX_IFMA); } - static bool supports_avx512pf() { return _vm_target_features.supports_feature(CPU_AVX512PF); } - static bool supports_avx512er() { return _vm_target_features.supports_feature(CPU_AVX512ER); } - static bool supports_avx512cd() { return _vm_target_features.supports_feature(CPU_AVX512CD); } - static bool supports_avx512bw() { return _vm_target_features.supports_feature(CPU_AVX512BW); } - static bool supports_avx512vl() { return _vm_target_features.supports_feature(CPU_AVX512VL); } + static bool supports_cmov() { return _features.supports_feature(CPU_CMOV); } + static bool supports_fxsr() { return _features.supports_feature(CPU_FXSR); } + static bool supports_ht() { return _features.supports_feature(CPU_HT); } + static bool supports_mmx() { return _features.supports_feature(CPU_MMX); } + static bool supports_sse() { return _features.supports_feature(CPU_SSE); } + static bool supports_sse2() { return _features.supports_feature(CPU_SSE2); } + static bool supports_sse3() { return _features.supports_feature(CPU_SSE3); } + static bool supports_ssse3() { return _features.supports_feature(CPU_SSSE3); } + static bool supports_sse4_1() { return _features.supports_feature(CPU_SSE4_1); } + static bool supports_sse4_2() { return _features.supports_feature(CPU_SSE4_2); } + static bool supports_popcnt() { return _features.supports_feature(CPU_POPCNT); } + static bool supports_avx() { return _features.supports_feature(CPU_AVX); } + static bool supports_avx2() { return _features.supports_feature(CPU_AVX2); } + static bool supports_tsc() { return _features.supports_feature(CPU_TSC); } + static bool supports_rdtscp() { return _features.supports_feature(CPU_RDTSCP); } + static bool supports_rdpid() { return _features.supports_feature(CPU_RDPID); } + static bool supports_aes() { return _features.supports_feature(CPU_AES); } + static bool supports_erms() { return _features.supports_feature(CPU_ERMS); } + static bool supports_fsrm() { return _features.supports_feature(CPU_FSRM); } + static bool supports_clmul() { return _features.supports_feature(CPU_CLMUL); } + static bool supports_rtm() { return _features.supports_feature(CPU_RTM); } + static bool supports_bmi1() { return _features.supports_feature(CPU_BMI1); } + static bool supports_bmi2() { return _features.supports_feature(CPU_BMI2); } + static bool supports_adx() { return _features.supports_feature(CPU_ADX); } + static bool supports_evex() { return _features.supports_feature(CPU_AVX512F); } + static bool supports_avx512dq() { return _features.supports_feature(CPU_AVX512DQ); } + static bool supports_avx512ifma() { return _features.supports_feature(CPU_AVX512_IFMA); } + static bool supports_avxifma() { return _features.supports_feature(CPU_AVX_IFMA); } + static bool supports_avx512pf() { return _features.supports_feature(CPU_AVX512PF); } + static bool supports_avx512er() { return _features.supports_feature(CPU_AVX512ER); } + static bool supports_avx512cd() { return _features.supports_feature(CPU_AVX512CD); } + static bool supports_avx512bw() { return _features.supports_feature(CPU_AVX512BW); } + static bool supports_avx512vl() { return _features.supports_feature(CPU_AVX512VL); } static bool supports_avx512vlbw() { return (supports_evex() && supports_avx512bw() && supports_avx512vl()); } static bool supports_avx512bwdq() { return (supports_evex() && supports_avx512bw() && supports_avx512dq()); } static bool supports_avx512vldq() { return (supports_evex() && supports_avx512dq() && supports_avx512vl()); } @@ -792,39 +836,39 @@ class VM_Version : public Abstract_VM_Version { static bool supports_avx512novl() { return (supports_evex() && !supports_avx512vl()); } static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } - static bool supports_apx_f() { return _vm_target_features.supports_feature(CPU_APX_F); } + static bool supports_apx_f() { return _features.supports_feature(CPU_APX_F); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } - static bool supports_sha() { return _vm_target_features.supports_feature(CPU_SHA); } - static bool supports_fma() { return _vm_target_features.supports_feature(CPU_FMA) && supports_avx(); } - static bool supports_vzeroupper() { return _vm_target_features.supports_feature(CPU_VZEROUPPER); } - static bool supports_avx512_vpopcntdq() { return _vm_target_features.supports_feature(CPU_AVX512_VPOPCNTDQ); } - static bool supports_avx512_vpclmulqdq() { return _vm_target_features.supports_feature(CPU_AVX512_VPCLMULQDQ); } - static bool supports_avx512_vaes() { return _vm_target_features.supports_feature(CPU_AVX512_VAES); } - static bool supports_gfni() { return _vm_target_features.supports_feature(CPU_GFNI); } - static bool supports_avx512_vnni() { return _vm_target_features.supports_feature(CPU_AVX512_VNNI); } - static bool supports_avx512_bitalg() { return _vm_target_features.supports_feature(CPU_AVX512_BITALG); } - static bool supports_avx512_vbmi() { return _vm_target_features.supports_feature(CPU_AVX512_VBMI); } - static bool supports_avx512_vbmi2() { return _vm_target_features.supports_feature(CPU_AVX512_VBMI2); } - static bool supports_avx512_fp16() { return _vm_target_features.supports_feature(CPU_AVX512_FP16); } - static bool supports_hv() { return _vm_target_features.supports_feature(CPU_HV); } - static bool supports_serialize() { return _vm_target_features.supports_feature(CPU_SERIALIZE); } - static bool supports_f16c() { return _vm_target_features.supports_feature(CPU_F16C); } - static bool supports_pku() { return _vm_target_features.supports_feature(CPU_PKU); } - static bool supports_ospke() { return _vm_target_features.supports_feature(CPU_OSPKE); } - static bool supports_cet_ss() { return _vm_target_features.supports_feature(CPU_CET_SS); } - static bool supports_cet_ibt() { return _vm_target_features.supports_feature(CPU_CET_IBT); } - static bool supports_sha512() { return _vm_target_features.supports_feature(CPU_SHA512); } + static bool supports_sha() { return _features.supports_feature(CPU_SHA); } + static bool supports_fma() { return _features.supports_feature(CPU_FMA) && supports_avx(); } + static bool supports_vzeroupper() { return _features.supports_feature(CPU_VZEROUPPER); } + static bool supports_avx512_vpopcntdq() { return _features.supports_feature(CPU_AVX512_VPOPCNTDQ); } + static bool supports_avx512_vpclmulqdq() { return _features.supports_feature(CPU_AVX512_VPCLMULQDQ); } + static bool supports_avx512_vaes() { return _features.supports_feature(CPU_AVX512_VAES); } + static bool supports_gfni() { return _features.supports_feature(CPU_GFNI); } + static bool supports_avx512_vnni() { return _features.supports_feature(CPU_AVX512_VNNI); } + static bool supports_avx512_bitalg() { return _features.supports_feature(CPU_AVX512_BITALG); } + static bool supports_avx512_vbmi() { return _features.supports_feature(CPU_AVX512_VBMI); } + static bool supports_avx512_vbmi2() { return _features.supports_feature(CPU_AVX512_VBMI2); } + static bool supports_avx512_fp16() { return _features.supports_feature(CPU_AVX512_FP16); } + static bool supports_hv() { return _features.supports_feature(CPU_HV); } + static bool supports_serialize() { return _features.supports_feature(CPU_SERIALIZE); } + static bool supports_f16c() { return _features.supports_feature(CPU_F16C); } + static bool supports_pku() { return _features.supports_feature(CPU_PKU); } + static bool supports_ospke() { return _features.supports_feature(CPU_OSPKE); } + static bool supports_cet_ss() { return _features.supports_feature(CPU_CET_SS); } + static bool supports_cet_ibt() { return _features.supports_feature(CPU_CET_IBT); } + static bool supports_sha512() { return _features.supports_feature(CPU_SHA512); } // IntelĀ® AVX10 introduces a versioned approach for enumeration that is monotonically increasing, inclusive, // and supporting all vector lengths. Feature set supported by an AVX10 vector ISA version is also supported // by all the versions above it. - static bool supports_avx10_1() { return _vm_target_features.supports_feature(CPU_AVX10_1);} - static bool supports_avx10_2() { return _vm_target_features.supports_feature(CPU_AVX10_2);} + static bool supports_avx10_1() { return _features.supports_feature(CPU_AVX10_1);} + static bool supports_avx10_2() { return _features.supports_feature(CPU_AVX10_2);} // // Feature identification not affected by VM flags // - static bool cpu_supports_evex() { return _cpu_target_features.supports_feature(CPU_AVX512F); } + static bool cpu_supports_evex() { return _cpu_features.supports_feature(CPU_AVX512F); } static bool supports_avx512_simd_sort() { if (supports_avx512dq()) { @@ -855,6 +899,8 @@ class VM_Version : public Abstract_VM_Version { static bool is_intel_tsc_synched_at_init(); + static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0); + // This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102) // that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode // mitigation causes regressions when jumps or fused conditional branches cross or end at @@ -862,19 +908,19 @@ class VM_Version : public Abstract_VM_Version { static bool has_intel_jcc_erratum() { return _has_intel_jcc_erratum; } // AMD features - static bool supports_3dnow_prefetch() { return _vm_target_features.supports_feature(CPU_3DNOW_PREFETCH); } - static bool supports_lzcnt() { return _vm_target_features.supports_feature(CPU_LZCNT); } - static bool supports_sse4a() { return _vm_target_features.supports_feature(CPU_SSE4A); } + static bool supports_3dnow_prefetch() { return _features.supports_feature(CPU_3DNOW_PREFETCH); } + static bool supports_lzcnt() { return _features.supports_feature(CPU_LZCNT); } + static bool supports_sse4a() { return _features.supports_feature(CPU_SSE4A); } static bool is_amd_Barcelona() { return is_amd() && extended_cpu_family() == CPU_FAMILY_AMD_11H; } // Intel and AMD newer cores support fast timestamps well static bool supports_tscinv_bit() { - return _vm_target_features.supports_feature(CPU_TSCINV_BIT); + return _features.supports_feature(CPU_TSCINV_BIT); } static bool supports_tscinv() { - return _vm_target_features.supports_feature(CPU_TSCINV); + return _features.supports_feature(CPU_TSCINV); } // Intel Core and newer cpus have fast IDIV instruction (excluding Atom). @@ -935,8 +981,8 @@ class VM_Version : public Abstract_VM_Version { static bool supports_clflush(); // Can't inline due to header file conflict // Note: CPU_FLUSHOPT and CPU_CLWB bits should always be zero for 32-bit - static bool supports_clflushopt() { return (_vm_target_features.supports_feature(CPU_FLUSHOPT)); } - static bool supports_clwb() { return (_vm_target_features.supports_feature(CPU_CLWB)); } + static bool supports_clflushopt() { return (_features.supports_feature(CPU_FLUSHOPT)); } + static bool supports_clwb() { return (_features.supports_feature(CPU_CLWB)); } // Old CPUs perform lea on AGU which causes additional latency transferring the // value from/to ALU for other operations diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index af747a0f98bea..b8a988dba5a55 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -147,11 +147,6 @@ JVMTI_ONLY(static_field(CompilerToVM::Data, _should_notify_object_alloc, int*)) \ \ static_field(Abstract_VM_Version, _features, uint64_t) \ - static_field(Abstract_VM_Version, _vm_target_features, VM_Features) \ - \ - nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ - static_field(VM_Features, _features_vector_size, uint32_t) \ - static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ \ nonstatic_field(Annotations, _class_annotations, AnnotationArray*) \ nonstatic_field(Annotations, _fields_annotations, Array*) \ @@ -980,7 +975,12 @@ #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ - static_field(VM_Version, _has_intel_jcc_erratum, bool) + static_field(VM_Version, _features, VM_Features) \ + \ + nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ + static_field(VM_Features, _features_vector_size, uint32_t) \ + static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ + static_field(VM_Version, _has_intel_jcc_erratum, bool) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 7bd9cfdb357c4..5b9d36115f8e9 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -37,11 +37,6 @@ const char* Abstract_VM_Version::_features_string = ""; const char* Abstract_VM_Version::_cpu_info_string = ""; uint64_t Abstract_VM_Version::_cpu_features = 0; -uint32_t VM_Features::_features_vector_element_shift_count = 6; -uint32_t VM_Features::_features_vector_size = MAX_FEATURE_VEC_SIZE; -VM_Features Abstract_VM_Version::_vm_target_features = {{0, 0, 0, 0}}; -VM_Features Abstract_VM_Version::_cpu_target_features = {{0, 0, 0, 0}}; - #ifndef SUPPORTS_NATIVE_CX8 bool Abstract_VM_Version::_supports_cx8 = false; #endif @@ -330,20 +325,6 @@ unsigned int Abstract_VM_Version::jvm_version() { (Abstract_VM_Version::vm_build_number() & 0xFF); } -void Abstract_VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], - uint features_names_index) { - while (features != 0) { - if (features & 1) { - int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]); - assert(res > 0, "not enough temporary space allocated"); - buf += res; - buflen -= res; - } - features >>= 1; - ++features_names_index; - } -} - const char* Abstract_VM_Version::extract_features_string(const char* cpu_info_string, size_t cpu_info_string_len, size_t features_offset) { @@ -421,28 +402,3 @@ const char* Abstract_VM_Version::cpu_description(void) { strncpy(tmp, _cpu_desc, CPU_DETAILED_DESC_BUF_SIZE); return tmp; } - -void VM_Features::set_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - _features_vector[index] |= (1ULL << (feature & index_mask)); -} - -void VM_Features::clear_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - _features_vector[index] &= ~(1ULL << (feature & index_mask)); -} - -bool VM_Features::supports_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - return (_features_vector[index] & (1ULL << (feature & index_mask))) != 0; -} - -bool VM_Features::is_within_feature_vector_bounds(uint32_t num_features) { - return _features_vector_size >= ((num_features >> _features_vector_element_shift_count) + 1); -} diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index c3411b22c4542..f0bd71d5251af 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -44,29 +44,6 @@ typedef enum { class outputStream; enum class vmIntrinsicID; -#define MAX_FEATURE_VEC_SIZE 4 - -class VM_Features { - public: - using FeatureVector = uint64_t [MAX_FEATURE_VEC_SIZE]; - - // Feature vector bitmap currently only used by x86 backend. - FeatureVector _features_vector; - - // Size of feature vector bitmap. - static uint32_t _features_vector_size; - - // Log2 of feature vector element size in bits, used by JVMCI to check enabled feature bits. - // Refer HotSpotJVMCIBackendFactory::convertFeaturesVector. - static uint32_t _features_vector_element_shift_count; - - static bool is_within_feature_vector_bounds(uint32_t num_features); - - void set_feature(uint32_t feature); - void clear_feature(uint32_t feature); - bool supports_feature(uint32_t feature); -}; - // Abstract_VM_Version provides information about the VM. class Abstract_VM_Version: AllStatic { @@ -87,34 +64,6 @@ class Abstract_VM_Version: AllStatic { // Original CPU feature flags, not affected by VM settings. static uint64_t _cpu_features; - // CPU feature flags vector, can be affected by VM settings. - static VM_Features _vm_target_features; - - // Original CPU feature flags vector, not affected by VM settings. - static VM_Features _cpu_target_features; - - static void sync_cpu_features() { - memcpy(_cpu_target_features._features_vector, _vm_target_features._features_vector, - sizeof(uint64_t) * VM_Features::_features_vector_size); - } - - static void clear_cpu_features() { - memset(_vm_target_features._features_vector, 0, sizeof(uint64_t) * VM_Features::_features_vector_size); - } - - static bool vm_features_exist() { - return VM_Features::_features_vector_size > 0; - } - - static uint32_t features_vector_size() { - return VM_Features::_features_vector_size; - } - - static uint64_t features_vector_elem(uint32_t elem) { - assert(elem < VM_Features::_features_vector_size, ""); - return _vm_target_features._features_vector[elem]; - } - // These are set by machine-dependent initializations #ifndef SUPPORTS_NATIVE_CX8 static bool _supports_cx8; @@ -180,13 +129,10 @@ class Abstract_VM_Version: AllStatic { static const char* jdk_debug_level(); static const char* printable_jdk_debug_level(); - static uint64_t features() { - return _features; - } + static uint64_t features() { return _features; } static const char* features_string() { return _features_string; } - static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0); static const char* cpu_info_string() { return _cpu_info_string; } static const char* extract_features_string(const char* cpu_info_string, size_t cpu_info_string_len, diff --git a/src/hotspot/share/runtime/init.cpp b/src/hotspot/share/runtime/init.cpp index da1d6ba564597..3756cdd4fd2d6 100644 --- a/src/hotspot/share/runtime/init.cpp +++ b/src/hotspot/share/runtime/init.cpp @@ -65,7 +65,6 @@ void classLoader_init1(); void compilationPolicy_init(); void codeCache_init(); void VM_Version_init(); -void VM_Version_pre_init(); void icache_init2(); void initial_stubs_init(); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index ff6ef7ed5661e..8ad7594f4e44a 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -707,11 +707,11 @@ static_field(Abstract_VM_Version, _vm_minor_version, int) \ static_field(Abstract_VM_Version, _vm_security_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ - static_field(Abstract_VM_Version, _vm_target_features, VM_Features) \ \ - nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ - static_field(VM_Features, _features_vector_size, uint32_t) \ - static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ + NOT_ZERO(X86_ONLY(static_field(VM_Version, _features, VM_Features))) \ + NOT_ZERO(X86_ONLY(nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector))) \ + NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_size, uint32_t))) \ + NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_element_shift_count, uint32_t))) \ \ /*************************/ \ /* JVMTI */ \ @@ -1169,8 +1169,9 @@ /********************/ \ \ declare_toplevel_type(Abstract_VM_Version) \ - declare_toplevel_type(VM_Features) \ - declare_toplevel_type(VM_Features::FeatureVector) \ + NOT_ZERO(declare_toplevel_type(VM_Features)) \ + NOT_ZERO(declare_toplevel_type(VM_Version)) \ + NOT_ZERO(declare_toplevel_type(VM_Features::FeatureVector)) \ \ /*************/ \ /* Arguments */ \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 6d216af196101..49504c1544707 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -51,7 +51,7 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; EnumSet features = HotSpotJVMCIBackendFactory.convertFeaturesVector(CPUFeature.class, constants, - config.vmVersionTargetFeatures, + config.vmVersionFeatures, config.vmFeaturesFeaturesVecOffset, config.vmFeaturesFeaturesVecSize, config.vmFeaturesFeaturesElemShiftCnt, diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index ce6d94c30dc0f..e155aac1813c2 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -42,7 +42,7 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); - final long vmVersionTargetFeatures = getFieldAddress("Abstract_VM_Version::_vm_target_features", "VM_Features"); + final long vmVersionFeatures = getFieldAddress("VM_Version::_features", "VM_Features"); final long vmFeaturesFeaturesVecOffset = getFieldOffset("VM_Features::_features_vector", Long.class, "VM_Features::FeatureVector"); final long vmFeaturesFeaturesVecSize = getFieldValue("VM_Features::_features_vector_size", Long.class, "uint32_t"); final long vmFeaturesFeaturesElemShiftCnt = getFieldValue("VM_Features::_features_vector_element_shift_count", Long.class, "uint32_t"); From 650e3d615107bc099ad7e1772824c6dda3c07f74 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Tue, 6 May 2025 16:08:09 +0530 Subject: [PATCH 09/16] build fixes for non-x86 targets --- src/hotspot/share/runtime/vmStructs.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 8ad7594f4e44a..7dadeaf78ec11 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1169,9 +1169,9 @@ /********************/ \ \ declare_toplevel_type(Abstract_VM_Version) \ - NOT_ZERO(declare_toplevel_type(VM_Features)) \ + NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features))) \ NOT_ZERO(declare_toplevel_type(VM_Version)) \ - NOT_ZERO(declare_toplevel_type(VM_Features::FeatureVector)) \ + NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features::FeatureVector))) \ \ /*************/ \ /* Arguments */ \ From 35aeb88d0d5667c9e4f699bb9b3b7169af96446a Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Tue, 6 May 2025 16:15:23 -0700 Subject: [PATCH 10/16] cleanups & refactorings --- src/hotspot/cpu/x86/vm_version_x86.cpp | 60 ++--------- src/hotspot/cpu/x86/vm_version_x86.hpp | 100 +++++++++++------- .../share/jvmci/jvmciCompilerToVMInit.cpp | 2 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 11 +- .../share/runtime/abstract_vm_version.hpp | 2 - src/hotspot/share/runtime/vmStructs.cpp | 10 +- .../hotspot/HotSpotJVMCIBackendFactory.java | 33 +++--- .../AMD64HotSpotJVMCIBackendFactory.java | 12 +-- .../hotspot/amd64/AMD64HotSpotVMConfig.java | 9 +- 9 files changed, 105 insertions(+), 134 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 5ce31e7060bb1..b06fe112654c4 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -63,10 +63,10 @@ address VM_Version::_cpuinfo_cont_addr_apx = nullptr; static BufferBlob* stub_blob; static const int stub_size = 2000; -uint32_t VM_Features::_features_vector_element_shift_count = 6; -uint32_t VM_Features::_features_vector_size = MAX_FEATURE_VEC_SIZE; -VM_Features VM_Version::_features; -VM_Features VM_Version::_cpu_features; +int VM_Version::VM_Features::_features_bitmap_size_in_bytes = sizeof(VM_Version::VM_Features::_features_bitmap); + +VM_Version::VM_Features VM_Version::_features; +VM_Version::VM_Features VM_Version::_cpu_features; extern "C" { typedef void (*get_cpu_info_stub_t)(void*); @@ -1101,11 +1101,8 @@ void VM_Version::get_processor_features() { cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, os::cpu_microcode_revision()); assert(cpu_info_size > 0, "not enough temporary space allocated"); - size_t buf_iter = cpu_info_size; - for (uint64_t i = 0; i < VM_Features::features_vector_size(); i++) { - insert_features_names(features_vector_elem(i), buf + buf_iter, sizeof(buf) - buf_iter, _features_names, 64 * i); - buf_iter = strlen(buf); - } + + insert_features_names(_features, buf + cpu_info_size, sizeof(buf) - cpu_info_size); _cpu_info_string = os::strdup(buf); @@ -2107,7 +2104,6 @@ static bool _vm_version_initialized = false; void VM_Version::initialize() { ResourceMark rm; - assert(VM_Features::is_within_feature_vector_bounds(MAX_CPU_FEATURES), "Feature out of vector bounds"); // Making this stub must be FIRST use of assembler stub_blob = BufferBlob::create("VM_Version stub", stub_size); @@ -2884,7 +2880,7 @@ int64_t VM_Version::maximum_qualified_cpu_frequency(void) { return _max_qualified_cpu_frequency; } -VM_Features VM_Version::CpuidInfo::feature_flags() const { +VM_Version::VM_Features VM_Version::CpuidInfo::feature_flags() const { VM_Features vm_features; if (std_cpuid1_edx.bits.cmpxchg8 != 0) vm_features.set_feature(CPU_CX8); @@ -3280,47 +3276,13 @@ bool VM_Version::is_intrinsic_supported(vmIntrinsicID id) { return true; } -void VM_Features::set_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - _features_vector[index] |= (1ULL << (feature & index_mask)); -} - -void VM_Features::clear_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - _features_vector[index] &= ~(1ULL << (feature & index_mask)); -} - -void VM_Features::clear_features() { - for (uint32_t i = 0; i < _features_vector_size; i++) { - _features_vector[i] = 0; - } -} - -bool VM_Features::supports_feature(uint32_t feature) { - uint32_t index = feature >> _features_vector_element_shift_count; - uint32_t index_mask = (1 << _features_vector_element_shift_count) - 1; - assert(index < _features_vector_size, "Features array index out of bounds"); - return (_features_vector[index] & (1ULL << (feature & index_mask))) != 0; -} - -bool VM_Features::is_within_feature_vector_bounds(uint32_t num_features) { - return _features_vector_size >= ((num_features >> _features_vector_element_shift_count) + 1); -} - -void VM_Version::insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], - uint features_names_index) { - while (features != 0) { - if (features & 1) { - int res = jio_snprintf(buf, buflen, ", %s", features_names[features_names_index]); +void VM_Version::insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen) { + for (int i = 0; i < MAX_CPU_FEATURES; i++) { + if (features.supports_feature((VM_Version::Feature_Flag)i)) { + int res = jio_snprintf(buf, buflen, ", %s", _features_names[i]); assert(res > 0, "not enough temporary space allocated"); buf += res; buflen -= res; } - features >>= 1; - ++features_names_index; } } diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 2b4b2bd6d9f5b..71b7764320cce 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -30,35 +30,6 @@ #include "utilities/macros.hpp" #include "utilities/sizes.hpp" -#define MAX_FEATURE_VEC_SIZE 4 - -class VM_Features { - public: - using FeatureVector = uint64_t [MAX_FEATURE_VEC_SIZE]; - - // Feature vector bitmap currently only used by x86 backend. - FeatureVector _features_vector; - - // log2 of feature vector element size in bits, used by JVMCI to check enabled feature bits. - // Refer HotSpotJVMCIBackendFactory::convertFeaturesVector. - static uint32_t _features_vector_element_shift_count; - - // Size of feature vector bitmap. - static uint32_t _features_vector_size; - - VM_Features() { - clear_features(); - } - - void set_feature(uint32_t feature); - void clear_feature(uint32_t feature); - bool supports_feature(uint32_t feature); - void clear_features(); - - static bool is_within_feature_vector_bounds(uint32_t num_features); - static uint32_t features_vector_size() { return _features_vector_size;} -}; - class VM_Version : public Abstract_VM_Version { friend class VMStructs; friend class JVMCIVMStructs; @@ -393,7 +364,7 @@ class VM_Version : public Abstract_VM_Version { * test/lib-test/jdk/test/whitebox/CPUInfoTest.java * src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/amd64/AMD64.java */ - enum Feature_Flag : uint32_t { + enum Feature_Flag { #define CPU_FEATURE_FLAGS(decl) \ decl(CX8, "cx8", 0) /* next bits are from cpuid 1 (EDX) */ \ decl(CMOV, "cmov", 1) \ @@ -479,7 +450,61 @@ class VM_Version : public Abstract_VM_Version { MAX_CPU_FEATURES }; - static const char* _features_names[]; + class VM_Features { + friend class VMStructs; + friend class JVMCIVMStructs; + + private: + uint64_t _features_bitmap[2]; // tracks up to 128 features + + STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte > MAX_CPU_FEATURES); + + // Number of 8-byte elements in _bitmap. + constexpr static int features_bitmap_element_count() { + return sizeof(_features_bitmap) / sizeof(uint64_t); + } + + constexpr static int features_bitmap_element_shift_count() { + return LogBitsPerLong; + } + + constexpr static uint64_t features_bitmap_element_mask() { + return (1ULL << features_bitmap_element_shift_count()) - 1; + } + + static int index(Feature_Flag feature) { + int idx = feature >> features_bitmap_element_shift_count(); + assert(idx < features_bitmap_element_count(), "Features array index out of bounds"); + return idx; + } + + static uint64_t bit_mask(Feature_Flag feature) { + return (1ULL << (feature & features_bitmap_element_mask())); + } + + static int _features_bitmap_size_in_bytes; // for JVMCI purposes + public: + VM_Features() { + for (int i = 0; i < features_bitmap_element_count(); i++) { + _features_bitmap[i] = 0; + } + } + + void set_feature(Feature_Flag feature) { + int idx = index(feature); + _features_bitmap[idx] |= bit_mask(feature); + } + + void clear_feature(VM_Version::Feature_Flag feature) { + int idx = index(feature); + _features_bitmap[idx] &= ~bit_mask(feature); + } + + bool supports_feature(VM_Version::Feature_Flag feature) { + int idx = index(feature); + return (_features_bitmap[idx] & bit_mask(feature)) != 0; + } + }; // CPU feature flags vector, can be affected by VM settings. static VM_Features _features; @@ -487,14 +512,11 @@ class VM_Version : public Abstract_VM_Version { // Original CPU feature flags vector, not affected by VM settings. static VM_Features _cpu_features; - static void clear_cpu_features() { - _features.clear_features(); - _cpu_features.clear_features(); - } + static const char* _features_names[]; - static uint64_t features_vector_elem(uint32_t elem) { - assert(elem < VM_Features::_features_vector_size, ""); - return _features._features_vector[elem]; + static void clear_cpu_features() { + _features = VM_Features(); + _cpu_features = VM_Features(); } enum Extended_Family { @@ -899,7 +921,7 @@ class VM_Version : public Abstract_VM_Version { static bool is_intel_tsc_synched_at_init(); - static void insert_features_names(uint64_t features, char* buf, size_t buflen, const char* features_names[], uint features_names_index = 0); + static void insert_features_names(VM_Version::VM_Features features, char* buf, size_t buflen); // This checks if the JVM is potentially affected by an erratum on Intel CPUs (SKX102) // that causes unpredictable behaviour when jcc crosses 64 byte boundaries. Its microcode diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index 005728db1d792..a0259983023aa 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -449,7 +449,7 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) { strcmp(vmField.typeString, "intptr_t") == 0 || strcmp(vmField.typeString, "uintptr_t") == 0 || strcmp(vmField.typeString, "OopHandle") == 0 || - strcmp(vmField.typeString, "VM_Features") == 0 || + strcmp(vmField.typeString, "VM_Version::VM_Features") == 0 || strcmp(vmField.typeString, "size_t") == 0 || // All foo* types are addresses. vmField.typeString[strlen(vmField.typeString) - 1] == '*') { diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index b8a988dba5a55..c36436b74eb58 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -975,12 +975,11 @@ #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ - static_field(VM_Version, _features, VM_Features) \ - \ - nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector) \ - static_field(VM_Features, _features_vector_size, uint32_t) \ - static_field(VM_Features, _features_vector_element_shift_count, uint32_t) \ - static_field(VM_Version, _has_intel_jcc_erratum, bool) + static_field(VM_Version, _features, VM_Version::VM_Features) \ + \ + nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \ + static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int) \ + static_field(VM_Version, _has_intel_jcc_erratum, bool) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index f0bd71d5251af..4972f02e3d8aa 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -129,8 +129,6 @@ class Abstract_VM_Version: AllStatic { static const char* jdk_debug_level(); static const char* printable_jdk_debug_level(); - static uint64_t features() { return _features; } - static const char* features_string() { return _features_string; } static const char* cpu_info_string() { return _cpu_info_string; } diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 7dadeaf78ec11..45605ac8febae 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -708,10 +708,9 @@ static_field(Abstract_VM_Version, _vm_security_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ \ - NOT_ZERO(X86_ONLY(static_field(VM_Version, _features, VM_Features))) \ - NOT_ZERO(X86_ONLY(nonstatic_field(VM_Features, _features_vector, VM_Features::FeatureVector))) \ - NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_size, uint32_t))) \ - NOT_ZERO(X86_ONLY(static_field(VM_Features, _features_vector_element_shift_count, uint32_t))) \ + NOT_ZERO(X86_ONLY( static_field(VM_Version, _features, VM_Version::VM_Features))) \ + NOT_ZERO(X86_ONLY(nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t))) \ + NOT_ZERO(X86_ONLY( static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int))) \ \ /*************************/ \ /* JVMTI */ \ @@ -1169,9 +1168,8 @@ /********************/ \ \ declare_toplevel_type(Abstract_VM_Version) \ - NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features))) \ NOT_ZERO(declare_toplevel_type(VM_Version)) \ - NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Features::FeatureVector))) \ + NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Version::VM_Features))) \ \ /*************/ \ /* Arguments */ \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java index 7763fe959ef68..319b9b9bc44d7 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotJVMCIBackendFactory.java @@ -83,28 +83,24 @@ static > EnumSet con } /** - * Converts a dynamically sized CPU features vector into enum constants. + * Converts CPU features bit map into enum constants. * * @param CPU feature enum type * @param enumType the class of {@code CPUFeatureType} * @param constants VM constants. Each entry whose key starts with {@code "VM_Version::CPU_"} * specifies a CPU feature and its value is a mask for a bit in {@code features} - * @param features_pointer pointer to {@code _vm_target_features} field of {@code Abstract_VM_Version} - * @param features_vector_offset offset of feature_vector field in {@code VM_Features} - * @param features_vector_size size of feature vector - * @param features_element_shift_count log2 of dynamic feature bit vector lanesize in bits. + * @param featuresBitMapAddress pointer to {@code VM_Features::_features_bitmap} field of {@code VM_Version::_features} + * @param featuresBitMapSize size of feature bit map in bytes * @param renaming maps from VM feature names to enum constant names where the two differ * @throws IllegalArgumentException if any VM CPU feature constant cannot be converted to an * enum value * @return the set of converted values */ - static > EnumSet convertFeaturesVector( + static > EnumSet convertFeatures( Class enumType, Map constants, - long features_pointer, - long features_vector_offset, - long features_vector_size, - long features_element_shift_count, + long featuresBitMapAddress, + long featuresBitMapSize, Map renaming) { EnumSet outFeatures = EnumSet.noneOf(enumType); List missing = new ArrayList<>(); @@ -115,19 +111,18 @@ static > EnumSet con if (key.startsWith("VM_Version::CPU_")) { String name = key.substring("VM_Version::CPU_".length()); try { + final long featuresElementShiftCount = 6; // log (# of bits per long) + final long featuresElementMask = (1L << featuresElementShiftCount) - 1; + CPUFeatureType feature = Enum.valueOf(enumType, renaming.getOrDefault(name, name)); - long features_vector_index = bitIndex >>> features_element_shift_count; - assert features_vector_index < features_vector_size; - long features_element_bitsize = (1L << features_element_shift_count); - assert (features_element_bitsize & (features_element_bitsize - 1)) == 0; + long featureIndex = bitIndex >>> featuresElementShiftCount; + long featureBitMask = 1L << (bitIndex & featuresElementMask); + assert featureIndex < featuresBitMapSize; - long features_element_size = features_element_bitsize / Byte.SIZE; - long features = UNSAFE.getLong(features_pointer + features_vector_offset + - features_vector_index * features_element_size); + long featuresElement = UNSAFE.getLong(featuresBitMapAddress + featureIndex * Long.BYTES); - long effective_bitMask = 1L << (bitIndex & (features_element_bitsize - 1)); - if ((features & effective_bitMask) != 0) { + if ((featuresElement & featureBitMask) != 0) { outFeatures.add(feature); } } catch (IllegalArgumentException iae) { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 49504c1544707..658bafea36dd3 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -50,12 +50,12 @@ private static EnumSet computeFeatures(AMD64HotSpotVMConfig config) Map constants = config.getStore().getConstants(); Map renaming = Map.of("3DNOW_PREFETCH", "AMD_3DNOW_PREFETCH"); assert config.useSSE >= 2 : "minimum config for x64"; - EnumSet features = HotSpotJVMCIBackendFactory.convertFeaturesVector(CPUFeature.class, constants, - config.vmVersionFeatures, - config.vmFeaturesFeaturesVecOffset, - config.vmFeaturesFeaturesVecSize, - config.vmFeaturesFeaturesElemShiftCnt, - renaming); + long featuresBitMapAddress = config.vmVersionFeatures + config.vmFeaturesFeaturesOffset; + EnumSet features = HotSpotJVMCIBackendFactory.convertFeatures(CPUFeature.class, + constants, + featuresBitMapAddress, + config.vmFeaturesFeaturesSize, + renaming); features.add(AMD64.CPUFeature.SSE); features.add(AMD64.CPUFeature.SSE2); return features; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index e155aac1813c2..7f5205a33f21a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -42,10 +42,9 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final boolean useCountTrailingZerosInstruction = getFlag("UseCountTrailingZerosInstruction", Boolean.class); final boolean useCompressedOops = getFlag("UseCompressedOops", Boolean.class); - final long vmVersionFeatures = getFieldAddress("VM_Version::_features", "VM_Features"); - final long vmFeaturesFeaturesVecOffset = getFieldOffset("VM_Features::_features_vector", Long.class, "VM_Features::FeatureVector"); - final long vmFeaturesFeaturesVecSize = getFieldValue("VM_Features::_features_vector_size", Long.class, "uint32_t"); - final long vmFeaturesFeaturesElemShiftCnt = getFieldValue("VM_Features::_features_vector_element_shift_count", Long.class, "uint32_t"); + final long vmVersionFeatures = getFieldAddress("VM_Version::_features", "VM_Version::VM_Features"); + final long vmFeaturesFeaturesOffset = getFieldOffset("VM_Version::VM_Features::_features_bitmap[0]", Long.class, "uint64_t"); + final long vmFeaturesFeaturesSize = getFieldValue("VM_Version::VM_Features::_features_bitmap_size_in_bytes", Long.class, "int"); // CPU capabilities final int useSSE = getFlag("UseSSE", Integer.class); @@ -91,6 +90,4 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long amd64OSPKE = getConstant("VM_Version::CPU_OSPKE", Long.class); final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class); final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class); - final long avx10_1 = getConstant("VM_Version::CPU_AVX10_1", Long.class); - final long avx10_2 = getConstant("VM_Version::CPU_AVX10_2", Long.class); } From cfc09d058f62aac7fac986fb3c707e7478ec98bf Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Wed, 7 May 2025 04:36:21 -0700 Subject: [PATCH 11/16] Making _features_bitmap size configurable --- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 71b7764320cce..dacd4b893383e 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -455,7 +455,7 @@ class VM_Version : public Abstract_VM_Version { friend class JVMCIVMStructs; private: - uint64_t _features_bitmap[2]; // tracks up to 128 features + uint64_t _features_bitmap[(MAX_CPU_FEATURES >> 6) + 1]; STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte > MAX_CPU_FEATURES); From 8acbd7a688aec208c1a1fad97f0557a8df777f81 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 8 May 2025 18:33:10 +0530 Subject: [PATCH 12/16] Reveiw suggestions incorporated --- src/hotspot/cpu/x86/vm_version_x86.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index dacd4b893383e..753aaddf680dd 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -455,9 +455,9 @@ class VM_Version : public Abstract_VM_Version { friend class JVMCIVMStructs; private: - uint64_t _features_bitmap[(MAX_CPU_FEATURES >> 6) + 1]; + uint64_t _features_bitmap[(MAX_CPU_FEATURES / BitsPerLong) + 1]; - STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte > MAX_CPU_FEATURES); + STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURES); // Number of 8-byte elements in _bitmap. constexpr static int features_bitmap_element_count() { From 1a3bce937076e35f77324d23133f62d4d69464e1 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Thu, 8 May 2025 19:03:54 +0530 Subject: [PATCH 13/16] Code re-factoring from Vladimir --- src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp | 3 +-- src/hotspot/cpu/x86/vmStructs_x86.hpp | 15 ++++++++++----- src/hotspot/share/runtime/vmStructs.cpp | 10 +++------- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp b/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp index bf9c965213cef..2ec901f6a2ed9 100644 --- a/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vmStructs_aarch64.hpp @@ -35,8 +35,7 @@ static_field(VM_Version, _rop_protection, bool) \ static_field(VM_Version, _pac_mask, uintptr_t) -#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ - declare_toplevel_type(VM_Version) +#define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) diff --git a/src/hotspot/cpu/x86/vmStructs_x86.hpp b/src/hotspot/cpu/x86/vmStructs_x86.hpp index d894d8b09a7f2..d6bc39b44db49 100644 --- a/src/hotspot/cpu/x86/vmStructs_x86.hpp +++ b/src/hotspot/cpu/x86/vmStructs_x86.hpp @@ -29,15 +29,20 @@ // constants required by the Serviceability Agent. This file is // referenced by vmStructs.cpp. -#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ - volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field) \ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ + static_field(VM_Version, _features, VM_Version::VM_Features) \ + nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \ + static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int) #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ + declare_toplevel_type(VM_Version::VM_Features) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ - LP64_ONLY(declare_constant(frame::arg_reg_save_area_bytes)) \ - declare_constant(frame::interpreter_frame_sender_sp_offset) \ - declare_constant(frame::interpreter_frame_last_sp_offset) + declare_constant(frame::arg_reg_save_area_bytes) \ + declare_constant(frame::interpreter_frame_sender_sp_offset) \ + declare_constant(frame::interpreter_frame_last_sp_offset) \ + declare_constant(frame::entry_frame_call_wrapper_offset) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 45605ac8febae..c47ad7092a8be 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1,3 +1,4 @@ + /* * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -708,10 +709,6 @@ static_field(Abstract_VM_Version, _vm_security_version, int) \ static_field(Abstract_VM_Version, _vm_build_number, int) \ \ - NOT_ZERO(X86_ONLY( static_field(VM_Version, _features, VM_Version::VM_Features))) \ - NOT_ZERO(X86_ONLY(nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t))) \ - NOT_ZERO(X86_ONLY( static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int))) \ - \ /*************************/ \ /* JVMTI */ \ /*************************/ \ @@ -1168,8 +1165,7 @@ /********************/ \ \ declare_toplevel_type(Abstract_VM_Version) \ - NOT_ZERO(declare_toplevel_type(VM_Version)) \ - NOT_ZERO(X86_ONLY(declare_toplevel_type(VM_Version::VM_Features))) \ + declare_toplevel_type(VM_Version) \ \ /*************/ \ /* Arguments */ \ @@ -1722,7 +1718,6 @@ /**********************/ \ NOT_ZERO(PPC64_ONLY(declare_constant(frame::entry_frame_locals_size))) \ \ - NOT_ZERO(X86_ONLY(declare_constant(frame::entry_frame_call_wrapper_offset))) \ declare_constant(frame::pc_return_offset) \ \ /*************/ \ @@ -2152,3 +2147,4 @@ void vmStructs_init() { VMStructs::init(); } #endif // ASSERT + From c65f0777232796c660e0c2b6aca0b6f2014ccb36 Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 9 May 2025 00:09:25 +0530 Subject: [PATCH 14/16] Addressing Yudi's comments --- src/hotspot/cpu/x86/vmStructs_x86.hpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.cpp | 2 +- src/hotspot/cpu/x86/vm_version_x86.hpp | 2 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 +- .../classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java | 4 +++- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/x86/vmStructs_x86.hpp b/src/hotspot/cpu/x86/vmStructs_x86.hpp index d6bc39b44db49..b8089a6413e46 100644 --- a/src/hotspot/cpu/x86/vmStructs_x86.hpp +++ b/src/hotspot/cpu/x86/vmStructs_x86.hpp @@ -33,7 +33,7 @@ volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) \ static_field(VM_Version, _features, VM_Version::VM_Features) \ nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \ - static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int) + static_field(VM_Version::VM_Features, _features_bitmap_size, int) #define VM_TYPES_CPU(declare_type, declare_toplevel_type, declare_oop_type, declare_integer_type, declare_unsigned_integer_type) \ declare_toplevel_type(VM_Version::VM_Features) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index b06fe112654c4..406dc446e0419 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -63,7 +63,7 @@ address VM_Version::_cpuinfo_cont_addr_apx = nullptr; static BufferBlob* stub_blob; static const int stub_size = 2000; -int VM_Version::VM_Features::_features_bitmap_size_in_bytes = sizeof(VM_Version::VM_Features::_features_bitmap); +int VM_Version::VM_Features::_features_bitmap_size = sizeof(VM_Version::VM_Features::_features_bitmap) / BytesPerLong; VM_Version::VM_Features VM_Version::_features; VM_Version::VM_Features VM_Version::_cpu_features; diff --git a/src/hotspot/cpu/x86/vm_version_x86.hpp b/src/hotspot/cpu/x86/vm_version_x86.hpp index 753aaddf680dd..a544eeb71b8cb 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.hpp +++ b/src/hotspot/cpu/x86/vm_version_x86.hpp @@ -482,7 +482,7 @@ class VM_Version : public Abstract_VM_Version { return (1ULL << (feature & features_bitmap_element_mask())); } - static int _features_bitmap_size_in_bytes; // for JVMCI purposes + static int _features_bitmap_size; // for JVMCI purposes public: VM_Features() { for (int i = 0; i < features_bitmap_element_count(); i++) { diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index c36436b74eb58..3cea665f86620 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -978,7 +978,7 @@ static_field(VM_Version, _features, VM_Version::VM_Features) \ \ nonstatic_field(VM_Version::VM_Features, _features_bitmap[0], uint64_t) \ - static_field(VM_Version::VM_Features, _features_bitmap_size_in_bytes, int) \ + static_field(VM_Version::VM_Features, _features_bitmap_size, int) \ static_field(VM_Version, _has_intel_jcc_erratum, bool) #define VM_INT_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant) \ diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java index 7f5205a33f21a..05803bdbfc784 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/amd64/AMD64HotSpotVMConfig.java @@ -44,7 +44,7 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long vmVersionFeatures = getFieldAddress("VM_Version::_features", "VM_Version::VM_Features"); final long vmFeaturesFeaturesOffset = getFieldOffset("VM_Version::VM_Features::_features_bitmap[0]", Long.class, "uint64_t"); - final long vmFeaturesFeaturesSize = getFieldValue("VM_Version::VM_Features::_features_bitmap_size_in_bytes", Long.class, "int"); + final long vmFeaturesFeaturesSize = getFieldValue("VM_Version::VM_Features::_features_bitmap_size", Long.class, "int"); // CPU capabilities final int useSSE = getFlag("UseSSE", Integer.class); @@ -90,4 +90,6 @@ class AMD64HotSpotVMConfig extends HotSpotVMConfigAccess { final long amd64OSPKE = getConstant("VM_Version::CPU_OSPKE", Long.class); final long amd64CET_IBT = getConstant("VM_Version::CPU_CET_IBT", Long.class); final long amd64CET_SS = getConstant("VM_Version::CPU_CET_SS", Long.class); + final long amd64AVX10_1 = getConstant("VM_Version::CPU_AVX10_1", Long.class); + final long amd64AVX10_2 = getConstant("VM_Version::CPU_AVX10_2", Long.class); } From f583a521bfc3a591bc291db4ea55f8bd6f98c20c Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Fri, 9 May 2025 20:01:30 +0530 Subject: [PATCH 15/16] Sandhya's review comments resoultion --- src/hotspot/cpu/x86/vm_version_x86.cpp | 12 ++++++++---- .../jtreg/serviceability/sa/ClhsdbLongConstant.java | 2 +- test/lib-test/jdk/test/whitebox/CPUInfoTest.java | 2 +- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 406dc446e0419..f4c820fcd59ec 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -466,11 +466,13 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); __ movl(rcx, 0x18000000); // cpuid1 bits osxsave | avx __ andl(rcx, Address(rsi, 8)); // cpuid1 bits osxsave | avx - __ jccb(Assembler::equal, done); // jump if AVX is not supported + __ cmpl(rcx, 0x18000000); + __ jccb(Assembler::notEqual, done); // jump if AVX is not supported __ movl(rax, 0x6); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ jccb(Assembler::notEqual, start_simd_check); // return if AVX is not supported + __ cmpl(rax, 0x6); + __ jccb(Assembler::equal, start_simd_check); // return if AVX is not supported // we need to bridge farther than imm8, so we use this island as a thunk __ bind(done); @@ -503,7 +505,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator { // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ jccb(Assembler::equal, legacy_setup); // jump if EVEX is not supported + __ cmpl(rax, 0xE0); + __ jccb(Assembler::notEqual, legacy_setup); // jump if EVEX is not supported if (FLAG_IS_DEFAULT(UseAVX)) { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); @@ -583,7 +586,8 @@ class VM_Version_StubGenerator: public StubCodeGenerator { // check _cpuid_info.xem_xcr0_eax.bits.zmm32 __ movl(rax, 0xE0); __ andl(rax, Address(rbp, in_bytes(VM_Version::xem_xcr0_offset()))); // xcr0 bits sse | ymm - __ jcc(Assembler::equal, legacy_save_restore); + __ cmpl(rax, 0xE0); + __ jcc(Assembler::notEqual, legacy_save_restore); if (FLAG_IS_DEFAULT(UseAVX)) { __ lea(rsi, Address(rbp, in_bytes(VM_Version::std_cpuid1_offset()))); diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java index 96f896f74180c..fceb2097e4625 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbLongConstant.java @@ -92,7 +92,7 @@ private static void checkForTruncation(String longConstantOutput) throws Excepti // Expected output snippet is of the form (on x64-64): // ... - // longConstant VM_Version::CPU_SHA 17179869184 + // longConstant VM_Version::CPU_SHA 34 // longConstant markWord::age_shift 3 // longConstant markWord::hash_mask_in_place 4398046509056 // ... diff --git a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java index 4a68333aa9278..8f0ef1088857e 100644 --- a/test/lib-test/jdk/test/whitebox/CPUInfoTest.java +++ b/test/lib-test/jdk/test/whitebox/CPUInfoTest.java @@ -66,7 +66,7 @@ public class CPUInfoTest { "hv", "fsrm", "avx512_bitalg", "gfni", "f16c", "pku", "ospke", "cet_ibt", "cet_ss", "avx512_ifma", "serialize", "avx_ifma", - "apx_f", "avx10_1", "avx10_2" + "apx_f", "avx10_1", "avx10_2" ); // @formatter:on // Checkstyle: resume From b4654fa417eaf8e4fbff9ef864ee98a37f1cef8c Mon Sep 17 00:00:00 2001 From: Jatin Bhateja Date: Sat, 10 May 2025 04:19:07 +0530 Subject: [PATCH 16/16] Review comments resolutions --- src/hotspot/cpu/x86/vm_version_x86.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index f4c820fcd59ec..fe59a1534133c 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -491,7 +491,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { // If UseAVX is uninitialized or is set by the user to include EVEX if (use_evex) { // check _cpuid_info.sef_cpuid7_ebx.bits.avx512f - // OR check _cpuid_info.std_cpuid24_ebx.bits.avx10 + // OR check _cpuid_info.sefsl1_cpuid7_edx.bits.avx10 __ lea(rsi, Address(rbp, in_bytes(VM_Version::sef_cpuid7_offset()))); __ movl(rax, 0x10000); __ andl(rax, Address(rsi, 4)); @@ -1066,6 +1066,8 @@ void VM_Version::get_processor_features() { _features.clear_feature(CPU_AVX512_IFMA); _features.clear_feature(CPU_AVX_IFMA); _features.clear_feature(CPU_AVX512_FP16); + _features.clear_feature(CPU_AVX10_1); + _features.clear_feature(CPU_AVX10_2); } }