Don't erase and rewrite the dispatcher when the cache is cleared. Fixes #9708

This commit is contained in:
Henrik Rydgård 2017-05-26 15:39:27 +02:00
parent be77ffd4e8
commit 0ec1e5e3b2
16 changed files with 41 additions and 36 deletions

View File

@ -302,7 +302,7 @@ const u8* ARM64XEmitter::AlignCode16()
{
int c = int((u64)m_code & 15);
if (c)
ReserveCodeSpace(16-c);
ReserveCodeSpace(16 - c);
return m_code;
}
@ -509,7 +509,7 @@ void ARM64XEmitter::EncodeTestBranchInst(u32 op, ARM64Reg Rt, u8 bits, const voi
distance >>= 2;
_assert_msg_(DYNA_REC, distance >= -0x3FFF && distance < 0x3FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
_assert_msg_(DYNA_REC, distance >= -0x1FFF && distance < 0x1FFF, "%s: Received too large distance: %llx", __FUNCTION__, distance);
Rt = DecodeReg(Rt);
Write32((b64Bit << 31) | (0x36 << 24) | (op << 24) | \
@ -3896,4 +3896,15 @@ void ARM64XEmitter::SUBSI2R(ARM64Reg Rd, ARM64Reg Rn, u64 imm, ARM64Reg scratch)
}
}
void ARM64CodeBlock::PoisonMemory(int offset) {
u32* ptr = (u32*)(region + offset);
u32* maxptr = (u32*)(region + region_size - offset);
// If our memory isn't a multiple of u32 then this won't write the last remaining bytes with anything
// Less than optimal, but there would be nothing we could do but throw a runtime warning anyway.
// AArch64: 0xD4200000 = BRK 0
while (ptr < maxptr)
*ptr++ = 0xD4200000;
FlushIcacheSection((u8 *)ptr, (u8 *)maxptr);
}
} // namespace

View File

@ -985,15 +985,6 @@ private:
class ARM64CodeBlock : public CodeBlock<ARM64XEmitter>
{
private:
void PoisonMemory() override
{
u32* ptr = (u32*)region;
u32* maxptr = (u32*)(region + region_size);
// If our memory isn't a multiple of u32 then this won't write the last remaining bytes with anything
// Less than optimal, but there would be nothing we could do but throw a runtime warning anyway.
// AArch64: 0xD4200000 = BRK 0
while (ptr < maxptr)
*ptr++ = 0xD4200000;
}
void PoisonMemory(int offset) override;
};
}

View File

@ -3211,10 +3211,10 @@ void ARMXEmitter::VCVTF16F32(ARMReg Dest, ARMReg Src) {
// Always clear code space with breakpoints, so that if someone accidentally executes
// uninitialized, it just breaks into the debugger.
void ARMXCodeBlock::PoisonMemory() {
void ARMXCodeBlock::PoisonMemory(int offset) {
// TODO: this isn't right for ARM!
memset(region, 0xCC, region_size);
ResetCodePtr();
memset(region + offset, 0xCC, region_size - offset);
ResetCodePtr(offset);
}
}

View File

@ -895,7 +895,7 @@ public:
class ARMXCodeBlock : public CodeBlock<ARMXEmitter> {
public:
void PoisonMemory() override;
void PoisonMemory(int offset) override;
};
// VFP Specific

View File

@ -42,7 +42,7 @@ template<class T> class CodeBlock : public CodeBlockCommon, public T, NonCopyabl
private:
// A privately used function to set the executable RAM space to something invalid.
// For debugging usefulness it should be used to set the RAM to a host specific breakpoint instruction
virtual void PoisonMemory() = 0;
virtual void PoisonMemory(int offset) = 0;
public:
CodeBlock() : writeStart_(nullptr) {}
@ -58,14 +58,13 @@ public:
// Always clear code space with breakpoints, so that if someone accidentally executes
// uninitialized, it just breaks into the debugger.
void ClearCodeSpace() {
void ClearCodeSpace(int offset) {
if (PlatformIsWXExclusive()) {
ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE);
} else {
ProtectMemoryPages(region, region_size, MEM_PROT_READ | MEM_PROT_WRITE | MEM_PROT_EXEC);
}
PoisonMemory();
ResetCodePtr();
// If not WX Exclusive, no need to call ProtectMemoryPages because we never change the protection from RWX.
PoisonMemory(offset);
ResetCodePtr(offset);
}
// BeginWrite/EndWrite assume that we keep appending.
@ -109,8 +108,8 @@ public:
return T::GetCodePointer();
}
void ResetCodePtr() {
T::SetCodePointer(region);
void ResetCodePtr(int offset) {
T::SetCodePointer(region + offset);
}
size_t GetSpaceLeft() const {

View File

@ -17,6 +17,8 @@
#include "ppsspp_config.h"
#include "base/logging.h"
#include "Common.h"
#include "MemoryUtil.h"
#include "StringUtils.h"

View File

@ -101,7 +101,7 @@ void ThunkManager::Init()
void ThunkManager::Reset()
{
thunks.clear();
ResetCodePtr();
ResetCodePtr(0);
}
void ThunkManager::Shutdown()

View File

@ -1980,9 +1980,9 @@ void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); }
void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); }
void XCodeBlock::PoisonMemory() {
void XCodeBlock::PoisonMemory(int offset) {
// x86/64: 0xCC = breakpoint
memset(region, 0xCC, region_size);
memset(region + offset, 0xCC, region_size - offset);
}
}

View File

@ -1061,7 +1061,7 @@ public:
class XCodeBlock : public CodeBlock<XEmitter> {
public:
void PoisonMemory() override;
void PoisonMemory(int offset) override;
};
} // namespace

View File

@ -152,7 +152,7 @@ void ArmJit::FlushPrefixV()
void ArmJit::ClearCache()
{
blocks.Clear();
ClearCodeSpace();
ClearCodeSpace(0);
GenerateFixedCode();
}

View File

@ -318,10 +318,11 @@ void Arm64Jit::GenerateFixedCode(const JitOptions &jo) {
}
}
// Don't forget to zap the instruction cache! This must stay at the end of this function.
FlushIcache();
// Let's spare the pre-generated code from unprotect-reprotect.
AlignCodePage();
jitStartOffset = (int)(GetCodePtr() - start);
// Don't forget to zap the instruction cache! This must stay at the end of this function.
FlushIcache();
EndWrite();
}

View File

@ -142,8 +142,7 @@ void Arm64Jit::FlushPrefixV() {
void Arm64Jit::ClearCache() {
ILOG("ARM64Jit: Clearing the cache!");
blocks.Clear();
ClearCodeSpace();
GenerateFixedCode(jo);
ClearCodeSpace(jitStartOffset);
}
void Arm64Jit::InvalidateCacheAt(u32 em_address, int length) {

View File

@ -280,6 +280,8 @@ public:
const u8 *applyRoundingMode;
const u8 *updateRoundingMode;
int jitStartOffset;
// Indexed by FPCR FZ:RN bits for convenience. Uses SCRATCH2.
const u8 *convertS0ToSCRATCH1[8];
};

View File

@ -219,7 +219,7 @@ void Jit::UpdateRoundingMode() {
void Jit::ClearCache()
{
blocks.Clear();
ClearCodeSpace();
ClearCodeSpace(0);
GenerateFixedCode(jo);
}

View File

@ -448,7 +448,7 @@ void JitSafeMemFuncs::Init(ThunkManager *thunks) {
}
void JitSafeMemFuncs::Shutdown() {
ResetCodePtr();
ResetCodePtr(0);
FreeCodeSpace();
}

View File

@ -1281,5 +1281,5 @@ VertexDecoderJitCache::VertexDecoderJitCache()
}
void VertexDecoderJitCache::Clear() {
ClearCodeSpace();
ClearCodeSpace(0);
}