diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index 44bf711e90..39006acf01 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -140,8 +140,7 @@ void CachedInterpreter::Jit(u32 address) return; } - int block_num = m_block_cache.AllocateBlock(PC); - JitBlock* b = m_block_cache.GetBlock(block_num); + JitBlock* b = m_block_cache.AllocateBlock(PC); js.blockStart = PC; js.firstFPInstructionFound = false; @@ -212,7 +211,7 @@ void CachedInterpreter::Jit(u32 address) b->codeSize = (u32)(GetCodePtr() - b->checkedEntry); b->originalSize = code_block.m_num_instructions; - m_block_cache.FinalizeBlock(block_num, jo.enableBlocklink, b->checkedEntry); + m_block_cache.FinalizeBlock(*b, jo.enableBlocklink, b->checkedEntry); } void CachedInterpreter::ClearCache() diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index a96078302e..580bab2577 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -589,9 +589,8 @@ void Jit64::Jit(u32 em_address) return; } - int block_num = blocks.AllocateBlock(em_address); - JitBlock* b = blocks.GetBlock(block_num); - blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); + JitBlock* b = blocks.AllocateBlock(em_address); + blocks.FinalizeBlock(*b, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); } const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index 988d8321fd..85c8b12cc0 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -507,9 +507,8 @@ void JitIL::Jit(u32 em_address) return; } - int block_num = blocks.AllocateBlock(em_address); - JitBlock* b = blocks.GetBlock(block_num); - blocks.FinalizeBlock(block_num, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); + JitBlock* b = blocks.AllocateBlock(em_address); + blocks.FinalizeBlock(*b, jo.enableBlocklink, DoJit(em_address, &code_buffer, b, nextPC)); } const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 5ee45e5613..a424166574 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -398,10 +398,9 @@ void JitArm64::Jit(u32) return; } - int block_num = blocks.AllocateBlock(em_address); - JitBlock* b = blocks.GetBlock(block_num); + JitBlock* b = blocks.AllocateBlock(em_address); const u8* BlockPtr = DoJit(em_address, &code_buffer, b, nextPC); - blocks.FinalizeBlock(block_num, jo.enableBlocklink, BlockPtr); + blocks.FinalizeBlock(*b, jo.enableBlocklink, BlockPtr); } const u8* JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 265bef38d9..93937f9e32 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -71,7 +71,7 @@ void JitBaseBlockCache::Clear() m_jit.js.pairedQuantizeAddresses.clear(); for (int i = 1; i < num_blocks; i++) { - DestroyBlock(i, false); + DestroyBlock(blocks[i], false); } links_to.clear(); block_map.clear(); @@ -96,12 +96,7 @@ void JitBaseBlockCache::SchedulateClearCacheThreadSafe() bool JitBaseBlockCache::IsFull() const { - return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; -} - -JitBlock* JitBaseBlockCache::GetBlock(int no) -{ - return &blocks[no]; + return num_blocks >= MAX_NUM_BLOCKS - 1; } JitBlock* JitBaseBlockCache::GetBlocks() @@ -109,17 +104,18 @@ JitBlock* JitBaseBlockCache::GetBlocks() return blocks.data(); } -int JitBaseBlockCache::GetNumBlocks() const -{ - return num_blocks; -} - int* JitBaseBlockCache::GetICache() { return iCache.data(); } -int JitBaseBlockCache::AllocateBlock(u32 em_address) +void JitBaseBlockCache::RunOnBlocks(std::function f) +{ + for (int i = 0; i < num_blocks; i++) + f(blocks[i]); +} + +JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address) { JitBlock& b = blocks[num_blocks]; b.invalid = false; @@ -128,48 +124,47 @@ int JitBaseBlockCache::AllocateBlock(u32 em_address) b.msrBits = MSR & JitBlock::JIT_CACHE_MSR_MASK; b.linkData.clear(); num_blocks++; // commit the current block - return num_blocks - 1; + return &b; } -void JitBaseBlockCache::FinalizeBlock(int block_num, bool block_link, const u8* code_ptr) +void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr) { - JitBlock& b = blocks[block_num]; - if (start_block_map.count(b.physicalAddress)) + if (start_block_map.count(block.physicalAddress)) { // We already have a block at this address; invalidate the old block. // This should be very rare. This will only happen if the same block // is called both with DR/IR enabled or disabled. - WARN_LOG(DYNA_REC, "Invalidating compiled block at same address %08x", b.physicalAddress); - int old_block_num = start_block_map[b.physicalAddress]; - const JitBlock& old_b = blocks[old_block_num]; + WARN_LOG(DYNA_REC, "Invalidating compiled block at same address %08x", block.physicalAddress); + JitBlock& old_b = *start_block_map[block.physicalAddress]; block_map.erase( std::make_pair(old_b.physicalAddress + 4 * old_b.originalSize - 1, old_b.physicalAddress)); - DestroyBlock(old_block_num, true); + DestroyBlock(old_b, true); } - start_block_map[b.physicalAddress] = block_num; - FastLookupEntryForAddress(b.effectiveAddress) = block_num; + const int block_num = static_cast(&block - &blocks[0]); + start_block_map[block.physicalAddress] = █ + FastLookupEntryForAddress(block.effectiveAddress) = block_num; - u32 pAddr = b.physicalAddress; + u32 pAddr = block.physicalAddress; - for (u32 block = pAddr / 32; block <= (pAddr + (b.originalSize - 1) * 4) / 32; ++block) - valid_block.Set(block); + for (u32 addr = pAddr / 32; addr <= (pAddr + (block.originalSize - 1) * 4) / 32; ++addr) + valid_block.Set(addr); - block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; + block_map[std::make_pair(pAddr + 4 * block.originalSize - 1, pAddr)] = █ if (block_link) { - for (const auto& e : b.linkData) + for (const auto& e : block.linkData) { - links_to.emplace(e.exitAddress, block_num); + links_to.emplace(e.exitAddress, &block); } - LinkBlock(block_num); + LinkBlock(block); } - JitRegister::Register(b.checkedEntry, b.codeSize, "JIT_PPC_%08x", b.physicalAddress); + JitRegister::Register(block.checkedEntry, block.codeSize, "JIT_PPC_%08x", block.physicalAddress); } -int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr, u32 msr) +JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr) { u32 translated_addr = addr; if (UReg_MSR(msr).IR) @@ -177,23 +172,20 @@ int JitBaseBlockCache::GetBlockNumberFromStartAddress(u32 addr, u32 msr) auto translated = PowerPC::JitCache_TranslateAddress(addr); if (!translated.valid) { - return -1; + return nullptr; } translated_addr = translated.address; } auto map_result = start_block_map.find(translated_addr); if (map_result == start_block_map.end()) - return -1; - int block_num = map_result->second; - const JitBlock& b = blocks[block_num]; - if (b.invalid) - return -1; - if (b.effectiveAddress != addr) - return -1; - if (b.msrBits != (msr & JitBlock::JIT_CACHE_MSR_MASK)) - return -1; - return block_num; + return nullptr; + + JitBlock* b = map_result->second; + if (b->invalid || b->effectiveAddress != addr || + b->msrBits != (msr & JitBlock::JIT_CACHE_MSR_MASK)) + return nullptr; + return b; } const u8* JitBaseBlockCache::Dispatch() @@ -235,7 +227,7 @@ 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, true); + DestroyBlock(*it->second, true); it = block_map.erase(it); } @@ -269,59 +261,53 @@ void JitBaseBlockCache::WriteDestroyBlock(const JitBlock& block) // Can be faster by doing a queue for blocks to link up, and only process those // Should probably be done -void JitBaseBlockCache::LinkBlockExits(int i) +void JitBaseBlockCache::LinkBlockExits(JitBlock& block) { - JitBlock& b = blocks[i]; - if (b.invalid) + if (block.invalid) { // This block is dead. Don't relink it. return; } - for (auto& e : b.linkData) + for (auto& e : block.linkData) { if (!e.linkStatus) { - int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress, b.msrBits); - if (destinationBlock != -1) + JitBlock* destinationBlock = GetBlockFromStartAddress(e.exitAddress, block.msrBits); + if (destinationBlock && !destinationBlock->invalid) { - if (!blocks[destinationBlock].invalid) - { - WriteLinkBlock(e, &blocks[destinationBlock]); - e.linkStatus = true; - } + WriteLinkBlock(e, destinationBlock); + e.linkStatus = true; } } } } -void JitBaseBlockCache::LinkBlock(int i) +void JitBaseBlockCache::LinkBlock(JitBlock& block) { - LinkBlockExits(i); - const JitBlock& b = blocks[i]; - auto ppp = links_to.equal_range(b.effectiveAddress); + LinkBlockExits(block); + auto ppp = links_to.equal_range(block.effectiveAddress); for (auto iter = ppp.first; iter != ppp.second; ++iter) { - const JitBlock& b2 = blocks[iter->second]; - if (b.msrBits == b2.msrBits) - LinkBlockExits(iter->second); + JitBlock& b2 = *iter->second; + if (block.msrBits == b2.msrBits) + LinkBlockExits(b2); } } -void JitBaseBlockCache::UnlinkBlock(int i) +void JitBaseBlockCache::UnlinkBlock(const JitBlock& block) { - JitBlock& b = blocks[i]; - auto ppp = links_to.equal_range(b.effectiveAddress); + auto ppp = links_to.equal_range(block.effectiveAddress); for (auto iter = ppp.first; iter != ppp.second; ++iter) { - JitBlock& sourceBlock = blocks[iter->second]; - if (sourceBlock.msrBits != b.msrBits) + JitBlock& sourceBlock = *iter->second; + if (sourceBlock.msrBits != block.msrBits) continue; for (auto& e : sourceBlock.linkData) { - if (e.exitAddress == b.effectiveAddress) + if (e.exitAddress == block.effectiveAddress) { WriteLinkBlock(e, nullptr); e.linkStatus = false; @@ -330,51 +316,45 @@ void JitBaseBlockCache::UnlinkBlock(int i) } } -void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate) +void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate) { - if (block_num < 0 || block_num >= num_blocks) - { - PanicAlert("DestroyBlock: Invalid block number %d", block_num); - return; - } - JitBlock& b = blocks[block_num]; - if (b.invalid) + if (block.invalid) { if (invalidate) - PanicAlert("Invalidating invalid block %d", block_num); + PanicAlert("Invalidating invalid block %p", &block); return; } - b.invalid = true; - start_block_map.erase(b.physicalAddress); - FastLookupEntryForAddress(b.effectiveAddress) = 0; + block.invalid = true; + start_block_map.erase(block.physicalAddress); + FastLookupEntryForAddress(block.effectiveAddress) = 0; - UnlinkBlock(block_num); + UnlinkBlock(block); // Delete linking addresses - auto it = links_to.equal_range(b.effectiveAddress); + auto it = links_to.equal_range(block.effectiveAddress); while (it.first != it.second) { - if (it.first->second == block_num) + if (it.first->second == &block) it.first = links_to.erase(it.first); else it.first++; } // Raise an signal if we are going to call this block again - WriteDestroyBlock(b); + WriteDestroyBlock(block); } void JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr) { - int block_num = GetBlockNumberFromStartAddress(addr, msr); - if (block_num < 0) + JitBlock* block = GetBlockFromStartAddress(addr, msr); + if (!block) { Jit(addr); } else { - FastLookupEntryForAddress(addr) = block_num; - LinkBlock(block_num); + FastLookupEntryForAddress(addr) = static_cast(block - &blocks[0]); + LinkBlock(*block); } } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index 0b1f23482e..3ffe6b8bd8 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -6,6 +6,7 @@ #include #include +#include #include #include #include @@ -126,17 +127,17 @@ public: bool IsFull() const; // Code Cache - JitBlock* GetBlock(int block_num); JitBlock* GetBlocks(); - int GetNumBlocks() const; int* GetICache(); + void RunOnBlocks(std::function f); - int AllocateBlock(u32 em_address); - void FinalizeBlock(int block_num, bool block_link, const u8* code_ptr); + JitBlock* AllocateBlock(u32 em_address); + void FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr); // Look for the block in the slow but accurate way. // This function shall be used if FastLookupEntryForAddress() failed. - int GetBlockNumberFromStartAddress(u32 em_address, u32 msr); + // This might return nullptr if there is no such block. + JitBlock* GetBlockFromStartAddress(u32 em_address, u32 msr); // Get the normal entry for the block associated with the current program // counter. This will JIT code if necessary. (This is the reference @@ -155,10 +156,10 @@ private: virtual void WriteLinkBlock(const JitBlock::LinkData& source, const JitBlock* dest) = 0; virtual void WriteDestroyBlock(const JitBlock& block); - void LinkBlockExits(int i); - void LinkBlock(int i); - void UnlinkBlock(int i); - void DestroyBlock(int block_num, bool invalidate); + void LinkBlockExits(JitBlock& block); + void LinkBlock(JitBlock& block); + void UnlinkBlock(const JitBlock& block); + void DestroyBlock(JitBlock& block, bool invalidate); void MoveBlockIntoFastCache(u32 em_address, u32 msr); @@ -172,16 +173,16 @@ private: // 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 + std::multimap links_to; // destination_PC -> number // Map indexed by the physical memory location. // It is used to invalidate blocks based on memory location. - std::map, u32> block_map; // (end_addr, start_addr) -> number + std::map, JitBlock*> block_map; // (end_addr, start_addr) -> block // 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, and both should be a multimap. - std::map start_block_map; // start_addr -> number + std::map 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. diff --git a/Source/Core/Core/PowerPC/JitInterface.cpp b/Source/Core/Core/PowerPC/JitInterface.cpp index d02377264c..a342f7a6d7 100644 --- a/Source/Core/Core/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/PowerPC/JitInterface.cpp @@ -134,26 +134,23 @@ void GetProfileResults(ProfileStats* prof_stats) prof_stats->cost_sum = 0; prof_stats->timecost_sum = 0; prof_stats->block_stats.clear(); - prof_stats->block_stats.reserve(g_jit->GetBlockCache()->GetNumBlocks()); Core::EState old_state = Core::GetState(); if (old_state == Core::CORE_RUN) Core::SetState(Core::CORE_PAUSE); QueryPerformanceFrequency((LARGE_INTEGER*)&prof_stats->countsPerSec); - for (int i = 0; i < g_jit->GetBlockCache()->GetNumBlocks(); i++) - { - const JitBlock* block = g_jit->GetBlockCache()->GetBlock(i); + g_jit->GetBlockCache()->RunOnBlocks([&prof_stats](const JitBlock& block) { // Rough heuristic. Mem instructions should cost more. - u64 cost = block->originalSize * (block->runCount / 4); - u64 timecost = block->ticCounter; + u64 cost = block.originalSize * (block.runCount / 4); + u64 timecost = block.ticCounter; // Todo: tweak. - if (block->runCount >= 1) - prof_stats->block_stats.emplace_back(i, block->effectiveAddress, cost, timecost, - block->runCount, block->codeSize); + if (block.runCount >= 1) + prof_stats->block_stats.emplace_back(block.effectiveAddress, cost, timecost, block.runCount, + block.codeSize); prof_stats->cost_sum += cost; prof_stats->timecost_sum += timecost; - } + }); sort(prof_stats->block_stats.begin(), prof_stats->block_stats.end()); if (old_state == Core::CORE_RUN) @@ -168,34 +165,31 @@ int GetHostCode(u32* address, const u8** code, u32* code_size) return 1; } - int block_num = g_jit->GetBlockCache()->GetBlockNumberFromStartAddress(*address, MSR); - if (block_num < 0) + JitBlock* block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address, MSR); + if (!block) { for (int i = 0; i < 500; i++) { - block_num = g_jit->GetBlockCache()->GetBlockNumberFromStartAddress(*address - 4 * i, MSR); - if (block_num >= 0) + block = g_jit->GetBlockCache()->GetBlockFromStartAddress(*address - 4 * i, MSR); + if (block) break; } - if (block_num >= 0) + if (block) { - JitBlock* block = g_jit->GetBlockCache()->GetBlock(block_num); if (!(block->effectiveAddress <= *address && block->originalSize + block->effectiveAddress >= *address)) - block_num = -1; + block = nullptr; } // Do not merge this "if" with the above - block_num changes inside it. - if (block_num < 0) + if (!block) { *code_size = 0; return 2; } } - JitBlock* block = g_jit->GetBlockCache()->GetBlock(block_num); - *code = block->checkedEntry; *code_size = block->codeSize; *address = block->effectiveAddress; diff --git a/Source/Core/Core/PowerPC/Profiler.h b/Source/Core/Core/PowerPC/Profiler.h index 4c11af58ed..6146bee4d1 100644 --- a/Source/Core/Core/PowerPC/Profiler.h +++ b/Source/Core/Core/PowerPC/Profiler.h @@ -43,11 +43,10 @@ struct BlockStat { - BlockStat(int bn, u32 _addr, u64 c, u64 ticks, u64 run, u32 size) - : blockNum(bn), addr(_addr), cost(c), tick_counter(ticks), run_count(run), block_size(size) + BlockStat(u32 _addr, u64 c, u64 ticks, u64 run, u32 size) + : addr(_addr), cost(c), tick_counter(ticks), run_count(run), block_size(size) { } - int blockNum; u32 addr; u64 cost; u64 tick_counter;