ee: drop SpatialArrayReserve allocator

Let's the kernel manage the memory either with builtin lazy allocation or
swapped memory.

Avoid to handle SIGSEGV manually (nicer for debug) and removes 250 lines of code.
This commit is contained in:
Gregory Hainaut 2015-11-11 11:11:01 +01:00
parent 71c8adcfb2
commit 7565bcc789
3 changed files with 12 additions and 253 deletions

View File

@ -266,72 +266,6 @@ protected:
virtual void CommitBlocks( uptr page, uint blocks );
};
// --------------------------------------------------------------------------------------
// SpatialArrayReserve
// --------------------------------------------------------------------------------------
// A spatial array is one where large areas of the memory reserve will remain unused during
// process execution. Only areas put to use will be committed to virtual memory.
//
// Spatial array efficiency depends heavily on selecting the right parameters for the array's
// primary intended use. Memory in a spatial array is arranged by blocks, with each block
// containing some number of pages (pages are 4096 bytes each on most platforms). When the
// array is accessed, the entire block containing the addressed memory will be committed at
// once. Blocks can be a single page in size (4096 bytes), though this is highly discouraged
// due to overhead and fragmentation penalties.
//
// Balancing block sizes:
// Larger blocks are good for reducing memory fragmentation and block-tracking overhead, but
// can also result in a lot of otherwise unused memory being committed to memory. Smaller
// blocks are good for arrays that will tend toward more sequential behavior, as they reduce
// the amount of unused memory being committed. However, since every block requires a
// tracking entry, assigning small blocks to a very large array can result in quite a bit of
// unwanted overhead. Furthermore, if the array is accessed randomly, system physical memory
// will become very fragmented, which will also hurt performance.
//
// By default, the base block size is based on a heuristic that balances the size of the spatial
// array reserve against a best-guess performance profile for the target platform.
//
class SpatialArrayReserve : public BaseVmReserveListener
{
typedef BaseVmReserveListener _parent;
protected:
uint m_numblocks;
// Array of block bits, each bit indicating if the block has been committed to memory
// or not. The array length is typically determined via ((numblocks+7) / 8), though the
// actual array size may be larger in order to accommodate 32-bit or 128-bit accelerated
// operations.
ScopedAlignedAlloc<u8,16> m_blockbits;
public:
SpatialArrayReserve( const wxString& name );
virtual void* Reserve( size_t size = 0, uptr base = 0, uptr upper_bounds = 0 );
virtual void Reset();
virtual bool TryResize( uint newsize );
void OnCommittedBlock( void* block );
SpatialArrayReserve& SetBlockCount( uint blocks );
SpatialArrayReserve& SetBlockSizeInPages( uint bytes );
uptr SetBlockSize( uptr bytes );
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[];
protected:
void ReprotectCommittedBlocks( const PageProtectionMode& newmode );
void DoCommitAndProtect( uptr page );
uint _calcBlockBitArrayLength() const;
};
#ifdef __linux__
# define PCSX2_PAGEFAULT_PROTECT

View File

@ -336,154 +336,6 @@ void BaseVmReserveListener::OnPageFaultEvent(const PageFaultInfo& info, bool& ha
#endif
}
// --------------------------------------------------------------------------------------
// SpatialArrayReserve (implementations)
// --------------------------------------------------------------------------------------
SpatialArrayReserve::SpatialArrayReserve( const wxString& name ) :
_parent( name ), m_numblocks(0)
{
m_prot_mode = PageAccess_ReadWrite();
}
uint SpatialArrayReserve::_calcBlockBitArrayLength() const
{
// divide by 8 (rounded up) to compress 8 bits into each byte.
// mask off lower bits (rounded up) to allow for 128-bit alignment and SSE operations.
return (((m_numblocks + 7) / 8) + 15) & ~15;
}
void* SpatialArrayReserve::Reserve( size_t size, uptr base, uptr upper_bounds )
{
void* addr = _parent::Reserve( size, base, upper_bounds );
if (!addr) return NULL;
if (m_blocksize) SetBlockSizeInPages( m_blocksize );
m_blockbits.Alloc( _calcBlockBitArrayLength() );
return addr;
}
void SpatialArrayReserve::ReprotectCommittedBlocks( const PageProtectionMode& newmode )
{
if (!m_pages_commited) return;
u8* curptr = GetPtr();
const uint blockBytes = m_blocksize * __pagesize;
for (uint i=0; i<m_numblocks; ++i, curptr+=blockBytes)
{
uint thisbit = 1 << (i & 7);
if (!(m_blockbits[i/8] & thisbit)) continue;
HostSys::MemProtect(curptr, blockBytes, newmode);
HostSys::MmapResetPtr(curptr, blockBytes);
}
}
// Resets/clears the spatial array, reducing the memory commit pool overhead to zero (0).
void SpatialArrayReserve::Reset()
{
ReprotectCommittedBlocks( PageAccess_None() );
memzero_sse_a(m_blockbits.GetPtr(), _calcBlockBitArrayLength());
}
// Important! The number of blocks of the array will be altered when using this method.
//
bool SpatialArrayReserve::TryResize( uint newsize )
{
uint newpages = (newsize + __pagesize - 1) / __pagesize;
// find the last allocated block -- we cannot be allowed to resize any smaller than that:
uint i;
for (i=m_numblocks-1; i; --i)
{
uint bit = i & 7;
if (m_blockbits[i / 8] & bit) break;
}
uint pages_in_use = i * m_blocksize;
if (newpages < pages_in_use) return false;
if (!_parent::TryResize( newsize )) return false;
// On success, we must re-calibrate the internal blockbits array.
m_blockbits.Resize( (m_numblocks + 7) / 8 );
return true;
}
// This method allows the programmer to specify the block size of the array as a function
// of its reserved size. This function *must* be called *after* the reserve has been made,
// and *before* the array contents have been accessed.
//
// Calls to this function prior to initializing the reserve or after the reserve has been
// accessed (resulting in committed blocks) will be ignored -- and will generate an assertion
// in debug builds.
SpatialArrayReserve& SpatialArrayReserve::SetBlockCount( uint blocks )
{
pxAssumeDev( !m_pages_commited, "Invalid object state: SetBlockCount must be called prior to reserved memory accesses." );
// Calculate such that the last block extends past the end of the array, if necessary.
m_numblocks = blocks;
m_blocksize = (m_pages_reserved + m_numblocks-1) / m_numblocks;
return *this;
}
// Sets the block size via pages (pages are defined by the __pagesize global, which is
// typically 4096).
//
// This method must be called prior to accessing or modifying the array contents. Calls to
// a modified buffer will be ignored (and generate an assertion in dev/debug modes).
SpatialArrayReserve& SpatialArrayReserve::SetBlockSizeInPages( uint pages )
{
if (pxAssertDev(!m_pages_commited, "Invalid object state: Block size can only be changed prior to accessing or modifying the reserved buffer contents."))
{
m_blocksize = pages;
m_numblocks = (m_pages_reserved + m_blocksize - 1) / m_blocksize;
m_blockbits.Alloc( _calcBlockBitArrayLength() );
}
return *this;
}
// SetBlockSize assigns the block size of the spatial array, in bytes. The actual size of
// each block will be rounded up to the nearest page size. The resulting size is returned.
//
// This method must be called prior to accessing or modifying the array contents. Calls to
// a modified buffer will be ignored (and generate an assertion in dev/debug modes).
uptr SpatialArrayReserve::SetBlockSize( uptr bytes )
{
SetBlockSizeInPages((bytes + __pagesize - 1) / __pagesize);
return m_blocksize * __pagesize;
}
void SpatialArrayReserve::DoCommitAndProtect( uptr page )
{
// Spatial Arrays work on block granularity only:
// Round the page into a block, and commit the whole block that the page belongs to.
uint block = page / m_blocksize;
CommitBlocks(block*m_blocksize, 1);
}
void SpatialArrayReserve::OnCommittedBlock( void* block )
{
// Determine the block position in the blockbits array, flag it, and be done!
uptr relative = (uptr)block - (uptr)m_baseptr;
relative /= m_blocksize * __pagesize;
//DbgCon.WriteLn("Check me out @ 0x%08x", block);
pxAssert( (m_blockbits[relative/8] & (1 << (relative & 7))) == 0 );
m_blockbits[relative/8] |= 1 << (relative & 7);
}
// --------------------------------------------------------------------------------------
// PageProtectionMode (implementations)
// --------------------------------------------------------------------------------------

View File

@ -62,23 +62,6 @@ __aligned16 GPR_reg64 g_cpuConstRegs[32] = {0};
u32 g_cpuHasConstReg = 0, g_cpuFlushedConstReg = 0;
bool g_cpuFlushedPC, g_cpuFlushedCode, g_recompilingDelaySlot, g_maySignalException;
// --------------------------------------------------------------------------------------
// R5900LutReserve_RAM
// --------------------------------------------------------------------------------------
class R5900LutReserve_RAM : public SpatialArrayReserve
{
typedef SpatialArrayReserve _parent;
public:
R5900LutReserve_RAM( const wxString& name )
: _parent( name )
{
}
protected:
void OnCommittedBlock( void* block );
};
////////////////////////////////////////////////////////////////
// Static Private Variables - R5900 Dynarec
@ -87,8 +70,9 @@ protected:
static const int RECCONSTBUF_SIZE = 16384 * 2; // 64 bit consts in 32 bit units
static RecompiledCodeReserve* recMem = NULL;
static SpatialArrayReserve* recRAMCopy = NULL;
static R5900LutReserve_RAM* recLutReserve_RAM = NULL;
static u8* recRAMCopy = NULL;
static u8* recLutReserve_RAM = NULL;
static const size_t recLutSize = Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1;
static uptr m_ConfiguredCacheReserve = 64;
@ -590,11 +574,6 @@ static __ri void ClearRecLUT(BASEBLOCK* base, int memsize)
base[i].SetFnptr((uptr)JITCompile);
}
void R5900LutReserve_RAM::OnCommittedBlock( void* block )
{
_parent::OnCommittedBlock(block);
ClearRecLUT((BASEBLOCK*)block, __pagesize * m_blocksize);
}
static void recThrowHardwareDeficiency( const wxChar* extFail )
{
@ -634,25 +613,19 @@ static void recAlloc()
{
if (!recRAMCopy)
{
recRAMCopy = new SpatialArrayReserve( L"R5900 RAM copy" );
recRAMCopy->SetBlockSize(_16kb);
recRAMCopy->Reserve(Ps2MemSize::MainRam);
recRAMCopy = (u8*)_aligned_malloc(Ps2MemSize::MainRam, 4096);
}
if (!recRAM)
{
recLutReserve_RAM = new R5900LutReserve_RAM( L"R5900 RAM LUT" );
recLutReserve_RAM->SetBlockSize(_16kb);
recLutReserve_RAM->Reserve(Ps2MemSize::MainRam + Ps2MemSize::Rom + Ps2MemSize::Rom1);
recLutReserve_RAM = (u8*)_aligned_malloc(recLutSize, 4096);
}
BASEBLOCK* basepos = (BASEBLOCK*)recLutReserve_RAM->GetPtr();
BASEBLOCK* basepos = (BASEBLOCK*)recLutReserve_RAM;
recRAM = basepos; basepos += (Ps2MemSize::MainRam / 4);
recROM = basepos; basepos += (Ps2MemSize::Rom / 4);
recROM1 = basepos; basepos += (Ps2MemSize::Rom1 / 4);
pxAssert(recLutReserve_RAM->GetPtrEnd() == (u8*)basepos);
for (int i = 0; i < 0x10000; i++)
recLUT_SetPage(recLUT, 0, 0, 0, i, 0);
@ -722,8 +695,8 @@ static void recResetRaw()
Console.WriteLn( Color_StrongBlack, "EE/iR5900-32 Recompiler Reset" );
recMem->Reset();
recRAMCopy->Reset();
recLutReserve_RAM->Reset();
ClearRecLUT((BASEBLOCK*)recLutReserve_RAM, recLutSize);
memset(recRAMCopy, 0, Ps2MemSize::MainRam);
maxrecmem = 0;
@ -747,8 +720,8 @@ static void recResetRaw()
static void recShutdown()
{
safe_delete( recMem );
safe_delete( recRAMCopy );
safe_delete( recLutReserve_RAM );
safe_aligned_free( recRAMCopy );
safe_aligned_free( recLutReserve_RAM );
recBlocks.Reset();
@ -2168,7 +2141,7 @@ StartRecomp:
if ((oldBlock->startpc + oldBlock->size * 4) <= HWADDR(startpc))
break;
if (memcmp(&(*recRAMCopy)[oldBlock->startpc / 4], PSM(oldBlock->startpc),
if (memcmp(&recRAMCopy[oldBlock->startpc / 4], PSM(oldBlock->startpc),
oldBlock->size * 4))
{
recClear(startpc, (pc - startpc) / 4);
@ -2178,7 +2151,7 @@ StartRecomp:
}
}
memcpy(&(*recRAMCopy)[HWADDR(startpc) / 4], PSM(startpc), pc - startpc);
memcpy(&recRAMCopy[HWADDR(startpc) / 4], PSM(startpc), pc - startpc);
}
s_pCurBlock->SetFnptr((uptr)recPtr);