diff --git a/src/dynarmic/backend/x64/block_of_code.cpp b/src/dynarmic/backend/x64/block_of_code.cpp index c0a469bf..c079a809 100644 --- a/src/dynarmic/backend/x64/block_of_code.cpp +++ b/src/dynarmic/backend/x64/block_of_code.cpp @@ -52,6 +52,41 @@ constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024; class CustomXbyakAllocator : public Xbyak::Allocator { public: +#ifndef _WIN32 + static constexpr size_t PAGE_SIZE = 4096; + + // Can't subclass Xbyak::MmapAllocator because it is not a pure interface + // and doesn't expose its construtor + uint8_t* alloc(size_t size) override { + // Waste a page to store the size + size += PAGE_SIZE; + +# if defined(MAP_ANONYMOUS) + int mode = MAP_PRIVATE | MAP_ANONYMOUS; +# elif defined(MAP_ANON) + int mode = MAP_PRIVATE | MAP_ANON; +# else +# error "not supported" +# endif +# ifdef MAP_JIT + mode |= MAP_JIT; +# endif + + void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0); + if (p == MAP_FAILED) { + throw Xbyak::Error(Xbyak::ERR_CANT_ALLOC); + } + std::memcpy(p, &size, sizeof(size_t)); + return static_cast(p) + PAGE_SIZE; + } + + void free(uint8_t* p) override { + size_t size; + std::memcpy(&size, p - PAGE_SIZE, sizeof(size_t)); + munmap(p - PAGE_SIZE, size); + } +#endif + #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT bool useProtect() const override { return false; } #endif