diff --git a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp index f0885fee93d..4f0977a414f 100644 --- a/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/z/zBarrierSetAssembler_aarch64.cpp @@ -879,9 +879,7 @@ void ZBarrierSetAssembler::patch_barrier_relocation(address addr, int format) { ShouldNotReachHere(); } - if (!UseSingleICacheInvalidation) { - ICache::invalidate_word((address)patch_addr); - } + ICache::invalidate_word((address)patch_addr); } #ifdef COMPILER1 diff --git a/src/hotspot/cpu/aarch64/globals_aarch64.hpp b/src/hotspot/cpu/aarch64/globals_aarch64.hpp index ba29646a828..e6de2c798b1 100644 --- a/src/hotspot/cpu/aarch64/globals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globals_aarch64.hpp @@ -127,8 +127,6 @@ define_pd_global(intx, InlineSmallCode, 1000); "Branch Protection to use: none, standard, pac-ret") \ product(bool, AlwaysMergeDMB, true, DIAGNOSTIC, \ "Always merge DMB instructions in code emission") \ - product(bool, NeoverseN1ICacheErratumMitigation, false, DIAGNOSTIC, \ - "Enable workaround for Neoverse N1 erratum 1542419") \ // end of ARCH_FLAGS diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp index f1b9fb213a2..dbec2d76d4f 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp @@ -54,12 +54,7 @@ void Relocation::pd_set_data_value(address x, bool verify_only) { bytes = MacroAssembler::pd_patch_instruction_size(addr(), x); break; } - - if (UseSingleICacheInvalidation) { - assert(_binding != nullptr, "expect to be called with RelocIterator in use"); - } else { - ICache::invalidate_range(addr(), bytes); - } + ICache::invalidate_range(addr(), bytes); } address Relocation::pd_call_destination(address orig_addr) { diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 0a40cd705cd..4423d9c5b58 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -52,9 +52,6 @@ uintptr_t VM_Version::_pac_mask; SpinWait VM_Version::_spin_wait; -bool VM_Version::_cache_dic_enabled; -bool VM_Version::_cache_idc_enabled; - const char* VM_Version::_features_names[MAX_CPU_FEATURES] = { nullptr }; static SpinWait get_spin_wait_desc() { @@ -66,19 +63,6 @@ static SpinWait get_spin_wait_desc() { return spin_wait; } -static bool has_neoverse_n1_errata_1542419() { - const int major_rev_num = VM_Version::cpu_variant(); - const int minor_rev_num = VM_Version::cpu_revision(); - // Neoverse N1: 0xd0c - // Erratum 1542419 affects r3p0, r3p1 and r4p0. - // It is fixed in r4p1 and later revisions, which are not affected. - return (VM_Version::cpu_family() == VM_Version::CPU_ARM && - VM_Version::model_is(0xd0c) && - ((major_rev_num == 3 && minor_rev_num == 0) || - (major_rev_num == 3 && minor_rev_num == 1) || - (major_rev_num == 4 && minor_rev_num == 0))); -} - void VM_Version::initialize() { #define SET_CPU_FEATURE_NAME(id, name, bit) \ _features_names[bit] = XSTR(name); @@ -90,9 +74,6 @@ void VM_Version::initialize() { _supports_atomic_getset8 = true; _supports_atomic_getadd8 = true; - _cache_dic_enabled = false; - _cache_idc_enabled = false; - get_os_cpu_info(); int dcache_line = VM_Version::dcache_line_size(); @@ -680,32 +661,6 @@ void VM_Version::initialize() { clear_feature(CPU_SVE); } - if (FLAG_IS_DEFAULT(UseSingleICacheInvalidation) && is_cache_idc_enabled() && is_cache_dic_enabled()) { - FLAG_SET_DEFAULT(UseSingleICacheInvalidation, true); - } - - if (FLAG_IS_DEFAULT(NeoverseN1ICacheErratumMitigation) && has_neoverse_n1_errata_1542419()) { - FLAG_SET_DEFAULT(NeoverseN1ICacheErratumMitigation, true); - } - - if (NeoverseN1ICacheErratumMitigation) { - if (!has_neoverse_n1_errata_1542419()) { - vm_exit_during_initialization("NeoverseN1ICacheErratumMitigation is set for the CPU not having Neoverse N1 errata 1542419"); - } - if (FLAG_IS_DEFAULT(UseSingleICacheInvalidation)) { - FLAG_SET_DEFAULT(UseSingleICacheInvalidation, true); - } - - if (!UseSingleICacheInvalidation) { - vm_exit_during_initialization("NeoverseN1ICacheErratumMitigation is set but UseSingleICacheInvalidation is not enabled"); - } - } - - if (UseSingleICacheInvalidation - && (!is_cache_idc_enabled() || (!is_cache_dic_enabled() && !NeoverseN1ICacheErratumMitigation))) { - vm_exit_during_initialization("UseSingleICacheInvalidation is set but neither IDC nor DIC nor NeoverseN1ICacheErratumMitigation is enabled"); - } - // Construct the "features" string stringStream ss(512); ss.print("0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp index 6145990d0d6..e8681611234 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.hpp @@ -58,8 +58,6 @@ protected: // When _prefer_sve_merging_mode_cpy is true, `cpy (imm, zeroing)` is // implemented as `movi; cpy(imm, merging)`. static constexpr bool _prefer_sve_merging_mode_cpy = true; - static bool _cache_dic_enabled; - static bool _cache_idc_enabled; static SpinWait _spin_wait; @@ -255,9 +253,6 @@ public: return vector_length_in_bytes <= 16; } - static bool is_cache_dic_enabled() { return _cache_dic_enabled; } - static bool is_cache_idc_enabled() { return _cache_idc_enabled; } - static void get_cpu_features_name(void* features_buffer, stringStream& ss); // Returns names of features present in features_set1 but not in features_set2 diff --git a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.cpp deleted file mode 100644 index 41cad5af325..00000000000 --- a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "runtime/icache.hpp" -#include "utilities/globalDefinitions.hpp" - -NOT_PRODUCT(THREAD_LOCAL AArch64ICacheInvalidationContext* AArch64ICacheInvalidationContext::_current_context = nullptr;) diff --git a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp b/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp index b410aebed7b..8fbaa7a6b6e 100644 --- a/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp +++ b/src/hotspot/os_cpu/linux_aarch64/icache_linux_aarch64.hpp @@ -26,10 +26,6 @@ #ifndef OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP #define OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP -#include "memory/allocation.hpp" -#include "runtime/vm_version.hpp" -#include "utilities/globalDefinitions.hpp" - // Interface for updating the instruction cache. Whenever the VM // modifies code, part of the processor instruction cache potentially // has to be flushed. @@ -41,103 +37,8 @@ class ICache : public AbstractICache { __builtin___clear_cache((char *)addr, (char *)(addr + 4)); } static void invalidate_range(address start, int nbytes) { - if (NeoverseN1ICacheErratumMitigation) { - assert(VM_Version::is_cache_idc_enabled(), - "Expect CTR_EL0.IDC to be enabled for Neoverse N1 with erratum " - "1542419"); - assert(!VM_Version::is_cache_dic_enabled(), - "Expect CTR_EL0.DIC to be disabled for Neoverse N1 with erratum " - "1542419"); - asm volatile("dsb ish \n" - "ic ivau, xzr \n" - "dsb ish \n" - "isb \n" - : : : "memory"); - } else { - __builtin___clear_cache((char *)start, (char *)(start + nbytes)); - } + __builtin___clear_cache((char *)start, (char *)(start + nbytes)); } }; -class AArch64ICacheInvalidationContext : StackObj { - private: - -#ifdef ASSERT - static THREAD_LOCAL AArch64ICacheInvalidationContext* _current_context; -#endif - - bool _has_modified_code; - - public: - NONCOPYABLE(AArch64ICacheInvalidationContext); - - AArch64ICacheInvalidationContext() - : _has_modified_code(false) { - assert(_current_context == nullptr, "nested ICacheInvalidationContext not supported"); -#ifdef ASSERT - _current_context = this; -#endif - } - - ~AArch64ICacheInvalidationContext() { - NOT_PRODUCT(_current_context = nullptr); - - if (!_has_modified_code || !UseSingleICacheInvalidation) { - return; - } - - assert(VM_Version::is_cache_idc_enabled(), "Expect CTR_EL0.IDC to be enabled"); - - asm volatile("dsb ish" : : : "memory"); - - if (NeoverseN1ICacheErratumMitigation) { - assert(!VM_Version::is_cache_dic_enabled(), - "Expect CTR_EL0.DIC to be disabled for Neoverse N1 with erratum " - "1542419"); - - // Errata 1542419: Neoverse N1 cores with the 'COHERENT_ICACHE' feature - // may fetch stale instructions when software depends on - // prefetch-speculation-protection instead of explicit synchronization. - // - // Neoverse-N1 implementation mitigates the errata 1542419 with a - // workaround: - // - Disable coherent icache. - // - Trap IC IVAU instructions. - // - Execute: - // - tlbi vae3is, xzr - // - dsb sy - // - Ignore trapped IC IVAU instructions. - // - // `tlbi vae3is, xzr` invalidates all translation entries (all VAs, all - // possible levels). It waits for all memory accesses using in-scope old - // translation information to complete before it is considered complete. - // - // As this workaround has significant overhead, Arm Neoverse N1 (MP050) - // Software Developer Errata Notice version 29.0 suggests: - // - // "Since one TLB inner-shareable invalidation is enough to avoid this - // erratum, the number of injected TLB invalidations should be minimized - // in the trap handler to mitigate the performance impact due to this - // workaround." - // As the address for icache invalidation is not relevant and - // IC IVAU instruction is ignored, we use XZR in it. - asm volatile( - "ic ivau, xzr \n" - "dsb ish \n" - : - : - : "memory"); - } else { - assert(VM_Version::is_cache_dic_enabled(), "Expect CTR_EL0.DIC to be enabled"); - } - asm volatile("isb" : : : "memory"); - } - - void set_has_modified_code() { - _has_modified_code = true; - } -}; - -#define PD_ICACHE_INVALIDATION_CONTEXT AArch64ICacheInvalidationContext - #endif // OS_CPU_LINUX_AARCH64_ICACHE_AARCH64_HPP diff --git a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp index dad7161a3cb..1fe06dc640d 100644 --- a/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp +++ b/src/hotspot/os_cpu/linux_aarch64/vm_version_linux_aarch64.cpp @@ -169,8 +169,6 @@ void VM_Version::get_os_cpu_info() { _icache_line_size = (1 << (ctr_el0 & 0x0f)) * 4; _dcache_line_size = (1 << ((ctr_el0 >> 16) & 0x0f)) * 4; - _cache_idc_enabled = ((ctr_el0 >> 28) & 0x1) != 0; - _cache_dic_enabled = ((ctr_el0 >> 29) & 0x1) != 0; if (!(dczid_el0 & 0x10)) { _zva_length = 4 << (dczid_el0 & 0xf); diff --git a/src/hotspot/share/asm/codeBuffer.cpp b/src/hotspot/share/asm/codeBuffer.cpp index 964aec8b501..ba525588f32 100644 --- a/src/hotspot/share/asm/codeBuffer.cpp +++ b/src/hotspot/share/asm/codeBuffer.cpp @@ -745,6 +745,9 @@ void CodeBuffer::copy_code_to(CodeBlob* dest_blob) { // Done moving code bytes; were they the right size? assert((int)align_up(dest.total_content_size(), oopSize) == dest_blob->content_size(), "sanity"); + + // Flush generated code + ICache::invalidate_range(dest_blob->code_begin(), dest_blob->code_size()); } // Move all my code into another code buffer. Consult applicable diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index d07386bd795..fcc0b42a461 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -331,13 +331,7 @@ RuntimeBlob::RuntimeBlob( : CodeBlob(name, kind, cb, size, header_size, frame_complete, frame_size, oop_maps, caller_must_gc_arguments, align_up(cb->total_relocation_size(), oopSize)) { - if (code_size() == 0) { - // Nothing to copy - return; - } - cb->copy_code_and_locs_to(this); - ICache::invalidate_range(code_begin(), code_size()); } void RuntimeBlob::free(RuntimeBlob* blob) { diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 5cb795a4723..5a6ed8ab3ed 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1328,7 +1328,6 @@ nmethod::nmethod( code_buffer->copy_values_to(this); post_init(); - ICache::invalidate_range(code_begin(), code_size()); } if (PrintNativeNMethods || PrintDebugInfo || PrintRelocations || PrintDependencies) { @@ -1810,7 +1809,6 @@ nmethod::nmethod( init_immutable_data_ref_count(); post_init(); - ICache::invalidate_range(code_begin(), code_size()); // we use the information of entry points to find out if a method is // static or non static @@ -2038,7 +2036,7 @@ void nmethod::copy_values(GrowableArray* array) { // The code and relocations have already been initialized by the // CodeBlob constructor, so it is valid even at this early point to // iterate over relocations and patch the code. - fix_oop_relocations(/*initialize_immediates=*/ true); + fix_oop_relocations(nullptr, nullptr, /*initialize_immediates=*/ true); } void nmethod::copy_values(GrowableArray* array) { @@ -2050,42 +2048,24 @@ void nmethod::copy_values(GrowableArray* array) { } } -bool nmethod::fix_oop_relocations(bool initialize_immediates) { +void nmethod::fix_oop_relocations(address begin, address end, bool initialize_immediates) { // re-patch all oop-bearing instructions, just in case some oops moved - RelocIterator iter(this); - bool modified_code = false; + RelocIterator iter(this, begin, end); while (iter.next()) { if (iter.type() == relocInfo::oop_type) { oop_Relocation* reloc = iter.oop_reloc(); - if (!reloc->oop_is_immediate()) { - // Refresh the oop-related bits of this instruction. - reloc->set_value(reloc->value()); - modified_code = true; - } else if (initialize_immediates) { + if (initialize_immediates && reloc->oop_is_immediate()) { oop* dest = reloc->oop_addr(); jobject obj = *reinterpret_cast(dest); initialize_immediate_oop(dest, obj); } + // Refresh the oop-related bits of this instruction. + reloc->fix_oop_relocation(); } else if (iter.type() == relocInfo::metadata_type) { metadata_Relocation* reloc = iter.metadata_reloc(); reloc->fix_metadata_relocation(); - modified_code |= !reloc->metadata_is_immediate(); } } - return modified_code; -} - -void nmethod::fix_oop_relocations() { - ICacheInvalidationContext icic; - fix_oop_relocations(&icic); -} - -void nmethod::fix_oop_relocations(ICacheInvalidationContext* icic) { - assert(icic != nullptr, "must provide context to track if code was modified"); - bool modified_code = fix_oop_relocations(/*initialize_immediates=*/ false); - if (modified_code) { - icic->set_has_modified_code(); - } } static void install_post_call_nop_displacement(nmethod* nm, address pc) { diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index ea8c0e2ad5d..092da181f12 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -41,7 +41,6 @@ class Dependencies; class DirectiveSet; class DebugInformationRecorder; class ExceptionHandlerTable; -class ICacheInvalidationContext; class ImplicitExceptionTable; class JvmtiThreadState; class MetadataClosure; @@ -802,15 +801,15 @@ public: // Relocation support private: - bool fix_oop_relocations(bool initialize_immediates); + void fix_oop_relocations(address begin, address end, bool initialize_immediates); inline void initialize_immediate_oop(oop* dest, jobject handle); protected: address oops_reloc_begin() const; public: - void fix_oop_relocations(ICacheInvalidationContext* icic); - void fix_oop_relocations(); + void fix_oop_relocations(address begin, address end) { fix_oop_relocations(begin, end, false); } + void fix_oop_relocations() { fix_oop_relocations(nullptr, nullptr, false); } bool is_at_poll_return(address pc); bool is_at_poll_or_poll_return(address pc); diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 25d91edc20f..2a6335e2118 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -590,6 +590,15 @@ oop oop_Relocation::oop_value() { return *oop_addr(); } + +void oop_Relocation::fix_oop_relocation() { + if (!oop_is_immediate()) { + // get the oop from the pool, and re-insert it into the instruction: + set_value(value()); + } +} + + void oop_Relocation::verify_oop_relocation() { if (!oop_is_immediate()) { // get the oop from the pool, and re-insert it into the instruction: diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp index bb2b2b5693f..6f1778ef479 100644 --- a/src/hotspot/share/code/relocInfo.hpp +++ b/src/hotspot/share/code/relocInfo.hpp @@ -988,6 +988,8 @@ class oop_Relocation : public DataRelocation { void pack_data_to(CodeSection* dest) override; void unpack_data() override; + void fix_oop_relocation(); // reasserts oop value + void verify_oop_relocation(); address value() override { return *reinterpret_cast(oop_addr()); } diff --git a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp index a439b3a167b..d80ce4e149d 100644 --- a/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp +++ b/src/hotspot/share/gc/z/zBarrierSetNMethod.cpp @@ -33,7 +33,6 @@ #include "gc/z/zThreadLocalData.hpp" #include "gc/z/zUncoloredRoot.inline.hpp" #include "logging/log.hpp" -#include "runtime/icache.hpp" #include "runtime/threadWXSetters.inline.hpp" bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { @@ -71,15 +70,12 @@ bool ZBarrierSetNMethod::nmethod_entry_barrier(nmethod* nm) { return false; } - { - ICacheInvalidationContext icic; - // Heal barriers - ZNMethod::nmethod_patch_barriers(nm, &icic); + // Heal barriers + ZNMethod::nmethod_patch_barriers(nm); - // Heal oops - ZUncoloredRootProcessWeakOopClosure cl(ZNMethod::color(nm)); - ZNMethod::nmethod_oops_do_inner(nm, &cl, &icic); - } + // Heal oops + ZUncoloredRootProcessWeakOopClosure cl(ZNMethod::color(nm)); + ZNMethod::nmethod_oops_do_inner(nm, &cl); const uintptr_t prev_color = ZNMethod::color(nm); const uintptr_t new_color = *ZPointerStoreGoodMaskLowOrderBitsAddr; diff --git a/src/hotspot/share/gc/z/zGeneration.cpp b/src/hotspot/share/gc/z/zGeneration.cpp index 0f9f4e34a5e..27f352a624f 100644 --- a/src/hotspot/share/gc/z/zGeneration.cpp +++ b/src/hotspot/share/gc/z/zGeneration.cpp @@ -58,7 +58,6 @@ #include "prims/jvmtiTagMap.hpp" #include "runtime/continuation.hpp" #include "runtime/handshake.hpp" -#include "runtime/icache.hpp" #include "runtime/safepoint.hpp" #include "runtime/threads.hpp" #include "runtime/vmOperations.hpp" @@ -1435,15 +1434,12 @@ public: virtual void do_nmethod(nmethod* nm) { ZLocker locker(ZNMethod::lock_for_nmethod(nm)); if (_bs_nm->is_armed(nm)) { - { - ICacheInvalidationContext icic; - // Heal barriers - ZNMethod::nmethod_patch_barriers(nm, &icic); + // Heal barriers + ZNMethod::nmethod_patch_barriers(nm); - // Heal oops - ZUncoloredRootProcessOopClosure cl(ZNMethod::color(nm)); - ZNMethod::nmethod_oops_do_inner(nm, &cl, &icic); - } + // Heal oops + ZUncoloredRootProcessOopClosure cl(ZNMethod::color(nm)); + ZNMethod::nmethod_oops_do_inner(nm, &cl); log_trace(gc, nmethod)("nmethod: " PTR_FORMAT " visited by old remapping", p2i(nm)); diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index ac7d86db240..03701ae9998 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -59,7 +59,6 @@ #include "oops/oop.inline.hpp" #include "runtime/continuation.hpp" #include "runtime/handshake.hpp" -#include "runtime/icache.hpp" #include "runtime/javaThread.hpp" #include "runtime/prefetch.inline.hpp" #include "runtime/safepointMechanism.hpp" @@ -719,15 +718,12 @@ public: virtual void do_nmethod(nmethod* nm) { ZLocker locker(ZNMethod::lock_for_nmethod(nm)); if (_bs_nm->is_armed(nm)) { - { - ICacheInvalidationContext icic; - // Heal barriers - ZNMethod::nmethod_patch_barriers(nm, &icic); + // Heal barriers + ZNMethod::nmethod_patch_barriers(nm); - // Heal oops - ZUncoloredRootMarkOopClosure cl(ZNMethod::color(nm)); - ZNMethod::nmethod_oops_do_inner(nm, &cl, &icic); - } + // Heal oops + ZUncoloredRootMarkOopClosure cl(ZNMethod::color(nm)); + ZNMethod::nmethod_oops_do_inner(nm, &cl); // CodeCache unloading support nm->mark_as_maybe_on_stack(); @@ -757,6 +753,10 @@ public: if (_bs_nm->is_armed(nm)) { const uintptr_t prev_color = ZNMethod::color(nm); + // Heal oops + ZUncoloredRootMarkYoungOopClosure cl(prev_color); + ZNMethod::nmethod_oops_do_inner(nm, &cl); + // Disarm only the young marking, not any potential old marking cycle const uintptr_t old_marked_mask = ZPointerMarkedMask ^ (ZPointerMarkedYoung0 | ZPointerMarkedYoung1); @@ -767,16 +767,9 @@ public: // Check if disarming for young mark, completely disarms the nmethod entry barrier const bool complete_disarm = ZPointer::is_store_good(new_disarm_value_ptr); - { - ICacheInvalidationContext icic; - if (complete_disarm) { - // We are about to completely disarm the nmethod, must take responsibility to patch all barriers before disarming - ZNMethod::nmethod_patch_barriers(nm, &icic); - } - - // Heal oops - ZUncoloredRootMarkYoungOopClosure cl(prev_color); - ZNMethod::nmethod_oops_do_inner(nm, &cl, &icic); + if (complete_disarm) { + // We are about to completely disarm the nmethod, must take responsibility to patch all barriers before disarming + ZNMethod::nmethod_patch_barriers(nm); } _bs_nm->guard_with(nm, (int)untype(new_disarm_value_ptr)); diff --git a/src/hotspot/share/gc/z/zNMethod.cpp b/src/hotspot/share/gc/z/zNMethod.cpp index a1348b63b6f..780bc9e3bf7 100644 --- a/src/hotspot/share/gc/z/zNMethod.cpp +++ b/src/hotspot/share/gc/z/zNMethod.cpp @@ -50,7 +50,6 @@ #include "oops/oop.inline.hpp" #include "runtime/atomicAccess.hpp" #include "runtime/continuation.hpp" -#include "runtime/icache.hpp" #include "utilities/debug.hpp" static ZNMethodData* gc_data(const nmethod* nm) { @@ -246,16 +245,8 @@ void ZNMethod::set_guard_value(nmethod* nm, int value) { } void ZNMethod::nmethod_patch_barriers(nmethod* nm) { - ICacheInvalidationContext icic; - nmethod_patch_barriers(nm, &icic); -} - -void ZNMethod::nmethod_patch_barriers(nmethod* nm, ICacheInvalidationContext* icic) { ZBarrierSetAssembler* const bs_asm = ZBarrierSet::assembler(); ZArrayIterator iter(gc_data(nm)->barriers()); - if (gc_data(nm)->barriers()->is_nonempty()) { - icic->set_has_modified_code(); - } for (ZNMethodDataBarrier barrier; iter.next(&barrier);) { bs_asm->patch_barrier_relocation(barrier._reloc_addr, barrier._reloc_format); } @@ -267,11 +258,6 @@ void ZNMethod::nmethod_oops_do(nmethod* nm, OopClosure* cl) { } void ZNMethod::nmethod_oops_do_inner(nmethod* nm, OopClosure* cl) { - ICacheInvalidationContext icic; - nmethod_oops_do_inner(nm, cl, &icic); -} - -void ZNMethod::nmethod_oops_do_inner(nmethod* nm, OopClosure* cl, ICacheInvalidationContext* icic) { // Process oops table { oop* const begin = nm->oops_begin(); @@ -297,7 +283,7 @@ void ZNMethod::nmethod_oops_do_inner(nmethod* nm, OopClosure* cl, ICacheInvalida // Process non-immediate oops if (data->has_non_immediate_oops()) { - nm->fix_oop_relocations(icic); + nm->fix_oop_relocations(); } } diff --git a/src/hotspot/share/gc/z/zNMethod.hpp b/src/hotspot/share/gc/z/zNMethod.hpp index 2779151c576..865ea11e7b9 100644 --- a/src/hotspot/share/gc/z/zNMethod.hpp +++ b/src/hotspot/share/gc/z/zNMethod.hpp @@ -56,11 +56,9 @@ public: static void set_guard_value(nmethod* nm, int value); static void nmethod_patch_barriers(nmethod* nm); - static void nmethod_patch_barriers(nmethod* nm, ICacheInvalidationContext* icic); static void nmethod_oops_do(nmethod* nm, OopClosure* cl); static void nmethod_oops_do_inner(nmethod* nm, OopClosure* cl); - static void nmethod_oops_do_inner(nmethod* nm, OopClosure* cl, ICacheInvalidationContext* icic); static void nmethods_do_begin(bool secondary); static void nmethods_do_end(bool secondary); diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 296c5dedf8a..60feddde09b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1978,8 +1978,6 @@ const int ObjectAlignmentInBytes = 8; develop(uint, BinarySearchThreshold, 16, \ "Minimal number of elements in a sorted collection to prefer" \ "binary search over simple linear search." ) \ - product(bool, UseSingleICacheInvalidation, false, DIAGNOSTIC, \ - "Defer multiple ICache invalidation to single invalidation") \ \ // end of RUNTIME_FLAGS diff --git a/src/hotspot/share/runtime/icache.hpp b/src/hotspot/share/runtime/icache.hpp index 692a876d9a6..bc153862323 100644 --- a/src/hotspot/share/runtime/icache.hpp +++ b/src/hotspot/share/runtime/icache.hpp @@ -129,27 +129,4 @@ class ICacheStubGenerator : public StubCodeGenerator { void generate_icache_flush(ICache::flush_icache_stub_t* flush_icache_stub); }; -class DefaultICacheInvalidationContext : StackObj { - public: - NONCOPYABLE(DefaultICacheInvalidationContext); - - DefaultICacheInvalidationContext() {} - - ~DefaultICacheInvalidationContext() {} - - void set_has_modified_code() {} -}; - -#ifndef PD_ICACHE_INVALIDATION_CONTEXT -#define PD_ICACHE_INVALIDATION_CONTEXT DefaultICacheInvalidationContext -#endif // PD_ICACHE_INVALIDATION_CONTEXT - -class ICacheInvalidationContext final : public PD_ICACHE_INVALIDATION_CONTEXT { - private: - NONCOPYABLE(ICacheInvalidationContext); - - public: - using PD_ICACHE_INVALIDATION_CONTEXT::PD_ICACHE_INVALIDATION_CONTEXT; -}; - #endif // SHARE_RUNTIME_ICACHE_HPP diff --git a/test/hotspot/jtreg/compiler/runtime/TestDeferredICacheInvalidationCmdOptions.java b/test/hotspot/jtreg/compiler/runtime/TestDeferredICacheInvalidationCmdOptions.java deleted file mode 100644 index 8bc74be5c62..00000000000 --- a/test/hotspot/jtreg/compiler/runtime/TestDeferredICacheInvalidationCmdOptions.java +++ /dev/null @@ -1,426 +0,0 @@ -/* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package compiler.runtime; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; -import jdk.test.whitebox.WhiteBox; -import jtreg.SkippedException; - -/* - * @test - * @bug 8370947 - * @summary Test command-line options for UseSingleICacheInvalidation and NeoverseN1ICacheErratumMitigation - * @library /test/lib - * @requires os.arch == "aarch64" - * @requires os.family == "linux" - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI compiler.runtime.TestDeferredICacheInvalidationCmdOptions - */ - -public class TestDeferredICacheInvalidationCmdOptions { - - // CPU identifiers - private static final int CPU_ARM = 0x41; - private static final int NEOVERSE_N1_MODEL = 0xd0c; - - private static boolean isAffected; - - public static void main(String[] args) throws Exception { - // Parse CPU features and print CPU info - parseCPUFeatures(); - - System.out.println("Testing UseSingleICacheInvalidation and NeoverseN1ICacheErratumMitigation command-line options..."); - - // Test case 1: Check defaults on Neoverse N1 pre-r4p1 (if applicable) - testCase1_DefaultsOnNeoverseN1(); - - // Test case 2: Check NeoverseN1ICacheErratumMitigation is false on unaffected CPUs - testCase2_DefaultsOnUnaffectedCPUs(); - - // Test case 3: Check if NeoverseN1ICacheErratumMitigation is set to false on affected CPUs, - // UseSingleICacheInvalidation is also set to false - testCase3_ExplicitlyDisableErrataAffectsDeferred(); - - // Test case 4: Check JVM error if UseSingleICacheInvalidation=true - // but NeoverseN1ICacheErratumMitigation=false on affected CPUs - testCase4_ConflictingFlagsOnAffectedCPUs(); - - // Test case 5: Check explicit NeoverseN1ICacheErratumMitigation=true enables UseSingleICacheInvalidation - testCase5_ExplicitlyEnableErrataEnablesDeferred(); - - // Test case 6: Check both flags can be explicitly set to false - testCase6_ExplicitlyDisableBothFlags(); - - // Test case 7: Check UseSingleICacheInvalidation=false with NeoverseN1ICacheErratumMitigation=true - testCase7_ConflictingErrataWithoutDeferred(); - - // Test case 8: Check setting NeoverseN1ICacheErratumMitigation=true on unaffected CPU causes an error - testCase8_EnablingErrataOnUnaffectedCPU(); - - System.out.println("All test cases passed!"); - } - - /** - * Parse CPU features string from WhiteBox.getCPUFeatures() to extract: - * - cpuFamily: 0x41 for ARM - * - cpuVariant: major revision - * - cpuModel: e.g., 0xd0c for Neoverse N1 - * - cpuRevision: minor revision - * - cpuModel2: secondary model (if present, in parentheses) - * - * Sets the static field isAffected and prints CPU info. - * - * Format: 0x%02x:0x%x:0x%03x:%d[(0x%03x)] - * Example: "0x41:0x3:0xd0c:0" or "0x41:0x3:0xd0c:0(0xd0c)" - * - * @throws SkippedException if not running on ARM CPU - */ - private static void parseCPUFeatures() { - WhiteBox wb = WhiteBox.getWhiteBox(); - String cpuFeatures = wb.getCPUFeatures(); - System.out.println("CPU Features string: " + cpuFeatures); - - if (cpuFeatures == null || cpuFeatures.isEmpty()) { - throw new RuntimeException("No CPU features available"); - } - - int commaIndex = cpuFeatures.indexOf(","); - if (commaIndex == -1) { - throw new RuntimeException("Unexpected CPU features format (no comma): " + cpuFeatures); - } - - String cpuPart = cpuFeatures.substring(0, commaIndex).trim(); - - String[] parts = cpuPart.split(":"); - if (parts.length < 4) { - throw new RuntimeException("Unexpected CPU features format: " + cpuPart); - } - - int cpuFamily = Integer.parseInt(parts[0].substring(2), 16); - if (cpuFamily != CPU_ARM) { - throw new SkippedException("Not running on ARM CPU (cpuFamily=0x" + Integer.toHexString(cpuFamily) + ")"); - } - - int cpuVariant = Integer.parseInt(parts[1].substring(2), 16); - int cpuModel = Integer.parseInt(parts[2].substring(2), 16); - int cpuModel2 = 0; - - int model2Start = parts[3].indexOf("("); - String revisionStr = parts[3]; - if (model2Start != -1) { - if (!parts[3].endsWith(")")) { - throw new RuntimeException("Unexpected CPU features format (missing closing parenthesis): " + parts[3]); - } - String model2Str = parts[3].substring(model2Start + 1, parts[3].length() - 1); - cpuModel2 = Integer.parseInt(model2Str.substring(2), 16); - revisionStr = parts[3].substring(0, model2Start); - } - int cpuRevision = Integer.parseInt(revisionStr); - - // Neoverse N1 errata 1542419 affects r3p0, r3p1 and r4p0. - // It is fixed in r4p1 and later revisions. - if (cpuModel == NEOVERSE_N1_MODEL || cpuModel2 == NEOVERSE_N1_MODEL) { - isAffected = (cpuVariant == 3 && cpuRevision == 0) || - (cpuVariant == 3 && cpuRevision == 1) || - (cpuVariant == 4 && cpuRevision == 0); - } - - printCPUInfo(cpuFamily, cpuVariant, cpuModel, cpuModel2, cpuRevision); - } - - private static void printCPUInfo(int cpuFamily, int cpuVariant, int cpuModel, int cpuModel2, int cpuRevision) { - boolean isNeoverseN1 = (cpuFamily == CPU_ARM) && - (cpuModel == NEOVERSE_N1_MODEL || cpuModel2 == NEOVERSE_N1_MODEL); - System.out.println("\n=== CPU Information ==="); - System.out.println("CPU Family: 0x" + Integer.toHexString(cpuFamily)); - System.out.println("CPU Variant: 0x" + Integer.toHexString(cpuVariant)); - System.out.println("CPU Model: 0x" + Integer.toHexString(cpuModel)); - if (cpuModel2 != 0) { - System.out.println("CPU Model2: 0x" + Integer.toHexString(cpuModel2)); - } - System.out.println("CPU Revision: " + cpuRevision); - System.out.println("Is Neoverse N1: " + isNeoverseN1); - System.out.println("Is affected by errata 1542419: " + isAffected); - System.out.println("======================\n"); - } - - /** - * Test case 1: Check the UseSingleICacheInvalidation and NeoverseN1ICacheErratumMitigation - * are set to true for Neoverse N1 pre-r4p1. - */ - private static void testCase1_DefaultsOnNeoverseN1() throws Exception { - if (!isAffected) { - System.out.println("\nTest case 1: Skipping since CPU is not affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 1: Check defaults on Neoverse N1 affected revisions"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - - String output_str = output.getOutput(); - boolean hasSingleEnabled = output_str.matches("(?s).*bool\\s+UseSingleICacheInvalidation\\s*=\\s*true.*"); - boolean hasErrataEnabled = output_str.matches("(?s).*bool\\s+NeoverseN1ICacheErratumMitigation\\s*=\\s*true.*"); - - System.out.println("UseSingleICacheInvalidation enabled: " + hasSingleEnabled); - System.out.println("NeoverseN1ICacheErratumMitigation enabled: " + hasErrataEnabled); - - // If running on affected Neoverse N1, both should be true - if (!hasSingleEnabled || !hasErrataEnabled) { - throw new RuntimeException("On affected Neoverse N1, both flags should be enabled by default"); - } - System.out.println("Correctly enabled on affected Neoverse N1"); - } - - /** - * Test case 2: Check NeoverseN1ICacheErratumMitigation is false on unaffected CPUs. - */ - private static void testCase2_DefaultsOnUnaffectedCPUs() throws Exception { - if (isAffected) { - System.out.println("\nTest case 2: Skipping since CPU is affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 2: Check NeoverseN1ICacheErratumMitigation is false on unaffected CPUs"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - - String output_str = output.getOutput(); - boolean hasErrataEnabled = output_str.matches("(?s).*bool\\s+NeoverseN1ICacheErratumMitigation\\s*=\\s*true.*"); - - System.out.println("NeoverseN1ICacheErratumMitigation enabled: " + hasErrataEnabled); - - // On non-Neoverse N1 or unaffected Neoverse N1 CPUs, NeoverseN1ICacheErratumMitigation should be false - if (hasErrataEnabled) { - throw new RuntimeException("On unaffected CPUs, NeoverseN1ICacheErratumMitigation should be disabled"); - } - System.out.println("Correctly disabled on unaffected CPU"); - } - - /** - * Test case 3: Check if NeoverseN1ICacheErratumMitigation is set to false via cmd on affected CPUs, - * UseSingleICacheInvalidation is set to false. - */ - private static void testCase3_ExplicitlyDisableErrataAffectsDeferred() throws Exception { - if (!isAffected) { - System.out.println("\nTest case 3: Skipping since CPU is not affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 3: Explicitly disable NeoverseN1ICacheErratumMitigation, check UseSingleICacheInvalidation"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:-NeoverseN1ICacheErratumMitigation", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - - String output_str = output.getOutput(); - boolean hasSingleDisabled = output_str.matches("(?s).*bool\\s+UseSingleICacheInvalidation\\s*=\\s*false.*"); - boolean hasErrataDisabled = output_str.matches("(?s).*bool\\s+NeoverseN1ICacheErratumMitigation\\s*=\\s*false.*"); - - System.out.println("NeoverseN1ICacheErratumMitigation disabled: " + hasErrataDisabled); - System.out.println("UseSingleICacheInvalidation disabled: " + hasSingleDisabled); - - if (!hasErrataDisabled) { - throw new RuntimeException("Failed to disable NeoverseN1ICacheErratumMitigation via command line"); - } - - // On affected CPUs, disabling errata should also disable UseSingleICacheInvalidation - if (!hasSingleDisabled) { - throw new RuntimeException("On affected CPU, disabling NeoverseN1ICacheErratumMitigation should also disable UseSingleICacheInvalidation"); - } - System.out.println("Correctly synchronized on affected CPU"); - } - - /** - * Test case 4: Check JVM reports an error if UseSingleICacheInvalidation is set to true - * but NeoverseN1ICacheErratumMitigation is set to false on affected CPUs. - */ - private static void testCase4_ConflictingFlagsOnAffectedCPUs() throws Exception { - if (!isAffected) { - System.out.println("\nTest case 4: Skipping since CPU is not affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 4: Try to set UseSingleICacheInvalidation=true with NeoverseN1ICacheErratumMitigation=false"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+UseSingleICacheInvalidation", - "-XX:-NeoverseN1ICacheErratumMitigation", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - if (output.getExitValue() == 0) { - throw new RuntimeException("On affected CPU, conflicting flags should cause error"); - } - output.shouldContain("Error"); - System.out.println("JVM correctly rejected conflicting flags on affected CPU"); - } - - /** - * Test case 5: Check explicit NeoverseN1ICacheErratumMitigation=true enables UseSingleICacheInvalidation. - */ - private static void testCase5_ExplicitlyEnableErrataEnablesDeferred() throws Exception { - if (!isAffected) { - System.out.println("\nTest case 5: Skipping since CPU is not affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 5: Explicitly enable NeoverseN1ICacheErratumMitigation, check UseSingleICacheInvalidation"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+NeoverseN1ICacheErratumMitigation", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - - String output_str = output.getOutput(); - boolean hasSingleEnabled = output_str.matches("(?s).*bool\\s+UseSingleICacheInvalidation\\s*=\\s*true.*"); - boolean hasErrataEnabled = output_str.matches("(?s).*bool\\s+NeoverseN1ICacheErratumMitigation\\s*=\\s*true.*"); - - System.out.println("NeoverseN1ICacheErratumMitigation enabled: " + hasErrataEnabled); - System.out.println("UseSingleICacheInvalidation enabled: " + hasSingleEnabled); - - if (!hasErrataEnabled) { - throw new RuntimeException("Failed to enable NeoverseN1ICacheErratumMitigation via command line"); - } - - if (!hasSingleEnabled) { - throw new RuntimeException("On affected CPU, enabling NeoverseN1ICacheErratumMitigation should also enable UseSingleICacheInvalidation"); - } - System.out.println("Correctly synchronized on affected CPU"); - } - - /** - * Test case 6: Check both flags can be explicitly set to false. - */ - private static void testCase6_ExplicitlyDisableBothFlags() throws Exception { - System.out.println("\nTest case 6: Explicitly disable both flags"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:-UseSingleICacheInvalidation", - "-XX:-NeoverseN1ICacheErratumMitigation", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldHaveExitValue(0); - - String output_str = output.getOutput(); - boolean hasSingleDisabled = output_str.matches("(?s).*bool\\s+UseSingleICacheInvalidation\\s*=\\s*false.*"); - boolean hasErrataDisabled = output_str.matches("(?s).*bool\\s+NeoverseN1ICacheErratumMitigation\\s*=\\s*false.*"); - - System.out.println("UseSingleICacheInvalidation disabled: " + hasSingleDisabled); - System.out.println("NeoverseN1ICacheErratumMitigation disabled: " + hasErrataDisabled); - - if (!hasErrataDisabled) { - throw new RuntimeException("Failed to disable NeoverseN1ICacheErratumMitigation via command line"); - } - - if (!hasSingleDisabled) { - throw new RuntimeException("Failed to disable UseSingleICacheInvalidation via command line"); - } - - System.out.println("Successfully disabled both flags"); - } - - /** - * Test case 7: Check UseSingleICacheInvalidation=false with NeoverseN1ICacheErratumMitigation=true. - * On affected CPUs, this should error (conflicting requirement). - */ - private static void testCase7_ConflictingErrataWithoutDeferred() throws Exception { - if (!isAffected) { - System.out.println("\nTest case 7: Skipping since CPU is not affected by Neoverse N1 errata 1542419"); - return; - } - System.out.println("\nTest case 7: Try to set NeoverseN1ICacheErratumMitigation=true with UseSingleICacheInvalidation=false"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:-UseSingleICacheInvalidation", - "-XX:+NeoverseN1ICacheErratumMitigation", - "-XX:+PrintFlagsFinal", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // This should fail on affected CPUs (conflicting requirement) - if (output.getExitValue() == 0) { - throw new RuntimeException("On affected CPU, setting NeoverseN1ICacheErratumMitigation=true with UseSingleICacheInvalidation=false should cause an error"); - } - output.shouldContain("Error"); - System.out.println("JVM correctly rejected conflicting flags on affected CPU"); - } - - /** - * Test case 8: Check setting NeoverseN1ICacheErratumMitigation=true on unaffected CPU causes an error. - */ - private static void testCase8_EnablingErrataOnUnaffectedCPU() throws Exception { - if (isAffected) { - System.out.println("\nTest case 8: Skipping since CPU is affected by Neoverse N1 errata 1542419"); - return; - } - - System.out.println("\nTest case 8: Try to set NeoverseN1ICacheErratumMitigation=true on unaffected CPU"); - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+NeoverseN1ICacheErratumMitigation", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - // This should fail on unaffected CPUs (errata not present) - if (output.getExitValue() == 0) { - throw new RuntimeException("On unaffected CPU, setting NeoverseN1ICacheErratumMitigation=true should cause error"); - } - output.shouldContain("Error"); - System.out.println("JVM correctly rejected enabling errata flag on unaffected CPU"); - } -} diff --git a/test/hotspot/jtreg/gc/TestDeferredICacheInvalidation.java b/test/hotspot/jtreg/gc/TestDeferredICacheInvalidation.java deleted file mode 100644 index 70cd1ab6d8c..00000000000 --- a/test/hotspot/jtreg/gc/TestDeferredICacheInvalidation.java +++ /dev/null @@ -1,306 +0,0 @@ -/* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package gc; - -/* - * @test id=parallel - * @bug 8370947 - * @summary Check no assertion is triggered when UseSingleICacheInvalidation is enabled for ParallelGC - * @library /test/lib - * @requires vm.debug - * @requires vm.gc.Parallel - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseParallelGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseParallelGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseParallelGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C2 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseParallelGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C2 - */ - -/* - * @test id=g1 - * @bug 8370947 - * @summary Check no assertion is triggered when UseSingleICacheInvalidation is enabled for G1GC - * @library /test/lib - * @requires vm.debug - * @requires vm.gc.G1 - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C2 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseG1GC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C2 - */ - -/* - * @test id=shenandoah - * @bug 8370947 - * @summary Check no assertion is triggered when UseSingleICacheInvalidation is enabled for ShenandoahGC - * @library /test/lib - * @requires vm.debug - * @requires vm.gc.Shenandoah - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C2 - */ - -/* - * @test id=genshen - * @bug 8370947 - * @summary Check no assertion is triggered when UseSingleICacheInvalidation is enabled for generational ShenandoahGC - * @library /test/lib - * @requires vm.debug - * @requires vm.gc.Shenandoah - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C2 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:ShenandoahGCMode=generational -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C2 - */ - -/* - * @test id=z - * @bug 8370947 - * @summary Check no assertion is triggered when UseSingleICacheInvalidation is enabled for ZGC - * @library /test/lib - * @requires vm.debug - * @requires vm.gc.Z - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseZGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseZGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C1 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseZGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation youngGC C2 - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+UseZGC -XX:-UseCodeCacheFlushing gc.TestDeferredICacheInvalidation fullGC C2 - */ - -/* - * Nmethods have GC barriers and OOPs embedded into their code. GCs can patch nmethod's code - * which requires icache invalidation. Doing invalidation per instruction can be expensive. - * CPU can support hardware dcache and icache coherence. This would allow to defer cache - * invalidation. - * - * There are assertions for deferred cache invalidation. This test checks that all of them - * are passed. - */ - -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import jdk.test.whitebox.WhiteBox; - -public class TestDeferredICacheInvalidation { - - private static final WhiteBox WB = WhiteBox.getWhiteBox(); - - public static class A { - public String s1; - public String s2; - public String s3; - public String s4; - public String s5; - public String s6; - public String s7; - public String s8; - public String s9; - } - - public static A a = new A(); - - private static int compLevel; - - public static class B { - public static void test0() { - } - - public static void test1() { - a.s1 = a.s1 + "1"; - } - - public static void test2() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - } - - public static void test3() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - } - - public static void test4() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - } - - public static void test5() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - a.s5 = a.s5 + "5"; - } - - public static void test6() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - a.s5 = a.s5 + "5"; - a.s6 = a.s6 + "6"; - } - - public static void test7() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - a.s5 = a.s5 + "5"; - a.s6 = a.s6 + "6"; - a.s7 = a.s7 + "7"; - } - - public static void test8() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - a.s5 = a.s5 + "5"; - a.s6 = a.s6 + "6"; - a.s7 = a.s7 + "7"; - a.s8 = a.s8 + "8"; - } - - public static void test9() { - a.s1 = a.s1 + "1"; - a.s2 = a.s2 + "2"; - a.s3 = a.s3 + "3"; - a.s4 = a.s4 + "4"; - a.s5 = a.s5 + "5"; - a.s6 = a.s6 + "6"; - a.s7 = a.s7 + "7"; - a.s8 = a.s8 + "8"; - a.s9 = a.s9 + "9"; - } - } - - private static void compileMethods() throws Exception { - for (var m : B.class.getDeclaredMethods()) { - if (!m.getName().startsWith("test")) { - continue; - } - m.invoke(null); - WB.markMethodProfiled(m); - WB.enqueueMethodForCompilation(m, compLevel); - while (WB.isMethodQueuedForCompilation(m)) { - Thread.sleep(100); - } - if (WB.getMethodCompilationLevel(m) != compLevel) { - throw new IllegalStateException("Method " + m + " is not compiled at the compilation level: " + compLevel + ". Got: " + WB.getMethodCompilationLevel(m)); - } - } - } - - public static void youngGC() throws Exception { - a = null; - WB.youngGC(); - } - - public static void fullGC() throws Exception { - // Thread synchronization - final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock(); - final ReentrantReadWriteLock.ReadLock readLock = rwLock.readLock(); - final ReentrantReadWriteLock.WriteLock writeLock = rwLock.writeLock(); - final AtomicBoolean running = new AtomicBoolean(true); - - // Thread 1: GC thread that runs for 1 second with 100ms sleep intervals - Thread gcThread = new Thread(() -> { - final long startTime = System.currentTimeMillis(); - final long duration = 1000; - try { - while (System.currentTimeMillis() - startTime < duration) { - writeLock.lock(); - try { - a = new A(); - WB.fullGC(); - } finally { - writeLock.unlock(); - } - Thread.sleep(100); - } - } catch (InterruptedException e) { - // Thread interrupted, exit - } - running.set(false); - }); - - // Threads 2-11: Test threads that execute test0() through test9() - Thread[] testThreads = new Thread[10]; - for (int i = 0; i < 10; i++) { - final int testIdx = i; - testThreads[i] = new Thread(() -> { - try { - var method = B.class.getDeclaredMethod("test" + testIdx); - while (running.get()) { - readLock.lock(); - try { - method.invoke(null); - } finally { - readLock.unlock(); - } - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(10); - } - }); - } - - // Start all threads - gcThread.start(); - for (Thread t : testThreads) { - t.start(); - } - - // Wait for all threads to complete - gcThread.join(); - for (Thread t : testThreads) { - t.join(); - } - } - - public static void main(String[] args) throws Exception { - if (!Boolean.TRUE.equals(WB.getBooleanVMFlag("UseSingleICacheInvalidation"))) { - System.out.println("Skip. Test requires UseSingleICacheInvalidation enabled."); - return; - } - compLevel = (args[1].equals("C1")) ? 1 : 4; - compileMethods(); - TestDeferredICacheInvalidation.class.getMethod(args[0]).invoke(null); - } -} diff --git a/test/micro/org/openjdk/bench/vm/gc/GCPatchingNmethodCost.java b/test/micro/org/openjdk/bench/vm/gc/GCPatchingNmethodCost.java deleted file mode 100644 index 53fa2378ead..00000000000 --- a/test/micro/org/openjdk/bench/vm/gc/GCPatchingNmethodCost.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -package org.openjdk.bench.vm.gc; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.TimeUnit; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.CompilerControl; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import org.openjdk.bench.util.InMemoryJavaCompiler; - -import jdk.test.whitebox.WhiteBox; -import jdk.test.whitebox.code.NMethod; - -/* - * Nmethods have OOPs and GC barriers emmedded into their code. - * GCs patch them which causes invalidation of nmethods' code. - * - * This benchmark can be used to estimate the cost of patching - * OOPs and GC barriers. - * - * We create 5000 nmethods which access fields of a class. - * We measure the time of different GC cycles to see - * the impact of patching nmethods. - * - * The benchmark parameters are method count and accessed field count. - */ - -@BenchmarkMode(Mode.SingleShotTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Benchmark) -@Fork(value = 1, jvmArgsAppend = { - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+UnlockExperimentalVMOptions", - "-XX:+WhiteBoxAPI", - "-Xbootclasspath/a:lib-test/wb.jar", - "-XX:-UseCodeCacheFlushing" -}) -@Warmup(iterations = 5) -@Measurement(iterations = 5) -public class GCPatchingNmethodCost { - - private static final int COMP_LEVEL = 1; - private static final String FIELD_USER = "FieldUser"; - - public static Fields fields; - - private static TestMethod[] methods = {}; - private static byte[] BYTE_CODE; - private static WhiteBox WB; - - @Param({"5000"}) - public int methodCount; - - @Param({"0", "2", "4", "8"}) - public int accessedFieldCount; - - public static class Fields { - public String f1; - public String f2; - public String f3; - public String f4; - public String f5; - public String f6; - public String f7; - public String f8; - public String f9; - } - - private static final class TestMethod { - private final Method method; - - public TestMethod(Method method) throws Exception { - this.method = method; - WB.testSetDontInlineMethod(method, true); - } - - public void profile() throws Exception { - method.invoke(null); - WB.markMethodProfiled(method); - } - - public void invoke() throws Exception { - method.invoke(null); - } - - public void compile() throws Exception { - WB.enqueueMethodForCompilation(method, COMP_LEVEL); - while (WB.isMethodQueuedForCompilation(method)) { - Thread.onSpinWait(); - } - if (WB.getMethodCompilationLevel(method) != COMP_LEVEL) { - throw new IllegalStateException("Method " + method + " is not compiled at the compilation level: " + COMP_LEVEL + ". Got: " + WB.getMethodCompilationLevel(method)); - } - } - - public NMethod getNMethod() { - return NMethod.get(method, false); - } - } - - private static ClassLoader createClassLoader() { - return new ClassLoader() { - @Override - public Class loadClass(String name) throws ClassNotFoundException { - if (!name.equals(FIELD_USER)) { - return super.loadClass(name); - } - - return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length); - } - }; - } - - private static void createTestMethods(int accessedFieldCount, int count) throws Exception { - String javaCode = "public class " + FIELD_USER + " {"; - String field = GCPatchingNmethodCost.class.getName() + ".fields.f"; - javaCode += "public static void accessFields() {"; - for (int i = 1; i <= accessedFieldCount; i++) { - javaCode += field + i + "= " + field + i + " + " + i + ";"; - } - javaCode += "}}"; - - BYTE_CODE = InMemoryJavaCompiler.compile(FIELD_USER, javaCode); - - fields = new Fields(); - - methods = new TestMethod[count]; - for (int i = 0; i < count; i++) { - var cl = createClassLoader().loadClass(FIELD_USER); - Method method = cl.getMethod("accessFields"); - methods[i] = new TestMethod(method); - methods[i].profile(); - methods[i].compile(); - } - } - - private static void initWhiteBox() { - WB = WhiteBox.getWhiteBox(); - } - - @Setup(Level.Trial) - public void setupCodeCache() throws Exception { - initWhiteBox(); - createTestMethods(accessedFieldCount, methodCount); - System.gc(); - } - - @Setup(Level.Iteration) - public void setupIteration() { - fields = new Fields(); - } - - @Benchmark - public void youngGC() throws Exception { - fields = null; - WB.youngGC(); - } - - @Benchmark - public void fullGC() throws Exception { - fields = null; - WB.fullGC(); - } - - @Benchmark - public void systemGC() throws Exception { - fields = null; - System.gc(); - } -}