#include "FEXCore/Utils/AllocatorHooks.h" #include "Interface/Context/Context.h" #include "Interface/Core/Dispatcher/Dispatcher.h" #include namespace FEXCore { namespace CPU { CPUBackend::CPUBackend(FEXCore::Core::InternalThreadState *ThreadState, size_t InitialCodeSize, size_t MaxCodeSize) : ThreadState(ThreadState), InitialCodeSize(InitialCodeSize), MaxCodeSize(MaxCodeSize) { #ifndef FEX_DISABLE_TELEMETRY auto &Common = ThreadState->CurrentFrame->Pointers.Common; // Fill in telemetry values for (size_t i = 0; i < FEXCore::Telemetry::TYPE_LAST; ++i) { auto &Telem = FEXCore::Telemetry::GetTelemetryValue(static_cast(i)); Common.TelemetryValueAddresses[i] = reinterpret_cast(Telem.GetAddr()); } #endif } CPUBackend::~CPUBackend() { for (auto CodeBuffer : CodeBuffers) { FreeCodeBuffer(CodeBuffer); } CodeBuffers.clear(); } auto CPUBackend::GetEmptyCodeBuffer() -> CodeBuffer * { if (ThreadState->CurrentFrame->SignalHandlerRefCounter == 0) { if (CodeBuffers.empty()) { auto NewCodeBuffer = AllocateNewCodeBuffer(InitialCodeSize); EmplaceNewCodeBuffer(NewCodeBuffer); } else { if (CodeBuffers.size() > 1) { // If we have more than one code buffer we are tracking then walk them and delete // This is a cleanup step for (size_t i = 1; i < CodeBuffers.size(); i++) { FreeCodeBuffer(CodeBuffers[i]); } CodeBuffers.resize(1); } // Set the current code buffer to the initial CurrentCodeBuffer = &CodeBuffers[0]; if (CurrentCodeBuffer->Size != MaxCodeSize) { FreeCodeBuffer(*CurrentCodeBuffer); // Resize the code buffer and reallocate our code size CurrentCodeBuffer->Size *= 1.5; CurrentCodeBuffer->Size = std::min(CurrentCodeBuffer->Size, MaxCodeSize); *CurrentCodeBuffer = AllocateNewCodeBuffer(CurrentCodeBuffer->Size); } } } 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); } return CurrentCodeBuffer; } auto CPUBackend::AllocateNewCodeBuffer(size_t Size) -> CodeBuffer { CodeBuffer Buffer; Buffer.Size = Size; Buffer.Ptr = static_cast( FEXCore::Allocator::VirtualAlloc(Buffer.Size, true)); LOGMAN_THROW_AA_FMT(!!Buffer.Ptr, "Couldn't allocate code buffer"); if (static_cast(ThreadState->CTX)->Config.GlobalJITNaming()) { static_cast(ThreadState->CTX)->Symbols.RegisterJITSpace(Buffer.Ptr, Buffer.Size); } return Buffer; } void CPUBackend::FreeCodeBuffer(CodeBuffer Buffer) { FEXCore::Allocator::VirtualFree(Buffer.Ptr, Buffer.Size); } bool CPUBackend::IsAddressInCodeBuffer(uintptr_t Address) const { for (auto &Buffer: CodeBuffers) { auto start = (uintptr_t)Buffer.Ptr; auto end = start + Buffer.Size; if (Address >= start && Address < end) { return true; } } return false; } } }