WIP: DO-NOT-MERGE: NCE experiments: Initial LRU
This commit is contained in:
parent
27ceda2c6c
commit
3d43fecece
2 changed files with 71 additions and 1 deletions
57
src/core/arm/nce/lru_cache.h
Normal file
57
src/core/arm/nce/lru_cache.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <list>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
template<typename KeyType, typename ValueType>
|
||||||
|
class LRUCache {
|
||||||
|
public:
|
||||||
|
explicit LRUCache(size_t capacity) : capacity(capacity) {}
|
||||||
|
|
||||||
|
ValueType* get(const KeyType& key) {
|
||||||
|
auto it = cache_map.find(key);
|
||||||
|
if (it == cache_map.end()) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the accessed item to the front of the list (most recently used)
|
||||||
|
cache_list.splice(cache_list.begin(), cache_list, it->second.first);
|
||||||
|
return &(it->second.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
void put(const KeyType& key, const ValueType& value) {
|
||||||
|
auto it = cache_map.find(key);
|
||||||
|
|
||||||
|
if (it != cache_map.end()) {
|
||||||
|
// Key exists, update value and move to front
|
||||||
|
it->second.second = value;
|
||||||
|
cache_list.splice(cache_list.begin(), cache_list, it->second.first);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the least recently used item if cache is full
|
||||||
|
if (cache_map.size() >= capacity) {
|
||||||
|
auto last = cache_list.back();
|
||||||
|
cache_map.erase(last);
|
||||||
|
cache_list.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert new item at the front
|
||||||
|
cache_list.push_front(key);
|
||||||
|
cache_map[key] = {cache_list.begin(), value};
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
cache_map.clear();
|
||||||
|
cache_list.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const {
|
||||||
|
return cache_map.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
size_t capacity;
|
||||||
|
std::list<KeyType> cache_list;
|
||||||
|
std::unordered_map<KeyType, std::pair<typename std::list<KeyType>::iterator, ValueType>> cache_map;
|
||||||
|
};
|
|
@ -13,6 +13,7 @@
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
#include "core/hle/kernel/k_typed_address.h"
|
#include "core/hle/kernel/k_typed_address.h"
|
||||||
#include "core/hle/kernel/physical_memory.h"
|
#include "core/hle/kernel/physical_memory.h"
|
||||||
|
#include "lru_cache.h"
|
||||||
|
|
||||||
namespace Core::NCE {
|
namespace Core::NCE {
|
||||||
|
|
||||||
|
@ -60,8 +61,20 @@ private:
|
||||||
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg);
|
void WriteCntpctHandler(ModuleDestLabel module_dest, oaknut::XReg dest_reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr size_t CACHE_SIZE = 1024; // Cache size for patch entries
|
||||||
|
LRUCache<uintptr_t, PatchTextAddress> patch_cache{CACHE_SIZE};
|
||||||
|
|
||||||
void BranchToPatch(uintptr_t module_dest) {
|
void BranchToPatch(uintptr_t module_dest) {
|
||||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
// Try to get existing patch entry from cache
|
||||||
|
if (auto* cached_patch = patch_cache.get(module_dest)) {
|
||||||
|
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), *cached_patch});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not in cache, create new entry and cache it
|
||||||
|
const auto patch_addr = c.offset();
|
||||||
|
curr_patch->m_branch_to_patch_relocations.push_back({patch_addr, module_dest});
|
||||||
|
patch_cache.put(module_dest, patch_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BranchToModule(uintptr_t module_dest) {
|
void BranchToModule(uintptr_t module_dest) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue