PyrGC::PyrGC(VMGlobals *g, AllocPool *inPool, PyrClass *mainProcessClass, long poolSize) { mVMGlobals = g; mPool = inPool; //mCurSet = 0; mNumToScan = 0; mFlips = 0; mCollects = 0; mAllocTotal = 0; mNumAllocs = 0; mScans = 0; mStackScans = 0; mNumPartialScans = 0; mSlotsScanned = 0; mGreyColor = 3<<2; mBlackColor = 2<<2; mWhiteColor = 1<<2; mFreeColor = 0; mRunning = false; mCanSweep = false; mPartialScanObj = NULL; mPartialScanSlot = 0; mGrey.classptr = NULL; mGrey.obj_sizeclass = 0; mGrey.size = 0; mGrey.gc_color = obj_gcmarker; mGrey.prev = &mGrey; mGrey.next = &mGrey; mNumGrey = 0; mNewPool.Init(mPool, poolSize, poolSize, 9000); // initialize treadmills for (int i=0; i<kNumGCSets; ++i) { mSets[i].Init(i); } mProcess = newPyrProcess(g, mainProcessClass); mStack = mProcess->mainThread.uot->stack.uo; ToBlack(mStack); SetNil(&mProcess->mainThread.uot->stack); mNumGrey = 0; ToGrey2(mProcess); g->sp = mStack->slots - 1; g->process = mProcess; mRunning = true; SanityCheck(); //assert(SanityCheck()); }
void PyrGC::Flip() { #ifdef GC_SANITYCHECK SanityCheck(); #endif ScanFinalizers(); GCSet *gcs = mSets; if ((mFlips & 3) == 0) { // major flip for (int i=0; i<kNumGCSets; ++i, ++gcs) { gcs->MajorFlip(); } // advance colors mBlackColor += 4; mWhiteColor += 4; mGreyColor += 4; mFreeColor += 4; } else { // minor flip for (int i=0; i<kNumGCSets; ++i, ++gcs) { gcs->MinorFlip(); } } // move root to grey area mNumGrey = 0; ToGrey2(mProcess); ToBlack(mStack); // reset counts mNumToScan = 0; mCanSweep = true; mFlips++; //post("flips %d collects %d nalloc %d alloc %d grey %d\n", mFlips, mCollects, mNumAllocs, mAllocTotal, mNumGrey); #ifdef GC_SANITYCHECK SanityCheck(); #endif }
HOT bool PyrGC::ScanOneObj() { // Find a set that has a grey object PyrObject* obj; obj = (PyrObject*)mGrey.next; if (IsMarker(obj)) { if (mNumGrey) fatalerror("grey count error\n"); return false; } /*if (!IsGrey(obj)) { postfl("Object on grey list not grey %d %d\n", obj->gc_color, mGreyColor); fatalerror("C1"); }*/ mScans++; //post("-> scan %d %d %d\n", mNumGrey, IsGrey(obj), mNumToScan); // Found a grey object // move obj from grey to black ToBlack(obj); int32 size = ScanSize(obj); //post("<- scan %d %d %d %d\n", mNumGrey, IsGrey(obj), mNumToScan, size); if (size > mNumToScan + 32) { mPartialScanObj = obj; mPartialScanSlot = 0; DoPartialScan(size); } else if (size > 0) { ScanSlots(obj->slots, size); mNumToScan -= 1L << obj->obj_sizeclass; if (mNumToScan < 0) mNumToScan = 0; } else { mNumToScan -= 1L << obj->obj_sizeclass; if (mNumToScan < 0) mNumToScan = 0; } return true; }
void PyrGC::ScanFrames() { VMGlobals *g = mVMGlobals; PyrFrame* frame = g->frame; while (frame) { #if 1 // this is more incremental if (IsWhite(frame)) { ToGrey2(frame); } #else // this is more efficient if (!IsBlack(frame)) { ToBlack(frame); int32 size = ScanSize(frame); PyrSlot *slots = ((PyrObject*)frame)->slots; ScanSlots(slots, size); } #endif frame = slotRawFrame(&frame->caller); } }