x64/block_of_code: Only commit minimum required memory
This commit is contained in:
parent
c08c5a9362
commit
b1584b66b6
5 changed files with 51 additions and 3 deletions
|
@ -167,6 +167,7 @@ private:
|
||||||
invalidate_entire_cache = true;
|
invalidate_entire_cache = true;
|
||||||
PerformCacheInvalidation();
|
PerformCacheInvalidation();
|
||||||
}
|
}
|
||||||
|
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
|
||||||
|
|
||||||
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
IR::Block ir_block = A32::Translate(A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
||||||
Optimization::PolyfillPass(ir_block, polyfill_options);
|
Optimization::PolyfillPass(ir_block, polyfill_options);
|
||||||
|
|
|
@ -270,6 +270,7 @@ private:
|
||||||
invalidate_entire_cache = true;
|
invalidate_entire_cache = true;
|
||||||
PerformRequestedCacheInvalidation();
|
PerformRequestedCacheInvalidation();
|
||||||
}
|
}
|
||||||
|
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
|
||||||
|
|
||||||
// JIT Compile
|
// JIT Compile
|
||||||
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
|
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
|
||||||
|
|
|
@ -55,10 +55,25 @@ const std::array<Xbyak::Reg64, ABI_PARAM_COUNT> BlockOfCode::ABI_PARAMS = {Block
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024;
|
constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024;
|
||||||
|
constexpr size_t PRELUDE_COMMIT_SIZE = 16 * 1024 * 1024;
|
||||||
|
|
||||||
class CustomXbyakAllocator : public Xbyak::Allocator {
|
class CustomXbyakAllocator : public Xbyak::Allocator {
|
||||||
public:
|
public:
|
||||||
#ifndef _WIN32
|
#ifdef _WIN32
|
||||||
|
uint8_t* alloc(size_t size) override {
|
||||||
|
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
|
||||||
|
if (p == nullptr) {
|
||||||
|
throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC);
|
||||||
|
}
|
||||||
|
return static_cast<uint8_t*>(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(uint8_t* p) override {
|
||||||
|
VirtualFree(static_cast<void*>(p), 0, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool useProtect() const override { return false; }
|
||||||
|
#else
|
||||||
static constexpr size_t DYNARMIC_PAGE_SIZE = 4096;
|
static constexpr size_t DYNARMIC_PAGE_SIZE = 4096;
|
||||||
|
|
||||||
// Can't subclass Xbyak::MmapAllocator because it is not a pure interface
|
// Can't subclass Xbyak::MmapAllocator because it is not a pure interface
|
||||||
|
@ -91,10 +106,10 @@ public:
|
||||||
std::memcpy(&size, p - DYNARMIC_PAGE_SIZE, sizeof(size_t));
|
std::memcpy(&size, p - DYNARMIC_PAGE_SIZE, sizeof(size_t));
|
||||||
munmap(p - DYNARMIC_PAGE_SIZE, size);
|
munmap(p - DYNARMIC_PAGE_SIZE, size);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
# ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||||
bool useProtect() const override { return false; }
|
bool useProtect() const override { return false; }
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -211,6 +226,7 @@ BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_cod
|
||||||
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
, constant_pool(*this, CONSTANT_POOL_SIZE)
|
||||||
, host_features(GetHostFeatures()) {
|
, host_features(GetHostFeatures()) {
|
||||||
EnableWriting();
|
EnableWriting();
|
||||||
|
EnsureMemoryCommitted(PRELUDE_COMMIT_SIZE);
|
||||||
GenRunCode(rcp);
|
GenRunCode(rcp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,13 +239,21 @@ void BlockOfCode::PreludeComplete() {
|
||||||
|
|
||||||
void BlockOfCode::EnableWriting() {
|
void BlockOfCode::EnableWriting() {
|
||||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||||
|
# ifdef _WIN32
|
||||||
|
ProtectMemory(getCode(), committed_size, false);
|
||||||
|
# else
|
||||||
ProtectMemory(getCode(), maxSize_, false);
|
ProtectMemory(getCode(), maxSize_, false);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void BlockOfCode::DisableWriting() {
|
void BlockOfCode::DisableWriting() {
|
||||||
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||||
|
# ifdef _WIN32
|
||||||
|
ProtectMemory(getCode(), committed_size, true);
|
||||||
|
# else
|
||||||
ProtectMemory(getCode(), maxSize_, true);
|
ProtectMemory(getCode(), maxSize_, true);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -246,6 +270,19 @@ size_t BlockOfCode::SpaceRemaining() const {
|
||||||
return &top_[maxSize_] - current_ptr;
|
return &top_[maxSize_] - current_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
# ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
|
||||||
|
VirtualAlloc(top_, committed_size, MEM_COMMIT, PAGE_READWRITE);
|
||||||
|
# else
|
||||||
|
VirtualAlloc(top_, committed_size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||||
|
# endif
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
HaltReason BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const {
|
HaltReason BlockOfCode::RunCode(void* jit_state, CodePtr code_ptr) const {
|
||||||
return run_code(jit_state, code_ptr);
|
return run_code(jit_state, code_ptr);
|
||||||
}
|
}
|
||||||
|
@ -480,6 +517,8 @@ void* BlockOfCode::AllocateFromCodeSpace(size_t alloc_size) {
|
||||||
throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
|
throw Xbyak::Error(Xbyak::ERR_CODE_IS_TOO_BIG);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EnsureMemoryCommitted(alloc_size);
|
||||||
|
|
||||||
void* ret = getCurr<void*>();
|
void* ret = getCurr<void*>();
|
||||||
size_ += alloc_size;
|
size_ += alloc_size;
|
||||||
memset(ret, 0, alloc_size);
|
memset(ret, 0, alloc_size);
|
||||||
|
|
|
@ -51,6 +51,8 @@ public:
|
||||||
void ClearCache();
|
void ClearCache();
|
||||||
/// Calculates how much space is remaining to use.
|
/// Calculates how much space is remaining to use.
|
||||||
size_t SpaceRemaining() const;
|
size_t SpaceRemaining() const;
|
||||||
|
/// Ensure at least codesize bytes of code cache memory are committed at the current code_ptr.
|
||||||
|
void EnsureMemoryCommitted(size_t codesize);
|
||||||
|
|
||||||
/// Runs emulated code from code_ptr.
|
/// Runs emulated code from code_ptr.
|
||||||
HaltReason RunCode(void* jit_state, CodePtr code_ptr) const;
|
HaltReason RunCode(void* jit_state, CodePtr code_ptr) const;
|
||||||
|
@ -176,6 +178,10 @@ private:
|
||||||
bool prelude_complete = false;
|
bool prelude_complete = false;
|
||||||
CodePtr code_begin = nullptr;
|
CodePtr code_begin = nullptr;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
size_t committed_size = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
ConstantPool constant_pool;
|
ConstantPool constant_pool;
|
||||||
|
|
||||||
using RunCodeFuncType = HaltReason (*)(void*, CodePtr);
|
using RunCodeFuncType = HaltReason (*)(void*, CodePtr);
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Dynarmic::Backend::X64 {
|
||||||
|
|
||||||
ConstantPool::ConstantPool(BlockOfCode& code, size_t size)
|
ConstantPool::ConstantPool(BlockOfCode& code, size_t size)
|
||||||
: code(code), insertion_point(0) {
|
: code(code), insertion_point(0) {
|
||||||
|
code.EnsureMemoryCommitted(align_size + size);
|
||||||
code.int3();
|
code.int3();
|
||||||
code.align(align_size);
|
code.align(align_size);
|
||||||
pool = std::span<ConstantT>(
|
pool = std::span<ConstantT>(
|
||||||
|
|
Loading…
Reference in a new issue