mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2024-11-14 21:37:52 -07:00
JitCache: Drop block_map.
It is only used for invalidation, and in a bad way. Just scan over all elements, as it is still in O(n), this shouldn't matter much.
This commit is contained in:
parent
98311cd9f4
commit
dc0fbc15f0
@ -36,6 +36,15 @@ static void ClearCacheThreadSafe(u64 userdata, s64 cyclesdata)
|
||||
JitInterface::ClearCache();
|
||||
}
|
||||
|
||||
bool JitBlock::Overlap(u32 addr, u32 length)
|
||||
{
|
||||
if (addr >= physicalAddress + originalSize)
|
||||
return false;
|
||||
if (physicalAddress >= addr + length)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit}
|
||||
{
|
||||
}
|
||||
@ -64,13 +73,12 @@ void JitBaseBlockCache::Clear()
|
||||
#endif
|
||||
m_jit.js.fifoWriteAddresses.clear();
|
||||
m_jit.js.pairedQuantizeAddresses.clear();
|
||||
for (auto& e : start_block_map)
|
||||
for (auto& e : block_map)
|
||||
{
|
||||
DestroyBlock(e.second);
|
||||
}
|
||||
start_block_map.clear();
|
||||
links_to.clear();
|
||||
block_map.clear();
|
||||
links_to.clear();
|
||||
|
||||
valid_block.ClearAll();
|
||||
|
||||
@ -95,14 +103,14 @@ JitBlock** JitBaseBlockCache::GetFastBlockMap()
|
||||
|
||||
void JitBaseBlockCache::RunOnBlocks(std::function<void(const JitBlock&)> f)
|
||||
{
|
||||
for (const auto& e : start_block_map)
|
||||
for (const auto& e : block_map)
|
||||
f(e.second);
|
||||
}
|
||||
|
||||
JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
||||
{
|
||||
u32 physicalAddress = PowerPC::JitCache_TranslateAddress(em_address).address;
|
||||
JitBlock& b = start_block_map.emplace(physicalAddress, JitBlock())->second;
|
||||
JitBlock& b = block_map.emplace(physicalAddress, JitBlock())->second;
|
||||
b.effectiveAddress = em_address;
|
||||
b.physicalAddress = physicalAddress;
|
||||
b.msrBits = MSR & JIT_CACHE_MSR_MASK;
|
||||
@ -111,18 +119,6 @@ JitBlock* JitBaseBlockCache::AllocateBlock(u32 em_address)
|
||||
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)
|
||||
iter.first = start_block_map.erase(iter.first);
|
||||
else
|
||||
iter.first++;
|
||||
}
|
||||
}
|
||||
|
||||
void JitBaseBlockCache::FinalizeBlock(JitBlock& block, bool block_link, const u8* code_ptr)
|
||||
{
|
||||
size_t index = FastLookupIndexForAddress(block.effectiveAddress);
|
||||
@ -134,8 +130,6 @@ 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.emplace(std::make_pair(pAddr + 4 * block.originalSize - 1, pAddr), &block);
|
||||
|
||||
if (block_link)
|
||||
{
|
||||
for (const auto& e : block.linkData)
|
||||
@ -162,7 +156,7 @@ JitBlock* JitBaseBlockCache::GetBlockFromStartAddress(u32 addr, u32 msr)
|
||||
translated_addr = translated.address;
|
||||
}
|
||||
|
||||
auto iter = start_block_map.equal_range(translated_addr);
|
||||
auto iter = block_map.equal_range(translated_addr);
|
||||
for (; iter.first != iter.second; iter.first++)
|
||||
{
|
||||
JitBlock& b = iter.first->second;
|
||||
@ -204,17 +198,20 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
|
||||
}
|
||||
|
||||
// destroy JIT blocks
|
||||
// !! this works correctly under assumption that any two overlapping blocks end at the same
|
||||
// address
|
||||
if (destroy_block)
|
||||
{
|
||||
auto it = block_map.lower_bound(std::make_pair(pAddr, 0));
|
||||
while (it != block_map.end() && it->first.second < pAddr + length)
|
||||
auto iter = block_map.begin();
|
||||
while (iter != block_map.end())
|
||||
{
|
||||
JitBlock* block = it->second;
|
||||
DestroyBlock(*block);
|
||||
FreeBlock(block);
|
||||
it = block_map.erase(it);
|
||||
if (iter->second.Overlap(pAddr, length))
|
||||
{
|
||||
DestroyBlock(iter->second);
|
||||
iter = block_map.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
// If the code was actually modified, we need to clear the relevant entries from the
|
||||
|
@ -24,6 +24,8 @@ class JitBase;
|
||||
// address.
|
||||
struct JitBlock
|
||||
{
|
||||
bool Overlap(u32 addr, u32 length);
|
||||
|
||||
// A special entry point for block linking; usually used to check the
|
||||
// downcount.
|
||||
const u8* checkedEntry;
|
||||
@ -35,8 +37,8 @@ struct JitBlock
|
||||
// The MSR bits expected for this block to be valid; see JIT_CACHE_MSR_MASK.
|
||||
u32 msrBits;
|
||||
// The physical address of the code represented by this block.
|
||||
// Various maps in the cache are indexed by this (start_block_map,
|
||||
// block_map, and valid_block in particular). This is useful because of
|
||||
// Various maps in the cache are indexed by this (block_map
|
||||
// and valid_block in particular). This is useful because of
|
||||
// of the way the instruction cache works on PowerPC.
|
||||
u32 physicalAddress;
|
||||
// The number of bytes of JIT'ed code contained in this block. Mostly
|
||||
@ -124,7 +126,6 @@ public:
|
||||
void RunOnBlocks(std::function<void(const JitBlock&)> 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.
|
||||
@ -163,20 +164,15 @@ private:
|
||||
// It is used to query all blocks which links to an address.
|
||||
std::multimap<u32, JitBlock*> links_to; // destination_PC -> number
|
||||
|
||||
// Map indexed by the physical memory location.
|
||||
// It is used to invalidate blocks based on memory location.
|
||||
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.
|
||||
std::multimap<u32, JitBlock> start_block_map; // start_addr -> block
|
||||
std::multimap<u32, JitBlock> 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.
|
||||
ValidBlockBitSet valid_block;
|
||||
|
||||
// This array is indexed with the masked PC and likely holds the correct block id.
|
||||
// This is used as a fast cache of start_block_map used in the assembly dispatcher.
|
||||
// This is used as a fast cache of block_map used in the assembly dispatcher.
|
||||
std::array<JitBlock*, FAST_BLOCK_MAP_ELEMENTS> fast_block_map; // start_addr & mask -> number
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user