From 3a8a67025e56713a35b62c9e9dfdffedc7bfadf0 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 18 May 2018 16:14:31 -0400 Subject: [PATCH 1/2] PPCAnalyst: Make CodeBuffer an alias for std::vector This class effectively acted as a "discount vector", that would simply allocate memory and then delete it in the destructor when it goes out of scope. We can just use a std::vector directly to reduce this boilerplate. --- .../CachedInterpreter/CachedInterpreter.cpp | 5 ++-- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 11 ++++---- .../Core/PowerPC/Jit64Common/Jit64Base.cpp | 4 +-- .../Core/Core/PowerPC/Jit64Common/Jit64Base.h | 8 ++---- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 11 ++++---- Source/Core/Core/PowerPC/PPCAnalyst.cpp | 25 ++++++------------- Source/Core/Core/PowerPC/PPCAnalyst.h | 17 +++---------- Source/Core/DolphinQt2/Debugger/JITWidget.cpp | 4 +-- Source/Core/DolphinWX/Debugger/JitWindow.cpp | 4 +-- 9 files changed, 31 insertions(+), 58 deletions(-) diff --git a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp index d2da611cfb..f1c93cfcc2 100644 --- a/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp +++ b/Source/Core/Core/PowerPC/CachedInterpreter/CachedInterpreter.cpp @@ -194,7 +194,7 @@ void CachedInterpreter::Jit(u32 address) ClearCache(); } - u32 nextPC = analyzer.Analyze(PC, &code_block, &code_buffer, code_buffer.GetSize()); + const u32 nextPC = analyzer.Analyze(PC, &code_block, &code_buffer, code_buffer.size()); if (code_block.m_memory_exception) { // Address of instruction could not be translated @@ -216,10 +216,9 @@ void CachedInterpreter::Jit(u32 address) b->checkedEntry = GetCodePtr(); b->normalEntry = GetCodePtr(); - PPCAnalyst::CodeOp* const ops = code_buffer.codebuffer; for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = ops[i]; + PPCAnalyst::CodeOp& op = code_buffer[i]; js.downcountAmount += op.opinfo->numCycles; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 65387f9d3d..52d0adc361 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -594,7 +594,7 @@ void Jit64::Jit(u32 em_address) ClearCache(); } - int blockSize = code_buffer.GetSize(); + std::size_t block_size = code_buffer.size(); if (SConfig::GetInstance().bEnableDebugging) { @@ -607,7 +607,7 @@ void Jit64::Jit(u32 em_address) { if (CPU::IsStepping()) { - blockSize = 1; + block_size = 1; // Do not link this block to other blocks While single stepping jo.enableBlocklink = false; @@ -624,7 +624,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. - u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, blockSize); + const u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, block_size); if (code_block.m_memory_exception) { @@ -739,10 +739,9 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc } // Translate instructions - PPCAnalyst::CodeOp* const ops = code_buf->codebuffer; for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = ops[i]; + PPCAnalyst::CodeOp& op = (*code_buf)[i]; js.compilerPC = op.address; js.op = &op; @@ -951,7 +950,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc b->originalSize = code_block.m_num_instructions; #ifdef JIT_LOG_X86 - LogGeneratedX86(code_block.m_num_instructions, code_buf, start, b); + LogGeneratedX86(code_block.m_num_instructions, code_buffer, start, b); #endif return normalEntry; diff --git a/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.cpp b/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.cpp index 16137339cd..d5f59732be 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.cpp +++ b/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.cpp @@ -127,12 +127,12 @@ bool Jitx86Base::BackPatch(u32 emAddress, SContext* ctx) return true; } -void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer* code_buffer, const u8* normalEntry, +void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry, const JitBlock* b) { for (size_t i = 0; i < size; i++) { - const PPCAnalyst::CodeOp& op = code_buffer->codebuffer[i]; + const PPCAnalyst::CodeOp& op = code_buffer[i]; std::string temp = StringFromFormat( "%08x %s", op.address, GekkoDisassembler::Disassemble(op.inst.hex, op.address).c_str()); DEBUG_LOG(DYNA_REC, "IR_X86 PPC: %s\n", temp.c_str()); diff --git a/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.h b/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.h index 06de777807..10acfd6a86 100644 --- a/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.h +++ b/Source/Core/Core/PowerPC/Jit64Common/Jit64Base.h @@ -13,11 +13,7 @@ #include "Core/PowerPC/Jit64Common/Jit64AsmCommon.h" #include "Core/PowerPC/Jit64Common/TrampolineCache.h" #include "Core/PowerPC/JitCommon/JitBase.h" - -namespace PPCAnalyst -{ -class CodeBuffer; -} +#include "Core/PowerPC/PPCAnalyst.h" // RSCRATCH and RSCRATCH2 are always scratch registers and can be used without // limitation. @@ -46,5 +42,5 @@ public: bool HandleFault(uintptr_t access_address, SContext* ctx) override; }; -void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer* code_buffer, const u8* normalEntry, +void LogGeneratedX86(size_t size, const PPCAnalyst::CodeBuffer& code_buffer, const u8* normalEntry, const JitBlock* b); diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 2848c5aaf0..93a027c515 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -553,19 +553,19 @@ void JitArm64::Jit(u32) ClearCache(); } - int blockSize = code_buffer.GetSize(); - u32 em_address = PowerPC::ppcState.pc; + std::size_t block_size = code_buffer.size(); + const u32 em_address = PowerPC::ppcState.pc; if (SConfig::GetInstance().bEnableDebugging) { // Comment out the following to disable breakpoints (speed-up) - blockSize = 1; + block_size = 1; } // 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. - u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, blockSize); + const u32 nextPC = analyzer.Analyze(em_address, &code_block, &code_buffer, block_size); if (code_block.m_memory_exception) { @@ -649,10 +649,9 @@ void JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* fpr.Start(js.fpa); // Translate instructions - PPCAnalyst::CodeOp* const ops = code_buf->codebuffer; for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = ops[i]; + PPCAnalyst::CodeOp& op = (*code_buf)[i]; js.compilerPC = op.address; js.op = &op; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.cpp b/Source/Core/Core/PowerPC/PPCAnalyst.cpp index 372ea5a279..ccdf019cb1 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.cpp +++ b/Source/Core/Core/PowerPC/PPCAnalyst.cpp @@ -42,17 +42,6 @@ constexpr u32 BRANCH_FOLLOWING_THRESHOLD = 2; constexpr u32 INVALID_BRANCH_TARGET = 0xFFFFFFFF; -CodeBuffer::CodeBuffer(int size) -{ - codebuffer = new PPCAnalyst::CodeOp[size]; - size_ = size; -} - -CodeBuffer::~CodeBuffer() -{ - delete[] codebuffer; -} - static u32 EvaluateBranchTarget(UGeckoInstruction instr, u32 pc) { switch (instr.OPCD) @@ -653,7 +642,7 @@ void PPCAnalyzer::SetInstructionStats(CodeBlock* block, CodeOp* code, const Gekk } } -u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 blockSize) +u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, std::size_t block_size) { // Clear block stats memset(block->m_stats, 0, sizeof(BlockStats)); @@ -675,7 +664,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 block->m_gqr_used = BitSet8(0); block->m_physical_addresses.clear(); - CodeOp* code = buffer->codebuffer; + CodeOp* const code = buffer->data(); bool found_exit = false; bool found_call = false; @@ -683,7 +672,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 u32 numFollows = 0; u32 num_inst = 0; - for (u32 i = 0; i < blockSize; ++i) + for (std::size_t i = 0; i < block_size; ++i) { auto result = PowerPC::TryReadInstruction(address); if (!result.valid) @@ -707,7 +696,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 block->m_stats->numCycles += opinfo->numCycles; block->m_physical_addresses.insert(result.physical_address); - SetInstructionStats(block, &code[i], opinfo, i); + SetInstructionStats(block, &code[i], opinfo, static_cast(i)); bool follow = false; u32 destination = 0; @@ -720,7 +709,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 // cache clearning will happen many times. if (HasOption(OPTION_BRANCH_FOLLOW) && numFollows < BRANCH_FOLLOWING_THRESHOLD) { - if (inst.OPCD == 18 && blockSize > 1) + if (inst.OPCD == 18 && block_size > 1) { // Always follow BX instructions. // TODO: Loop unrolling might bloat the code size too much. @@ -734,7 +723,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 } } else if (inst.OPCD == 16 && (inst.BO & BO_DONT_DECREMENT_FLAG) && - (inst.BO & BO_DONT_CHECK_CONDITION) && blockSize > 1) + (inst.BO & BO_DONT_CHECK_CONDITION) && block_size > 1) { // Always follow unconditional BCX instructions, but they are very rare. follow = true; @@ -832,7 +821,7 @@ u32 PPCAnalyzer::Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 if (block->m_num_instructions > 1) ReorderInstructions(block->m_num_instructions, code); - if ((!found_exit && num_inst > 0) || blockSize == 1) + if ((!found_exit && num_inst > 0) || block_size == 1) { // We couldn't find an exit block->m_broken = true; diff --git a/Source/Core/Core/PowerPC/PPCAnalyst.h b/Source/Core/Core/PowerPC/PPCAnalyst.h index b9785eb27a..2200537354 100644 --- a/Source/Core/Core/PowerPC/PPCAnalyst.h +++ b/Source/Core/Core/PowerPC/PPCAnalyst.h @@ -5,7 +5,9 @@ #pragma once #include +#include #include +#include #include "Common/BitSet.h" #include "Common/CommonTypes.h" @@ -113,18 +115,7 @@ struct BlockRegStats } }; -class CodeBuffer -{ -public: - CodeBuffer(int size); - ~CodeBuffer(); - - int GetSize() const { return size_; } - PPCAnalyst::CodeOp* codebuffer; - -private: - int size_; -}; +using CodeBuffer = std::vector; struct CodeBlock { @@ -205,7 +196,7 @@ public: void SetOption(AnalystOption option) { m_options |= option; } void ClearOption(AnalystOption option) { m_options &= ~(option); } bool HasOption(AnalystOption option) const { return !!(m_options & option); } - u32 Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, u32 blockSize); + u32 Analyze(u32 address, CodeBlock* block, CodeBuffer* buffer, std::size_t block_size); private: enum class ReorderType diff --git a/Source/Core/DolphinQt2/Debugger/JITWidget.cpp b/Source/Core/DolphinQt2/Debugger/JITWidget.cpp index b0b4a772a5..476792b394 100644 --- a/Source/Core/DolphinQt2/Debugger/JITWidget.cpp +++ b/Source/Core/DolphinQt2/Debugger/JITWidget.cpp @@ -155,12 +155,12 @@ void JITWidget::Update() code_block.m_gpa = &gpa; code_block.m_fpa = &fpa; - if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, 32000) != 0xFFFFFFFF) + if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, code_buffer.size()) != 0xFFFFFFFF) { std::ostringstream ppc_disasm; for (u32 i = 0; i < code_block.m_num_instructions; i++) { - const PPCAnalyst::CodeOp& op = code_buffer.codebuffer[i]; + const PPCAnalyst::CodeOp& op = code_buffer[i]; std::string opcode = GekkoDisassembler::Disassemble(op.inst.hex, op.address); ppc_disasm << std::setfill('0') << std::setw(8) << std::hex << op.address; ppc_disasm << " " << opcode << std::endl; diff --git a/Source/Core/DolphinWX/Debugger/JitWindow.cpp b/Source/Core/DolphinWX/Debugger/JitWindow.cpp index bf2eab365c..47a70e3697 100644 --- a/Source/Core/DolphinWX/Debugger/JitWindow.cpp +++ b/Source/Core/DolphinWX/Debugger/JitWindow.cpp @@ -93,12 +93,12 @@ void CJitWindow::Compare(u32 em_address) code_block.m_gpa = &gpa; code_block.m_fpa = &fpa; - if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, 32000) != 0xFFFFFFFF) + if (analyzer.Analyze(ppc_addr, &code_block, &code_buffer, code_buffer.size()) != 0xFFFFFFFF) { std::ostringstream ppc_disasm; for (u32 i = 0; i < code_block.m_num_instructions; i++) { - const PPCAnalyst::CodeOp& op = code_buffer.codebuffer[i]; + const PPCAnalyst::CodeOp& op = code_buffer[i]; std::string opcode = GekkoDisassembler::Disassemble(op.inst.hex, op.address); ppc_disasm << std::setfill('0') << std::setw(8) << std::hex << op.address; ppc_disasm << " " << opcode << std::endl; From 9ad7d9ff87fc75416dc77abb0abb465faad9f9cb Mon Sep 17 00:00:00 2001 From: Lioncash Date: Fri, 18 May 2018 16:50:20 -0400 Subject: [PATCH 2/2] Jit64/JitArm64: Remove unnecessary code buffer parameter for DoJit() This function in both JITs is only ever called by passing the JIT's code buffer into it. Given this is already accessible, since the functions are part of the respective JIT class, we can just remove this parameter. This also cleans up accesses with the new code buffer, as we don't need to do janky looking dereference-then-index expressions. --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 6 +++--- Source/Core/Core/PowerPC/Jit64/Jit.h | 2 +- Source/Core/Core/PowerPC/JitArm64/Jit.cpp | 6 +++--- Source/Core/Core/PowerPC/JitArm64/Jit.h | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 52d0adc361..e6c3baf9cf 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -637,11 +637,11 @@ void Jit64::Jit(u32 em_address) } JitBlock* b = blocks.AllocateBlock(em_address); - DoJit(em_address, &code_buffer, b, nextPC); + DoJit(em_address, b, nextPC); blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses); } -const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) +const u8* Jit64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) { js.firstFPInstructionFound = false; js.isLastInstruction = false; @@ -741,7 +741,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBloc // Translate instructions for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = (*code_buf)[i]; + PPCAnalyst::CodeOp& op = code_buffer[i]; js.compilerPC = op.address; js.op = &op; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index ce8de7509b..1cf1726185 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -46,7 +46,7 @@ public: // Jit! void Jit(u32 em_address) override; - const u8* DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC); + const u8* DoJit(u32 em_address, JitBlock* b, u32 nextPC); BitSet32 CallerSavedRegistersInUse() const; BitSet8 ComputeStaticGQRs(const PPCAnalyst::CodeBlock&) const; diff --git a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp index 93a027c515..ab690b3cb3 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.cpp @@ -578,11 +578,11 @@ void JitArm64::Jit(u32) } JitBlock* b = blocks.AllocateBlock(em_address); - DoJit(em_address, &code_buffer, b, nextPC); + DoJit(em_address, b, nextPC); blocks.FinalizeBlock(*b, jo.enableBlocklink, code_block.m_physical_addresses); } -void JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC) +void JitArm64::DoJit(u32 em_address, JitBlock* b, u32 nextPC) { if (em_address == 0) { @@ -651,7 +651,7 @@ void JitArm64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* // Translate instructions for (u32 i = 0; i < code_block.m_num_instructions; i++) { - PPCAnalyst::CodeOp& op = (*code_buf)[i]; + PPCAnalyst::CodeOp& op = 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 b2fbf4d6fb..eaceffb0e1 100644 --- a/Source/Core/Core/PowerPC/JitArm64/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm64/Jit.h @@ -200,7 +200,7 @@ private: void SafeLoadToReg(u32 dest, s32 addr, s32 offsetReg, u32 flags, s32 offset, bool update); void SafeStoreFromReg(s32 dest, u32 value, s32 regOffset, u32 flags, s32 offset); - void DoJit(u32 em_address, PPCAnalyst::CodeBuffer* code_buf, JitBlock* b, u32 nextPC); + void DoJit(u32 em_address, JitBlock* b, u32 nextPC); void DoDownCount(); void Cleanup();