CPU/CodeCache: Fix possible crash on invalidate->recompile->overflow

This commit is contained in:
Connor McLaughlin 2020-12-31 01:48:43 +10:00
parent 9b73f0194c
commit 02377b1a92
1 changed files with 18 additions and 7 deletions

View File

@ -85,7 +85,7 @@ static CodeBlock* LookupBlock(CodeBlockKey key);
static bool RevalidateBlock(CodeBlock* block); static bool RevalidateBlock(CodeBlock* block);
static bool CompileBlock(CodeBlock* block); static bool CompileBlock(CodeBlock* block);
static void FlushBlock(CodeBlock* block); static void RemoveReferencesToBlock(CodeBlock* block);
static void AddBlockToPageMap(CodeBlock* block); static void AddBlockToPageMap(CodeBlock* block);
static void RemoveBlockFromPageMap(CodeBlock* block); static void RemoveBlockFromPageMap(CodeBlock* block);
@ -456,6 +456,11 @@ bool RevalidateBlock(CodeBlock* block)
return true; return true;
recompile: recompile:
// remove any references to the block from the lookup table.
// this is an edge case where compiling causes a flush-all due to no space,
// and we don't want to nuke the block we're compiling...
RemoveReferencesToBlock(block);
#ifdef WITH_RECOMPILER #ifdef WITH_RECOMPILER
RemoveBlockFromHostCodeMap(block); RemoveBlockFromHostCodeMap(block);
#endif #endif
@ -464,17 +469,20 @@ recompile:
if (!CompileBlock(block)) if (!CompileBlock(block))
{ {
Log_WarningPrintf("Failed to recompile block 0x%08X - flushing.", block->GetPC()); Log_WarningPrintf("Failed to recompile block 0x%08X - flushing.", block->GetPC());
FlushBlock(block); delete block;
return false; return false;
} }
#ifdef WITH_RECOMPILER
// re-add to page map again
AddBlockToHostCodeMap(block);
#endif
if (block->IsInRAM())
AddBlockToPageMap(block); AddBlockToPageMap(block);
#ifdef WITH_RECOMPILER
// re-add to page map again
SetFastMap(block->GetPC(), block->host_code);
AddBlockToHostCodeMap(block);
#endif
// re-insert into the block map since we removed it earlier.
s_blocks.emplace(block->key.bits, block);
return true; return true;
} }
@ -490,6 +498,11 @@ bool CompileBlock(CodeBlock* block)
__debugbreak(); __debugbreak();
#endif #endif
block->icache_line_count = 0;
block->uncached_fetch_ticks = 0;
block->contains_double_branches = false;
block->contains_loadstore_instructions = false;
u32 last_cache_line = ICACHE_LINES; u32 last_cache_line = ICACHE_LINES;
for (;;) for (;;)
@ -641,11 +654,10 @@ void InvalidateBlocksWithPageIndex(u32 page_index)
Bus::ClearRAMCodePage(page_index); Bus::ClearRAMCodePage(page_index);
} }
void FlushBlock(CodeBlock* block) void RemoveReferencesToBlock(CodeBlock* block)
{ {
BlockMap::iterator iter = s_blocks.find(block->key.GetPC()); BlockMap::iterator iter = s_blocks.find(block->key.GetPC());
Assert(iter != s_blocks.end() && iter->second == block); Assert(iter != s_blocks.end() && iter->second == block);
Log_DevPrintf("Flushing block at address 0x%08X", block->GetPC());
#ifdef WITH_RECOMPILER #ifdef WITH_RECOMPILER
SetFastMap(block->GetPC(), FastCompileBlockFunction); SetFastMap(block->GetPC(), FastCompileBlockFunction);
@ -662,7 +674,6 @@ void FlushBlock(CodeBlock* block)
#endif #endif
s_blocks.erase(iter); s_blocks.erase(iter);
delete block;
} }
void AddBlockToPageMap(CodeBlock* block) void AddBlockToPageMap(CodeBlock* block)