mirror of
https://github.com/libretro/pcsx2.git
synced 2024-11-29 04:10:48 +00:00
newHostVM:
* Moved profiler management to the RecompiledCodeReserve class. * Improved error handling some more. * Numerous minor cleanups. git-svn-id: http://pcsx2.googlecode.com/svn/branches/newHostVM@3991 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
parent
bd8127f75e
commit
5579350d22
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
|
@ -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<endpos; init += m_block_size*__pagesize )
|
||||
OnCommittedBlock(init);
|
||||
|
||||
m_commited += m_def_commit * __pagesize;
|
||||
}*/
|
||||
|
||||
return m_baseptr;
|
||||
}
|
||||
|
||||
@ -123,7 +109,7 @@ void BaseVirtualMemoryReserve::Reset()
|
||||
if (!m_commited) return;
|
||||
|
||||
HostSys::MemProtect(m_baseptr, m_commited*__pagesize, PageAccess_None());
|
||||
HostSys::MmapReset(m_baseptr, m_commited*__pagesize);
|
||||
HostSys::MmapResetPtr(m_baseptr, m_commited*__pagesize);
|
||||
m_commited = 0;
|
||||
}
|
||||
|
||||
@ -145,8 +131,7 @@ void BaseVirtualMemoryReserve::OnPageFaultEvent(const PageFaultInfo& info, bool&
|
||||
// first block being committed! Commit the default requested
|
||||
// amount if its different from the blocksize.
|
||||
|
||||
HostSys::MmapCommit(m_baseptr, camt);
|
||||
HostSys::MemProtect(m_baseptr, camt, m_prot_mode);
|
||||
HostSys::MmapCommitPtr(m_baseptr, camt, m_prot_mode);
|
||||
|
||||
u8* init = (u8*)m_baseptr;
|
||||
u8* endpos = init + camt;
|
||||
@ -163,8 +148,7 @@ void BaseVirtualMemoryReserve::OnPageFaultEvent(const PageFaultInfo& info, bool&
|
||||
|
||||
// Depending on the operating system, one or both of these could fail if the system
|
||||
// is low on either physical ram or virtual memory.
|
||||
HostSys::MmapCommit(bleh, m_block_size*__pagesize);
|
||||
HostSys::MemProtect(bleh, m_block_size*__pagesize, m_prot_mode);
|
||||
HostSys::MmapCommitPtr(bleh, m_block_size*__pagesize, m_prot_mode);
|
||||
|
||||
m_commited += m_block_size;
|
||||
OnCommittedBlock(bleh);
|
||||
|
@ -17,27 +17,59 @@
|
||||
#include "Utilities/RedtapeWindows.h"
|
||||
#include <winnt.h>
|
||||
|
||||
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)",
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include "CDVD/CDVD.h"
|
||||
#include "Patch.h"
|
||||
#include "GameDatabase.h"
|
||||
#include "SamplProf.h"
|
||||
|
||||
using namespace R5900; // for R5900 disasm tools
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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<uint>( 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;
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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<Module>::const_iterator
|
||||
iter = ProfModules.begin(),
|
||||
end = ProfModules.end(); iter<end; ++iter )
|
||||
{
|
||||
if( iter->name.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;
|
||||
|
@ -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 = {
|
||||
|
@ -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 =
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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]);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user