diff --git a/common/include/Utilities/Dependencies.h b/common/include/Utilities/Dependencies.h index 69018be958..25fd3bd22c 100644 --- a/common/include/Utilities/Dependencies.h +++ b/common/include/Utilities/Dependencies.h @@ -185,6 +185,7 @@ static const sptr _256kb = _128kb * 2; static const s64 _1mb = 0x100000; static const s64 _8mb = _1mb * 8; static const s64 _16mb = _1mb * 16; +static const s64 _32mb = _1mb * 32; static const s64 _64mb = _1mb * 64; static const s64 _256mb = _1mb * 256; static const s64 _1gb = _256mb * 4; diff --git a/common/include/Utilities/General.h b/common/include/Utilities/General.h index cc66993397..4946f33c6c 100644 --- a/common/include/Utilities/General.h +++ b/common/include/Utilities/General.h @@ -172,10 +172,11 @@ public: m_read = m_write = m_exec = allow; return *this; } - + bool CanRead() const { return m_read; } bool CanWrite() const { return m_write; } bool CanExecute() const { return m_exec && m_read; } + bool IsNone() const { return !m_read && !m_write; } wxString ToString() const; }; @@ -218,8 +219,12 @@ static __fi PageProtectionMode PageAccess_Any() namespace HostSys { void* MmapReserve(uptr base, size_t size); - void MmapCommit(void* base, size_t size); - void MmapReset(void* base, size_t size); + void MmapCommit(uptr base, size_t size, const PageProtectionMode& mode); + void MmapReset(uptr base, size_t size); + + void* MmapReservePtr(void* base, size_t size); + void MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode); + void MmapResetPtr(void* base, size_t size); // Maps a block of memory for use as a recompiled code buffer. // Returns NULL on allocation failure. diff --git a/common/src/Utilities/Linux/LnxHostSys.cpp b/common/src/Utilities/Linux/LnxHostSys.cpp index 8a7b451531..4b9689b5d4 100644 --- a/common/src/Utilities/Linux/LnxHostSys.cpp +++ b/common/src/Utilities/Linux/LnxHostSys.cpp @@ -35,7 +35,7 @@ static __ri void PageSizeAssertionTest( size_t size ) ); } -void* HostSys::MmapReserve(uptr base, size_t size) +void* HostSys::MmapReservePtr(void* base, size_t size) { PageSizeAssertionTest(size); @@ -43,17 +43,21 @@ void* HostSys::MmapReserve(uptr base, size_t size) // or anonymous source, with PROT_NONE (no-access) permission. Since the mapping // is completely inaccessible, the OS will simply reserve it and will not put it // against the commit table. - return mmap((void*)base, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + return mmap(base, size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); } -void HostSys::MmapCommit(void* base, size_t size) +void HostSys::MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode) { // In linux, reserved memory is automatically committed when its permissions are - // changed to something other than PROT_NONE. Since PCSX2 code *must* do that itself - // prior to making use of memory anyway, this call should be a NOP. + // changed to something other than PROT_NONE. If the user is committing memory + // as PROT_NONE, then just ignore this call (memory will be committed automatically + // later when the user changes permissions to something useful via calls to MemProtect). + + if (mode.IsNone()) return; + MemProtect( base, size, mode ); } -void HostSys::MmapReset(void* base, size_t size) +void HostSys::MmapResetPtr(void* base, size_t size) { // On linux the only way to reset the memory is to unmap and remap it as PROT_NONE. // That forces linux to unload all committed pages and start from scratch. @@ -73,6 +77,21 @@ void HostSys::MmapReset(void* base, size_t size) )); } +void* HostSys::MmapReserve(uptr base, size_t size) +{ + return MmapReservePtr((void*)base, size); +} + +void HostSys::MmapCommit(uptr base, size_t size, const PageProtectionMode& mode) +{ + MmapCommitPtr( (void*)base, size, mode ); +} + +void HostSys::MmapReset(uptr base, size_t size) +{ + MmapResetPtr((void*)base, size); +} + void* HostSys::Mmap(uptr base, size_t size) { PageSizeAssertionTest(size); diff --git a/common/src/Utilities/VirtualMemory.cpp b/common/src/Utilities/VirtualMemory.cpp index 6e6915b677..393d1d602e 100644 --- a/common/src/Utilities/VirtualMemory.cpp +++ b/common/src/Utilities/VirtualMemory.cpp @@ -85,7 +85,7 @@ void* BaseVirtualMemoryReserve::Reserve( uint size, uptr base, uptr upper_bounds // Let's try again at an OS-picked memory area, and then hope it meets needed // boundschecking criteria below. SafeSysMunmap( m_baseptr, reserved_bytes ); - m_baseptr = (void*)HostSys::MmapReserve( NULL, reserved_bytes ); + m_baseptr = HostSys::MmapReserve( 0, reserved_bytes ); } if ((upper_bounds != 0) && (((uptr)m_baseptr + reserved_bytes) > upper_bounds)) @@ -100,20 +100,6 @@ void* BaseVirtualMemoryReserve::Reserve( uint size, uptr base, uptr upper_bounds DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), m_baseptr, (uptr)m_baseptr+reserved_bytes, reserved_bytes / _1mb); - /*if (m_def_commit) - { - const uint camt = m_def_commit * __pagesize; - HostSys::MmapCommit(m_baseptr, camt); - HostSys::MemProtect(m_baseptr, camt, m_prot_mode); - - u8* init = (u8*)m_baseptr; - u8* endpos = init + camt; - for( ; init -void* HostSys::MmapReserve(uptr base, size_t size) +static DWORD ConvertToWinApi( const PageProtectionMode& mode ) { - return VirtualAlloc((void*)base, size, MEM_RESERVE, PAGE_NOACCESS); + DWORD winmode = PAGE_NOACCESS; + + // Windows has some really bizarre memory protection enumeration that uses bitwise + // numbering (like flags) but is in fact not a flag value. *Someone* from the early + // microsoft days wasn't a very good coder, me thinks. --air + + if (mode.CanExecute()) + { + winmode = mode.CanWrite() ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; + } + else if (mode.CanRead()) + { + winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY; + } + + return winmode; } -void HostSys::MmapCommit(void* base, size_t size) +void* HostSys::MmapReservePtr(void* base, size_t size) { - // Execution flag for this and the Reserve should match... ? - void* result = VirtualAlloc(base, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); + return VirtualAlloc(base, size, MEM_RESERVE, PAGE_NOACCESS); +} + +void HostSys::MmapCommitPtr(void* base, size_t size, const PageProtectionMode& mode) +{ + void* result = VirtualAlloc(base, size, MEM_COMMIT, ConvertToWinApi(mode)); pxAssumeDev(result, L"VirtualAlloc COMMIT failed: " + Exception::WinApiError().GetMsgFromWindows()); } -void HostSys::MmapReset(void* base, size_t size) +void HostSys::MmapResetPtr(void* base, size_t size) { - // Execution flag is actually irrelevant for this operation, but whatever. - //void* result = VirtualAlloc((void*)base, size, MEM_RESET, PAGE_EXECUTE_READWRITE); - //pxAssumeDev(result, L"VirtualAlloc RESET failed: " + Exception::WinApiError().GetMsgFromWindows()); - VirtualFree(base, size, MEM_DECOMMIT); } + +void* HostSys::MmapReserve(uptr base, size_t size) +{ + return MmapReservePtr((void*)base, size); +} + +void HostSys::MmapCommit(uptr base, size_t size, const PageProtectionMode& mode) +{ + MmapCommitPtr( (void*)base, size, mode ); +} + +void HostSys::MmapReset(uptr base, size_t size) +{ + MmapResetPtr((void*)base, size); +} + + void* HostSys::Mmap(uptr base, size_t size) { return VirtualAlloc((void*)base, size, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); @@ -57,24 +89,9 @@ void HostSys::MemProtect( void* baseaddr, size_t size, const PageProtectionMode& L"\tPage Size: 0x%04x (%d), Block Size: 0x%04x (%d)", __pagesize, __pagesize, size, size ) ); - - DWORD winmode = PAGE_NOACCESS; - - // Windows has some really bizarre memory protection enumeration that uses bitwise - // numbering (like flags) but is in fact not a flag value. *Someone* from the early - // microsoft days wasn't a very good coder, me thinks. --air - - if (mode.CanExecute()) - { - winmode = mode.CanWrite() ? PAGE_EXECUTE_READWRITE : PAGE_EXECUTE_READ; - } - else if (mode.CanRead()) - { - winmode = mode.CanWrite() ? PAGE_READWRITE : PAGE_READONLY; - } DWORD OldProtect; // enjoy my uselessness, yo! - if (!VirtualProtect( baseaddr, size, winmode, &OldProtect )) + if (!VirtualProtect( baseaddr, size, ConvertToWinApi(mode), &OldProtect )) { throw Exception::WinApiError().SetDiagMsg( pxsFmt(L"VirtualProtect failed @ 0x%08X -> 0x%08X (mode=%s)", diff --git a/pcsx2/Interpreter.cpp b/pcsx2/Interpreter.cpp index ddc463d37b..9744295304 100644 --- a/pcsx2/Interpreter.cpp +++ b/pcsx2/Interpreter.cpp @@ -437,6 +437,14 @@ static void intThrowException( const BaseException& ex ) ex.Rethrow(); } +static void intSetCacheReserve( uint reserveInMegs ) +{ +} + +static uint intGetCacheReserve() +{ + return 0; +} R5900cpu intCpu = { @@ -451,4 +459,7 @@ R5900cpu intCpu = intThrowException, intThrowException, intClear, + + intGetCacheReserve, + intSetCacheReserve, }; diff --git a/pcsx2/R3000AInterpreter.cpp b/pcsx2/R3000AInterpreter.cpp index dcf6dd1698..1722932123 100644 --- a/pcsx2/R3000AInterpreter.cpp +++ b/pcsx2/R3000AInterpreter.cpp @@ -184,11 +184,23 @@ static void intClear(u32 Addr, u32 Size) { static void intShutdown() { } +static void intSetCacheReserve( uint reserveInMegs ) +{ +} + +static uint intGetCacheReserve() +{ + return 0; +} + R3000Acpu psxInt = { intReserve, intReset, intExecute, intExecuteBlock, intClear, - intShutdown + intShutdown, + + intGetCacheReserve, + intSetCacheReserve }; diff --git a/pcsx2/R5900.cpp b/pcsx2/R5900.cpp index 6c5d915256..d093da9fcb 100644 --- a/pcsx2/R5900.cpp +++ b/pcsx2/R5900.cpp @@ -32,7 +32,6 @@ #include "CDVD/CDVD.h" #include "Patch.h" #include "GameDatabase.h" -#include "SamplProf.h" using namespace R5900; // for R5900 disasm tools diff --git a/pcsx2/SamplProf.h b/pcsx2/SamplProf.h index 5ad112293d..7fa918d7c6 100644 --- a/pcsx2/SamplProf.h +++ b/pcsx2/SamplProf.h @@ -30,6 +30,10 @@ void ProfilerRegisterSource(const char* Name, const void* buff, u32 sz); void ProfilerRegisterSource(const char* Name, const void* function); void ProfilerTerminateSource( const char* Name ); +void ProfilerRegisterSource(const wxString& Name, const void* buff, u32 sz); +void ProfilerRegisterSource(const wxString& Name, const void* function); +void ProfilerTerminateSource( const wxString& Name ); + #else // Disables the profiler in Debug & Linux builds. diff --git a/pcsx2/System.cpp b/pcsx2/System.cpp index 9a4a349650..b27563f54c 100644 --- a/pcsx2/System.cpp +++ b/pcsx2/System.cpp @@ -18,6 +18,8 @@ #include "IopCommon.h" #include "VUmicro.h" +#include "SamplProf.h" + // Includes needed for cleanup, since we don't have a good system (yet) for // cleaning up these things. #include "GameDatabase.h" @@ -34,14 +36,104 @@ extern void resetNewVif(int idx); // -------------------------------------------------------------------------------------- // RecompiledCodeReserve (implementations) // -------------------------------------------------------------------------------------- + +// Constructor! +// Parameters: +// name - a nice long name that accurately describes the contents of this reserve. RecompiledCodeReserve::RecompiledCodeReserve( const wxString& name, uint defCommit ) : BaseVirtualMemoryReserve( name ) { m_block_size = (1024 * 128) / __pagesize; m_prot_mode = PageAccess_Any(); m_def_commit = defCommit / __pagesize; + + m_profiler_registered = false; } +RecompiledCodeReserve::~RecompiledCodeReserve() throw() +{ + _termProfiler(); +} + +void RecompiledCodeReserve::_registerProfiler() +{ + if (m_profiler_name.IsEmpty() || !IsOk()) return; + ProfilerRegisterSource( m_profiler_name, m_baseptr, GetReserveSizeInBytes() ); + m_profiler_registered = true; +} + +void RecompiledCodeReserve::_termProfiler() +{ + if (m_profiler_registered) + ProfilerTerminateSource( m_profiler_name ); +} + +void* RecompiledCodeReserve::Reserve( uint size, uptr base, uptr upper_bounds ) +{ + if (!__parent::Reserve(size, base, upper_bounds)) return NULL; + _registerProfiler(); + return m_baseptr; +} + + +// If growing the array, or if shrinking the array to some point that's still *greater* than the +// committed memory range, then attempt a passive "on-the-fly" resize that maps/unmaps some portion +// of the reserve. +// +// If the above conditions are not met, or if the map/unmap fails, this method returns false. +// The caller will be responsible for manually resetting the reserve. +// +// Parameters: +// newsize - new size of the reserved buffer, in bytes. +bool RecompiledCodeReserve::TryResize( uint newsize ) +{ + uint newPages = (newsize + __pagesize - 1) / __pagesize; + + if (newPages > m_reserved) + { + uint toReservePages = newPages - m_reserved; + uint toReserveBytes = toReservePages * __pagesize; + + DevCon.WriteLn( L"%-32s is being expanded by %u pages.", Name.c_str(), toReservePages); + + m_baseptr = (void*)HostSys::MmapReserve((uptr)GetPtrEnd(), toReserveBytes); + + if (!m_baseptr) + { + Console.Warning("%-32s could not be passively resized due to virtual memory conflict!"); + Console.Indent().Warning("(attempted to map memory @ 0x%08X -> 0x%08X", m_baseptr, (uptr)m_baseptr+toReserveBytes); + } + + DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), + m_baseptr, (uptr)m_baseptr+toReserveBytes, toReserveBytes / _1mb); + } + else if (newPages < m_reserved) + { + if (m_commited > newsize) return false; + + uint toRemovePages = m_reserved - newPages; + uint toRemoveBytes = toRemovePages * __pagesize; + + DevCon.WriteLn( L"%-32s is being shrunk by %u pages.", Name.c_str(), toRemovePages); + + HostSys::MmapResetPtr(GetPtrEnd(), toRemoveBytes); + + DevCon.WriteLn( Color_Blue, L"%-32s @ 0x%08X -> 0x%08X [%umb]", Name.c_str(), + m_baseptr, (uptr)m_baseptr+toRemoveBytes, toRemoveBytes / _1mb); + } + + return true; +} + +// Sets the abbreviated name used by the profiler. Name should be under 10 characters long. +// After a name has been set, a profiler source will be automatically registered and cleared +// in accordance with changes in the reserve area. +RecompiledCodeReserve& RecompiledCodeReserve::SetProfilerName( const wxString& shortname ) +{ + m_profiler_name = shortname; + _registerProfiler(); + return *this; +} void RecompiledCodeReserve::OnCommittedBlock( void* block ) { @@ -57,7 +149,7 @@ void RecompiledCodeReserve::OnCommittedBlock( void* block ) void RecompiledCodeReserve::ResetProcessReserves() const { - //Cpu->SetCacheReserve( (Cpu->GetCacheReserve() * 3) / 2 ); + Cpu->SetCacheReserve( (Cpu->GetCacheReserve() * 3) / 2 ); Cpu->Reset(); CpuVU0->SetCacheReserve( (CpuVU0->GetCacheReserve() * 3) / 2 ); @@ -66,7 +158,7 @@ void RecompiledCodeReserve::ResetProcessReserves() const CpuVU1->SetCacheReserve( (CpuVU1->GetCacheReserve() * 3) / 2 ); CpuVU1->Reset(); - //psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 3) / 2 ); + psxCpu->SetCacheReserve( (psxCpu->GetCacheReserve() * 3) / 2 ); psxCpu->Reset(); } @@ -93,8 +185,7 @@ void RecompiledCodeReserve::OnOutOfMemory( const Exception::OutOfMemory& ex, voi ResetProcessReserves(); uint cusion = std::min( m_block_size, 4 ); - HostSys::MmapCommit((u8*)blockptr, cusion * __pagesize); - HostSys::MemProtect((u8*)blockptr, cusion * __pagesize, m_prot_mode); + HostSys::MmapCommitPtr((u8*)blockptr, cusion * __pagesize, m_prot_mode); handled = true; } diff --git a/pcsx2/System/RecTypes.h b/pcsx2/System/RecTypes.h index 995444669d..b44c2f46e6 100644 --- a/pcsx2/System/RecTypes.h +++ b/pcsx2/System/RecTypes.h @@ -27,20 +27,37 @@ // class RecompiledCodeReserve : public BaseVirtualMemoryReserve { + typedef BaseVirtualMemoryReserve __parent; + protected: + wxString m_profiler_name; + bool m_profiler_registered; public: RecompiledCodeReserve( const wxString& name, uint defCommit = 0 ); - + virtual ~RecompiledCodeReserve() throw(); + + virtual void* Reserve( uint size, uptr base=0, uptr upper_bounds=0 ); virtual void OnCommittedBlock( void* block ); virtual void OnOutOfMemory( const Exception::OutOfMemory& ex, void* blockptr, bool& handled ); + virtual RecompiledCodeReserve& SetProfilerName( const wxString& shortname ); + virtual RecompiledCodeReserve& SetProfilerName( const char* shortname ) + { + return SetProfilerName( fromUTF8(shortname) ); + } + + virtual bool TryResize( uint newsize ); + operator void*() { return m_baseptr; } operator const void*() const { return m_baseptr; } operator u8*() { return (u8*)m_baseptr; } operator const u8*() const { return (u8*)m_baseptr; } - + protected: void ResetProcessReserves() const; + + void _registerProfiler(); + void _termProfiler(); }; diff --git a/pcsx2/gui/AppInit.cpp b/pcsx2/gui/AppInit.cpp index 755907a65b..d0a4288d8e 100644 --- a/pcsx2/gui/AppInit.cpp +++ b/pcsx2/gui/AppInit.cpp @@ -286,40 +286,40 @@ void Pcsx2App::AllocateCoreStuffs() if( BaseException* ex = m_CpuProviders->GetException_EE() ) { - scrollableTextArea->AppendText( L"* R5900 (EE)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* R5900 (EE)\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.EnableEE = false; } if( BaseException* ex = m_CpuProviders->GetException_IOP() ) { - scrollableTextArea->AppendText( L"* R3000A (IOP)\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* R3000A (IOP)\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.EnableIOP = false; } if( BaseException* ex = m_CpuProviders->GetException_MicroVU0() ) { - scrollableTextArea->AppendText( L"* microVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* microVU0\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.UseMicroVU0 = false; recOps.EnableVU0 = recOps.EnableVU0 && m_CpuProviders->IsRecAvailable_SuperVU0(); } if( BaseException* ex = m_CpuProviders->GetException_MicroVU1() ) { - scrollableTextArea->AppendText( L"* microVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* microVU1\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.UseMicroVU1 = false; recOps.EnableVU1 = recOps.EnableVU1 && m_CpuProviders->IsRecAvailable_SuperVU1(); } if( BaseException* ex = m_CpuProviders->GetException_SuperVU0() ) { - scrollableTextArea->AppendText( L"* SuperVU0\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* SuperVU0\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.UseMicroVU0 = m_CpuProviders->IsRecAvailable_MicroVU0(); recOps.EnableVU0 = recOps.EnableVU0 && recOps.UseMicroVU0; } if( BaseException* ex = m_CpuProviders->GetException_SuperVU1() ) { - scrollableTextArea->AppendText( L"* SuperVU1\n\t" + ex->FormatDiagnosticMessage() + L"\n\n" ); + scrollableTextArea->AppendText( L"* SuperVU1\n\t" + ex->FormatDisplayMessage() + L"\n\n" ); recOps.UseMicroVU1 = m_CpuProviders->IsRecAvailable_MicroVU1(); recOps.EnableVU1 = recOps.EnableVU1 && recOps.UseMicroVU1; } diff --git a/pcsx2/windows/SamplProf.cpp b/pcsx2/windows/SamplProf.cpp index 74e3dfaf4b..89ea7302b1 100644 --- a/pcsx2/windows/SamplProf.cpp +++ b/pcsx2/windows/SamplProf.cpp @@ -119,40 +119,47 @@ static bool _registeredName( const wxString& name ) return false; } -void ProfilerRegisterSource(const char* Name, const void* buff, u32 sz) +void ProfilerRegisterSource(const wxString& Name, const void* buff, u32 sz) { if( ProfRunning ) EnterCriticalSection( &ProfModulesLock ); - wxString strName( fromUTF8(Name) ); - if( !_registeredName( strName ) ) - ProfModules.push_back( Module( strName, buff, sz ) ); + if( !_registeredName( Name ) ) + ProfModules.push_back( Module( Name, buff, sz ) ); if( ProfRunning ) LeaveCriticalSection( &ProfModulesLock ); } +void ProfilerRegisterSource(const wxString& Name, const void* function) +{ + if( ProfRunning ) + EnterCriticalSection( &ProfModulesLock ); + + if( !_registeredName( Name ) ) + ProfModules.push_back( Module(Name,function) ); + + if( ProfRunning ) + LeaveCriticalSection( &ProfModulesLock ); +} + +void ProfilerRegisterSource(const char* Name, const void* buff, u32 sz) +{ + ProfilerRegisterSource( fromUTF8(Name), buff, sz ); +} + void ProfilerRegisterSource(const char* Name, const void* function) { - if( ProfRunning ) - EnterCriticalSection( &ProfModulesLock ); - - wxString strName( fromUTF8(Name) ); - if( !_registeredName( strName ) ) - ProfModules.push_back( Module(strName,function) ); - - if( ProfRunning ) - LeaveCriticalSection( &ProfModulesLock ); + ProfilerRegisterSource( fromUTF8(Name), function ); } -void ProfilerTerminateSource( const char* Name ) +void ProfilerTerminateSource( const wxString& Name ) { - wxString strName( fromUTF8(Name) ); for( vector::const_iterator iter = ProfModules.begin(), end = ProfModules.end(); itername.compare( strName ) == 0 ) + if( iter->name.compare( Name ) == 0 ) { ProfModules.erase( iter ); break; @@ -160,6 +167,11 @@ void ProfilerTerminateSource( const char* Name ) } } +void ProfilerTerminateSource( const char* Name ) +{ + ProfilerTerminateSource( fromUTF8(Name) ); +} + static bool DispatchKnownModules( uint Eip ) { bool retval = false; diff --git a/pcsx2/x86/iR3000A.cpp b/pcsx2/x86/iR3000A.cpp index 83bd77cbea..757b49a4f7 100644 --- a/pcsx2/x86/iR3000A.cpp +++ b/pcsx2/x86/iR3000A.cpp @@ -33,7 +33,6 @@ #include "IopCommon.h" #include "iCore.h" -#include "SamplProf.h" #include "NakedAsm.h" #include "AppConfig.h" @@ -750,19 +749,41 @@ void psxRecompileCodeConst3(R3000AFNPTR constcode, R3000AFNPTR_INFO constscode, noconstcode(0); } +static uptr m_ConfiguredCacheReserve = 32; static u8* m_recBlockAlloc = NULL; static const uint m_recBlockAllocSize = (((Ps2MemSize::IopRam + Ps2MemSize::Rom + Ps2MemSize::Rom1) / 4) * sizeof(BASEBLOCK)); +static void recReserveCache() +{ + extern wxString GetMsg_RecVmFailed(); + + if (!recMem) recMem = new RecompiledCodeReserve(L"R3000A Recompiler Cache", _1mb * 2); + recMem->SetProfilerName("IOPrec"); + + while (!recMem->IsOk()) + { + if (recMem->Reserve( m_ConfiguredCacheReserve * _1mb, HostMemoryMap::IOPrec ) != NULL) break; + + // If it failed, then try again (if possible): + if (m_ConfiguredCacheReserve < 4) break; + m_ConfiguredCacheReserve /= 2; + } + + if (!recMem->IsOk()) + { + throw Exception::VirtualMemoryMapConflict(recMem->GetName()) + .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) + .SetUserMsg(GetMsg_RecVmFailed()); + } +} + static void recReserve() { - if (!recMem) - { - recMem = new RecompiledCodeReserve(L"R3000A Recompiler Cache", _1mb * 2); - recMem->Reserve( _16mb, HostMemoryMap::IOPrec ); - ProfilerRegisterSource( "IOP Rec", *recMem, recMem->GetReserveSizeInBytes() ); - } + // IOP has no hardware requirements! + + recReserveCache(); } static void recAlloc() @@ -846,7 +867,6 @@ void recResetIOP() static void recShutdown() { - ProfilerTerminateSource( "IOPRec" ); safe_delete( recMem ); safe_aligned_free( m_recBlockAlloc ); @@ -1399,13 +1419,12 @@ StartRecomp: static void recSetCacheReserve( uint reserveInMegs ) { - //m_ConfiguredCacheReserve = reserveInMegs * _1mb; + m_ConfiguredCacheReserve = reserveInMegs; } static uint recGetCacheReserve() { - return 0; - //return m_ConfiguredCacheReserve / _1mb; + return m_ConfiguredCacheReserve; } R3000Acpu psxRec = { diff --git a/pcsx2/x86/ix86-32/iR5900-32.cpp b/pcsx2/x86/ix86-32/iR5900-32.cpp index d07e3039b2..6a605c59d0 100644 --- a/pcsx2/x86/ix86-32/iR5900-32.cpp +++ b/pcsx2/x86/ix86-32/iR5900-32.cpp @@ -25,7 +25,6 @@ #include "System/RecTypes.h" #include "vtlb.h" -#include "SamplProf.h" #include "Dump.h" #include "System/SysThreads.h" @@ -64,7 +63,7 @@ bool g_cpuFlushedPC, g_cpuFlushedCode, g_recompilingDelaySlot, g_maySignalExcept static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units static RecompiledCodeReserve* recMem = NULL; -static uptr m_ConfiguredCacheReserve = _64mb; +static uptr m_ConfiguredCacheReserve = 64; static u32* recConstBuf = NULL; // 64-bit pseudo-immediates static BASEBLOCK *recRAM = NULL; // and the ptr to the blocks here @@ -551,38 +550,35 @@ static void recThrowHardwareDeficiency( const wxChar* extFail ) // This error message is shared by R5900, R3000, and microVU recompilers. It is not used by the // SuperVU recompiler, since it has its own customized message. -wxString GetMsg_RecVmFailed( const char* recName ) +wxString GetMsg_RecVmFailed() { return pxE( ".Error:Recompiler:VirtualMemoryAlloc", - pxsFmt( - "The %s recompiler was unable to reserve contiguous memory required " - "for internal caches. This problem may be fixable by reducing the default " - "cache sizes for all PCSX2 recompilers, found under Host Settings.", - recName - ) + L"This recompiler was unable to reserve contiguous memory required " + L"for internal caches. This problem may be fixable by reducing the default " + L"cache sizes for all PCSX2 recompilers, found under Host Settings." ); } static void recReserveCache() { if (!recMem) recMem = new RecompiledCodeReserve(L"R5900-32 Recompiler Cache", _1mb * 4); + recMem->SetProfilerName("EErec"); - recMem->Reserve( m_ConfiguredCacheReserve, HostMemoryMap::EErec ); - - while (!recMem->IsOk() && (m_ConfiguredCacheReserve >= 16)) + while (!recMem->IsOk()) { + if (recMem->Reserve( m_ConfiguredCacheReserve * _1mb, HostMemoryMap::EErec ) != NULL) break; + + // If it failed, then try again (if possible): + if (m_ConfiguredCacheReserve < 16) break; m_ConfiguredCacheReserve /= 2; - recMem->Reserve( m_ConfiguredCacheReserve * _1mb, HostMemoryMap::EErec ); } if (!recMem->IsOk()) { throw Exception::VirtualMemoryMapConflict(recMem->GetName()) - .SetDiagMsg(pxsFmt( L"R5900-32 recompiled code cache could not be mapped." )) - .SetUserMsg(GetMsg_RecVmFailed("R5900-32")); + .SetDiagMsg(pxsFmt( L"Recompiled code cache could not be mapped." )) + .SetUserMsg(GetMsg_RecVmFailed()); } - - ProfilerRegisterSource( "EE Rec", *recMem, recMem->GetReserveSizeInBytes() ); } static void recReserve() @@ -721,7 +717,6 @@ static void recResetRaw() static void recShutdown() { - ProfilerTerminateSource( "EERec" ); safe_delete( recMem ); recBlocks.Reset(); @@ -1922,12 +1917,12 @@ static void recThrowException( const BaseException& ex ) static void recSetCacheReserve( uint reserveInMegs ) { - m_ConfiguredCacheReserve = reserveInMegs * _1mb; + m_ConfiguredCacheReserve = reserveInMegs; } static uint recGetCacheReserve() { - return m_ConfiguredCacheReserve / _1mb; + return m_ConfiguredCacheReserve; } R5900cpu recCpu = diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 976f4f9306..479311a7d0 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -85,6 +85,19 @@ static __fi void mVUthrowHardwareDeficiency(const wxChar* extFail, int vuIndex) .SetUserMsg(wxsFormat(_("%s Extensions not found. microVU requires a host CPU with MMX, SSE, and SSE2 extensions."), extFail )); } +void microVU::reserveCache() +{ + cache_reserve = new RecompiledCodeReserve( pxsFmt("Micro VU%u Recompiler Cache", index) ); + cache_reserve->SetProfilerName( pxsFmt("mVU%urec", index) ); + + cache = index ? + (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU1rec ) : + (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU0rec ); + + if(!cache_reserve->IsOk()) + throw Exception::VirtualMemoryMapConflict().SetDiagMsg(pxsFmt( L"Micro VU%u Recompiler Cache", index )); +} + // Only run this once per VU! ;) void microVU::init(uint vuIndex) { @@ -105,16 +118,6 @@ void microVU::init(uint vuIndex) { if (!dispCache) throw Exception::OutOfMemory( index ? L"Micro VU1 Dispatcher" : L"Micro VU0 Dispatcher" ); memset(dispCache, 0xcc, mVUdispCacheSize); - cache_reserve = new RecompiledCodeReserve( pxsFmt("Micro VU%u Recompiler Cache", index) ); - cache = index ? - (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU1rec ) : - (u8*)cache_reserve->Reserve( cacheSize, HostMemoryMap::mVU0rec ); - - if(!cache_reserve->IsOk()) - throw Exception::VirtualMemoryMapConflict().SetDiagMsg(pxsFmt( L"Micro VU%u Recompiler Cache", index )); - - ProfilerRegisterSource (index ? "mVU1 Rec" : "mVU0 Rec", cache, cacheSize); - regAlloc = new microRegAlloc(index); } @@ -130,10 +133,6 @@ void microVU::reset() { //memset(&prog, 0, sizeof(prog)); memset(&prog.lpState, 0, sizeof(prog.lpState)); - if (IsDevBuild) { // Release builds shouldn't need this - memset(cache, 0xcc, cacheSize); - } - // Program Variables prog.cleared = 1; prog.isSame = -1; @@ -145,7 +144,7 @@ void microVU::reset() { u8* z = cache; prog.x86start = z; prog.x86ptr = z; - prog.x86end = z + (cacheSize - mVUcacheSafeZone); + prog.x86end = z + ((cacheSize - mVUcacheSafeZone) * _1mb); for (u32 i = 0; i < (progSize / 2); i++) { if (!prog.prog[i]) @@ -168,11 +167,7 @@ void microVU::reset() { // Free Allocated Resources void microVU::close() { - if (cache_reserve && cache_reserve->IsOk()) - { - ProfilerTerminateSource (index ? "mVU1 Rec" : "mVU0 Rec"); - safe_delete(cache_reserve); - } + safe_delete(cache_reserve); SafeSysMunmap(dispCache, mVUdispCacheSize); @@ -367,18 +362,18 @@ void recMicroVU1::Clear(u32 addr, u32 size) { uint recMicroVU0::GetCacheReserve() const { - return microVU0.cacheSize / _1mb; + return microVU0.cacheSize; } uint recMicroVU1::GetCacheReserve() const { - return microVU1.cacheSize / _1mb; + return microVU1.cacheSize; } void recMicroVU0::SetCacheReserve( uint reserveInMegs ) const { - microVU0.cacheSize = reserveInMegs * _1mb; + microVU0.cacheSize = reserveInMegs; } void recMicroVU1::SetCacheReserve( uint reserveInMegs ) const { - microVU1.cacheSize = reserveInMegs * _1mb; + microVU1.cacheSize = reserveInMegs; } diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index 57cd99a092..ce33e897d3 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -28,7 +28,6 @@ using namespace x86Emitter; #include "iR5900.h" #include "R5900OpcodeTables.h" #include "x86emitter/x86emitter.h" -#include "SamplProf.h" #include "microVU_Misc.h" #include "microVU_IR.h" @@ -150,11 +149,8 @@ struct microProgManager { microRegInfo lpState; // Pipeline state from where program left off (useful for continuing execution) }; -#define mVUdispCacheSize (__pagesize) // Dispatcher Cache Size -#define mVUcacheSize ((index) ? (_1mb * 17) : (_1mb * 7)) // Initial Size (Excluding Safe-Zone) -#define mVUcacheMaxSize ((mVU->index) ? (_1mb * 100) : (_1mb * 50)) // Max Size allowed to grow to -#define mVUcacheGrowBy ((mVU->index) ? (_1mb * 15) : (_1mb * 10)) // Grows by this amount -#define mVUcacheSafeZone ((index) ? (_1mb * 3) : (_1mb * 3)) // Safe-Zone for last program +static const uint mVUdispCacheSize = __pagesize; // Dispatcher Cache Size (in bytes) +static const uint mVUcacheSafeZone = 3; // Safe-Zone for program recompilation (in megabytes) struct microVU { @@ -229,13 +225,14 @@ struct microVU { microVU() { - cacheSize = _1mb * 64; + cacheSize = 64; cache = NULL; dispCache = NULL; startFunct = NULL; exitFunct = NULL; } + void reserveCache(); void init(uint vuIndex); void reset(); void close(); diff --git a/pcsx2/x86/sVU_zerorec.cpp b/pcsx2/x86/sVU_zerorec.cpp index 5183167940..ff0b03f4ff 100644 --- a/pcsx2/x86/sVU_zerorec.cpp +++ b/pcsx2/x86/sVU_zerorec.cpp @@ -38,7 +38,6 @@ #include "System/RecTypes.h" #include "sVU_zerorec.h" -#include "SamplProf.h" #include "NakedAsm.h" #include "AppConfig.h" @@ -350,9 +349,10 @@ static void SuperVUAlloc(int vuindex) { if (s_recVUMem[vuindex]) return; - s_recVUMem[vuindex] = new RecompiledCodeReserve( L"SuperVU Recompiler Cache", 0 ); + s_recVUMem[vuindex] = new RecompiledCodeReserve( pxsFmt("SuperVU%u Recompiler Cache", vuindex), 0 ); s_recVUMem[vuindex]->Reserve( sVU_EXESIZE, vuindex ? HostMemoryMap::sVU1rec : HostMemoryMap::sVU0rec, _256mb ); - + s_recVUMem[vuindex]->SetProfilerName(pxsFmt("sVU%urec",vuindex)); + // upper 4 bits must be zero! if (!s_recVUMem[vuindex]->IsOk()) { @@ -364,8 +364,6 @@ static void SuperVUAlloc(int vuindex) L"ranges required, and will not be available for use. This is not a critical error, since " L"the sVU rec is obsolete, and you should use microVU instead anyway. :)" )); - - ProfilerRegisterSource("sVU Rec", *s_recVUMem[vuindex], sVU_EXESIZE); } } @@ -413,8 +411,6 @@ void SuperVUDestroy(int vuindex) } DestroyVUHeaders(vuindex); - ProfilerTerminateSource(vuindex ? "sVU1Rec" : "sVU0Rec"); - safe_delete(s_recVUMem[vuindex]); safe_delete_array(recVUStack[vuindex]); }