recompiler: more robust code cache allocation (#1242)

- align static code cache to 64 KiB (up from 4 KiB)
- remove dependency on alignas() and associated build workaround
- check for mprotect() failure and fall back on dynamic allocation
- perform dynamic allocation (if needed) at top of main on all platforms
このコミットが含まれているのは:
invertego 2023-09-28 02:12:39 -07:00 committed by GitHub
コミット 4b3b78b77e
この署名に対応する既知のキーがデータベースに存在しません
GPGキーID: 4AEE18F83AFDEB23
6個のファイルの変更24行の追加29行の削除

ファイルの表示

@ -1,21 +1,32 @@
#include <ares/ares.hpp> #include <ares/ares.hpp>
#if !defined(PLATFORM_MACOS)
#define STATIC_ALLOCATION
#endif
namespace ares::Memory { namespace ares::Memory {
constexpr u32 fixedBufferSize = 128_MiB; constexpr u32 fixedBufferSize = 128_MiB;
#if defined(PLATFORM_MACOS) #if defined(STATIC_ALLOCATION)
//dynamic allocation for unsupported platforms u8 fixedBuffer[fixedBufferSize + 64_KiB];
FixedAllocator::FixedAllocator() { #endif
_allocator.resize(fixedBufferSize, bump_allocator::executable);
}
#else
alignas(4096) u8 fixedBuffer[fixedBufferSize];
FixedAllocator::FixedAllocator() { FixedAllocator::FixedAllocator() {
_allocator.resize(sizeof(fixedBuffer), 0, fixedBuffer); u8* buffer = nullptr;
#if defined(STATIC_ALLOCATION)
//align to 64 KiB (maximum page size of any supported OS)
auto offset = -(uintptr)fixedBuffer % 64_KiB;
//set protection to executable
if(memory::protect(fixedBuffer + offset, fixedBufferSize, true)) {
//use static allocation
buffer = fixedBuffer + offset;
}
#endif
_allocator.resize(fixedBufferSize, bump_allocator::executable, buffer);
} }
#endif
auto FixedAllocator::get() -> bump_allocator& { auto FixedAllocator::get() -> bump_allocator& {
static FixedAllocator allocator; static FixedAllocator allocator;

ファイルの表示

@ -44,10 +44,8 @@ auto locate(const string& name) -> string {
#include <nall/main.hpp> #include <nall/main.hpp>
auto nall::main(Arguments arguments) -> void { auto nall::main(Arguments arguments) -> void {
#if defined(PLATFORM_MACOS)
//force early allocation for better proximity to executable code //force early allocation for better proximity to executable code
ares::Memory::FixedAllocator::get(); ares::Memory::FixedAllocator::get();
#endif
#if defined(PLATFORM_WINDOWS) #if defined(PLATFORM_WINDOWS)
bool createTerminal = arguments.take("--terminal"); bool createTerminal = arguments.take("--terminal");

ファイルの表示

@ -246,10 +246,6 @@ ifeq ($(findstring clang++,$(compiler)),clang++)
ifneq ($(platform),macos) ifneq ($(platform),macos)
options += -fuse-ld=lld options += -fuse-ld=lld
endif endif
ifeq ($(arch),arm64)
# work around bad interaction with alignas(n) when n >= 4096
flags += -mno-global-merge
endif
# gcc settings # gcc settings
else ifeq ($(findstring g++,$(compiler)),g++) else ifeq ($(findstring g++,$(compiler)),g++)
flags += -fno-strict-aliasing -fwrapv -Wno-trigraphs flags += -fno-strict-aliasing -fwrapv -Wno-trigraphs

ファイルの表示

@ -28,9 +28,6 @@ struct bump_allocator {
reset(); reset();
if(buffer) { if(buffer) {
if(flags & executable) {
memory::protect(buffer, capacity, true);
}
if(flags & zero_fill) { if(flags & zero_fill) {
memset(buffer, 0x00, capacity); memset(buffer, 0x00, capacity);
} }

ファイルの表示

@ -29,18 +29,17 @@ NALL_HEADER_INLINE auto unmap(void* target, u32 size) -> void {
#endif #endif
} }
NALL_HEADER_INLINE auto protect(void* target, u32 size, bool executable) -> void { NALL_HEADER_INLINE auto protect(void* target, u32 size, bool executable) -> bool {
#if defined(API_WINDOWS) #if defined(API_WINDOWS)
DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; DWORD protect = executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
DWORD oldProtect; DWORD oldProtect;
VirtualProtect(target, size, protect, &oldProtect); return VirtualProtect(target, size, protect, &oldProtect);
#elif defined(API_POSIX) #elif defined(API_POSIX)
int prot = PROT_READ | PROT_WRITE; int prot = PROT_READ | PROT_WRITE;
if(executable) { if(executable) {
prot |= PROT_EXEC; prot |= PROT_EXEC;
} }
int ret = mprotect(target, size, prot); return !mprotect(target, size, prot);
assert(ret == 0);
#endif #endif
} }

ファイルの表示

@ -34,7 +34,7 @@ namespace nall::memory {
auto map(u32 size, bool executable) -> void*; auto map(u32 size, bool executable) -> void*;
auto unmap(void* target, u32 size) -> void; auto unmap(void* target, u32 size) -> void;
auto protect(void* target, u32 size, bool executable) -> void; auto protect(void* target, u32 size, bool executable) -> bool;
auto jitprotect(bool executable) -> void; auto jitprotect(bool executable) -> void;
} }
@ -195,12 +195,6 @@ template<u32 size, typename T> auto writem(void* target, T data) -> void {
for(s32 n = size - 1; n >= 0; n--) *p++ = data >> n * 8; for(s32 n = size - 1; n >= 0; n--) *p++ = data >> n * 8;
} }
auto map(u32 size, bool executable) -> void*;
auto unmap(void* target, u32 size) -> void;
auto protect(void* target, u32 size, bool executable) -> void;
inline auto jitprotect(bool executable) -> void { inline auto jitprotect(bool executable) -> void {
#if defined(PLATFORM_MACOS) #if defined(PLATFORM_MACOS)
if(__builtin_available(macOS 11.0, *)) { if(__builtin_available(macOS 11.0, *)) {