From 8978e463ecb15274163de6da0f1516d99fa30823 Mon Sep 17 00:00:00 2001 From: cottonvibes Date: Thu, 11 Mar 2010 04:03:08 +0000 Subject: [PATCH] mVU: fixed some memleaks and fixed some rare bugs in microprogram range detection... git-svn-id: http://pcsx2.googlecode.com/svn/trunk@2692 96395faa-99c1-11dd-bbfe-3dabce05a288 --- pcsx2/x86/microVU.cpp | 37 ++++++++------- pcsx2/x86/microVU.h | 19 +++----- pcsx2/x86/microVU_Alloc.inl | 2 +- pcsx2/x86/microVU_Compile.inl | 84 +++++++++++++++-------------------- pcsx2/x86/microVU_Misc.h | 4 +- 5 files changed, 65 insertions(+), 81 deletions(-) diff --git a/pcsx2/x86/microVU.cpp b/pcsx2/x86/microVU.cpp index 81b1f0a4a3..bc0b388387 100644 --- a/pcsx2/x86/microVU.cpp +++ b/pcsx2/x86/microVU.cpp @@ -132,6 +132,11 @@ _f void mVUreset(mV) { mVU->prog.x86end = (u8*)((uptr)z + (uptr)(mVU->cacheSize - (_1mb * 3))); // 3mb "Safe Zone" for (u32 i = 0; i < (mVU->progSize / 2); i++) { + deque::iterator it = mVU->prog.prog[i].list->begin(); + for ( ; it != mVU->prog.prog[i].list->end(); it++) { + if (!isVU1) mVUdeleteProg<0>(it[0]); + else mVUdeleteProg<1>(it[0]); + } mVU->prog.prog[i].list->clear(); mVU->prog.quick[i].block = NULL; mVU->prog.quick[i].prog = NULL; @@ -147,7 +152,8 @@ _f void mVUclose(mV) { for (u32 i = 0; i < (mVU->progSize / 2); i++) { deque::iterator it = mVU->prog.prog[i].list->begin(); for ( ; it != mVU->prog.prog[i].list->end(); it++) { - safe_aligned_free(it[0]); + if (!isVU1) mVUdeleteProg<0>(it[0]); + else mVUdeleteProg<1>(it[0]); } safe_delete(mVU->prog.prog[i].list); } @@ -176,18 +182,14 @@ _f void mVUvsyncUpdate(mV) { //mVU->prog.curFrame++; } -// Clears program data -_mVUt _f void mVUclearProg(microProgram& program, u32 startPC, bool deleteBlocks) { +// Deletes a program +_mVUt _f void mVUdeleteProg(microProgram*& prog) { microVU* mVU = mVUx; - program.startPC = startPC; - for (int j = 0; j <= program.ranges.max; j++) { - program.ranges.range[j][0] = -1; // Set range to - program.ranges.range[j][1] = -1; // indeterminable status - program.ranges.total = -1; - } for (u32 i = 0; i < (mVU->progSize / 2); i++) { - if (deleteBlocks) safe_delete(program.block[i]); + safe_delete(prog->block[i]); } + safe_delete(prog->ranges); + safe_aligned_free(prog); } // Creates a new Micro Program @@ -195,8 +197,9 @@ _mVUt _f microProgram* mVUcreateProg(int startPC) { microVU* mVU = mVUx; microProgram* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64); memzero_ptr(prog); - prog->idx = mVU->prog.total++; - mVUclearProg(*prog, startPC); + prog->idx = mVU->prog.total++; + prog->ranges = new deque(); + prog->startPC = startPC; mVUcacheProg(*prog); // Cache Micro Program float cacheSize = (float)((u32)mVU->prog.x86end - (u32)mVU->prog.x86start); float cacheUsed =((float)((u32)mVU->prog.x86ptr - (u32)mVU->prog.x86start)) / cacheSize * 100; @@ -217,10 +220,10 @@ _mVUt _f void mVUcacheProg(microProgram& prog) { // Compare partial program by only checking compiled ranges... _mVUt _f bool mVUcmpPartial(microProgram& prog) { microVU* mVU = mVUx; - for (int i = 0; i <= prog.ranges.total; i++) { - if((prog.ranges.range[i][0] < 0) - || (prog.ranges.range[i][1] < 0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, i, prog.ranges.total); } - if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((prog.ranges.range[i][1] + 8) - prog.ranges.range[i][0]))) { + deque::const_iterator it = prog.ranges->begin(); + for ( ; it != prog.ranges->end(); it++) { + if((it[0].start<0)||(it[0].end<0)) { DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU->index, it[0].start, it[0].end); } + if (memcmp_mmx(cmpOffset(prog.data), cmpOffset(mVU->regs->Micro), ((it[0].end + 8) - it[0].start))) { return 0; } } @@ -246,7 +249,7 @@ _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState) { microProgramQuick& quick = mVU->prog.quick[startPC/8]; microProgramList& list = mVU->prog.prog [startPC/8]; if(!quick.prog) { // If null, we need to search for new program - deque::iterator it = list.list->begin(); + deque::const_iterator it = list.list->begin(); for ( ; it != list.list->end(); it++) { if (mVUcmpProg(*it[0], 0)) { quick.block = it[0]->block[startPC/8]; diff --git a/pcsx2/x86/microVU.h b/pcsx2/x86/microVU.h index d9cae7fbf7..5d299fb826 100644 --- a/pcsx2/x86/microVU.h +++ b/pcsx2/x86/microVU.h @@ -109,25 +109,16 @@ public: } }; -#define mMaxRanges 128 struct microRange { - static const int max = mMaxRanges - 1; - int total; - s32 range[mMaxRanges][2]; -}; - -enum microProgramAge { - isYoung = 0, - isAged = 1, - isOld = 2, - isDead = 3 + s32 start; // Start PC (The opcode the block starts at) + s32 end; // End PC (The opcode the block ends with) }; #define mProgSize (0x4000/4) struct microProgram { u32 data [mProgSize]; // Holds a copy of the VU microProgram microBlockManager* block[mProgSize/2]; // Array of Block Managers - microRange ranges; // The ranges of the microProgram that have already been recompiled + deque* ranges; // The ranges of the microProgram that have already been recompiled u32 startPC; // Start PC of this program int idx; // Program index }; @@ -214,8 +205,8 @@ mVUop(mVUopU); mVUop(mVUopL); // Private Functions -_mVUt _f void mVUclearProg(microProgram& prog, u32 startPC = -1, bool deleteBlocks = 1); -_mVUt _f void mVUcacheProg(microProgram& prog); +_mVUt _f void mVUcacheProg (microProgram& prog); +_mVUt _f void mVUdeleteProg(microProgram*& prog); _mVUt _f void* mVUsearchProg(u32 startPC, uptr pState); _mVUt _f microProgram* mVUfindLeastUsedProg(); void* __fastcall mVUexecuteVU0(u32 startPC, u32 cycles); diff --git a/pcsx2/x86/microVU_Alloc.inl b/pcsx2/x86/microVU_Alloc.inl index 02f0af0bab..bcf1e51b7b 100644 --- a/pcsx2/x86/microVU_Alloc.inl +++ b/pcsx2/x86/microVU_Alloc.inl @@ -144,7 +144,7 @@ _f void mVUallocVIb(mV, int GPRreg, int _reg_) { } //------------------------------------------------------------------ -// I/P/Q Reg Allocators +// P/Q Reg Allocators //------------------------------------------------------------------ _f void getPreg(mV, int reg) { diff --git a/pcsx2/x86/microVU_Compile.inl b/pcsx2/x86/microVU_Compile.inl index fbf39a5f2b..27b496466e 100644 --- a/pcsx2/x86/microVU_Compile.inl +++ b/pcsx2/x86/microVU_Compile.inl @@ -44,64 +44,54 @@ _f void mVUcheckIsSame(mV) { } // Sets up microProgram PC ranges based on whats been recompiled -_f void mVUsetupRange(mV, s32 pc, bool isStartPC) { +_f void mVUsetupRange(microVU* mVU, s32 pc, bool isStartPC) { + deque*& ranges = mVUcurProg.ranges; + pc &= mVU->microMemSize - 8; - if (isStartPC || !(mVUrange[1] == -1)) { - for (int i = 0; i <= mVUcurProg.ranges.total; i++) { - if ((pc >= mVUcurProg.ranges.range[i][0]) - && (pc <= mVUcurProg.ranges.range[i][1])) { return; } + if (isStartPC) { // Check if startPC is already within a block we've recompiled + deque::const_iterator it = ranges->begin(); + for ( ; it != ranges->end(); it++) { + if ((pc >= it[0].start) && (pc <= it[0].end)) { + if (it[0].start != it[0].end) + return; // Last case makes sure its not a 1-opcode EvilBlock + } } } + elif (mVUrange.end != -1) return; // Above case was true mVUcheckIsSame(mVU); if (isStartPC) { - if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) { - mVUcurProg.ranges.total++; - mVUrange[0] = pc; + microRange mRange = {pc, -1}; + ranges->push_front(mRange); + return; + } + if (mVUrange.start <= pc) { + mVUrange.end = pc; + bool mergedRange = 0; + s32 rStart = mVUrange.start; + s32 rEnd = mVUrange.end; + deque::iterator it = ranges->begin(); + for (it++; it != ranges->end(); it++) { + if((it[0].start >= rStart) && (it[0].start <= rEnd)) { + it[0].end = aMax(it[0].end, rEnd); + mergedRange = 1; + } + elif((it[0].end >= rStart) && (it[0].end <= rEnd)) { + it[0].start = aMin(it[0].start, rStart); + mergedRange = 1; + } } - else { - mVUcurProg.ranges.total = 0; - mVUrange[0] = 0; - mVUrange[1] = mVU->microMemSize - 8; - DevCon.Warning("microVU%d: Prog Range List Full", mVU->index); + if (mergedRange) { + //DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Merging", mVU->index); + ranges->erase(ranges->begin()); } } else { - if (mVUrange[0] <= pc) { - mVUrange[1] = pc; - bool mergedRange = 0; - for (int i = 0; i <= (mVUcurProg.ranges.total-1); i++) { - int rStart = (mVUrange[0] < 8) ? 0 : (mVUrange[0] - 8); - int rEnd = pc; - if((mVUcurProg.ranges.range[i][1] >= rStart) - && (mVUcurProg.ranges.range[i][1] <= rEnd)){ - mVUcurProg.ranges.range[i][1] = pc; - mergedRange = 1; - //DevCon.Status("microVU%d: Prog Range Merging", mVU->index); - } - } - if (mergedRange) { - mVUrange[0] = -1; - mVUrange[1] = -1; - mVUcurProg.ranges.total--; - } - } - else { - DevCon.WriteLn("microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange[0], mVUrange[1]); - mVUrange[1] = mVU->microMemSize - 8; - if (mVUcurProg.ranges.total < mVUcurProg.ranges.max) { - mVUcurProg.ranges.total++; - mVUrange[0] = 0; - mVUrange[1] = pc; - } - else { - mVUcurProg.ranges.total = 0; - mVUrange[0] = 0; - mVUrange[1] = mVU->microMemSize - 8; - DevCon.Warning("microVU%d: Prog Range List Full", mVU->index); - } - } + //DevCon.WriteLn(Color_Green, "microVU%d: Prog Range Wrap [%04x] [%d]", mVU->index, mVUrange.start, mVUrange.end); + mVUrange.end = mVU->microMemSize; + microRange mRange = {0, pc}; + ranges->push_front(mRange); } } diff --git a/pcsx2/x86/microVU_Misc.h b/pcsx2/x86/microVU_Misc.h index a863279424..5858aa8773 100644 --- a/pcsx2/x86/microVU_Misc.h +++ b/pcsx2/x86/microVU_Misc.h @@ -177,7 +177,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define sFLAG mVUinfo.sFlag #define mFLAG mVUinfo.mFlag #define cFLAG mVUinfo.cFlag -#define mVUrange mVUcurProg.ranges.range[mVUcurProg.ranges.total] +#define mVUrange (mVUcurProg.ranges[0])[0] #define isEvilBlock (mVUpBlock->pState.blockType == 2) #define isBadOrEvil (mVUlow.badBranch || mVUlow.evilBranch) #define xPC ((iPC / 2) * 8) @@ -189,7 +189,7 @@ typedef u32 (__fastcall *mVUCall)(void*, void*); #define branchAddr ((xPC + 8 + (_Imm11_ * 8)) & (mVU->microMemSize-8)) #define branchAddrN ((xPC + 16 + (_Imm11_ * 8)) & (mVU->microMemSize-8)) #define shufflePQ (((mVU->p) ? 0xb0 : 0xe0) | ((mVU->q) ? 0x01 : 0x04)) -#define cmpOffset(x) ((u8*)&(((u8*)x)[prog.ranges.range[i][0]])) +#define cmpOffset(x) ((u8*)&(((u8*)x)[it[0].start])) #define Rmem (uptr)&mVU->regs->VI[REG_R].UL #define aWrap(x, m) ((x > m) ? 0 : x) #define shuffleSS(x) ((x==1)?(0x27):((x==2)?(0xc6):((x==4)?(0xe1):(0xe4))))