Allocate low executable memory on OS X as on Windows and Linux.

Even with LoadStorePaired accounted for, there are still some
niggling 64-bit cleanliness bugs left that are not practical
to weed out on a single platform. We should probably have an
option to use >2GB memory only on all platforms for debugging.


git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6792 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Soren Jorvang 2011-01-09 14:09:27 +00:00
parent f634d58035
commit d4158f076a
8 changed files with 55 additions and 149 deletions

View File

@ -58,19 +58,12 @@ void MemArena::ReleaseSpace()
} }
void* MemArena::CreateView(s64 offset, size_t size, bool ensure_low_mem) void* MemArena::CreateView(s64 offset, size_t size)
{ {
#ifdef _WIN32 #ifdef _WIN32
return MapViewOfFile(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size); return MapViewOfFile(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size);
#else #else
void* ptr = mmap(0, size, return mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
PROT_READ | PROT_WRITE,
MAP_SHARED
#ifdef __x86_64__
| (ensure_low_mem ? MAP_32BIT : 0)
#endif
, fd, offset);
return ptr;
#endif #endif
} }

View File

@ -27,14 +27,13 @@
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it. // This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
// Multiple views can mirror the same section of the block, which makes it very convient for emulating // Multiple views can mirror the same section of the block, which makes it very convient for emulating
// memory mirrors. // memory mirrors.
// Pass ensure_low_mem = true to CreateView if you want arbitrarily positioned views to end up in the low 2GB.
class MemArena class MemArena
{ {
public: public:
void GrabLowMemSpace(size_t size); void GrabLowMemSpace(size_t size);
void ReleaseSpace(); void ReleaseSpace();
void* CreateView(s64 offset, size_t size, bool ensure_low_mem = false); void* CreateView(s64 offset, size_t size);
void* CreateViewAt(s64 offset, size_t size, void* base); void* CreateViewAt(s64 offset, size_t size, void* base);
void ReleaseView(void* view, size_t size); void ReleaseView(void* view, size_t size);

View File

@ -34,59 +34,42 @@ void* AllocateExecutableMemory(size_t size, bool low)
{ {
#ifdef _WIN32 #ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE
#if defined __linux__ && defined __x86_64__
| (low ? MAP_32BIT : 0)
#endif
, -1, 0);
#endif
// printf("Mapped executable memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate executable memory");
if ((u64)ptr >= 0x80000000) if ((u64)ptr >= 0x80000000)
{
PanicAlert("Executable memory ended up above 2GB!"); PanicAlert("Executable memory ended up above 2GB!");
// If this happens, we have to implement a free ram search scheme. ector knows how.
}
return ptr; return ptr;
#else
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE
#ifdef __x86_64__
| (low ? MAP_32BIT : 0)
#endif
, -1, 0); // | MAP_FIXED
// printf("Mapped executable memory at %p (size %i)\n", retval, size);
if (!retval)
{
PanicAlert("Failed to allocate executable memory, errno=%i", errno);
}
return retval;
#endif
} }
void* AllocateMemoryPages(size_t size) void* AllocateMemoryPages(size_t size)
{ {
#ifdef _WIN32 #ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
if (!ptr)
{
PanicAlert("Failed to allocate raw memory");
}
return ptr;
#else #else
void* retval = mmap(0, size, PROT_READ | PROT_WRITE, void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0); // | MAP_FIXED MAP_ANON | MAP_PRIVATE, -1, 0);
// printf("Mapped memory at %p (size %i)\n", retval, size);
if (!retval)
{
PanicAlert("Failed to allocate raw memory, errno=%i", errno);
}
return retval;
#endif #endif
// printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size);
if (ptr == NULL)
PanicAlert("Failed to allocate raw memory");
return ptr;
} }
void FreeMemoryPages(void* ptr, size_t size) void FreeMemoryPages(void* ptr, size_t size)
@ -125,27 +108,25 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
#endif #endif
} }
std::string MemUsage() std::string MemUsage()
{ {
#ifdef _WIN32 #ifdef _WIN32
DWORD processID = GetCurrentProcessId(); DWORD processID = GetCurrentProcessId();
HANDLE hProcess; HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc; PROCESS_MEMORY_COUNTERS pmc;
std::string Ret; std::string Ret;
// Print information about the memory usage of the process. // Print information about the memory usage of the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if (NULL == hProcess) return "MemUsage Error"; if (NULL == hProcess) return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str()); Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
CloseHandle(hProcess); CloseHandle(hProcess);
return Ret; return Ret;
#else
#else
return ""; return "";
#endif #endif
} }

View File

@ -23,11 +23,6 @@
#endif #endif
#include <string> #include <string>
// Linux-specific mmap(2) flag
#ifndef MAP_32BIT
#define MAP_32BIT 0
#endif
void* AllocateExecutableMemory(size_t size, bool low = true); void* AllocateExecutableMemory(size_t size, bool low = true);
void* AllocateMemoryPages(size_t size); void* AllocateMemoryPages(size_t size);
void FreeMemoryPages(void* ptr, size_t size); void FreeMemoryPages(void* ptr, size_t size);

View File

@ -91,27 +91,11 @@ void SCoreStartupParameter::LoadDefaults()
bJITOff = false; // debugger only settings bJITOff = false; // debugger only settings
bJITLoadStoreOff = false; bJITLoadStoreOff = false;
bJITLoadStoreFloatingOff = false; bJITLoadStoreFloatingOff = false;
bJITLoadStorePairedOff = false; bJITLoadStorePairedOff = false; // XXX not 64-bit clean
bJITFloatingPointOff = false; bJITFloatingPointOff = false;
bJITIntegerOff = false; bJITIntegerOff = false;
bJITPairedOff = false; bJITPairedOff = false;
bJITSystemRegistersOff = false; bJITSystemRegistersOff = false;
#ifdef __APPLE__
// These are required for the JIT cores to work in OSX
// Older revs (~4854) Only required LoadStorePaired to be turned off
// Newer revs (~4890) require both turned off
#ifdef _M_X64
// These work fine in 32bit OSX
// Since the reason why 64bit OSX fails out is due to casting (u32)(u64)
// Since all 64bit applications are above the 32bit memory boundary
bJITLoadStorePairedOff = true;
#endif
//#elif defined(__linux__)
// Similar to OSX, something with LoadStorePaired seems to cause
// crashes on linux. Only Win32 seems to be forgiving enough to
// not do anything funny...(FIXME)
// bJITLoadStorePairedOff = true;
#endif
m_strName = "NONE"; m_strName = "NONE";
m_strUniqueID = "00000000"; m_strUniqueID = "00000000";

View File

@ -35,63 +35,7 @@
using namespace Gen; using namespace Gen;
static int temp32;
#if defined(__APPLE__) && _M_X64
void CommonAsmRoutines::GenFifoWrite(int size)
{
// Assume value in ABI_PARAM1
PUSH(RSI);
if (size != 32)
PUSH(EDX);
BSWAP(size, ABI_PARAM1);
MOV(32, R(EAX), Imm32((u64)GPFifo::m_gatherPipe));
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
if (size != 32) {
MOV(32, R(EDX), R(ABI_PARAM1));
MOV(size, MComplex(RAX, RSI, 1, 0), R(EDX));
} else {
MOV(size, MComplex(RAX, RSI, 1, 0), R(ABI_PARAM1));
}
ADD(64, R(RSI), Imm8(size >> 3));
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
if (size != 32)
POP(EDX);
POP(RSI);
RET();
}
void CommonAsmRoutines::GenFifoFloatWrite()
{
// Assume value in XMM0
PUSH(RSI);
PUSH(EDX);
MOVSS(M(&temp32), XMM0);
MOV(32, R(EDX), M(&temp32));
BSWAP(32, EDX);
MOV(64, R(RAX), Imm64((u64)GPFifo::m_gatherPipe));
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
MOV(32, MComplex(RAX, RSI, 1, 0), R(EDX));
ADD(64, R(RSI), Imm8(4));
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
POP(EDX);
POP(RSI);
RET();
}
void CommonAsmRoutines::GenFifoXmm64Write()
{
// Assume value in XMM0. Assume pre-byteswapped (unlike the others here!)
PUSH(RSI);
MOV(64, R(RAX), Imm32((u64)GPFifo::m_gatherPipe));
MOV(64, R(RSI), M(&GPFifo::m_gatherPipeCount));
MOVQ_xmm(MComplex(RAX, RSI, 1, 0), XMM0);
ADD(64, R(RSI), Imm8(8));
MOV(64, M(&GPFifo::m_gatherPipeCount), R(RSI));
POP(RSI);
RET();
}
#else
void CommonAsmRoutines::GenFifoWrite(int size) void CommonAsmRoutines::GenFifoWrite(int size)
{ {
// Assume value in ABI_PARAM1 // Assume value in ABI_PARAM1
@ -116,6 +60,8 @@ void CommonAsmRoutines::GenFifoWrite(int size)
} }
void CommonAsmRoutines::GenFifoFloatWrite() void CommonAsmRoutines::GenFifoFloatWrite()
{ {
int temp32;
// Assume value in XMM0 // Assume value in XMM0
PUSH(ESI); PUSH(ESI);
PUSH(EDX); PUSH(EDX);
@ -143,8 +89,6 @@ void CommonAsmRoutines::GenFifoXmm64Write()
POP(ESI); POP(ESI);
RET(); RET();
} }
#endif
// Safe + Fast Quantizers, originally from JITIL by magumagu // Safe + Fast Quantizers, originally from JITIL by magumagu

View File

@ -14,6 +14,10 @@ libs = [
'inputcommon', 'common', 'lua', 'z', 'sfml-network', 'inputcommon', 'common', 'lua', 'z', 'sfml-network',
] ]
wxlibs = [ ]
ldflags = [ ]
if env['HAVE_WX']: if env['HAVE_WX']:
files += [ files += [
'AboutDolphin.cpp', 'AboutDolphin.cpp',
@ -46,7 +50,7 @@ if env['HAVE_WX']:
'WxUtils.cpp', 'WxUtils.cpp',
] ]
wxlibs = [ 'debwx', 'debugger_ui_util', 'inputuicommon' ] wxlibs += [ 'debwx', 'debugger_ui_util', 'inputuicommon' ]
else: else:
files += [ files += [
'MainNoGUI.cpp', 'MainNoGUI.cpp',
@ -57,14 +61,15 @@ if sys.platform == 'win32':
files += [ "stdafx.cpp" ] files += [ "stdafx.cpp" ]
elif sys.platform == 'darwin' and not env['HAVE_WX']: elif sys.platform == 'darwin' and not env['HAVE_WX']:
files += [ 'cocoaApp.m' ] files += [ 'cocoaApp.m' ]
ldflags += [ '-Wl,-pagezero_size,0x1000' ]
exeNoGUI = '#' + env['prefix'] + '/DolphinNoGUI' exeNoGUI = '#' + env['prefix'] + '/DolphinNoGUI'
elif sys.platform == 'darwin' and env['HAVE_WX']: elif sys.platform == 'darwin' and env['HAVE_WX']:
wxlibs += env['wxconfiglibs'] wxlibs += env['wxconfiglibs']
ldflags += [ '-Wl,-pagezero_size,0x1000' ]
exeGUI = '#' + env['prefix'] + '/Dolphin.app/Contents/MacOS/Dolphin' exeGUI = '#' + env['prefix'] + '/Dolphin.app/Contents/MacOS/Dolphin'
env.Install('#' + env['prefix'] + '/Dolphin.app/Contents/' + env.Install('#' + env['prefix'] + '/Dolphin.app/Contents/' +
'Library/Frameworks/Cg.framework', 'Library/Frameworks', '#Externals/Cg/Cg.framework')
'#Externals/Cg/Cg.framework/Cg')
env.Install(env['data_dir'], '#Data/Sys') env.Install(env['data_dir'], '#Data/Sys')
env.Install(env['data_dir'], '#Data/User') env.Install(env['data_dir'], '#Data/User')
@ -104,7 +109,10 @@ else:
env.InstallAs(env['data_dir'] + '/sys', '#Data/Sys') env.InstallAs(env['data_dir'] + '/sys', '#Data/Sys')
env.InstallAs(env['data_dir'] + '/user', '#Data/User') env.InstallAs(env['data_dir'] + '/user', '#Data/User')
libs = wxlibs + libs + env['LIBS']
linkflags = ldflags + env['LINKFLAGS']
if env['HAVE_WX']: if env['HAVE_WX']:
env.Program(exeGUI, files, LIBS = wxlibs + libs + env['LIBS']) env.Program(exeGUI, files, LIBS = libs, LINKFLAGS = linkflags)
else: else:
env.Program(exeNoGUI, files, LIBS = libs + env['LIBS']) env.Program(exeNoGUI, files, LIBS = libs, LINKFLAGS = linkflags)

View File

@ -31,15 +31,17 @@ files = [
'VertexFormatConverter.cpp', 'VertexFormatConverter.cpp',
'VertexLoader.cpp', 'VertexLoader.cpp',
'VideoConfig.cpp', 'VideoConfig.cpp',
'VideoConfigDialog.cpp',
'XFMemLoader.cpp', 'XFMemLoader.cpp',
] ]
libs = [ 'videocommon', 'GLEW', 'SOIL', 'common' ] if env['HAVE_WX']:
files += [ 'VideoConfigDialog.cpp' ]
if sys.platform == 'darwin' and not env['HAVE_WX']: if sys.platform == 'darwin' and not env['HAVE_WX']:
files += [ 'cocoaGL.m' ] files += [ 'cocoaGL.m' ]
elif sys.platform == 'win32': elif sys.platform == 'win32':
files += [ 'Win32.cpp' ] files += [ 'Win32.cpp' ]
libs = [ 'videocommon', 'GLEW', 'SOIL', 'common' ]
env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = env['LIBS'] + libs) env.SharedLibrary(env['plugin_dir'] + name, files, LIBS = env['LIBS'] + libs)