diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 8da453eef9..a108a3fdb6 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -118,6 +118,7 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address) b.physicalAddress = PowerPC::JitCache_TranslateAddress(em_address).address; b.msrBits = MSR & JitBlock::JIT_CACHE_MSR_MASK; b.linkData.clear(); + b.in_icache = 0; num_blocks++; // commit the current block return &b; } @@ -136,7 +137,9 @@ void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8 DestroyBlock(old_b, true); } start_block_map[block.physicalAddress] = █ - FastLookupEntryForAddress(block.effectiveAddress) = █ + size_t icache = FastLookupEntryForAddress(block.effectiveAddress); + iCache[icache] = █ + block.in_icache = icache; u32 pAddr = block.physicalAddress; @@ -184,13 +187,13 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr) const u8* JitBaseBlockCache::Dispatch() { - JitBlock* block = FastLookupEntryForAddress(PC); + JitBlock* block = iCache[FastLookupEntryForAddress(PC)]; while (!block || block->effectiveAddress != PC || block->msrBits != (MSR & JitBlock::JIT_CACHE_MSR_MASK)) { MoveBlockIntoFastCache(PC, MSR & JitBlock::JIT_CACHE_MSR_MASK); - block = FastLookupEntryForAddress(PC); + block = iCache[FastLookupEntryForAddress(PC)]; } return block->normalEntry; @@ -320,7 +323,8 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate) } block.invalid = true; start_block_map.erase(block.physicalAddress); - FastLookupEntryForAddress(block.effectiveAddress) = nullptr; + if (iCache[block.in_icache] == &block) + iCache[block.in_icache] = nullptr; UnlinkBlock(block); @@ -350,12 +354,19 @@ void JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr) } else { - FastLookupEntryForAddress(addr) = block; + // Drop old icache entry + if (iCache[block->in_icache] == block) + iCache[block->in_icache] = nullptr; + + // And create a new one + size_t icache = FastLookupEntryForAddress(addr); + iCache[icache] = block; + block->in_icache = icache; LinkBlock(*block); } } -JitBlock*& JitBaseBlockCache::FastLookupEntryForAddress(u32 address) +size_t JitBaseBlockCache::FastLookupEntryForAddress(u32 address) { - return iCache[(address >> 2) & iCache_Mask]; + return (address >> 2) & iCache_Mask; } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index 8c3f141c90..d0bcd07bf2 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -74,6 +74,10 @@ struct JitBlock u64 ticStart; // for profiling - time. u64 ticStop; // for profiling - time. u64 ticCounter; // for profiling - time. + + // This tracks the position if this block within the icache. + // We allow each block to have one icache entry. + size_t in_icache; }; typedef void (*CompiledCode)(); @@ -163,7 +167,7 @@ private: void MoveBlockIntoFastCache(u32 em_address, u32 msr); // Fast but risky block lookup based on iCache. - JitBlock*& FastLookupEntryForAddress(u32 address); + 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.