From ab51958b26c2d5bbc6d63b2423529fe6d082400a Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 2 Apr 2025 19:48:28 +0200 Subject: [PATCH] Move AllocateNewCodeBuffer from CPUBackend to a new CodeBufferManager interface --- FEXCore/Source/Interface/Context/Context.h | 2 +- FEXCore/Source/Interface/Core/CPUBackend.cpp | 34 ++++++++------------ FEXCore/Source/Interface/Core/CPUBackend.h | 15 ++++++--- FEXCore/Source/Interface/Core/JIT/JIT.cpp | 2 +- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/FEXCore/Source/Interface/Context/Context.h b/FEXCore/Source/Interface/Context/Context.h index 374aacd41..0e44d23c1 100644 --- a/FEXCore/Source/Interface/Context/Context.h +++ b/FEXCore/Source/Interface/Context/Context.h @@ -75,7 +75,7 @@ struct CustomIRResult { using BlockDelinkerFunc = void (*)(FEXCore::Core::CpuStateFrame* Frame, FEXCore::Context::ExitFunctionLinkData* Record); constexpr uint32_t TSC_SCALE_MAXIMUM = 1'000'000'000; ///< 1Ghz -class ContextImpl final : public FEXCore::Context::Context { +class ContextImpl final : public FEXCore::Context::Context, CPU::CodeBufferManager { public: // Context base class implementation. bool InitCore() override; diff --git a/FEXCore/Source/Interface/Core/CPUBackend.cpp b/FEXCore/Source/Interface/Core/CPUBackend.cpp index 7c4f83f3b..384c0aca2 100644 --- a/FEXCore/Source/Interface/Core/CPUBackend.cpp +++ b/FEXCore/Source/Interface/Core/CPUBackend.cpp @@ -309,42 +309,34 @@ namespace CPU { auto CPUBackend::GetEmptyCodeBuffer() -> CodeBuffer* { if (ThreadState->CurrentFrame->SignalHandlerRefCounter == 0) { if (CodeBuffers.empty()) { - auto NewCodeBuffer = AllocateNewCodeBuffer(InitialCodeSize); - EmplaceNewCodeBuffer(NewCodeBuffer); + EmplaceNewCodeBuffer(manager.AllocateNew(InitialCodeSize)); } else { // If we have more than one code buffer we are tracking then walk them and delete // This is a cleanup step CodeBuffers.resize(1); - // Set the current code buffer to the initial - CurrentCodeBuffer = CodeBuffers[0]; - - if (CurrentCodeBuffer->Size != MaxCodeSize) { - auto Size = CurrentCodeBuffer->Size; + if (CurrentCodeBufferSize != MaxCodeSize) { CodeBuffers.clear(); - CurrentCodeBuffer.reset(); // Resize the code buffer and reallocate our code size - Size *= 1.5; - Size = std::min(Size, MaxCodeSize); + CurrentCodeBufferSize *= 1.5; + CurrentCodeBufferSize = std::min(CurrentCodeBufferSize, MaxCodeSize); - CurrentCodeBuffer = AllocateNewCodeBuffer(Size); - EmplaceNewCodeBuffer(CurrentCodeBuffer); + EmplaceNewCodeBuffer(manager.AllocateNew(CurrentCodeBufferSize)); } } } else { // We have signal handlers that have generated code // This means that we can not safely clear the code at this point in time // Allocate some new code buffers that we can switch over to instead - auto NewCodeBuffer = AllocateNewCodeBuffer(InitialCodeSize); - EmplaceNewCodeBuffer(NewCodeBuffer); + EmplaceNewCodeBuffer(manager.AllocateNew(InitialCodeSize)); } - return CurrentCodeBuffer.get(); + return CodeBuffers.back().get(); } void CPUBackend::EmplaceNewCodeBuffer(fextl::shared_ptr Buffer) { - CurrentCodeBuffer = Buffer; + CurrentCodeBufferSize = Buffer->Size; CodeBuffers.emplace_back(Buffer); } @@ -362,10 +354,11 @@ namespace CPU { } CodeBuffer::~CodeBuffer() { + // TODO: Assert that mutex is held? FEXCore::Allocator::VirtualFree(Ptr, Size); } - auto CPUBackend::AllocateNewCodeBuffer(size_t Size) -> fextl::shared_ptr { + auto CodeBufferManager::AllocateNew(size_t Size) -> fextl::shared_ptr { #ifndef _WIN32 // MDWE (Memory-Deny-Write-Execute) is a new Linux 6.3 feature. // It's equivalent to systemd's `MemoryDenyWriteExecute` but implemented entirely in the kernel. @@ -393,9 +386,10 @@ namespace CPU { auto Buffer = fextl::make_shared(Size); - if (static_cast(ThreadState->CTX)->Config.GlobalJITNaming()) { - static_cast(ThreadState->CTX)->Symbols.RegisterJITSpace(Buffer->Ptr, Buffer->Size); - } + // TODO: Re-enable + // if (static_cast(ThreadState->CTX)->Config.GlobalJITNaming()) { + // static_cast(ThreadState->CTX)->Symbols.RegisterJITSpace(Buffer.Ptr, Buffer.Size); + // } return Buffer; } diff --git a/FEXCore/Source/Interface/Core/CPUBackend.h b/FEXCore/Source/Interface/Core/CPUBackend.h index 96cad330b..c434d3240 100644 --- a/FEXCore/Source/Interface/Core/CPUBackend.h +++ b/FEXCore/Source/Interface/Core/CPUBackend.h @@ -46,6 +46,11 @@ namespace CPU { ~CodeBuffer(); }; + class CodeBufferManager { + public: + fextl::shared_ptr AllocateNew(size_t Size); + }; + class CPUBackend { public: @@ -53,7 +58,7 @@ namespace CPU { * @param InitialCodeSize - Initial size for the code buffers * @param MaxCodeSize - Max size for the code buffers */ - CPUBackend(FEXCore::Core::InternalThreadState* ThreadState, size_t InitialCodeSize, size_t MaxCodeSize); + CPUBackend(FEXCore::Core::InternalThreadState*, size_t InitialCodeSize, size_t MaxCodeSize); virtual ~CPUBackend(); @@ -163,12 +168,12 @@ namespace CPU { [[nodiscard]] CodeBuffer* GetEmptyCodeBuffer(); - // This is the current code buffer that we are tracking - std::shared_ptr CurrentCodeBuffer; + // This is the size of the last code buffer we allocated + size_t CurrentCodeBufferSize = 0; + + CodeBufferManager manager; // TODO: Rename private: - fextl::shared_ptr AllocateNewCodeBuffer(size_t Size); - void EmplaceNewCodeBuffer(fextl::shared_ptr Buffer); // This is the array of code buffers. Unless signals force us to keep more than diff --git a/FEXCore/Source/Interface/Core/JIT/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/JIT.cpp index aa2513ecb..7d3e4e59f 100644 --- a/FEXCore/Source/Interface/Core/JIT/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/JIT.cpp @@ -693,7 +693,7 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry, uint64_t Size // Fairly excessive buffer range to make sure we don't overflow uint32_t BufferRange = SSACount * 16; - if ((GetCursorOffset() + BufferRange) > (CurrentCodeBuffer->Size - Utils::FEX_PAGE_SIZE)) { + if ((GetCursorOffset() + BufferRange) > (CurrentCodeBufferSize - Utils::FEX_PAGE_SIZE)) { CTX->ClearCodeCache(ThreadState); }