JitCache: Extract ErasePhysicalRange as function.

This commit is contained in:
degasus 2017-01-23 20:32:27 +01:00
parent 70caf447b9
commit 7f6b8e3555
2 changed files with 49 additions and 42 deletions

View File

@ -36,9 +36,10 @@ static void ClearCacheThreadSafe(u64 userdata, s64 cyclesdata)
JitInterface::ClearCache(); JitInterface::ClearCache();
} }
bool JitBlock::Overlap(u32 addr, u32 length) bool JitBlock::OverlapsPhysicalRange(u32 address, u32 length) const
{ {
return physical_addresses.lower_bound(addr) != physical_addresses.lower_bound(addr + length); return physical_addresses.lower_bound(address) !=
physical_addresses.lower_bound(address + length);
} }
JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit} JitBaseBlockCache::JitBaseBlockCache(JitBase& jit) : m_jit{jit}
@ -182,7 +183,7 @@ const u8* JitBaseBlockCache::Dispatch()
return block->normalEntry; return block->normalEntry;
} }
void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool forced) void JitBaseBlockCache::InvalidateICache(u32 address, u32 length, bool forced)
{ {
auto translated = PowerPC::JitCache_TranslateAddress(address); auto translated = PowerPC::JitCache_TranslateAddress(address);
if (!translated.valid) if (!translated.valid)
@ -199,45 +200,10 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
valid_block.Clear(pAddr / 32); valid_block.Clear(pAddr / 32);
} }
// destroy JIT blocks
if (destroy_block) if (destroy_block)
{ {
// Iterate over all macro blocks which overlap the given range. // destroy JIT blocks
u32 range_mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1); ErasePhysicalRange(pAddr, length);
auto start = block_range_map.lower_bound(pAddr & range_mask);
auto end = block_range_map.lower_bound(pAddr + length);
while (start != end)
{
// Iterate over all blocks in the macro block.
auto iter = start->second.begin();
while (iter != start->second.end())
{
JitBlock* block = *iter;
if (block->Overlap(pAddr, length))
{
// If the block overlaps, also remove all other occupied slots in the other macro blocks.
// This will leak empty macro blocks, but they may be reused or cleared later on.
for (u32 addr : block->physical_addresses)
if ((addr & range_mask) != start->first)
block_range_map[addr & range_mask].erase(block);
// And remove the block.
DestroyBlock(*block);
block_map.erase(block->physicalAddress);
iter = start->second.erase(iter);
}
else
{
iter++;
}
}
// If the macro block is empty, drop it.
if (start->second.empty())
start = block_range_map.erase(start);
else
start++;
}
// If the code was actually modified, we need to clear the relevant entries from the // If the code was actually modified, we need to clear the relevant entries from the
// FIFO write address cache, so we don't end up with FIFO checks in places they shouldn't // FIFO write address cache, so we don't end up with FIFO checks in places they shouldn't
@ -254,6 +220,46 @@ void JitBaseBlockCache::InvalidateICache(u32 address, const u32 length, bool for
} }
} }
void JitBaseBlockCache::ErasePhysicalRange(u32 address, u32 length)
{
// Iterate over all macro blocks which overlap the given range.
u32 range_mask = ~(BLOCK_RANGE_MAP_ELEMENTS - 1);
auto start = block_range_map.lower_bound(address & range_mask);
auto end = block_range_map.lower_bound(address + length);
while (start != end)
{
// Iterate over all blocks in the macro block.
auto iter = start->second.begin();
while (iter != start->second.end())
{
JitBlock* block = *iter;
if (block->OverlapsPhysicalRange(address, length))
{
// If the block overlaps, also remove all other occupied slots in the other macro blocks.
// This will leak empty macro blocks, but they may be reused or cleared later on.
for (u32 addr : block->physical_addresses)
if ((addr & range_mask) != start->first)
block_range_map[addr & range_mask].erase(block);
// And remove the block.
DestroyBlock(*block);
block_map.erase(block->physicalAddress);
iter = start->second.erase(iter);
}
else
{
iter++;
}
}
// If the macro block is empty, drop it.
if (start->second.empty())
start = block_range_map.erase(start);
else
start++;
}
}
u32* JitBaseBlockCache::GetBlockBitSet() const u32* JitBaseBlockCache::GetBlockBitSet() const
{ {
return valid_block.m_valid_block.get(); return valid_block.m_valid_block.get();

View File

@ -25,7 +25,7 @@ class JitBase;
// address. // address.
struct JitBlock struct JitBlock
{ {
bool Overlap(u32 addr, u32 length); bool OverlapsPhysicalRange(u32 address, u32 length) const;
// A special entry point for block linking; usually used to check the // A special entry point for block linking; usually used to check the
// downcount. // downcount.
@ -143,7 +143,8 @@ public:
// assembly version.) // assembly version.)
const u8* Dispatch(); const u8* Dispatch();
void InvalidateICache(u32 address, const u32 length, bool forced); void InvalidateICache(u32 address, u32 length, bool forced);
void ErasePhysicalRange(u32 address, u32 length);
u32* GetBlockBitSet() const; u32* GetBlockBitSet() const;