diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 13:25:48 -0500 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-11-01 13:25:48 -0500 |
| commit | 6e57ed519f01897cd25c068484a87360d75a7751 (patch) | |
| tree | f18353941be7fc6fbdb4596464e1650709af3c1e /src | |
| parent | f71c7f38495081db8279e85747c54a9c75de458f (diff) | |
| parent | e9f31461b6ff98643bc2bfe330914d57b5facf38 (diff) | |
Merge remote-tracking branch 'origin/fix/dynarmic-reserve-code-cache' into test/linux-all-prs
Diffstat (limited to 'src')
| -rw-r--r-- | src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp index 384d6203a4..57001d4ef0 100644 --- a/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp @@ -60,6 +60,34 @@ namespace { constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024; constexpr size_t PRELUDE_COMMIT_SIZE = 16 * 1024 * 1024; +#ifdef _WIN32 +constexpr size_t COMMIT_STEP = 4 * 1024 * 1024; + +// Reserves the code space; EnsureMemoryCommitted commits it as code is emitted. Xbyak's default +// allocator commits all of it up front: 512 MiB per core, 3 GiB of commit charge for six cores +// of which a game fills a fraction. +struct ReservingAllocator final : Xbyak::Allocator { + uint8_t* alloc(size_t size) override { + return static_cast<uint8_t*>(VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_NOACCESS)); + } + void free(uint8_t* p) override { + VirtualFree(p, 0, MEM_RELEASE); + } + bool useProtect() const override { + return false; + } +}; + +Xbyak::Allocator* CodeAllocator() { + // Never destroyed: code blocks may outlive static destruction. + static auto* const allocator = new ReservingAllocator; + return allocator; +} +#else +Xbyak::Allocator* CodeAllocator() { + return nullptr; +} +#endif #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT void ProtectMemory(const void* base, size_t size, bool is_executable) { @@ -149,7 +177,7 @@ BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_cod #else , nullptr //Allow RWE #endif - , nullptr) + , CodeAllocator()) , constant_pool(*this, CONSTANT_POOL_SIZE) , jsi(jsi) , cb(std::move(cb)) @@ -206,7 +234,9 @@ size_t BlockOfCode::SpaceRemaining() const { void BlockOfCode::EnsureMemoryCommitted([[maybe_unused]] size_t codesize) { #ifdef _WIN32 if (committed_size < size_ + codesize) { - committed_size = std::min<size_t>(maxSize_, committed_size + codesize); + // The code space is only reserved (CodeAllocator), so everything up to the end of the next + // emission has to be committed; in steps, as each VirtualAlloc call is a kernel call. + committed_size = std::min<size_t>(maxSize_, (std::max)(committed_size + COMMIT_STEP, size_ + codesize)); # ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT VirtualAlloc(top_, committed_size, MEM_COMMIT, PAGE_READWRITE); # else |
