Many small memoryleak fixes in PCSX2 (mostly related to newVIF's recompiler) and one memoryleak fixed in USBnull. Had to juggle around the initialization/reset code for VIF a bit to get it happy. This also removes quite a bit of redundant memory allocations and clears when starting/resetting the emulator; expect a small speedup on slower machines.

git-svn-id: http://pcsx2.googlecode.com/svn/trunk@3103 96395faa-99c1-11dd-bbfe-3dabce05a288
This commit is contained in:
Jake.Stine 2010-05-28 16:54:42 +00:00
parent 9e7394afff
commit 81c35c9fcc
20 changed files with 151 additions and 66 deletions

View File

@ -556,7 +556,7 @@ void cdvdReset()
cdvd.RTC.month = (u8)curtime.GetMonth(wxDateTime::GMT9) + 1; // WX returns Jan as "0"
cdvd.RTC.year = (u8)(curtime.GetYear(wxDateTime::GMT9) - 2000);
GameDB = new DataBase_Loader("GameIndex.dbf");
if( !GameDB ) GameDB = new DataBase_Loader("GameIndex.dbf");
}
struct Freeze_v10Compat

View File

@ -17,6 +17,7 @@
#include "Common.h"
#include "Hardware.h"
#include "newVif.h"
using namespace R5900;
@ -25,14 +26,22 @@ u8 *psH; // hw mem
const int rdram_devices = 2; // put 8 for TOOL and 2 for PS2 and PSX
int rdram_sdevid = 0;
static bool hwInitialized = false;
void hwInit()
{
gsInit();
if( hwInitialized ) return;
VifUnpackSSE_Init();
vif0Init();
vif1Init();
gsInit();
sifInit();
sprInit();
ipuInit();
hwInitialized = true;
}
/*void hwShutdown()
@ -52,8 +61,13 @@ void hwReset()
psHu32(DMAC_ENABLEW) = 0x1201;
psHu32(DMAC_ENABLER) = 0x1201;
sifInit();
sprInit();
gsReset();
ipuReset();
vif0Reset();
vif1Reset();
}
__forceinline void intcInterrupt()

View File

@ -142,11 +142,7 @@ int ipuInit()
void ipuReset()
{
memzero(*ipuRegs);
g_nDMATransfer.reset();
IPU1Status.InProgress = false;
IPU1Status.DMAMode = DMA_MODE_NORMAL;
IPU1Status.DMAFinished = true;
ipuInit();
}
void ipuShutdown()

View File

@ -78,8 +78,6 @@ void cpuReset()
EEoCycle = cpuRegs.cycle;
hwReset();
vif0Reset();
vif1Reset();
rcntInit();
psxReset();

View File

@ -17,11 +17,14 @@
#include "Common.h"
#include "HostGui.h"
#include "sVU_zerorec.h" // for SuperVUDestroy
#include "System/PageFaultSource.h"
#include "Utilities/EventSource.inl"
// Includes needed for cleanup, since we don't have a good system (yet) for
// cleaning up these things.
#include "sVU_zerorec.h"
#include "DataBase_Loader.h"
extern void closeNewVif(int idx);
extern void resetNewVif(int idx);
@ -323,6 +326,10 @@ void SysCoreAllocations::CleanupMess() throw()
{
try
{
GameDB.Delete();
closeNewVif(0);
closeNewVif(1);
// Special SuperVU "complete" terminator (stupid hacky recompiler)
SuperVUDestroy( -1 );
@ -330,8 +337,6 @@ void SysCoreAllocations::CleanupMess() throw()
recCpu.Shutdown();
vuMicroMemShutdown();
closeNewVif(0);
closeNewVif(1);
psxMemShutdown();
memShutdown();
vtlb_Core_Shutdown();
@ -389,12 +394,11 @@ void SysClearExecutionCache()
Cpu->Reset();
psxCpu->Reset();
CpuVU0->Reset();
CpuVU1->Reset();
resetNewVif(0);
resetNewVif(1);
CpuVU0->Reset();
CpuVU1->Reset();
}
// Maps a block of memory for use as a recompiled code buffer, and ensures that the

View File

@ -355,12 +355,13 @@ void BaseScopedCoreThread::DoResume()
// handle the code directly).
bool BaseScopedCoreThread::PostToSysExec( BaseSysExecEvent_ScopedCore* msg )
{
if( !msg || GetSysExecutorThread().IsSelf()) return false;
ScopedPtr<BaseSysExecEvent_ScopedCore> smsg( msg );
if( !smsg || GetSysExecutorThread().IsSelf()) return false;
msg->SetSyncState(m_sync);
msg->SetResumeStates(m_sync_resume, m_mtx_resume);
GetSysExecutorThread().PostEvent( msg );
GetSysExecutorThread().PostEvent( smsg.DetachPtr() );
m_sync.WaitForResult();
m_sync.RethrowException();

View File

@ -657,6 +657,6 @@ struct CrtDebugBreak
}
};
//CrtDebugBreak breakAt( 1175 );
//CrtDebugBreak breakAt( 8564 );
#endif

View File

@ -227,11 +227,12 @@ void pxEvtHandler::AddPendingEvent( SysExecEvent& evt )
//
void pxEvtHandler::PostEvent( SysExecEvent* evt )
{
if( !evt ) return;
ScopedPtr<SysExecEvent> sevt( evt );
if( !sevt ) return;
if( m_Quitting )
{
evt->PostResult();
sevt->PostResult();
return;
}
@ -239,7 +240,7 @@ void pxEvtHandler::PostEvent( SysExecEvent* evt )
//DbgCon.WriteLn( L"(%s) Posting event: %s (queue count=%d)", GetEventHandlerName().c_str(), evt->GetEventName().c_str(), m_pendingEvents.size() );
m_pendingEvents.push_back( evt );
m_pendingEvents.push_back( sevt.DetachPtr() );
if( m_pendingEvents.size() == 1)
m_wakeup.Post();
}
@ -421,7 +422,7 @@ void ExecutorThread::ShutdownQueue()
// Exposes the internal pxEvtHandler::PostEvent API. See pxEvtHandler for details.
void ExecutorThread::PostEvent( SysExecEvent* evt )
{
if( !pxAssert( m_EvtHandler ) ) return;
if( !pxAssert( m_EvtHandler ) ) { delete evt; return; }
m_EvtHandler->PostEvent( evt );
}

View File

@ -251,7 +251,7 @@ GSFrame::GSFrame(wxWindow* parent, const wxString& title)
wxStaticText* label = new wxStaticText( this, wxID_ANY, _("GS Output is Disabled!") );
m_id_OutputDisabled = label->GetId();
label->SetFont( *new wxFont( 20, wxDEFAULT, wxNORMAL, wxBOLD ) );
label->SetFont( wxFont( 20, wxDEFAULT, wxNORMAL, wxBOLD ) );
label->SetForegroundColour( *wxWHITE );
label->Show( EmuConfig.GS.DisableOutput );

View File

@ -278,7 +278,6 @@ MainEmuFrame::MainEmuFrame(wxWindow* parent, const wxString& title)
, m_menubar( *new wxMenuBar() )
, m_menuBoot ( *new wxMenu() )
, m_menuCDVD ( *new wxMenu() )
, m_menuSys ( *new wxMenu() )
, m_menuConfig ( *new wxMenu() )

View File

@ -116,7 +116,6 @@ protected:
wxMenuBar& m_menubar;
wxMenu& m_menuBoot;
wxMenu& m_menuCDVD;
wxMenu& m_menuSys;
wxMenu& m_menuConfig;

View File

@ -95,6 +95,8 @@ uint FileMcd_GetMtapPort(uint slot)
return 0; // technically unreachable.
}
// Returns the multitap slot number, range 1 to 3 (slot 0 refers to the standard
// 1st and 2nd player slots).
uint FileMcd_GetMtapSlot(uint slot)
{
switch( slot )
@ -103,8 +105,8 @@ uint FileMcd_GetMtapSlot(uint slot)
pxFailDev( "Invalid parameter in call to GetMtapSlot -- specified slot is one of the base slots, not a Multitap slot." );
break;
case 2: case 3: case 4: return slot-2;
case 5: case 6: case 7: return slot-5;
case 2: case 3: case 4: return slot-1;
case 5: case 6: case 7: return slot-4;
jNO_DEFAULT
}

View File

@ -532,13 +532,11 @@ void Panels::MemoryCardListPanel_Simple::DoRefresh()
{
for( uint slot=0; slot<8; ++slot )
{
if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] ) continue;
wxFileName fullpath( m_FolderPicker->GetPath() + g_Conf->Mcd[slot].Filename.GetFullName() );
EnumerateMemoryCard( m_Cards[slot], fullpath );
m_Cards[slot].Slot = slot;
if( FileMcd_IsMultitapSlot(slot) && !m_MultitapEnabled[FileMcd_GetMtapPort(slot)] )
m_Cards[slot].IsEnabled = false;
}
if( m_listview ) m_listview->SetMcdProvider( this );

View File

@ -21,7 +21,12 @@
#include "x86emitter/x86emitter.h"
using namespace x86Emitter;
// newVif_HashBucket.h uses this typedef, so it has to be decared first.
static const s64 _1mb = 0x100000;
#define aMax(x, y) std::max(x,y)
#define aMin(x, y) std::min(x,y)
#define _f __forceinline
// newVif_HashBucket.h uses this typedef, so it has to be declared first.
typedef u32 (__fastcall *nVifCall)(void*, void*);
typedef void (__fastcall *nVifrecCall)(uptr dest, uptr src);
@ -32,18 +37,15 @@ extern void mVUmergeRegs(int dest, int src, int xyzw, bool modXYZW = 0);
extern void _nVifUnpack (int idx, u8 *data, u32 size, bool isFill);
extern void dVifUnpack (int idx, u8 *data, u32 size, bool isFill);
extern void dVifInit (int idx);
extern void dVifReset (int idx);
extern void dVifClose (int idx);
extern void VifUnpackSSE_Init();
#define VUFT VIFUnpackFuncTable
#define _1mb (0x100000)
#define _v0 0
#define _v1 0x55
#define _v2 0xaa
#define _v3 0xff
#define aMax(x, y) std::max(x,y)
#define aMin(x, y) std::min(x,y)
#define _f __forceinline
#define xmmCol0 xmm2
#define xmmCol1 xmm3
#define xmmCol2 xmm4
@ -88,7 +90,7 @@ struct nVifStruct {
u32 bSize; // Size of 'buffer'
u8 buffer[_1mb]; // Buffer for partial transfers
u8* recPtr; // Cur Pos to recompile to
u8* recEnd; // End of Rec Cache
u8* recEnd; // 'Safe' End of Rec Cache
BlockBuffer* vifCache; // Block Buffer
HashBucket<_tParams>* vifBlocks; // Vif Blocks
int numBlocks; // # of Blocks Recompiled

View File

@ -26,34 +26,61 @@
// deletion/cleanup respectfully...
class BlockBuffer {
protected:
u32 mSize; // Cur Size
u32 mSizeT; // Total Size
u8* mData; // Data Ptr
u32 mSize; // Cur Size (in bytes)
u32 mSizeT; // Total Size (in bytes)
u32 mGrowBy; // amount to grow by when buffer fills (in bytes)
u8* mData; // Data Ptr (allocated via SysMmap)
void alloc(int size) {
mData = SysMmapEx(NULL, size, 0, "nVif_BlockBuffer");
if (!mData) throw Exception::OutOfMemory("nVif Error: Failed to allocate recompiler memory!");
memset(mData, 0xcc, size);
clear();
}
void dealloc(u8* &dPtr, int size) {
if (dPtr) { HostSys::Munmap(dPtr, size); dPtr = NULL; }
SafeSysMunmap( dPtr, size );
}
public:
BlockBuffer(u32 tSize) { mSizeT = tSize; mSize = 0; alloc(mSizeT); }
~BlockBuffer() { dealloc(mData, mSizeT); }
virtual ~BlockBuffer() throw() {
dealloc(mData, mSizeT);
}
BlockBuffer(u32 tSize, u32 growby=_1mb*2) {
mSizeT = tSize;
mGrowBy = growby;
mSize = 0;
alloc(mSizeT);
}
void append(void *addr, u32 size) {
if (mSize + size > mSizeT) grow(mSize*2 + size);
memcpy(&mData[mSize], addr, size);
if ((mSize + size) > mSizeT) grow(mSizeT + mGrowBy);
memcpy_fast(&mData[mSize], addr, size);
mSize += size;
}
// Increases the allocation size. Warning: Unlike 'realloc' this function will
// CLEAR all contents of the buffer. This is because copying contents of recompiled
// caches is mostly useless since it invalidates any pointers into the block.
// (code relocation techniques are possible, but are difficult, potentially slow,
// and easily bug prone. Not recommended at this time). --air
void grow(u32 newSize) {
pxAssume( newSize > mSizeT );
u8* temp = mData;
alloc (newSize);
memcpy (mData, temp, mSize);
alloc(newSize);
dealloc(temp, mSizeT);
clear();
mSizeT = newSize;
}
void clear() { mSize = 0; }
u32 getCurSize() { return mSize; }
u32 getSize() { return mSizeT; }
u8* getBlock() { return mData; }
// clears the entire buffer to recompiler fill (0xcc), and sets mSize to 0.
// (indicating none of the buffer is allocated).
void clear() {
if( mSize == 0 ) return; // no clears needed if nothing's been written/modified
mSize = 0;
memset(mData, 0xcc, mSizeT);
}
u32 getCurSize() { return mSize; }
u32 getAllocSize() { return mSizeT; }
u8* getBlock() { return mData; }
};

View File

@ -21,13 +21,40 @@
#include "newVif_UnpackSSE.h"
static __aligned16 nVifBlock _vBlock = {0};
static bool dVifIsInitialized[2] = { false, false };
void dVifInit(int idx) {
nVif[idx].vifCache = NULL;
nVif[idx].vifBlocks = NULL;
nVif[idx].numBlocks = 0;
nVif[idx].vifCache = new BlockBuffer(_1mb*4); // 4mb Rec Cache
nVif[idx].vifBlocks = new HashBucket<_tParams>();
nVif[idx].recPtr = NULL;
nVif[idx].recEnd = NULL;
dVifIsInitialized[idx] = true;
}
void dVifReset(int idx) {
if( !dVifIsInitialized[idx] ) return;
// If the VIF cache is greater than 12mb, then it's due for a complete reset back
// down to a reasonable starting point of 4mb.
if( nVif[idx].vifCache && (nVif[idx].vifCache->getAllocSize() > _1mb*12) )
safe_delete(nVif[idx].vifCache);
if( !nVif[idx].vifCache )
nVif[idx].vifCache = new BlockBuffer(_1mb*4);
else
nVif[idx].vifCache->clear();
if( !nVif[idx].vifBlocks )
nVif[idx].vifBlocks = new HashBucket<_tParams>();
else
nVif[idx].vifBlocks->clear();
nVif[idx].numBlocks = 0;
nVif[idx].recPtr = nVif[idx].vifCache->getBlock();
nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getSize()-(_1mb/4)]; // .25mb Safe Zone
nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone
}
void dVifClose(int idx) {
@ -201,11 +228,14 @@ static _f u8* dVifsetVUptr(const nVifStruct& v, int cl, int wl, bool isFill) {
return ptr;
}
// [TODO] : Finish implementing support for VIF's growable recBlocks buffer. Currently
// it clears the buffer only.
static _f void dVifRecLimit(int idx) {
if (nVif[idx].recPtr > nVif[idx].recEnd) {
DevCon.WriteLn("nVif Rec - Out of Rec Cache! [%x > %x]", nVif[idx].recPtr, nVif[idx].recEnd);
nVif[idx].vifBlocks->clear();
nVif[idx].recPtr = nVif[idx].vifCache->getBlock();
nVif[idx].recEnd = &nVif[idx].recPtr[nVif[idx].vifCache->getAllocSize()-(_1mb/4)]; // .25mb Safe Zone
}
}
@ -255,6 +285,8 @@ void dVifUnpack(int idx, u8 *data, u32 size, bool isFill) {
VifUnpackSSE_Dynarec( v, _vBlock ).CompileRoutine();
nVif[idx].recPtr = xGetPtr();
// [TODO] : Ideally we should test recompile buffer limits prior to each instruction,
// which would be safer and more memory efficient than using an 0.25 meg recEnd marker.
dVifRecLimit(idx);
// Run the block we just compiled. Various conditions may force us to still use

View File

@ -57,7 +57,7 @@ public:
mBucket[i].Size = 0;
}
}
~HashBucket() { clear(); }
virtual ~HashBucket() throw() { clear(); }
int quickFind(u32 data) {
return mBucket[data % hSize].Size;
}

View File

@ -69,7 +69,11 @@ static const __aligned16 Fnptr_VifUnpackLoop UnpackSingleTable[2][2][2] = {
};
// ----------------------------------------------------------------------------
void initNewVif(int idx) {
void resetNewVif(int idx)
{
// Safety Reset : Reassign all VIF structure info, just in case the VU1 pointers have
// changed for some reason.
nVif[idx].idx = idx;
nVif[idx].VU = idx ? &VU1 : &VU0;
nVif[idx].vif = idx ? &vif1 : &vif0;
@ -80,12 +84,17 @@ void initNewVif(int idx) {
nVif[idx].bSize = 0;
memzero(nVif[idx].buffer);
VifUnpackSSE_Init();
if (newVifDynaRec) dVifReset(idx);
}
void initNewVif(int idx) {
resetNewVif(idx);
if (newVifDynaRec) dVifInit(idx);
}
void closeNewVif(int idx) { if (newVifDynaRec) dVifClose(idx); }
void resetNewVif(int idx) { closeNewVif(idx); initNewVif(idx); }
void closeNewVif(int idx) {
if (newVifDynaRec) dVifClose(idx);
}
static _f u8* setVUptr(int vuidx, const u8* vuMemBase, int offset) {
return (u8*)(vuMemBase + ( offset & (vuidx ? 0x3ff0 : 0xff0) ));

View File

@ -60,13 +60,12 @@ EXPORT_C_(s32) FWinit()
FWLog.WriteLn("Initializing FWnull");
// Initializing our registers.
fwregs = (s8*)malloc(0x10000);
fwregs = (s8*)calloc(0x10000,1);
if (fwregs == NULL)
{
FWLog.Message("Error allocating Memory");
return -1;
}
memset(fwregs, 0, 0x10000);
return 0;
}
@ -74,6 +73,8 @@ EXPORT_C_(void) FWshutdown()
{
// Freeing the registers.
free(fwregs);
fwregs = NULL;
FWLog.Close();
}

View File

@ -56,7 +56,7 @@ EXPORT_C_(s32) USBinit()
USBLog.WriteLn("Initializing USBnull");
// Initialize memory structures here.
usbregs = (s8*)malloc(0x10000);
usbregs = (s8*)calloc(0x10000, 1);
if (usbregs == NULL)
{
@ -64,7 +64,6 @@ EXPORT_C_(s32) USBinit()
return -1;
}
memset(usbregs, 0, 0x10000);
return 0;
}
@ -73,6 +72,9 @@ EXPORT_C_(void) USBshutdown()
// Yes, we close things in the Shutdown routine, and
// don't do anything in the close routine.
USBLog.Close();
free(usbregs);
usbregs = NULL;
}
EXPORT_C_(s32) USBopen(void *pDsp)