diff --git a/src/backend_x64/emit_x64.cpp b/src/backend_x64/emit_x64.cpp index 184dd93c..ce24aa62 100644 --- a/src/backend_x64/emit_x64.cpp +++ b/src/backend_x64/emit_x64.cpp @@ -3532,30 +3532,19 @@ void EmitX64::ClearCache() { void EmitX64::InvalidateCacheRange(const Common::AddressRange& range) { // Remove cached block descriptors and patch information overlapping with the given range. + for (auto it = block_descriptors.begin(); it != block_descriptors.end();) { + IR::LocationDescriptor descriptor = it->second.start_location; + u32 start = descriptor.PC(); + u32 end = it->second.end_location_pc; + if (range.Overlaps(start, end)) { + it = block_descriptors.erase(it); - switch (range.which()) { - case 0: // FullAddressRange - ClearCache(); - break; - - case 1: // AddressInterval - auto interval = boost::get(range); - for (auto it = std::begin(block_descriptors); it != std::end(block_descriptors);) { - const IR::LocationDescriptor& descriptor = it->second.start_location; - u32 start = descriptor.PC(); - u32 end = it->second.end_location_pc; - if (interval.Overlaps(start, end)) { - it = block_descriptors.erase(it); - - auto patch_it = patch_information.find(descriptor.UniqueHash()); - if (patch_it != patch_information.end()) { - Unpatch(descriptor); - } - } else { - ++it; + if (patch_information.count(descriptor.UniqueHash())) { + Unpatch(descriptor); } + } else { + ++it; } - break; } } diff --git a/src/backend_x64/interface_x64.cpp b/src/backend_x64/interface_x64.cpp index 4f0c1322..b970d8a7 100644 --- a/src/backend_x64/interface_x64.cpp +++ b/src/backend_x64/interface_x64.cpp @@ -4,8 +4,8 @@ * General Public License version 2 or any later version. */ +#include #include -#include #include @@ -45,7 +45,8 @@ struct Jit::Impl { const UserCallbacks callbacks; // Requests made during execution to invalidate the cache are queued up here. - std::queue invalid_cache_ranges; + std::deque invalid_cache_ranges; + bool invalidate_entire_cache = false; size_t Execute(size_t cycle_count) { return block_of_code.RunCode(&jit_state, cycle_count); @@ -90,19 +91,28 @@ struct Jit::Impl { } void PerformCacheInvalidation() { + if (invalidate_entire_cache) { + jit_state.ResetRSB(); + block_of_code.ClearCache(); + emitter.ClearCache(); + + invalid_cache_ranges.clear(); + invalidate_entire_cache = false; + return; + } + if (invalid_cache_ranges.empty()) { return; } jit_state.ResetRSB(); - block_of_code.ClearCache(); while (!invalid_cache_ranges.empty()) { emitter.InvalidateCacheRange(invalid_cache_ranges.front()); - invalid_cache_ranges.pop(); + invalid_cache_ranges.pop_front(); } } - void HandleNewCacheRange() { + void RequestCacheInvalidation() { if (jit_interface->is_executing) { jit_state.halt_requested = true; return; @@ -160,13 +170,13 @@ size_t Jit::Run(size_t cycle_count) { } void Jit::ClearCache() { - impl->invalid_cache_ranges.push(Common::FullAddressRange{}); - impl->HandleNewCacheRange(); + impl->invalidate_entire_cache = true; + impl->RequestCacheInvalidation(); } void Jit::InvalidateCacheRange(std::uint32_t start_address, std::size_t length) { - impl->invalid_cache_ranges.push(Common::AddressInterval{start_address, length}); - impl->HandleNewCacheRange(); + impl->invalid_cache_ranges.emplace_back(Common::AddressRange{start_address, length}); + impl->RequestCacheInvalidation(); } void Jit::Reset() { diff --git a/src/common/address_range.h b/src/common/address_range.h index b8d7875b..f1abdb97 100644 --- a/src/common/address_range.h +++ b/src/common/address_range.h @@ -6,20 +6,14 @@ #pragma once -#include - -#include - #include "common/common_types.h" namespace Dynarmic { namespace Common { -struct FullAddressRange {}; - -struct AddressInterval { +struct AddressRange { u32 start_address; - std::size_t length; + size_t length; // Does this interval overlap with [from, to)? bool Overlaps(u32 from, u32 to) const { @@ -27,7 +21,5 @@ struct AddressInterval { } }; -using AddressRange = boost::variant; - } // namespace Common } // namespace Dynarmic