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
|
// performance hit, it's not enabled by default, but it's useful for
|
||||||
// locating performance issues.
|
// locating performance issues.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -125,18 +126,7 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
||||||
|
|
||||||
void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr)
|
void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr)
|
||||||
{
|
{
|
||||||
if (start_block_map.count(block.physicalAddress))
|
start_block_map.emplace(block.physicalAddress, &block);
|
||||||
{
|
|
||||||
// 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] = █
|
|
||||||
size_t icache = FastLookupEntryForAddress(block.effectiveAddress);
|
size_t icache = FastLookupEntryForAddress(block.effectiveAddress);
|
||||||
iCache[icache] = █
|
iCache[icache] = █
|
||||||
block.in_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)
|
for (u32 addr = pAddr / 32; addr <= (pAddr + (block.originalSize - 1) * 4) / 32; ++addr)
|
||||||
valid_block.Set(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)
|
if (block_link)
|
||||||
{
|
{
|
||||||
|
@ -174,15 +164,15 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
||||||
translated_addr = translated.address;
|
translated_addr = translated.address;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto map_result = start_block_map.find(translated_addr);
|
auto iter = start_block_map.equal_range(translated_addr);
|
||||||
if (map_result == start_block_map.end())
|
for (; iter.first != iter.second; iter.first++)
|
||||||
return nullptr;
|
{
|
||||||
|
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 nullptr;
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const u8* JitBaseBlockCache::Dispatch()
|
const u8* JitBaseBlockCache::Dispatch()
|
||||||
|
@ -321,10 +311,18 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block, bool invalidate)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block.invalid = true;
|
block.invalid = true;
|
||||||
start_block_map.erase(block.physicalAddress);
|
|
||||||
if (iCache[block.in_icache] == &block)
|
if (iCache[block.in_icache] == &block)
|
||||||
iCache[block.in_icache] = nullptr;
|
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);
|
UnlinkBlock(block);
|
||||||
|
|
||||||
// Delete linking addresses
|
// Delete linking addresses
|
||||||
|
|
|
@ -177,12 +177,12 @@ private:
|
||||||
|
|
||||||
// Map indexed by the physical memory location.
|
// Map indexed by the physical memory location.
|
||||||
// It is used to invalidate blocks based on 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.
|
// 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.
|
// 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.
|
// TODO: This is redundant with block_map.
|
||||||
std::map<u32, JitBlock*> start_block_map; // start_addr -> block
|
std::multimap<u32, JitBlock*> start_block_map; // start_addr -> block
|
||||||
|
|
||||||
// This bitsets shows which cachelines overlap with any blocks.
|
// 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.
|
// It is used to provide a fast way to query if no icache invalidation is needed.
|
||||||
|
|
Loading…
Reference in New Issue