FEXCore: Fixes ever shrinking JIT code buffer

I accidentally replaced a couple usages of `AllocatedSize` with
`GetAllocatedSize()`. This resulted in a JIT buffer that ran out of
space would actually allocate a slightly smaller buffer each time, and
then it cascades downwards resulting in catastrophic performance.

Fix the use in `SharedCodeBufferManager.cpp` and `Core.cpp` which were
incorrect and renames the function to be more explicit.
This commit is contained in:
Ryan Houdek committed 2026-08-22 18:31:22 -07:00
1 parent b563703701
commit db3817a260
4 files changed
+13 -8

No files matched your search

+5 -5
View File
@@ -314,7 +314,7 @@ bool CodeCache::SaveData(Core::InternalThreadState& Thread, int fd, const Execut
std::ranges::copy(GIT_HASH, header.FEXVersion);
header.NumBlocks = LookupCache.BlockList.size();
header.NumCodePages = LookupCache.CodePages.size();
header.CodeBufferSize = FEXCore::AlignUp(CodeBuffer->GetAllocatedSize(), Utils::FEX_PAGE_SIZE);
header.CodeBufferSize = FEXCore::AlignUp(CodeBuffer->AllocatedSpaceUsed(), Utils::FEX_PAGE_SIZE);
header.NumRelocations = Relocations.size();
header.SerializedBaseAddress = SerializedBaseAddress;
::write(fd, &header, sizeof(header));
@@ -362,7 +362,7 @@ bool CodeCache::SaveData(Core::InternalThreadState& Thread, int fd, const Execut
// Dump the host code (relocated for position-independent serialization)
std::span CodeBufferData(reinterpret_cast<std::byte*>(CodeBuffer->GetBufferBase()),
reinterpret_cast<std::byte*>(CodeBuffer->GetBufferBase()) + CodeBuffer->GetAllocatedSize());
reinterpret_cast<std::byte*>(CodeBuffer->GetBufferBase()) + CodeBuffer->AllocatedSpaceUsed());
if (!ApplyCodeRelocations(SerializedBaseAddress, CodeBufferData, Relocations, 0, true)) {
LOGMAN_THROW_A_FMT(false, "Failed to apply code relocations");
return false;
@@ -427,7 +427,7 @@ void CodeCache::Validate(const ExecutableFileSectionInfo& Section, fextl::set<ui
while (CachedCode.size_bytes() > NewCodeBuffer->UsableSize()) {
ValidationCTX->ClearCodeCache(ValidationThread.get());
NewCodeBuffer = ValidationCTX->GetLatest();
LogMan::Msg::IFmt("Increased cache validation code buffer size to {} MiB", NewCodeBuffer->GetAllocatedSize() / 1024 / 1024);
LogMan::Msg::IFmt("Increased cache validation code buffer size to {} MiB", NewCodeBuffer->TotalAllocationSize() / 1024 / 1024);
}
std::span<std::byte> CodeBufferRangeRef =
@@ -448,10 +448,10 @@ void CodeCache::Validate(const ExecutableFileSectionInfo& Section, fextl::set<ui
}));
(void)ApplyCodeRelocations(Section.FileStartVA, CodeBufferRangeRef, NewRelocations, 0, false);
if (NewCodeBuffer->GetAllocatedSize() <= CodeBufferRangeRef.size()) {
if (NewCodeBuffer->AllocatedSpaceUsed() <= CodeBufferRangeRef.size()) {
// Reference compilation produced fewer bytes than our cache, so validation is going to fail.
// Make sure we don't output any garbage bytes though.
CodeBufferRangeRef = CodeBufferRangeRef.subspan(0, NewCodeBuffer->GetAllocatedSize());
CodeBufferRangeRef = CodeBufferRangeRef.subspan(0, NewCodeBuffer->AllocatedSpaceUsed());
}
auto [Mismatch, _] = std::mismatch(CodeBufferRangeRef.begin(), CodeBufferRangeRef.end(), CachedCode.begin());
+1 -1
View File
@@ -483,7 +483,7 @@ void ContextImpl::LockBeforeFork(FEXCore::Core::InternalThreadState* Thread) {
void ContextImpl::OnCodeBufferAllocated(const fextl::shared_ptr<CPU::CodeBuffer>& Buffer) {
if (Config.GlobalJITNaming()) {
Symbols.RegisterJITSpace(Buffer->GetBufferBase(), Buffer->GetAllocatedSize());
Symbols.RegisterJITSpace(Buffer->GetBufferBase(), Buffer->TotalAllocationSize());
}
{
@@ -88,7 +88,7 @@ fextl::shared_ptr<CodeBuffer> SharedCodeBufferManager::StartLargerCodeBuffer() {
return GetLatest();
}
auto NewCodeBufferSize = GetLatest()->GetAllocatedSize();
auto NewCodeBufferSize = GetLatest()->TotalAllocationSize();
NewCodeBufferSize = std::min<size_t>(NewCodeBufferSize * 2, MAX_CODE_SIZE);
return AllocateNew(NewCodeBufferSize);
}
@@ -71,8 +71,13 @@ struct CodeBuffer {
return AllocatedSize - FEXCore::Utils::FEX_PAGE_SIZE;
}
// Returns the full size of the buffer, including the guard page.
size_t TotalAllocationSize() const {
return AllocatedSize;
}
// Returns the num of bytes currently allocated from the allocator.
size_t GetAllocatedSize() const {
size_t AllocatedSpaceUsed() const {
return CodeBufferOffset - Ptr;
}