Merge pull request #5489 from unknownbrackets/jit-minor

Fix stack overflow on x64 with memchecks, darn it
This commit is contained in:
Henrik Rydgård 2014-02-17 07:23:45 +01:00
commit b894bd9b27
4 changed files with 58 additions and 21 deletions

View File

@ -47,8 +47,28 @@ void ThunkManager::Shutdown()
FreeCodeSpace();
}
int ThunkManager::ThunkStackOffset()
{
return 0;
}
int ThunkManager::ThunkBytesNeeded()
{
return 0;
}
const void *ThunkManager::ProtectFunction(const void *function, int num_params)
{
_dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash.");
return NULL;
}
void Enter(ThunkEmitter *emit)
{
_dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash.");
}
void Leave(ThunkEmitter *emit)
{
_dbg_assert_msg_(JIT, false, "Arm ThunkManager not implemented? Will crash.");
}

View File

@ -151,16 +151,11 @@ const void *ThunkManager::ProtectFunction(const void *function, int num_params)
PanicAlert("Trying to protect functions before the emu is started. Bad bad bad.");
const u8 *call_point = GetCodePtr();
// Make sure to align stack.
Enter(this);
#ifdef _M_X64
SUB(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded()));
ABI_CallFunction(save_regs);
ABI_CallFunction(function);
ABI_CallFunction(load_regs);
ADD(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded()));
RET();
#else
CALL((const void *)save_regs);
// Since parameters are in the previous stack frame, not in registers, this takes some
// trickery : we simply re-push the parameters. might not be optimal, but that doesn't really
// matter.
@ -172,10 +167,32 @@ const void *ThunkManager::ProtectFunction(const void *function, int num_params)
}
CALL(function);
ABI_RestoreStack(num_params * 4);
CALL((void*)load_regs);
RET();
#endif
Leave(this);
RET();
thunks[function] = call_point;
return (const void *)call_point;
}
void ThunkManager::Enter(ThunkEmitter *emit)
{
#ifdef _M_X64
// Make sure to align stack.
emit->SUB(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded()));
emit->ABI_CallFunction(save_regs);
#else
emit->CALL((const void *)save_regs);
#endif
}
void ThunkManager::Leave(ThunkEmitter *emit)
{
#ifdef _M_X64
emit->ABI_CallFunction(load_regs);
emit->ADD(64, R(ESP), Imm32(ThunkStackOffset() + ThunkBytesNeeded()));
#else
emit->CALL((void*)load_regs);
#endif
}

View File

@ -39,10 +39,14 @@
// NOT THREAD SAFE. This may only be used from the CPU thread.
// Any other thread using this stuff will be FATAL.
#if defined(ARM)
class ThunkManager : public ArmGen::ARMXCodeBlock
typedef ArmGen::ARMXEmitter ThunkEmitter;
typedef ArmGen::ARMXCodeBlock ThunkCodeBlock;
#else
class ThunkManager : public Gen::XCodeBlock
typedef Gen::XEmitter ThunkEmitter;
typedef Gen::XCodeBlock ThunkCodeBlock;
#endif
class ThunkManager : public ThunkCodeBlock
{
std::map<const void *, const u8 *> thunks;
@ -83,12 +87,8 @@ public:
return ProtectFunction((const void *)func, 4);
}
const u8 *GetSaveRegsFunction() const {
return save_regs;
}
const u8 *GetLoadRegsFunction() const {
return load_regs;
}
void Enter(ThunkEmitter *emit);
void Leave(ThunkEmitter *emit);
private:
void Init();

View File

@ -999,17 +999,17 @@ void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const OpArg
void Jit::CallProtectedFunction(const void *func, const u32 arg1, const u32 arg2, const u32 arg3)
{
// On x64, we need to save R8, which is caller saved.
ABI_CallFunction(thunks.GetSaveRegsFunction());
thunks.Enter(this);
ABI_CallFunctionCCC(func, arg1, arg2, arg3);
ABI_CallFunction(thunks.GetLoadRegsFunction());
thunks.Leave(this);
}
void Jit::CallProtectedFunction(const void *func, const OpArg &arg1, const u32 arg2, const u32 arg3)
{
// On x64, we need to save R8, which is caller saved.
ABI_CallFunction(thunks.GetSaveRegsFunction());
thunks.Enter(this);
ABI_CallFunctionACC(func, arg1, arg2, arg3);
ABI_CallFunction(thunks.GetLoadRegsFunction());
thunks.Leave(this);
}
void Jit::Comp_DoNothing(MIPSOpcode op) { }