JitCache: Split off JIT call from dispatcher.
This avoid flushing the BLR optimization stack on fast_block_cache misses.
This commit is contained in:
parent
eed64bb0fe
commit
d3aee2de08
|
@ -36,6 +36,12 @@ void CachedInterpreter::Shutdown()
|
||||||
void CachedInterpreter::ExecuteOneBlock()
|
void CachedInterpreter::ExecuteOneBlock()
|
||||||
{
|
{
|
||||||
const u8* normal_entry = m_block_cache.Dispatch();
|
const u8* normal_entry = m_block_cache.Dispatch();
|
||||||
|
if (!normal_entry)
|
||||||
|
{
|
||||||
|
Jit(PC);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
|
const Instruction* code = reinterpret_cast<const Instruction*>(normal_entry);
|
||||||
|
|
||||||
for (; code->type != Instruction::INSTRUCTION_ABORT; ++code)
|
for (; code->type != Instruction::INSTRUCTION_ABORT; ++code)
|
||||||
|
|
|
@ -140,17 +140,14 @@ void Jit64AsmRoutineManager::Generate()
|
||||||
// Failure, fallback to the C++ dispatcher for calling the JIT.
|
// Failure, fallback to the C++ dispatcher for calling the JIT.
|
||||||
}
|
}
|
||||||
|
|
||||||
// We reset the stack because Jit might clear the code cache.
|
|
||||||
// Also if we are in the middle of disabling BLR optimization on windows
|
|
||||||
// we need to reset the stack before _resetstkoflw() is called in Jit
|
|
||||||
// otherwise we will generate a second stack overflow exception during DoJit()
|
|
||||||
ResetStack(*this);
|
|
||||||
|
|
||||||
// Ok, no block, let's call the slow dispatcher
|
// Ok, no block, let's call the slow dispatcher
|
||||||
ABI_PushRegistersAndAdjustStack({}, 0);
|
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||||
ABI_CallFunction(JitBase::Dispatch);
|
ABI_CallFunction(JitBase::Dispatch);
|
||||||
ABI_PopRegistersAndAdjustStack({}, 0);
|
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||||
|
|
||||||
|
TEST(64, R(ABI_RETURN), R(ABI_RETURN));
|
||||||
|
FixupBranch no_block_available = J_CC(CC_Z);
|
||||||
|
|
||||||
// Switch to the correct memory base, in case MSR.DR has changed.
|
// Switch to the correct memory base, in case MSR.DR has changed.
|
||||||
TEST(32, PPCSTATE(msr), Imm32(1 << (31 - 27)));
|
TEST(32, PPCSTATE(msr), Imm32(1 << (31 - 27)));
|
||||||
FixupBranch physmem = J_CC(CC_Z);
|
FixupBranch physmem = J_CC(CC_Z);
|
||||||
|
@ -160,6 +157,21 @@ void Jit64AsmRoutineManager::Generate()
|
||||||
MOV(64, R(RMEM), ImmPtr(Memory::physical_base));
|
MOV(64, R(RMEM), ImmPtr(Memory::physical_base));
|
||||||
JMPptr(R(ABI_RETURN));
|
JMPptr(R(ABI_RETURN));
|
||||||
|
|
||||||
|
SetJumpTarget(no_block_available);
|
||||||
|
|
||||||
|
// We reset the stack because Jit might clear the code cache.
|
||||||
|
// Also if we are in the middle of disabling BLR optimization on windows
|
||||||
|
// we need to reset the stack before _resetstkoflw() is called in Jit
|
||||||
|
// otherwise we will generate a second stack overflow exception during DoJit()
|
||||||
|
ResetStack(*this);
|
||||||
|
|
||||||
|
ABI_PushRegistersAndAdjustStack({}, 0);
|
||||||
|
MOV(32, R(ABI_PARAM1), PPCSTATE(pc));
|
||||||
|
ABI_CallFunction(JitTrampoline);
|
||||||
|
ABI_PopRegistersAndAdjustStack({}, 0);
|
||||||
|
|
||||||
|
JMP(dispatcherNoCheck, true);
|
||||||
|
|
||||||
SetJumpTarget(bail);
|
SetJumpTarget(bail);
|
||||||
doTiming = GetCodePtr();
|
doTiming = GetCodePtr();
|
||||||
|
|
||||||
|
|
|
@ -106,18 +106,25 @@ void JitArm64::GenerateAsm()
|
||||||
MOVP2R(X30, reinterpret_cast<void*>(&JitBase::Dispatch));
|
MOVP2R(X30, reinterpret_cast<void*>(&JitBase::Dispatch));
|
||||||
BLR(X30);
|
BLR(X30);
|
||||||
|
|
||||||
// set the mem_base based on MSR flags
|
FixupBranch no_block_available = CBZ(X0);
|
||||||
|
|
||||||
|
// set the mem_base based on MSR flags and jump to next block.
|
||||||
LDR(INDEX_UNSIGNED, ARM64Reg::W28, PPC_REG, PPCSTATE_OFF(msr));
|
LDR(INDEX_UNSIGNED, ARM64Reg::W28, PPC_REG, PPCSTATE_OFF(msr));
|
||||||
FixupBranch physmem = TBNZ(ARM64Reg::W28, 31 - 27);
|
FixupBranch physmem = TBNZ(ARM64Reg::W28, 31 - 27);
|
||||||
MOVP2R(MEM_REG, Memory::physical_base);
|
MOVP2R(MEM_REG, Memory::physical_base);
|
||||||
FixupBranch membaseend = B();
|
BR(X0);
|
||||||
SetJumpTarget(physmem);
|
SetJumpTarget(physmem);
|
||||||
MOVP2R(MEM_REG, Memory::logical_base);
|
MOVP2R(MEM_REG, Memory::logical_base);
|
||||||
SetJumpTarget(membaseend);
|
|
||||||
|
|
||||||
// Jump to next block.
|
|
||||||
BR(X0);
|
BR(X0);
|
||||||
|
|
||||||
|
// Call JIT
|
||||||
|
SetJumpTarget(no_block_available);
|
||||||
|
MOV(W0, DISPATCHER_PC);
|
||||||
|
MOVP2R(X30, reinterpret_cast<void*>(&JitTrampoline));
|
||||||
|
BLR(X30);
|
||||||
|
LDR(INDEX_UNSIGNED, DISPATCHER_PC, PPC_REG, PPCSTATE_OFF(pc));
|
||||||
|
B(dispatcherNoCheck);
|
||||||
|
|
||||||
SetJumpTarget(bail);
|
SetJumpTarget(bail);
|
||||||
doTiming = GetCodePtr();
|
doTiming = GetCodePtr();
|
||||||
// Write the current PC out to PPCSTATE
|
// Write the current PC out to PPCSTATE
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
|
|
||||||
JitBase* g_jit;
|
JitBase* g_jit;
|
||||||
|
|
||||||
void Jit(u32 em_address)
|
void JitTrampoline(u32 em_address)
|
||||||
{
|
{
|
||||||
g_jit->Jit(em_address);
|
g_jit->Jit(em_address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,7 +125,7 @@ public:
|
||||||
virtual bool HandleStackFault() { return false; }
|
virtual bool HandleStackFault() { return false; }
|
||||||
};
|
};
|
||||||
|
|
||||||
void Jit(u32 em_address);
|
void JitTrampoline(u32 em_address);
|
||||||
|
|
||||||
// Merged routines that should be moved somewhere better
|
// Merged routines that should be moved somewhere better
|
||||||
u32 Helper_Mask(u8 mb, u8 me);
|
u32 Helper_Mask(u8 mb, u8 me);
|
||||||
|
|
|
@ -174,11 +174,11 @@ const u8* JitBaseBlockCache::Dispatch()
|
||||||
{
|
{
|
||||||
JitBlock* block = fast_block_map[FastLookupIndexForAddress(PC)];
|
JitBlock* block = fast_block_map[FastLookupIndexForAddress(PC)];
|
||||||
|
|
||||||
while (!block || block->effectiveAddress != PC || block->msrBits != (MSR & JIT_CACHE_MSR_MASK))
|
if (!block || block->effectiveAddress != PC || block->msrBits != (MSR & JIT_CACHE_MSR_MASK))
|
||||||
{
|
block = MoveBlockIntoFastCache(PC, MSR & JIT_CACHE_MSR_MASK);
|
||||||
MoveBlockIntoFastCache(PC, MSR & JIT_CACHE_MSR_MASK);
|
|
||||||
block = fast_block_map[FastLookupIndexForAddress(PC)];
|
if (!block)
|
||||||
}
|
return nullptr;
|
||||||
|
|
||||||
return block->normalEntry;
|
return block->normalEntry;
|
||||||
}
|
}
|
||||||
|
@ -349,25 +349,23 @@ void JitBaseBlockCache::DestroyBlock(JitBlock& block)
|
||||||
WriteDestroyBlock(block);
|
WriteDestroyBlock(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr)
|
JitBlock* JitBaseBlockCache::MoveBlockIntoFastCache(u32 addr, u32 msr)
|
||||||
{
|
{
|
||||||
JitBlock* block = GetBlockFromStartAddress(addr, msr);
|
JitBlock* block = GetBlockFromStartAddress(addr, msr);
|
||||||
if (!block)
|
|
||||||
{
|
|
||||||
Jit(addr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Drop old fast block map entry
|
|
||||||
if (fast_block_map[block->fast_block_map_index] == block)
|
|
||||||
fast_block_map[block->fast_block_map_index] = nullptr;
|
|
||||||
|
|
||||||
// And create a new one
|
if (!block)
|
||||||
size_t index = FastLookupIndexForAddress(addr);
|
return nullptr;
|
||||||
fast_block_map[index] = block;
|
|
||||||
block->fast_block_map_index = index;
|
// Drop old fast block map entry
|
||||||
LinkBlock(*block);
|
if (fast_block_map[block->fast_block_map_index] == block)
|
||||||
}
|
fast_block_map[block->fast_block_map_index] = nullptr;
|
||||||
|
|
||||||
|
// And create a new one
|
||||||
|
size_t index = FastLookupIndexForAddress(addr);
|
||||||
|
fast_block_map[index] = block;
|
||||||
|
block->fast_block_map_index = index;
|
||||||
|
|
||||||
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t JitBaseBlockCache::FastLookupIndexForAddress(u32 address)
|
size_t JitBaseBlockCache::FastLookupIndexForAddress(u32 address)
|
||||||
|
|
|
@ -161,7 +161,7 @@ private:
|
||||||
void UnlinkBlock(const JitBlock& block);
|
void UnlinkBlock(const JitBlock& block);
|
||||||
void DestroyBlock(JitBlock& block);
|
void DestroyBlock(JitBlock& block);
|
||||||
|
|
||||||
void MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
JitBlock* MoveBlockIntoFastCache(u32 em_address, u32 msr);
|
||||||
|
|
||||||
// Fast but risky block lookup based on fast_block_map.
|
// Fast but risky block lookup based on fast_block_map.
|
||||||
size_t FastLookupIndexForAddress(u32 address);
|
size_t FastLookupIndexForAddress(u32 address);
|
||||||
|
|
Loading…
Reference in New Issue