JitCache: Use a multimap for block_map and start_block_map.
We may have duplicated entries here because of MSR mismatch. Just store both and validate the matching one on cache access.
This commit is contained in:
parent
9d58127dec
commit
113d6b3b84
|
@ -9,6 +9,7 @@
|
|||
// performance hit, it's not enabled by default, but it's useful for
|
||||
// locating performance issues.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
|
@ -125,18 +126,7 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
|||
|
||||
void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr)
|
||||
{
|
||||
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", 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_b, true);
|
||||
}
|
||||
start_block_map[block.physicalAddress] = █
|
||||
start_block_map.emplace(block.physicalAddress, &block);
|
||||
size_t icache = FastLookupEntryForAddress(block.effectiveAddress);
|
||||
iCache[icache] = █
|
||||
block.in_icache = icache;
|
||||
|
@ -146,7 +136,7 @@ void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8
|
|||
for (u32 addr = pAddr / 32; addr <= (pAddr + (block.originalSize - 1) * 4) / 32; ++addr)
|
||||
valid_block.Set(addr);
|
||||
|
||||
block_map[std::make_pair(pAddr + 4 * block.originalSize - 1, pAddr)] = █
|
||||
block_map.emplace(std::make_pair(pAddr + 4 * block.originalSize - 1, pAddr), &block);
|
||||
|
||||
if (block_link)
|
||||
{
|
||||
|
@ -174,15 +164,15 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
|||
translated_addr = translated.address;
|
||||
}
|
||||
|
||||
auto map_result = start_block_map.find(translated_addr);
|
||||
if (map_result == start_block_map.end())
|
||||
return nullptr;
|
||||
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))
|
||||
return &b;
|
||||
}
|
||||
|
||||
JitBlock* b = map_result->second;
|
||||
if (b->invalid || b->effectiveAddress != addr ||
|
||||
b->msrBits != (msr & JIT_CACHE_MSR_MASK))
|
||||
return nullptr;
|
||||
return b;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const u8* JitBaseBlockCache::Dispatch()
|
||||
|
@ -321,10 +311,18 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate)
|
|||
return;
|
||||
}
|
||||
block.invalid = true;
|
||||
start_block_map.erase(block.physicalAddress);
|
||||
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
|
||||
|
|
|
@ -177,12 +177,12 @@ private:
|
|||
|
||||
// Map indexed by the physical memory location.
|
||||
// It is used to invalidate blocks based on memory location.
|
||||
std::map<std::pair<u32, u32>, JitBlock*> block_map; // (end_addr, start_addr) -> block
|
||||
std::multimap<std::pair<u32, u32>, 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<u32, JitBlock*> start_block_map; // start_addr -> block
|
||||
// TODO: This is redundant with block_map.
|
||||
std::multimap<u32, JitBlock*> 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.
|
||||
|
|
Loading…
Reference in New Issue