mirror of https://github.com/PCSX2/pcsx2.git
pcsx2: remove the reserve feature of recompiler memory
Cons: * requires ~180MB of physical memory (virtual memory is the same so it doesn't impact the 4GB limit) From steam: 98.81% got at least 2GB of RAM. 83.62% got at least 4GB of RAM. That being said, it might not really increase RAM requirements as OS could put the new allocation in the swap. Pro: * code is much easier * remove at least half of the signal listener * last but not least, it is way easier for profiler/debugger
This commit is contained in:
parent
903d3595e5
commit
b9369e7c00
|
@ -215,63 +215,6 @@ protected:
|
|||
virtual void ReprotectCommittedBlocks(const PageProtectionMode &newmode);
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseVmReserveListener
|
||||
// --------------------------------------------------------------------------------------
|
||||
class BaseVmReserveListener : public VirtualMemoryReserve
|
||||
{
|
||||
DeclareNoncopyableObject(BaseVmReserveListener);
|
||||
|
||||
typedef VirtualMemoryReserve _parent;
|
||||
|
||||
protected:
|
||||
EventListenerHelper_PageFault<BaseVmReserveListener> m_pagefault_listener;
|
||||
|
||||
// Incremental size by which the buffer grows (in pages)
|
||||
uptr m_blocksize;
|
||||
|
||||
public:
|
||||
BaseVmReserveListener(const wxString &name, size_t size = 0);
|
||||
virtual ~BaseVmReserveListener() throw() {}
|
||||
|
||||
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; }
|
||||
|
||||
using _parent::operator[];
|
||||
|
||||
void OnPageFaultEvent(const PageFaultInfo &info, bool &handled);
|
||||
|
||||
virtual uptr SetBlockSize(uptr bytes)
|
||||
{
|
||||
m_blocksize = (bytes + __pagesize - 1) / __pagesize;
|
||||
return m_blocksize * __pagesize;
|
||||
}
|
||||
|
||||
virtual void Reset()
|
||||
{
|
||||
_parent::Reset();
|
||||
}
|
||||
|
||||
protected:
|
||||
// This function is called from OnPageFaultEvent after the address has been translated
|
||||
// and confirmed to apply to this reserved area in question. OnPageFaultEvent contains
|
||||
// a try/catch exception handler, which ensures "reasonable" error response behavior if
|
||||
// this function throws exceptions.
|
||||
//
|
||||
// Important: This method is called from the context of an exception/signal handler. On
|
||||
// Windows this isn't a big deal (most operations are ok). On Linux, however, logging
|
||||
// and other facilities are probably not a good idea.
|
||||
virtual void DoCommitAndProtect(uptr offset) = 0;
|
||||
|
||||
// This function is called for every committed block.
|
||||
virtual void OnCommittedBlock(void *block) = 0;
|
||||
|
||||
virtual void CommitBlocks(uptr page, uint blocks);
|
||||
};
|
||||
|
||||
#ifdef __POSIX__
|
||||
|
||||
#define PCSX2_PAGEFAULT_PROTECT
|
||||
|
|
|
@ -257,80 +257,6 @@ bool VirtualMemoryReserve::TryResize(uint newsize)
|
|||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// BaseVmReserveListener (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
||||
BaseVmReserveListener::BaseVmReserveListener(const wxString &name, size_t size)
|
||||
: VirtualMemoryReserve(name, size)
|
||||
, m_pagefault_listener(this)
|
||||
{
|
||||
m_blocksize = __pagesize;
|
||||
}
|
||||
|
||||
void BaseVmReserveListener::CommitBlocks(uptr page, uint blocks)
|
||||
{
|
||||
const uptr blocksbytes = blocks * m_blocksize * __pagesize;
|
||||
void *blockptr = (u8 *)m_baseptr + (page * __pagesize);
|
||||
|
||||
// Depending on the operating system, this call could fail if the system is low on either
|
||||
// physical ram or virtual memory.
|
||||
if (!HostSys::MmapCommitPtr(blockptr, blocksbytes, m_prot_mode)) {
|
||||
throw Exception::OutOfMemory(m_name)
|
||||
.SetDiagMsg(pxsFmt("An additional %u blocks @ 0x%08x were requested, but could not be committed!", blocks, blockptr));
|
||||
}
|
||||
|
||||
u8 *init = (u8 *)blockptr;
|
||||
u8 *endpos = init + blocksbytes;
|
||||
for (; init < endpos; init += m_blocksize * __pagesize)
|
||||
OnCommittedBlock(init);
|
||||
|
||||
m_pages_commited += m_blocksize * blocks;
|
||||
}
|
||||
|
||||
void BaseVmReserveListener::OnPageFaultEvent(const PageFaultInfo &info, bool &handled)
|
||||
{
|
||||
sptr offset = (info.addr - (uptr)m_baseptr) / __pagesize;
|
||||
if ((offset < 0) || ((uptr)offset >= m_pages_reserved))
|
||||
return;
|
||||
|
||||
if (!m_allow_writes) {
|
||||
pxFailRel(pxsFmt(
|
||||
L"Memory Protection Fault @ %ls (%s)\n"
|
||||
L"Modification of this reserve has been disabled (m_allow_writes == false).",
|
||||
pxsPtr(info.addr), WX_STR(m_name)));
|
||||
return;
|
||||
}
|
||||
|
||||
// Linux Note! the SIGNAL handler is very limited in what it can do, and not only can't
|
||||
// we let the C++ exception try to unwind the stack, we may not be able to log it either.
|
||||
// (but we might as well try -- kernel/posix rules says not to do it, but Linux kernel
|
||||
// implementations seem to support it).
|
||||
// Note also that logging the exception and/or issuing an assertion dialog are always
|
||||
// possible if the thread handling the signal is not the main thread.
|
||||
|
||||
// In windows we can let exceptions bubble out of the page fault handler. SEH will more
|
||||
// or less handle them in a semi-expected way, and might even avoid a GPF long enough
|
||||
// for the system to log the error or something.
|
||||
|
||||
#ifndef __WXMSW__
|
||||
try {
|
||||
#endif
|
||||
DoCommitAndProtect(offset);
|
||||
handled = true;
|
||||
|
||||
#ifndef __WXMSW__
|
||||
} catch (Exception::BaseException &ex) {
|
||||
handled = false;
|
||||
if (!wxThread::IsMain()) {
|
||||
pxFailRel(ex.FormatDiagnosticMessage());
|
||||
} else {
|
||||
pxTrap();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------------------
|
||||
// PageProtectionMode (implementations)
|
||||
// --------------------------------------------------------------------------------------
|
||||
|
|
|
@ -36,11 +36,9 @@
|
|||
// Parameters:
|
||||
// name - a nice long name that accurately describes the contents of this reserve.
|
||||
RecompiledCodeReserve::RecompiledCodeReserve( const wxString& name, uint defCommit )
|
||||
: BaseVmReserveListener( name )
|
||||
: VirtualMemoryReserve( name, defCommit )
|
||||
{
|
||||
m_blocksize = (1024 * 128) / __pagesize;
|
||||
m_prot_mode = PageAccess_Any();
|
||||
m_def_commit = defCommit / __pagesize;
|
||||
}
|
||||
|
||||
RecompiledCodeReserve::~RecompiledCodeReserve() throw()
|
||||
|
@ -59,19 +57,13 @@ void RecompiledCodeReserve::_termProfiler()
|
|||
{
|
||||
}
|
||||
|
||||
uint RecompiledCodeReserve::_calcDefaultCommitInBlocks() const
|
||||
{
|
||||
return (m_def_commit + m_blocksize - 1) / m_blocksize;
|
||||
}
|
||||
|
||||
void* RecompiledCodeReserve::Reserve( size_t size, uptr base, uptr upper_bounds )
|
||||
{
|
||||
if (!_parent::Reserve(size, base, upper_bounds)) return NULL;
|
||||
_registerProfiler();
|
||||
|
||||
// Pre-Allocate the first block (to reduce the number of segmentation fault
|
||||
// in debugger)
|
||||
DoCommitAndProtect(0);
|
||||
Commit();
|
||||
|
||||
_registerProfiler();
|
||||
|
||||
return m_baseptr;
|
||||
}
|
||||
|
@ -80,11 +72,24 @@ void RecompiledCodeReserve::Reset()
|
|||
{
|
||||
_parent::Reset();
|
||||
|
||||
// Pre-Allocate the first block (to reduce the number of segmentation fault
|
||||
// in debugger)
|
||||
DoCommitAndProtect(0);
|
||||
Commit();
|
||||
}
|
||||
|
||||
bool RecompiledCodeReserve::Commit()
|
||||
{
|
||||
bool status = _parent::Commit();
|
||||
|
||||
if (IsDevBuild && m_baseptr)
|
||||
{
|
||||
// Clear the recompiled code block to 0xcc (INT3) -- this helps disasm tools show
|
||||
// the assembly dump more cleanly. We don't clear the block on Release builds since
|
||||
// it can add a noticeable amount of overhead to large block recompilations.
|
||||
|
||||
memset(m_baseptr, 0xCC, m_pages_commited * __pagesize);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -96,23 +101,6 @@ RecompiledCodeReserve& RecompiledCodeReserve::SetProfilerName( const wxString& s
|
|||
return *this;
|
||||
}
|
||||
|
||||
void RecompiledCodeReserve::DoCommitAndProtect( uptr page )
|
||||
{
|
||||
CommitBlocks(page, (m_pages_commited || !m_def_commit) ? 1 : _calcDefaultCommitInBlocks() );
|
||||
}
|
||||
|
||||
void RecompiledCodeReserve::OnCommittedBlock( void* block )
|
||||
{
|
||||
if (IsDevBuild)
|
||||
{
|
||||
// Clear the recompiled code block to 0xcc (INT3) -- this helps disasm tools show
|
||||
// the assembly dump more cleanly. We don't clear the block on Release builds since
|
||||
// it can add a noticeable amount of overhead to large block recompilations.
|
||||
|
||||
memset(block, 0xCC, m_blocksize * __pagesize);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
void RecompiledCodeReserve::ThrowIfNotOk() const
|
||||
|
|
|
@ -23,16 +23,11 @@
|
|||
// A recompiled code reserve is a simple sequential-growth block of memory which is auto-
|
||||
// cleared to INT 3 (0xcc) as needed.
|
||||
//
|
||||
class RecompiledCodeReserve : public BaseVmReserveListener
|
||||
class RecompiledCodeReserve : public VirtualMemoryReserve
|
||||
{
|
||||
typedef BaseVmReserveListener _parent;
|
||||
typedef VirtualMemoryReserve _parent;
|
||||
|
||||
protected:
|
||||
// Specifies the number of blocks that should be committed automatically when the
|
||||
// reserve is created. Typically this chunk is larger than the block size, and
|
||||
// should be based on whatever typical overhead is needed for basic block use.
|
||||
uint m_def_commit;
|
||||
|
||||
wxString m_profiler_name;
|
||||
|
||||
public:
|
||||
|
@ -40,15 +35,15 @@ public:
|
|||
virtual ~RecompiledCodeReserve() throw();
|
||||
|
||||
virtual void* Reserve( size_t size, uptr base=0, uptr upper_bounds=0 );
|
||||
virtual void OnCommittedBlock( void* block );
|
||||
virtual void Reset();
|
||||
virtual bool Commit();
|
||||
|
||||
virtual RecompiledCodeReserve& SetProfilerName( const wxString& shortname );
|
||||
virtual RecompiledCodeReserve& SetProfilerName( const char* shortname )
|
||||
{
|
||||
return SetProfilerName( fromUTF8(shortname) );
|
||||
}
|
||||
|
||||
|
||||
void ThrowIfNotOk() const;
|
||||
|
||||
operator void*() { return m_baseptr; }
|
||||
|
@ -59,10 +54,7 @@ public:
|
|||
|
||||
protected:
|
||||
void ResetProcessReserves() const;
|
||||
void DoCommitAndProtect( uptr page );
|
||||
|
||||
void _registerProfiler();
|
||||
void _termProfiler();
|
||||
|
||||
uint _calcDefaultCommitInBlocks() const;
|
||||
};
|
||||
|
|
|
@ -420,7 +420,6 @@ void VifUnpackSSE_Init()
|
|||
|
||||
nVifUpkExec = new RecompiledCodeReserve(L"VIF SSE-optimized Unpacking Functions", _64kb);
|
||||
nVifUpkExec->SetProfilerName("iVIF-SSE");
|
||||
nVifUpkExec->SetBlockSize( 1 );
|
||||
nVifUpkExec->Reserve( _64kb );
|
||||
|
||||
nVifUpkExec->ThrowIfNotOk();
|
||||
|
|
Loading…
Reference in New Issue