From a3f29411730619cfa1003264b4bb49bc019b73f4 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 8 Jun 2018 17:48:07 -0400 Subject: [PATCH 1/2] JitBase: Centralize location of code buffer Given the code buffer is something truly common to all JIT implementations, we can centralize it in the base class and avoid duplicating it all over the place, while still allowing for differently sized buffers. --- .../CachedInterpreter/CachedInterpreter.cpp | 8 +++----- .../PowerPC/CachedInterpreter/CachedInterpreter.h | 1 - Source/Core/Core/PowerPC/Jit64/Jit.cpp | 13 +++++++++---- Source/Core/Core/PowerPC/Jit64/Jit.h | 15 +++++++++------ Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 12 +++++++++--- Source/Core/Core/PowerPC/JitArm64/Jit.h | 7 +++---- Source/Core/Core/PowerPC/JitCommon/JitBase.cpp | 4 +++- Source/Core/Core/PowerPC/JitCommon/JitBase.h | 12 ++++++++---- 8 files changed, 44 insertions(+), 28 deletions(-) diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index f1c93cfcc2..a11bc851ca 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -48,9 +48,7 @@ struct CachedInterpreter::Instruction Type type = Type::Abort; }; -CachedInterpreter::CachedInterpreter() : code_buffer(32000) -{ -} +CachedInterpreter::CachedInterpreter() = default; CachedInterpreter::~CachedInterpreter() = default; @@ -194,7 +192,7 @@ void CachedInterpreter::Jit(u32 address) ClearCache(); } - const u32 nextPC = analyzer.Analyze(PC, &code_block, &code_buffer, code_buffer.size()); + const u32 nextPC = analyzer.Analyze(PC, &code_block, &m_code_buffer, m_code_buffer.size()); if (code_block.m_memory_exception) { // Address of instruction could not be translated @@ -218,7 +216,7 @@ void CachedInterpreter::Jit(u32 address) for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = code_buffer[i]; + PPCAnalyst::CodeOp& op = m_code_buffer[i]; js.downcountAmount += op.opinfo->numCycles; diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h index b7dbd5cfdd..2b9f41edd9 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.h @@ -42,5 +42,4 @@ private: BlockCache m_block_cache{*this}; std::vector m_code; - PPCAnalyst::CodeBuffer code_buffer; }; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 55b858498c..003edd684c 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -33,6 +33,7 @@ #include "Core/PowerPC/Jit64Common/TrampolineCache.h" #include "Core/PowerPC/JitInterface.h" #include "Core/PowerPC/MMU.h" +#include "Core/PowerPC/PPCAnalyst.h" #include "Core/PowerPC/PowerPC.h" #include "Core/PowerPC/Profiler.h" #if defined(_DEBUG) || defined(DEBUGFAST) @@ -145,6 +146,10 @@ enum GUARD_OFFSET = STACK_SIZE - SAFE_STACK_SIZE - GUARD_SIZE, }; +Jit64::Jit64() = default; + +Jit64::~Jit64() = default; + void Jit64::AllocStack() { #ifndef _WIN32 @@ -594,7 +599,7 @@ void Jit64::Jit(u32 em_address) ClearCache(); } - std::size_t block_size = code_buffer.size(); + std::size_t block_size = m_code_buffer.size(); if (SConfig::GetInstance().bEnableDebugging) { @@ -624,7 +629,7 @@ void Jit64::Jit(u32 em_address) // Analyze the block, collect all instructions it is made of (including inlining, // if that is enabled), reorder instructions for optimal performance, and join joinable // instructions. - const u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, block_size); + const u32 nextPC = analyzer.Analyze(em_address, &code_block, &m_code_buffer, block_size); if (code_block.m_memory_exception) { @@ -741,7 +746,7 @@ const u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) // Translate instructions for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = code_buffer[i]; + PPCAnalyst::CodeOp& op = m_code_buffer[i]; js.compilerPC = op.address; js.op = &op; @@ -950,7 +955,7 @@ const u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) b->originalSize = code_block.m_num_instructions; #ifdef JIT_LOG_X86 - LogGeneratedX86(code_block.m_num_instructions, code_buffer, start, b); + LogGeneratedX86(code_block.m_num_instructions, m_code_buffer, start, b); #endif return normalEntry; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index 1cf1726185..cf69cde143 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -27,13 +27,19 @@ #include "Core/PowerPC/Jit64/JitRegCache.h" #include "Core/PowerPC/Jit64Common/Jit64Base.h" #include "Core/PowerPC/JitCommon/JitCache.h" -#include "Core/PowerPC/PPCAnalyst.h" + +namespace PPCAnalyst +{ +struct CodeBlock; +struct CodeOp; +} class Jit64 : public Jitx86Base { public: - Jit64() : code_buffer(32000) {} - ~Jit64() {} + Jit64(); + ~Jit64() override; + void Init() override; void Shutdown() override; @@ -242,9 +248,6 @@ private: GPRRegCache gpr{*this}; FPURegCache fpr{*this}; - // The default code buffer. We keep it around to not have to alloc/dealloc a - // large chunk of memory for each recompiled block. - PPCAnalyst::CodeBuffer code_buffer; Jit64AsmRoutineManager asm_routines{*this}; bool m_enable_blr_optimization; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 96d8115854..6827d9a29c 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -36,6 +36,12 @@ constexpr size_t SAFE_STACK_SIZE = 512 * 1024; constexpr size_t GUARD_SIZE = 0x10000; // two guards - bottom (permanent) and middle (see above) constexpr size_t GUARD_OFFSET = STACK_SIZE - SAFE_STACK_SIZE - GUARD_SIZE; +JitArm64::JitArm64() : m_float_emit(this) +{ +} + +JitArm64::~JitArm64() = default; + void JitArm64::Init() { InitializeInstructionTables(); @@ -553,7 +559,7 @@ void JitArm64::Jit(u32) ClearCache(); } - std::size_t block_size = code_buffer.size(); + std::size_t block_size = m_code_buffer.size(); const u32 em_address = PowerPC::ppcState.pc; if (SConfig::GetInstance().bEnableDebugging) @@ -565,7 +571,7 @@ void JitArm64::Jit(u32) // Analyze the block, collect all instructions it is made of (including inlining, // if that is enabled), reorder instructions for optimal performance, and join joinable // instructions. - const u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, block_size); + const u32 nextPC = analyzer.Analyze(em_address, &code_block, &m_code_buffer, block_size); if (code_block.m_memory_exception) { @@ -651,7 +657,7 @@ void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) // Translate instructions for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = code_buffer[i]; + PPCAnalyst::CodeOp& op = m_code_buffer[i]; js.compilerPC = op.address; js.op = &op; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.h b/Source/Core/Core/PowerPC/JitArm64/Jit.h index eaceffb0e1..a9a982ded4 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -21,8 +21,9 @@ class JitArm64 : public JitBase, public Arm64Gen::ARM64CodeBlock, public CommonAsmRoutinesBase { public: - JitArm64() : code_buffer(32000), m_float_emit(this) {} - ~JitArm64() {} + JitArm64(); + ~JitArm64() override; + void Init() override; void Shutdown() override; @@ -245,8 +246,6 @@ private: JitArm64BlockCache blocks{*this}; - PPCAnalyst::CodeBuffer code_buffer; - Arm64Gen::ARM64FloatEmitter m_float_emit; Arm64Gen::ARM64CodeBlock farcode; diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp index 1680e618ff..606d0d3af0 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.cpp @@ -28,7 +28,9 @@ u32 Helper_Mask(u8 mb, u8 me) return mb > me ? ~mask : mask; } -JitBase::JitBase() = default; +JitBase::JitBase() : m_code_buffer(code_buffer_size) +{ +} JitBase::~JitBase() = default; diff --git a/Source/Core/Core/PowerPC/JitCommon/JitBase.h b/Source/Core/Core/PowerPC/JitCommon/JitBase.h index ac834090a3..2452df1d8b 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitBase.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitBase.h @@ -8,6 +8,7 @@ //#define JIT_LOG_GPR // Enables logging of the PPC general purpose regs //#define JIT_LOG_FPR // Enables logging of the PPC floating point regs +#include #include #include @@ -102,6 +103,7 @@ protected: }; PPCAnalyst::CodeBlock code_block; + PPCAnalyst::CodeBuffer m_code_buffer; PPCAnalyst::PPCAnalyzer analyzer; bool CanMergeNextInstructions(int count) const; @@ -109,10 +111,6 @@ protected: void UpdateMemoryOptions(); public: - // This should probably be removed from public: - JitOptions jo{}; - JitState js{}; - JitBase(); ~JitBase() override; @@ -125,6 +123,12 @@ public: virtual bool HandleFault(uintptr_t access_address, SContext* ctx) = 0; virtual bool HandleStackFault() { return false; } + + static constexpr std::size_t code_buffer_size = 32000; + + // This should probably be removed from public: + JitOptions jo{}; + JitState js{}; }; void JitTrampoline(JitBase& jit, u32 em_address); From e18824e3f38b868ce0eee090e2575b67eef9d610 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Sat, 9 Jun 2018 08:13:49 -0400 Subject: [PATCH 2/2] PPCAnalyst: get rid of code buffer size variable Rather than have a separate independent variable that we need to keep track of in conjunction with the JIT code buffer size itself, amend the analyst code to use the code buffer constant in JitBase. Now if the size ever changes, then the analyst will automatically adjust to handle it. --- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 3955f454b8..b65108f7a8 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -15,6 +15,7 @@ #include "Common/Logging/Log.h" #include "Common/StringUtil.h" #include "Core/ConfigManager.h" +#include "Core/PowerPC/JitCommon/JitBase.h" #include "Core/PowerPC/MMU.h" #include "Core/PowerPC/PPCSymbolDB.h" #include "Core/PowerPC/PPCTables.h" @@ -35,8 +36,6 @@ namespace PPCAnalyst { -constexpr int CODEBUFFER_SIZE = 32000; - // 0 does not perform block merging constexpr u32 BRANCH_FOLLOWING_THRESHOLD = 2; @@ -90,7 +89,7 @@ bool AnalyzeFunction(u32 startAddr, Common::Symbol& func, u32 max_size) for (u32 addr = startAddr; true; addr += 4) { func.size += 4; - if (func.size >= CODEBUFFER_SIZE * 4 || !PowerPC::HostIsInstructionRAMAddress(addr)) // weird + if (func.size >= JitBase::code_buffer_size * 4 || !PowerPC::HostIsInstructionRAMAddress(addr)) return false; if (max_size && func.size > max_size)