diff --git a/src/core/arm/nce/lru_cache.h b/src/core/arm/nce/lru_cache.h deleted file mode 100644 index 947b66f675..0000000000 --- a/src/core/arm/nce/lru_cache.h +++ /dev/null @@ -1,187 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - -#pragma once -#include -#include -#include -#include -#include - -#include "common/logging/log.h" - -template -class LRUCache { -public: - using key_type = KeyType; - using value_type = ValueType; - using size_type = std::size_t; - - struct Statistics { - size_type hits = 0; - size_type misses = 0; - void reset() noexcept { hits = misses = 0; } - }; - - explicit LRUCache(size_type capacity, bool enabled = true) - : enabled_{enabled}, capacity_{capacity} { - cache_map_.reserve(capacity_); - LOG_WARNING(Core, "LRU Cache initialised (state: {} | capacity: {})", enabled_ ? "enabled" : "disabled", capacity_); - } - - // Non-movable copy semantics - LRUCache(const LRUCache&) = delete; - LRUCache& operator=(const LRUCache&) = delete; - LRUCache(LRUCache&& other) noexcept { *this = std::move(other); } - LRUCache& operator=(LRUCache&& other) noexcept { - if (this == &other) return *this; - std::unique_lock this_lock(mutex_, std::defer_lock); - std::unique_lock other_lock(other.mutex_, std::defer_lock); - std::lock(this_lock, other_lock); - enabled_ = other.enabled_; - capacity_ = other.capacity_; - cache_list_ = std::move(other.cache_list_); - cache_map_ = std::move(other.cache_map_); - stats_ = other.stats_; - return *this; - } - ~LRUCache() = default; - - [[nodiscard]] value_type* get(const key_type& key) { - if (!enabled_) [[unlikely]] return nullptr; - std::unique_lock lock(mutex_); - auto it = cache_map_.find(key); - if (it == cache_map_.end()) { - ++stats_.misses; - return nullptr; - } - move_to_front(it); - ++stats_.hits; - return &it->second.second; - } - - [[nodiscard]] value_type* peek(const key_type& key) const { - if (!enabled_) [[unlikely]] return nullptr; - std::shared_lock lock(mutex_); - auto it = cache_map_.find(key); - return it == cache_map_.end() ? nullptr : &it->second.second; - } - - template - void put(const key_type& key, V&& value) { - if (!enabled_) [[unlikely]] return; - std::unique_lock lock(mutex_); - insert_or_update(key, std::forward(value)); - } - - template - value_type& get_or_emplace(const key_type& key, ValueFactory&& factory) { - std::unique_lock lock(mutex_); - auto it = cache_map_.find(key); - if (it != cache_map_.end()) { - move_to_front(it); - return it->second.second; - } - value_type new_value = factory(); - insert_or_update(key, std::move(new_value)); - return cache_map_.find(key)->second.second; - } - - [[nodiscard]] bool contains(const key_type& key) const { - if (!enabled_) return false; - std::shared_lock lock(mutex_); - return cache_map_.find(key) != cache_map_.end(); - } - - bool erase(const key_type& key) { - if (!enabled_) return false; - std::unique_lock lock(mutex_); - auto it = cache_map_.find(key); - if (it == cache_map_.end()) return false; - cache_list_.erase(it->second.first); - cache_map_.erase(it); - return true; - } - - void clear() { - std::unique_lock lock(mutex_); - cache_list_.clear(); - cache_map_.clear(); - stats_.reset(); - } - - [[nodiscard]] size_type size() const { - if (!enabled_) return 0; - std::shared_lock lock(mutex_); - return cache_map_.size(); - } - - [[nodiscard]] size_type get_capacity() const { return capacity_; } - - void resize(size_type new_capacity) { - if (!enabled_) return; - std::unique_lock lock(mutex_); - capacity_ = new_capacity; - shrink_if_needed(); - cache_map_.reserve(capacity_); - } - - void setEnabled(bool state) { - std::unique_lock lock(mutex_); - enabled_ = state; - LOG_WARNING(Core, "LRU Cache state changed to: {}", state ? "enabled" : "disabled"); - if (!enabled_) clear(); - } - - [[nodiscard]] bool isEnabled() const { return enabled_; } - - [[nodiscard]] Statistics stats() const { - std::shared_lock lock(mutex_); - return stats_; - } - -private: - using list_type = std::list; - using list_iterator = typename list_type::iterator; - using map_value_type = std::pair; - using map_type = ankerl::unordered_dense::map; - - template - void insert_or_update(const key_type& key, V&& value) { - auto it = cache_map_.find(key); - if (it != cache_map_.end()) { - it->second.second = std::forward(value); - move_to_front(it); - return; - } - // evict LRU if full - if (cache_map_.size() >= capacity_) { - const auto& lru_key = cache_list_.back(); - cache_map_.erase(lru_key); - cache_list_.pop_back(); - } - cache_list_.push_front(key); - cache_map_[key] = {cache_list_.begin(), std::forward(value)}; - } - - void move_to_front(typename map_type::iterator it) { - cache_list_.splice(cache_list_.begin(), cache_list_, it->second.first); - it->second.first = cache_list_.begin(); - } - - void shrink_if_needed() { - while (cache_map_.size() > capacity_) { - const auto& lru_key = cache_list_.back(); - cache_map_.erase(lru_key); - cache_list_.pop_back(); - } - } - -private: - mutable std::shared_mutex mutex_; - bool enabled_{true}; - size_type capacity_; - list_type cache_list_; - map_type cache_map_; - mutable Statistics stats_; -}; diff --git a/src/core/arm/nce/patcher.cpp b/src/core/arm/nce/patcher.cpp index 3a620bff12..bd8e4fd7fb 100644 --- a/src/core/arm/nce/patcher.cpp +++ b/src/core/arm/nce/patcher.cpp @@ -17,27 +17,6 @@ namespace Core::NCE { -Patcher::Patcher(Patcher&& other) noexcept - : patch_cache(std::move(other.patch_cache)), - m_patch_instructions(std::move(other.m_patch_instructions)), - m_patch_instructions_pre(std::move(other.m_patch_instructions_pre)), - c(m_patch_instructions), - c_pre(m_patch_instructions_pre), - m_save_context(other.m_save_context), - m_load_context(other.m_load_context), - m_save_context_pre(other.m_save_context_pre), - m_load_context_pre(other.m_load_context_pre), - mode(other.mode), - total_program_size(other.total_program_size), - m_relocate_module_index(other.m_relocate_module_index), - modules(std::move(other.modules)), - curr_patch(nullptr) { - if (!modules.empty()) { - curr_patch = &modules.back(); - } -} - - using namespace Common::Literals; using namespace oaknut::util; @@ -47,8 +26,6 @@ constexpr size_t MaxRelativeBranch = 128_MiB; constexpr u32 ModuleCodeIndex = 0x24 / sizeof(u32); Patcher::Patcher() : c(m_patch_instructions), c_pre(m_patch_instructions_pre) { - LOG_WARNING(Core_ARM, "Patcher initialized with LRU cache {}", - patch_cache.isEnabled() ? "enabled" : "disabled"); // The first word of the patch section is always a branch to the first instruction of the // module. c.dw(0); diff --git a/src/core/arm/nce/patcher.h b/src/core/arm/nce/patcher.h index 8612cfc63d..ea7f58ddec 100644 --- a/src/core/arm/nce/patcher.h +++ b/src/core/arm/nce/patcher.h @@ -14,7 +14,6 @@ #include "core/hle/kernel/code_set.h" #include "core/hle/kernel/k_typed_address.h" #include "core/hle/kernel/physical_memory.h" -#include "lru_cache.h" #include using ModuleID = std::array; // NSO build ID struct PatchCacheKey { @@ -99,28 +98,9 @@ private: void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg) { WriteCntpctHandler(module_dest, dest_reg, c); } private: - static constexpr size_t CACHE_SIZE = 16384; // Cache size for patch entries - LRUCache patch_cache{CACHE_SIZE, Settings::values.lru_cache_enabled.GetValue()}; - void BranchToPatch(uintptr_t module_dest) { - if (patch_cache.isEnabled()) { - PatchCacheKey key{module_id, module_dest}; - LOG_DEBUG(Core_ARM, "LRU cache lookup for module={}, offset={:#x}", fmt::ptr(module_id.data()), module_dest); - // Try to get existing patch entry from cache - if (auto* cached_patch = patch_cache.get(key)) { - LOG_WARNING(Core_ARM, "LRU cache hit for module offset {:#x}", module_dest); - curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch}); - return; - } - LOG_DEBUG(Core_ARM, "LRU cache miss for module offset {:#x}, creating new patch", module_dest); - // Not in cache: create and store - const auto patch_addr = c.offset(); - curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest}); - patch_cache.put(key, patch_addr); - } else { - LOG_DEBUG(Core_ARM, "LRU cache disabled - direct patch for offset {:#x}", module_dest); - curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest}); - } + LOG_DEBUG(Core_ARM, "LRU cache disabled - direct patch for offset {:#x}", module_dest); + curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest}); } void BranchToPatchPre(uintptr_t module_dest) {