From fda087e24f8090ccf46837abe33c40525f72e0de Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 20 Feb 2026 17:59:16 +0100 Subject: [PATCH] FEXCore: Add helper function to query available CodeBuffer size --- FEXCore/Source/Interface/Core/CPUBackend.cpp | 8 ++++---- FEXCore/Source/Interface/Core/CPUBackend.h | 7 ++++++- FEXCore/Source/Interface/Core/CodeCache.cpp | 9 +++++---- FEXCore/Source/Interface/Core/Core.cpp | 2 +- FEXCore/Source/Interface/Core/JIT/JIT.cpp | 6 +++--- 5 files changed, 19 insertions(+), 13 deletions(-) diff --git a/FEXCore/Source/Interface/Core/CPUBackend.cpp b/FEXCore/Source/Interface/Core/CPUBackend.cpp index 8450860a6..8a964dc3e 100644 --- a/FEXCore/Source/Interface/Core/CPUBackend.cpp +++ b/FEXCore/Source/Interface/Core/CPUBackend.cpp @@ -349,7 +349,7 @@ namespace CPU { } CodeBuffer::CodeBuffer(size_t Size) - : Size(Size) { + : AllocatedSize(Size) { Ptr = static_cast(FEXCore::Allocator::VirtualAlloc(Size, true)); LOGMAN_THROW_A_FMT(!!Ptr, "Couldn't allocate code buffer"); @@ -366,7 +366,7 @@ namespace CPU { } CodeBuffer::~CodeBuffer() { - FEXCore::Allocator::VirtualFree(Ptr, Size); + FEXCore::Allocator::VirtualFree(Ptr, AllocatedSize); } auto CodeBufferManager::AllocateNew(size_t Size) -> fextl::shared_ptr { @@ -418,7 +418,7 @@ namespace CPU { return GetLatest(); } - auto NewCodeBufferSize = GetLatest()->Size; + auto NewCodeBufferSize = GetLatest()->AllocatedSize; NewCodeBufferSize = std::min(NewCodeBufferSize * 2, MAX_CODE_SIZE); return AllocateNew(NewCodeBufferSize); } @@ -428,7 +428,7 @@ namespace CPU { auto CheckCodeBuffer = [](CodeBuffer& Buffer, uintptr_t Address) { // The last page of the code buffer is protected, so we need to exclude it from the valid range // when checking if the address is in the code buffer. - uintptr_t LastPageAddr = AlignDown(reinterpret_cast(Buffer.Ptr) + Buffer.Size - 1, FEXCore::Utils::FEX_PAGE_SIZE); + uintptr_t LastPageAddr = AlignDown(reinterpret_cast(Buffer.Ptr) + Buffer.AllocatedSize - 1, FEXCore::Utils::FEX_PAGE_SIZE); return (Address >= reinterpret_cast(Buffer.Ptr) && Address < LastPageAddr); }; diff --git a/FEXCore/Source/Interface/Core/CPUBackend.h b/FEXCore/Source/Interface/Core/CPUBackend.h index b8963ebc6..5efe37dfc 100644 --- a/FEXCore/Source/Interface/Core/CPUBackend.h +++ b/FEXCore/Source/Interface/Core/CPUBackend.h @@ -43,7 +43,7 @@ struct GuestToHostMap; namespace CPU { struct CodeBuffer { uint8_t* Ptr; - size_t Size; + size_t AllocatedSize; // including guard page; see UsableSize() fextl::unique_ptr LookupCache; @@ -54,6 +54,11 @@ namespace CPU { CodeBuffer& operator=(CodeBuffer&&) = delete; ~CodeBuffer(); + + /// Returns the number of bytes available for storing code + size_t UsableSize() const { + return AllocatedSize - FEXCore::Utils::FEX_PAGE_SIZE; + } }; /** diff --git a/FEXCore/Source/Interface/Core/CodeCache.cpp b/FEXCore/Source/Interface/Core/CodeCache.cpp index f262cc3e1..53b4054a8 100644 --- a/FEXCore/Source/Interface/Core/CodeCache.cpp +++ b/FEXCore/Source/Interface/Core/CodeCache.cpp @@ -433,11 +433,11 @@ bool CodeCache::LoadData(Core::InternalThreadState* Thread, std::byte* MappedCac const auto Delta = AlignUp(CTX.LatestOffset, 0x1000) - CTX.LatestOffset; CTX.LatestOffset += Delta; - while (CTX.LatestOffset + header.CodeBufferSize > CodeBuffer->Size - Utils::FEX_PAGE_SIZE) { + while (CTX.LatestOffset + header.CodeBufferSize > CodeBuffer->UsableSize()) { if (Thread) { CTX.ClearCodeCache(Thread); CodeBuffer = CTX.GetLatest(); - LogMan::Msg::IFmt("Increased code buffer size to {} MiB for cache load", CodeBuffer->Size / 1024 / 1024); + LogMan::Msg::IFmt("Increased code buffer size to {} MiB for cache load", CodeBuffer->AllocatedSize / 1024 / 1024); } else { ERROR_AND_DIE_FMT("Cannot extend codebuffer without thread!"); } @@ -445,7 +445,8 @@ bool CodeCache::LoadData(Core::InternalThreadState* Thread, std::byte* MappedCac // Read CodeBuffer data from file. Make sure the destination is page-aligned. // TODO: Only load the data needed for the selected section - auto CodeBufferRange = std::as_writable_bytes(std::span {CodeBuffer->Ptr, CodeBuffer->Size}).subspan(CTX.LatestOffset, header.CodeBufferSize); + auto CodeBufferRange = + std::as_writable_bytes(std::span {CodeBuffer->Ptr, CodeBuffer->UsableSize()}).subspan(CTX.LatestOffset, header.CodeBufferSize); ::memcpy(CodeBufferRange.data(), MappedCacheFile, header.CodeBufferSize); MappedCacheFile += header.CodeBufferSize; CTX.LatestOffset += header.CodeBufferSize; @@ -540,7 +541,7 @@ void CodeCache::Validate(const ExecutableFileSectionInfo& Section, fextl::setGetLatest(); std::span CodeBufferRangeRef = - std::as_writable_bytes(std::span {NewCodeBuffer->Ptr, NewCodeBuffer->Ptr + NewCodeBuffer->Size}).subspan(0, CachedCode.size_bytes()); + std::as_writable_bytes(std::span {NewCodeBuffer->Ptr, NewCodeBuffer->Ptr + NewCodeBuffer->UsableSize()}).subspan(0, CachedCode.size_bytes()); while (!GuestBlocks.empty()) { auto [CompiledBlocks, _, _2, _3, _4] = ValidationCTX->CompileCode(ValidationThread.get(), *GuestBlocks.begin(), 0 /* TODO: Set MaxInst? */); diff --git a/FEXCore/Source/Interface/Core/Core.cpp b/FEXCore/Source/Interface/Core/Core.cpp index 9aaa7595e..379abc616 100644 --- a/FEXCore/Source/Interface/Core/Core.cpp +++ b/FEXCore/Source/Interface/Core/Core.cpp @@ -471,7 +471,7 @@ void ContextImpl::LockBeforeFork(FEXCore::Core::InternalThreadState* Thread) { void ContextImpl::OnCodeBufferAllocated(const fextl::shared_ptr& Buffer) { if (Config.GlobalJITNaming()) { - Symbols.RegisterJITSpace(Buffer->Ptr, Buffer->Size); + Symbols.RegisterJITSpace(Buffer->Ptr, Buffer->AllocatedSize); } { diff --git a/FEXCore/Source/Interface/Core/JIT/JIT.cpp b/FEXCore/Source/Interface/Core/JIT/JIT.cpp index cadf8104e..f74d1abe7 100644 --- a/FEXCore/Source/Interface/Core/JIT/JIT.cpp +++ b/FEXCore/Source/Interface/Core/JIT/JIT.cpp @@ -676,7 +676,7 @@ void Arm64JITCore::ClearCache() { auto lk = PrevCodeBuffer->LookupCache->AcquireWriteLock(); auto CodeBuffer = GetEmptyCodeBuffer(); - SetBuffer(CodeBuffer->Ptr, CodeBuffer->Size); + SetBuffer(CodeBuffer->Ptr, CodeBuffer->AllocatedSize); EmitDetectionString(); ThreadState->LookupCache->ChangeGuestToHostMapping(*PrevCodeBuffer, *CurrentCodeBuffer->LookupCache, lk); @@ -1082,9 +1082,9 @@ CPUBackend::CompiledCode Arm64JITCore::CompileCode(uint64_t Entry, uint64_t Size } // NOTE: 16-byte alignment of the new cursor offset must be preserved for block linking records - SetBuffer(CurrentCodeBuffer->Ptr, CurrentCodeBuffer->Size); + SetBuffer(CurrentCodeBuffer->Ptr, CurrentCodeBuffer->AllocatedSize); SetCursorOffset(AlignUp(CodeBuffers.LatestOffset, 16)); - if ((GetCursorOffset() + TempSize) > (CurrentCodeBuffer->Size - Utils::FEX_PAGE_SIZE)) { + if ((GetCursorOffset() + TempSize) > CurrentCodeBuffer->UsableSize()) { CTX->ClearCodeCache(ThreadState); }