From 830ae6a2c181c9fadb0dec1cd7bbb17bafb99ad9 Mon Sep 17 00:00:00 2001 From: degasus Date: Wed, 11 Jan 2017 22:41:30 +0100 Subject: [PATCH] JitCache: Store the JitBlock in the std::map. --- .../CachedInterpreter/CachedInterpreter.cpp | 2 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 2 +- Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 3 +- .../Core/Core/PowerPC/JitCommon/JitCache.cpp | 77 +++++++------------ Source/Core/Core/PowerPC/JitCommon/JitCache.h | 16 +--- 6 files changed, 34 insertions(+), 68 deletions(-) diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 39006acf01..1e41dc63c2 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -123,7 +123,7 @@ static bool CheckDSI(u32 data) void CachedInterpreter::Jit(u32 address) { - if (m_code.size() >= CODE_SIZE / sizeof(Instruction) - 0x1000 || m_block_cache.IsFull() || + if (m_code.size() >= CODE_SIZE / sizeof(Instruction) - 0x1000 || SConfig::GetInstance().bJITNoBlockCache) { ClearCache(); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 580bab2577..f7b75223e2 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -543,7 +543,7 @@ void Jit64::Jit(u32 em_address) } if (IsAlmostFull() || m_far_code.IsAlmostFull() || trampolines.IsAlmostFull() || - blocks.IsFull() || SConfig::GetInstance().bJITNoBlockCache) + SConfig::GetInstance().bJITNoBlockCache) { ClearCache(); } diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index 85c8b12cc0..dac66a2e4b 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -466,7 +466,7 @@ void JitIL::Trace() void JitIL::Jit(u32 em_address) { if (IsAlmostFull() || m_far_code.IsAlmostFull() || trampolines.IsAlmostFull() || - blocks.IsFull() || SConfig::GetInstance().bJITNoBlockCache) + SConfig::GetInstance().bJITNoBlockCache) { ClearCache(); } diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index a424166574..c0db4b4e76 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -368,8 +368,7 @@ void JitArm64::SingleStep() void JitArm64::Jit(u32) { - if (IsAlmostFull() || farcode.IsAlmostFull() || blocks.IsFull() || - SConfig::GetInstance().bJITNoBlockCache) + if (IsAlmostFull() || farcode.IsAlmostFull() || SConfig::GetInstance().bJITNoBlockCache) { ClearCache(); } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 12bbd5ab21..134b3ebca4 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -47,14 +47,11 @@ void JitBaseBlockCache::Init() s_clear_jit_cache_thread_safe = CoreTiming::RegisterEvent("clearJitCache", ClearCacheThreadSafe); JitRegister::Init(SConfig::GetInstance().m_perfDir); - iCache.fill(nullptr); Clear(); } void JitBaseBlockCache::Shutdown() { - num_blocks = 1; - JitRegister::Shutdown(); } @@ -63,26 +60,21 @@ void JitBaseBlockCache::Shutdown() void JitBaseBlockCache::Clear() { #if defined(_DEBUG) || defined(DEBUGFAST) - if (IsFull()) - Core::DisplayMessage("Clearing block cache.", 3000); - else - Core::DisplayMessage("Clearing code cache.", 3000); + Core::DisplayMessage("Clearing code cache.", 3000); #endif m_jit.js.fifoWriteAddresses.clear(); m_jit.js.pairedQuantizeAddresses.clear(); - for (int i = 1; i < num_blocks; i++) + for (auto& e : start_block_map) { - if (!block.invalid) - DestroyBlock(blocks[i]); + DestroyBlock(e.second); } + start_block_map.clear(); links_to.clear(); block_map.clear(); valid_block.ClearAll(); - num_blocks = 1; - blocks[0].msrBits = 0xFFFFFFFF; - blocks[0].invalid = true; + iCache.fill(nullptr); } void JitBaseBlockCache::Reset() @@ -96,11 +88,6 @@ void JitBaseBlockCache::SchedulateClearCacheThreadSafe() CoreTiming::ScheduleEvent(0, s_clear_jit_cache_thread_safe, 0, CoreTiming::FromThread::NON_CPU); } -bool JitBaseBlockCache::IsFull() const -{ - return num_blocks >= MAX_NUM_BLOCKS - 1; -} - JitBlock** JitBaseBlockCache::GetICache() { return iCache.data(); @@ -108,26 +95,36 @@ JitBlock** JitBaseBlockCache::GetICache() void JitBaseBlockCache::RunOnBlocks(std::function f) { - for (int i = 0; i < num_blocks; i++) - f(blocks[i]); + for (const auto& e : start_block_map) + f(e.second); } JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address) { - JitBlock& b = blocks[num_blocks]; - b.invalid = false; + u32 physicalAddress = PowerPC::JitCache_TranslateAddress(em_address).address; + JitBlock& b = start_block_map.emplace(physicalAddress, JitBlock())->second; b.effectiveAddress = em_address; - b.physicalAddress = PowerPC::JitCache_TranslateAddress(em_address).address; + b.physicalAddress = physicalAddress; b.msrBits = MSR & JIT_CACHE_MSR_MASK; b.linkData.clear(); b.in_icache = 0; - num_blocks++; // commit the current block return &b; } +void JitBaseBlockCache::FreeBlock(JitBlock* block) +{ + auto iter = start_block_map.equal_range(block->physicalAddress); + while (iter.first != iter.second) + { + if (&iter.first->second == block) + start_block_map.erase(iter.first); + else + iter.first++; + } +} + void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr) { - start_block_map.emplace(block.physicalAddress, &block); size_t icache = FastLookupEntryForAddress(block.effectiveAddress); iCache[icache] = █ block.in_icache = icache; @@ -168,8 +165,8 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr) auto iter = start_block_map.equal_range(translated_addr); for (; iter.first != iter.second; iter.first++) { - JitBlock& b = *iter.first->second; - if (!b.invalid && b.effectiveAddress == addr && b.msrBits == (msr & JIT_CACHE_MSR_MASK)) + JitBlock& b = iter.first->second; + if (b.effectiveAddress == addr && b.msrBits == (msr & JIT_CACHE_MSR_MASK)) return &b; } @@ -214,7 +211,9 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for auto it = block_map.lower_bound(std::make_pair(pAddr, 0)); while (it != block_map.end() && it->first.second < pAddr + length) { - DestroyBlock(*it->second); + JitBlock* block = it->second; + DestroyBlock(*block); + FreeBlock(block); it = block_map.erase(it); } @@ -250,17 +249,12 @@ void JitBaseBlockCache::WriteDestroyBlock(const JitBlock& block) void JitBaseBlockCache::LinkBlockExits(JitBlock& block) { - if (block.invalid) - { - // This block is dead. Don't relink it. - return; - } for (auto& e : block.linkData) { if (!e.linkStatus) { JitBlock* destinationBlock = GetBlockFromStartAddress(e.exitAddress, block.msrBits); - if (destinationBlock && !destinationBlock->invalid) + if (destinationBlock) { WriteLinkBlock(e, destinationBlock); e.linkStatus = true; @@ -305,24 +299,9 @@ void JitBaseBlockCache::UnlinkBlock(const JitBlock& block) void JitBaseBlockCache::DestroyBlock(JitBlock& block) { - if (block.invalid) - { - PanicAlert("Invalidating invalid block %p", &block); - return; - } - block.invalid = true; if (iCache[block.in_icache] == &block) iCache[block.in_icache] = nullptr; - auto iter = start_block_map.equal_range(block.physicalAddress); - while (iter.first != iter.second) - { - if (iter.first->second == &block) - iter.first = start_block_map.erase(iter.first); - else - iter.first++; - } - UnlinkBlock(block); // Delete linking addresses diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index 341d7c8d6d..0f1c36efef 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -47,11 +47,6 @@ struct JitBlock u32 originalSize; int runCount; // for profiling. - // Whether this struct refers to a valid block. This is mostly useful as - // a debugging aid. - // FIXME: Change current users of invalid bit to assertions? - bool invalid; - // Information about exits to a known address from this block. // This is used to implement block linking. struct LinkData @@ -112,7 +107,6 @@ public: // is valid (MSR.IR and MSR.DR, the address translation bits). static constexpr u32 JIT_CACHE_MSR_MASK = 0x30; - static constexpr int MAX_NUM_BLOCKS = 65536 * 2; static constexpr u32 iCache_Num_Elements = 0x10000; static constexpr u32 iCache_Mask = iCache_Num_Elements - 1; @@ -125,13 +119,12 @@ public: void Reset(); void SchedulateClearCacheThreadSafe(); - bool IsFull() const; - // Code Cache JitBlock** GetICache(); void RunOnBlocks(std::function f); JitBlock* AllocateBlock(u32 em_address); + void FreeBlock(JitBlock* block); void FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr); // Look for the block in the slow but accurate way. @@ -166,11 +159,6 @@ private: // Fast but risky block lookup based on iCache. size_t FastLookupEntryForAddress(u32 address); - // We store the metadata of all blocks in a linear way within this array. - // Note: blocks[0] must not be used as it is referenced as invalid block in iCache. - std::array blocks; // number -> JitBlock - int num_blocks = 1; - // links_to hold all exit points of all valid blocks in a reverse way. // It is used to query all blocks which links to an address. std::multimap links_to; // destination_PC -> number @@ -182,7 +170,7 @@ private: // Map indexed by the physical address of the entry point. // This is used to query the block based on the current PC in a slow way. // TODO: This is redundant with block_map. - std::multimap start_block_map; // start_addr -> block + std::multimap start_block_map; // start_addr -> block // This bitsets shows which cachelines overlap with any blocks. // It is used to provide a fast way to query if no icache invalidation is needed.