From 4b4cf509f8746a8c4afb73a2a2de165179201db6 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Fri, 14 Apr 2017 12:53:32 +0200 Subject: [PATCH] Remove code for only allocating low memory This is unnecessary when we have position-independent code. --- CMakeLists.txt | 4 -- Source/Core/Common/CodeBlock.h | 4 +- Source/Core/Common/MemArena.cpp | 31 ++++++----- Source/Core/Common/MemoryUtil.cpp | 59 ++------------------- Source/Core/Common/MemoryUtil.h | 2 +- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 8 --- Source/Core/VideoCommon/VertexLoaderX64.cpp | 2 +- 7 files changed, 26 insertions(+), 84 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 58aaaa9c43..fdb17010e1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -283,10 +283,6 @@ if(CMAKE_SYSTEM_NAME MATCHES "Darwin") # Linker flags. # Drop unreachable code and data. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-dead_strip,-dead_strip_dylibs") - # Reserve the minimum size for the zero page. - # Our JIT requires virtual memory space below 2GB, while the default zero - # page on x86_64 is 4GB in size. - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-pagezero_size,0x1000") find_library(APPKIT_LIBRARY AppKit) find_library(APPSERV_LIBRARY ApplicationServices) diff --git a/Source/Core/Common/CodeBlock.h b/Source/Core/Common/CodeBlock.h index 9c3da1058b..cd933647ed 100644 --- a/Source/Core/Common/CodeBlock.h +++ b/Source/Core/Common/CodeBlock.h @@ -44,11 +44,11 @@ public: } // Call this before you generate any code. - void AllocCodeSpace(size_t size, bool need_low = true) + void AllocCodeSpace(size_t size) { region_size = size; total_region_size = size; - region = static_cast(Common::AllocateExecutableMemory(total_region_size, need_low)); + region = static_cast(Common::AllocateExecutableMemory(total_region_size)); T::SetCodePtr(region); } diff --git a/Source/Core/Common/MemArena.cpp b/Source/Core/Common/MemArena.cpp index ce6cc2662e..cff92ce794 100644 --- a/Source/Core/Common/MemArena.cpp +++ b/Source/Core/Common/MemArena.cpp @@ -7,6 +7,7 @@ #include #include +#include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" #include "Common/Logging/Log.h" #include "Common/MemArena.h" @@ -125,19 +126,22 @@ void MemArena::ReleaseView(void* view, size_t size) u8* MemArena::FindMemoryBase() { -#if _ARCH_64 +#if _ARCH_32 + const size_t memory_size = 0x31000000; +#else + const size_t memory_size = 0x400000000; +#endif + #ifdef _WIN32 - // 64 bit - u8* base = (u8*)VirtualAlloc(0, 0x400000000, MEM_RESERVE, PAGE_READWRITE); + u8* base = static_cast(VirtualAlloc(nullptr, memory_size, MEM_RESERVE, PAGE_READWRITE)); + if (!base) + { + PanicAlert("Failed to map enough memory space: %s", GetLastErrorMsg().c_str()); + return nullptr; + } VirtualFree(base, 0, MEM_RELEASE); return base; #else - // Very precarious - mmap cannot return an error when trying to map already used pages. - // This makes the Windows approach above unusable on Linux, so we will simply pray... - return reinterpret_cast(0x2300000000ULL); -#endif - -#else // 32 bit #ifdef ANDROID // Android 4.3 changed how mmap works. // if we map it private and then munmap it, we can't use the base returned. @@ -146,14 +150,13 @@ u8* MemArena::FindMemoryBase() #else const int flags = MAP_ANON | MAP_PRIVATE; #endif - const u32 MemSize = 0x31000000; - void* base = mmap(0, MemSize, PROT_NONE, flags, -1, 0); + void* base = mmap(nullptr, memory_size, PROT_NONE, flags, -1, 0); if (base == MAP_FAILED) { - PanicAlert("Failed to map 1 GB of memory space: %s", strerror(errno)); - return 0; + PanicAlert("Failed to map enough memory space: %s", GetLastErrorMsg().c_str()); + return nullptr; } - munmap(base, MemSize); + munmap(base, memory_size); return static_cast(base); #endif } diff --git a/Source/Core/Common/MemoryUtil.cpp b/Source/Core/Common/MemoryUtil.cpp index 4eb2e1f2d3..db8201f84e 100644 --- a/Source/Core/Common/MemoryUtil.cpp +++ b/Source/Core/Common/MemoryUtil.cpp @@ -29,74 +29,25 @@ #endif #endif -// Valgrind doesn't support MAP_32BIT. -// Uncomment the following line to be able to run Dolphin in Valgrind. -//#undef MAP_32BIT - namespace Common { -#if !defined(_WIN32) && defined(_M_X86_64) && !defined(MAP_32BIT) -#include -static uintptr_t RoundPage(uintptr_t addr) -{ - uintptr_t mask = getpagesize() - 1; - return (addr + mask) & ~mask; -} -#endif - // This is purposely not a full wrapper for virtualalloc/mmap, but it // provides exactly the primitive operations that Dolphin needs. -void* AllocateExecutableMemory(size_t size, bool low) +void* AllocateExecutableMemory(size_t size) { #if defined(_WIN32) void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); #else - static char* map_hint = nullptr; -#if defined(_M_X86_64) && !defined(MAP_32BIT) - // This OS has no flag to enforce allocation below the 4 GB boundary, - // but if we hint that we want a low address it is very likely we will - // get one. - // An older version of this code used MAP_FIXED, but that has the side - // effect of discarding already mapped pages that happen to be in the - // requested virtual memory range (such as the emulated RAM, sometimes). - if (low && (!map_hint)) - map_hint = (char*)RoundPage(512 * 1024 * 1024); /* 0.5 GB rounded up to the next page */ -#endif - void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE -#if defined(_M_X86_64) && defined(MAP_32BIT) - | (low ? MAP_32BIT : 0) -#endif - , - -1, 0); -#endif /* defined(_WIN32) */ + void* ptr = + mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANON | MAP_PRIVATE, -1, 0); -#ifdef _WIN32 - if (ptr == nullptr) - { -#else if (ptr == MAP_FAILED) - { ptr = nullptr; #endif - PanicAlert("Failed to allocate executable memory. If you are running Dolphin in Valgrind, try " - "'#undef MAP_32BIT'."); - } -#if !defined(_WIN32) && defined(_M_X86_64) && !defined(MAP_32BIT) - else - { - if (low) - { - map_hint += size; - map_hint = (char*)RoundPage((uintptr_t)map_hint); /* round up to the next page */ - } - } -#endif -#if _M_X86_64 - if ((u64)ptr >= 0x80000000 && low == true) - PanicAlert("Executable memory ended up above 2GB!"); -#endif + if (ptr == nullptr) + PanicAlert("Failed to allocate executable memory"); return ptr; } diff --git a/Source/Core/Common/MemoryUtil.h b/Source/Core/Common/MemoryUtil.h index 1e2402f5d2..96709174dd 100644 --- a/Source/Core/Common/MemoryUtil.h +++ b/Source/Core/Common/MemoryUtil.h @@ -9,7 +9,7 @@ namespace Common { -void* AllocateExecutableMemory(size_t size, bool low = true); +void* AllocateExecutableMemory(size_t size); void* AllocateMemoryPages(size_t size); void FreeMemoryPages(void* ptr, size_t size); void* AllocateAlignedMemory(size_t size, size_t alignment); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index a4e68617c6..02e58d1db4 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -50,14 +50,6 @@ using namespace PowerPC; // * Does not recompile all instructions - sometimes falls back to inserting a CALL to the // corresponding Interpreter function. -// Various notes below - -// IMPORTANT: -// Make sure that all generated code and all emulator state sits under the 2GB boundary so that -// RIP addressing can be used easily. Windows will always allocate static code under the 2GB -// boundary. -// Also make sure to use VirtualAlloc and specify EXECUTE permission. - // Open questions // * Should there be any statically allocated registers? r3, r4, r5, r8, r0 come to mind.. maybe sp // * Does it make sense to finish off the remaining non-jitted instructions? Seems we are hitting diff --git a/Source/Core/VideoCommon/VertexLoaderX64.cpp b/Source/Core/VideoCommon/VertexLoaderX64.cpp index 92edf8dd5c..c29981b9ec 100644 --- a/Source/Core/VideoCommon/VertexLoaderX64.cpp +++ b/Source/Core/VideoCommon/VertexLoaderX64.cpp @@ -46,7 +46,7 @@ VertexLoaderX64::VertexLoaderX64(const TVtxDesc& vtx_desc, const VAT& vtx_att) if (!IsInitialized()) return; - AllocCodeSpace(4096, false); + AllocCodeSpace(4096); ClearCodeSpace(); GenerateVertexLoader(); WriteProtect();