mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2024-11-22 13:55:38 +00:00
CPU/CodeCache: Impove overflow handling
This commit is contained in:
parent
bdde3ce07b
commit
601e3586b2
|
@ -195,13 +195,13 @@ void LogCurrentState();
|
|||
static CodeBlockKey GetNextBlockKey();
|
||||
|
||||
/// Looks up the block in the cache if it's already been compiled.
|
||||
static CodeBlock* LookupBlock(CodeBlockKey key);
|
||||
static CodeBlock* LookupBlock(CodeBlockKey key, bool allow_flush);
|
||||
|
||||
/// Can the current block execute? This will re-validate the block if necessary.
|
||||
/// The block can also be flushed if recompilation failed, so ignore the pointer if false is returned.
|
||||
static bool RevalidateBlock(CodeBlock* block);
|
||||
static bool RevalidateBlock(CodeBlock* block, bool allow_flush);
|
||||
|
||||
static bool CompileBlock(CodeBlock* block);
|
||||
static bool CompileBlock(CodeBlock* block, bool allow_flush);
|
||||
static void RemoveReferencesToBlock(CodeBlock* block);
|
||||
static void AddBlockToPageMap(CodeBlock* block);
|
||||
static void RemoveBlockFromPageMap(CodeBlock* block);
|
||||
|
@ -310,7 +310,7 @@ static void ExecuteImpl()
|
|||
next_block_key = GetNextBlockKey();
|
||||
while (g_state.pending_ticks < g_state.downcount)
|
||||
{
|
||||
CodeBlock* block = LookupBlock(next_block_key);
|
||||
CodeBlock* block = LookupBlock(next_block_key, true);
|
||||
if (!block)
|
||||
{
|
||||
InterpretUncachedBlock<pgxp_mode>();
|
||||
|
@ -346,7 +346,7 @@ static void ExecuteImpl()
|
|||
{
|
||||
// we can jump straight to it if there's no pending interrupts
|
||||
// ensure it's not a self-modifying block
|
||||
if (!block->invalidated || RevalidateBlock(block))
|
||||
if (!block->invalidated || RevalidateBlock(block, true))
|
||||
goto reexecute_block;
|
||||
}
|
||||
else if (!block->invalidated)
|
||||
|
@ -358,7 +358,7 @@ static void ExecuteImpl()
|
|||
CodeBlock* linked_block = li.block;
|
||||
if (linked_block->key.bits == next_block_key.bits)
|
||||
{
|
||||
if (linked_block->invalidated && !RevalidateBlock(linked_block))
|
||||
if (linked_block->invalidated && !RevalidateBlock(linked_block, true))
|
||||
{
|
||||
// CanExecuteBlock can result in a block flush, so stop iterating here.
|
||||
break;
|
||||
|
@ -371,7 +371,7 @@ static void ExecuteImpl()
|
|||
}
|
||||
|
||||
// No acceptable blocks found in the successor list, try a new one.
|
||||
CodeBlock* next_block = LookupBlock(next_block_key);
|
||||
CodeBlock* next_block = LookupBlock(next_block_key, false);
|
||||
if (next_block)
|
||||
{
|
||||
// Link the previous block to this new block if we find a new block.
|
||||
|
@ -537,7 +537,7 @@ static void FallbackExistingBlockToInterpreter(CodeBlock* block)
|
|||
delete block;
|
||||
}
|
||||
|
||||
CodeBlock* LookupBlock(CodeBlockKey key)
|
||||
CodeBlock* LookupBlock(CodeBlockKey key, bool allow_flush)
|
||||
{
|
||||
BlockMap::iterator iter = s_blocks.find(key.bits);
|
||||
if (iter != s_blocks.end())
|
||||
|
@ -548,7 +548,7 @@ CodeBlock* LookupBlock(CodeBlockKey key)
|
|||
return existing_block;
|
||||
|
||||
// if compilation fails or we're forced back to the interpreter, bail out
|
||||
if (RevalidateBlock(existing_block))
|
||||
if (RevalidateBlock(existing_block, allow_flush))
|
||||
return existing_block;
|
||||
else
|
||||
return nullptr;
|
||||
|
@ -557,7 +557,7 @@ CodeBlock* LookupBlock(CodeBlockKey key)
|
|||
CodeBlock* block = new CodeBlock(key);
|
||||
block->recompile_frame_number = System::GetFrameNumber();
|
||||
|
||||
if (CompileBlock(block))
|
||||
if (CompileBlock(block, allow_flush))
|
||||
{
|
||||
// add it to the page map if it's in ram
|
||||
AddBlockToPageMap(block);
|
||||
|
@ -574,11 +574,13 @@ CodeBlock* LookupBlock(CodeBlockKey key)
|
|||
block = nullptr;
|
||||
}
|
||||
|
||||
if (block || allow_flush)
|
||||
s_blocks.emplace(key.bits, block);
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
bool RevalidateBlock(CodeBlock* block)
|
||||
bool RevalidateBlock(CodeBlock* block, bool allow_flush)
|
||||
{
|
||||
for (const CodeBlockInstruction& cbi : block->instructions)
|
||||
{
|
||||
|
@ -634,7 +636,7 @@ recompile:
|
|||
|
||||
block->instructions.clear();
|
||||
|
||||
if (!CompileBlock(block))
|
||||
if (!CompileBlock(block, allow_flush))
|
||||
{
|
||||
Log_PerfPrintf("Failed to recompile block 0x%08X, falling back to interpreter.", block->GetPC());
|
||||
FallbackExistingBlockToInterpreter(block);
|
||||
|
@ -657,7 +659,7 @@ recompile:
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CompileBlock(CodeBlock* block)
|
||||
bool CompileBlock(CodeBlock* block, bool allow_flush)
|
||||
{
|
||||
u32 pc = block->GetPC();
|
||||
bool is_branch_delay_slot = false;
|
||||
|
@ -776,10 +778,18 @@ bool CompileBlock(CodeBlock* block)
|
|||
(block->instructions.size() * Recompiler::MAX_NEAR_HOST_BYTES_PER_INSTRUCTION) ||
|
||||
s_code_buffer.GetFreeFarCodeSpace() <
|
||||
(block->instructions.size() * Recompiler::MAX_FAR_HOST_BYTES_PER_INSTRUCTION))
|
||||
{
|
||||
if (allow_flush)
|
||||
{
|
||||
Log_WarningPrintf("Out of code space, flushing all blocks.");
|
||||
Flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
Log_ErrorPrintf("Out of code space and cannot flush while compiling %08X.", block->GetPC());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
s_code_buffer.WriteProtect(false);
|
||||
Recompiler::CodeGenerator codegen(&s_code_buffer);
|
||||
|
@ -801,7 +811,7 @@ bool CompileBlock(CodeBlock* block)
|
|||
|
||||
void FastCompileBlockFunction()
|
||||
{
|
||||
CodeBlock* block = LookupBlock(GetNextBlockKey());
|
||||
CodeBlock* block = LookupBlock(GetNextBlockKey(), true);
|
||||
if (block)
|
||||
{
|
||||
s_single_block_asm_dispatcher(block->host_code);
|
||||
|
@ -1218,9 +1228,9 @@ void CPU::Recompiler::Thunks::ResolveBranch(CodeBlock* block, void* host_pc, voi
|
|||
using namespace CPU::CodeCache;
|
||||
|
||||
CodeBlockKey key = GetNextBlockKey();
|
||||
CodeBlock* successor_block = LookupBlock(key);
|
||||
if (!successor_block || (successor_block->invalidated && !RevalidateBlock(successor_block)) || !block->can_link ||
|
||||
!successor_block->can_link)
|
||||
CodeBlock* successor_block = LookupBlock(key, false);
|
||||
if (!successor_block || (successor_block->invalidated && !RevalidateBlock(successor_block, false)) ||
|
||||
!block->can_link || !successor_block->can_link)
|
||||
{
|
||||
// just turn it into a return to the dispatcher instead.
|
||||
s_code_buffer.WriteProtect(false);
|
||||
|
|
Loading…
Reference in a new issue