gen_markcompact.c

来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,514 行 · 第 1/4 页

C
1,514
字号
/* Pops an item and removes it from the todoList. */static CVMObject *popFromTodo(CVMGenMarkCompactGeneration* thisGen){    CVMObject* ref = thisGen->todoList;    volatile CVMAddr *headerAddr = &CVMobjectVariousWord(ref);    CVMAddr next = *headerAddr;    thisGen->todoList = (CVMObject *)(next & ~0x1);    /* Restore the header various word that we used to store the next       pointer of the todoList: */    if ((next & 0x1) != 0) {        CVMInt32 idx = --thisGen->preservedIdx;        CVMMCPreservedItem* item = &thisGen->preservedItems[idx];        CVMassert(idx >= 0);        CVMassert(item->movedRef == ref);        CVMassert(!CVMobjectTrivialHeaderWord(item->originalWord));        *headerAddr = item->originalWord;        CVMtraceGcScan(("GC[MC,%d]: "                        "Restoring header %x for obj 0x%x at i=%d\n",                        thisGen->gen.generationNo, item->originalWord,                        ref, idx));    } else {        /* NOTE: popFromTodo can be used to handle objects in the youngGen	   as well.  For those, we want to ensure that their GC age is at	   least 1.  This is because we must have at least gone through one	   youngGen GC before getting here.  If we simply reset the header	   word to CVM_OBJECT_DEFAULT_VARIOUS_WORD, then the age will be	   reset to 0 thereby causing the object to stay longer in the	   youngGen then it should.  Setting the age to 1 does not guarantee	   that we have the proper age of the object, but it is at least	   closer to the real age than an age of 0.	*/        *headerAddr = CVM_OBJECT_DEFAULT_VARIOUS_WORD | (1 << CVM_GC_SHIFT);    }    return ref;}/* Checks to see if the todoList is empty. *//* static CVMBool   todoListIsEmpty(CVMGenMarkCompactGeneration* thisGen); */#define todoListIsEmpty(thisGen)    ((thisGen)->todoList == NULL)/* * Restore all preserved header words. */static voidrestorePreservedHeaderWords(CVMGenMarkCompactGeneration* thisGen){    CVMInt32 idx;    CVMtraceGcScan(("GC[MC,%d]: Restoring %d preserved headers\n",		    thisGen->gen.generationNo,		    thisGen->preservedIdx));    while ((idx = --thisGen->preservedIdx) >= 0) {	CVMMCPreservedItem* item = &thisGen->preservedItems[idx];	CVMObject* movedRef = item->movedRef;	/*	 * Make sure that the object we are looking at now has the default	 * various word set up for now	 */	CVMassert(CVMobjectTrivialHeaderWord(CVMobjectVariousWord(movedRef)));	/*	 * And also, that we did not evacuate this word for nothing	 */	CVMassert(!CVMobjectTrivialHeaderWord(item->originalWord));	CVMobjectVariousWord(movedRef) = item->originalWord;	CVMtraceGcScan(("GC[MC,%d]: "			"Restoring header %x for obj 0x%x at i=%d\n",			thisGen->gen.generationNo, item->originalWord,			movedRef, idx));    }}/* * Preserve a header word for an object in its new address. */static voidpreserveHeaderWord(CVMGenMarkCompactGeneration* thisGen,		   CVMObject* movedRef, CVMAddr originalWord){    CVMMCPreservedItem* item = &thisGen->preservedItems[thisGen->preservedIdx];    if (thisGen->preservedIdx >= thisGen->preservedSize) {        thisGen->lastProcessedRef = movedRef;        gcError(thisGen);    }    /* Write out the new item: */    item->movedRef     = movedRef;    item->originalWord = originalWord;    CVMtraceGcScan(("GC[MC,%d]: Preserving header %x for obj 0x%x at i=%d\n",		    thisGen->gen.generationNo, originalWord, movedRef,		    thisGen->preservedIdx));    thisGen->preservedIdx++;#ifdef MAX_STACK_DEPTHS    if (thisGen->preservedIdx >= preservedIdxMax) {	preservedIdxMax = thisGen->preservedIdx;	CVMconsolePrintf("**** preserved: max depth=%d\n", preservedIdxMax);    }#endif /* MAX_STACK_DEPTHS */}/* Sweep the heap, compute the compacted addresses, write them into the   original object headers, and return the new allocPtr of this space. */static CVMUint32*sweep(CVMExecEnv* ee, CVMGenMarkCompactGeneration* thisGen,      CVMUint32* base, CVMUint32* top){    CVMUint32* forwardingAddress = base;    CVMUint32* curr = base;    CVMtraceGcCollect(("GC[MC,%d]: Sweeping object range [%x,%x)\n",		       thisGen->gen.generationNo, base, top));    while (curr < top) {        CVMUint32* nextChunk = curr + CHUNK_SIZE;        if (nextChunk > top) {            nextChunk = top;        }        while (curr < nextChunk) {	    CVMObject* currObj    = (CVMObject*)curr;	    CVMAddr    classWord  = CVMobjectGetClassWord(currObj);	    CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord);	    CVMUint32  objSize    = CVMobjectSizeGivenClass(currObj, currCb);	    if (CVMobjectMarkedOnClassWord(classWord)) {	        volatile CVMAddr* headerAddr   = &CVMobjectVariousWord(currObj);	        CVMAddr  originalWord = *headerAddr;	        CVMtraceGcScan(("GC[MC,%d]: obj 0x%x -> 0x%x\n",			        thisGen->gen.generationNo, curr,			        forwardingAddress));	        if (!CVMobjectTrivialHeaderWord(originalWord)) {		    /* Preserve the old header word with the new address                       of object, but only if it is non-trivial. */		    preserveHeaderWord(thisGen, 		        (CVMObject *)forwardingAddress, originalWord);	        }	        /* Set forwardingAddress in header */	        *headerAddr = (CVMAddr)forwardingAddress;	        /* Pretend to have copied this live object! */	        forwardingAddress += objSize / 4;            } else {#ifdef CVM_JVMPI	        {		    extern CVMUint32 liveObjectCount;                    if (CVMjvmpiEventObjectFreeIsEnabled()) {                        CVMjvmpiPostObjectFreeEvent(currObj);                    }		    liveObjectCount--;	        }#endif#ifdef CVM_JVMTI	        {                    if (CVMjvmtiShouldPostObjectFree()) {                        CVMjvmtiPostObjectFreeEvent(currObj);                    }	        }#endif#ifdef CVM_INSPECTOR	        /* We only need to report this if there are captured states that	           need to be updated: */	        if (CVMglobals.inspector.hasCapturedState) {    	            CVMgcHeapStateObjectFreed(currObj);	        }#endif	    }	    /* iterate */	    curr += objSize / 4;        }        CVMthreadSchedHook(CVMexecEnv2threadID(ee));    }    CVMassert(curr == top); /* This had better be exact */    CVMtraceGcCollect(("GC[MC,%d]: Swept object range [%x,%x) -> 0x%x\n",		       thisGen->gen.generationNo, base, top,		       forwardingAddress));    return forwardingAddress;}static void unmark(CVMGenMarkCompactGeneration* thisGen, CVMUint32* base, CVMUint32* top){    CVMUint32* curr = base;    CVMtraceGcCollect(("GC[MC,%d]: Unmarking object range [%x,%x)\n",		       thisGen->gen.generationNo, base, top));    while (curr < top) {	CVMObject*     currObj   = (CVMObject*)curr;	CVMAddr        classWord = CVMobjectGetClassWord(currObj);	CVMClassBlock* currCb    = CVMobjectGetClassFromClassWord(classWord);	CVMUint32      objSize   = CVMobjectSizeGivenClass(currObj, currCb);	if (CVMobjectMarkedOnClassWord(classWord)) {	    CVMobjectClearMarkedOnClassWord(classWord);	    CVMobjectSetClassWord(currObj, classWord);	}	/* iterate */	curr += objSize / 4;    }    CVMassert(curr == top); /* This had better be exact */}/* Purpose: Get the header words that were saved away by preservedHeaderWord.            This should only be called by unsweepAndUnmark() below.  Since	    unsweepAndUnmark() scans the heap in exactly the same order as	    sweep(), we should be getting the objects in exactly the same	    order as was preserved by preservedHeaderWords.  This should allow	    us to restore the original words to the objects.  NOTE: We cannot use restorePreservedHeaderWords() to restore the header        words because it assumes that the objects has been moved and does its        restoration based on forwarded pointers.  We want to restore the        original objects because we're aborting the GC before the object	motion in the compact phase.*/static CVMAddrgetHeaderWord(CVMGenMarkCompactGeneration* thisGen, CVMObject* ref,	      CVMObject* forwardedRef){    CVMAddr result = CVM_OBJECT_DEFAULT_VARIOUS_WORD;    /* We only do restorations when we encountered an error due to having       exhausted the preservedSize.  So, we only have preserved words for       the case when we haven't exhausted the preservedSize yet. */    if (thisGen->lastProcessedRef != NULL) {        if (thisGen->lastProcessedRef == forwardedRef) {            /* We have reached the last of the list of objects that were               swept: */	    /* NOTE: The lastProcessedRef points to the next object that	       would have been swept if we had not run out of scratch space.	       Hence, it's header word is still intact.  Nothing needs to	       be done to restore it.	    */            thisGen->lastProcessedRef = NULL; /* Indicate we're done. */            goto noMoreSweptObjects;        } else {            CVMMCPreservedItem* item;            CVMassert(thisGen->preservedIdx <= thisGen->preservedSize);            item = &thisGen->preservedItems[thisGen->preservedIdx];            /* If the forwarding address in the object's header matches the	       current preserved item in the list, then the original word	       must have been preserved in the preserved item.  Restore this	       word and increment the preserved index.	       Otherwise, the original word must have been the default	       various word value (i.e. CVM_OBJECT_DEFAULT_VARIOUS_WORD)	       or equivalent.  The only difference may be the GC age, but	       that information is inconsequential for objects in the old	       generation.  Hence, we simply restore it to the default word.	    */            if (item->movedRef == forwardedRef) {                result = item->originalWord;                thisGen->preservedIdx++;	    }	}    } else {noMoreSweptObjects:        /* This object's header wasn't changed.  Just return the original word	   in the object header: */        result = CVMobjectVariousWord(ref);    }    return result;}/* Purpose: Restore the objects header words modified by the sweep phase. */static voidunsweepAndUnmark(CVMGenMarkCompactGeneration* thisGen, CVMUint32* base,		 CVMUint32* top){    CVMUint32* forwardingAddress = base;    CVMUint32* curr = base;    while (curr < top) {	CVMObject*     currObj   = (CVMObject*)curr;	CVMAddr        classWord = CVMobjectGetClassWord(currObj);	CVMClassBlock* currCb    = CVMobjectGetClassFromClassWord(classWord);	CVMUint32      objSize   = CVMobjectSizeGivenClass(currObj, currCb);	if (CVMobjectMarkedOnClassWord(classWord)) {	    if (thisGen->lastProcessedRef != NULL) {	        volatile CVMAddr* headerAddr = &CVMobjectVariousWord(currObj);	        CVMAddr  originalWord;	        originalWord = getHeaderWord(thisGen, currObj,					     (CVMObject *)forwardingAddress);	        *headerAddr = originalWord;	        /* Pretend to have copied this live object! */	        forwardingAddress += objSize / 4;            }            /* Deleted mark in the object. */	    /* NOTE: The sweep phase would leave the mark on the object	       intact.  It's the compact phase that unmarks it.  But in this	       case, we are already iterating the heap to undo the sweep	       effects in an abort operation.  Hence, we'll take this	       opportunity to unmark the objects too. */            CVMobjectClearMarkedOnClassWord(classWord);            CVMobjectSetClassWord(currObj, classWord);        }	/* iterate */	curr += objSize / 4;    }    CVMassert(curr == top); /* This had better be exact */}/* Finally we can move objects, reset marks, and restore original   header words. */static void compact(CVMExecEnv* ee, CVMGenMarkCompactGeneration* thisGen,        CVMUint32* base, CVMUint32* top){    CVMUint32* curr = base;    CVMtraceGcCollect(("GC[MC,%d]: Compacting object range [%x,%x)\n",		       thisGen->gen.generationNo, base, top));    while (curr < top) {        CVMUint32* nextChunk = curr + CHUNK_SIZE;        if (nextChunk > top) {            nextChunk = top;        }        while (curr < nextChunk) {	    CVMObject*     currObj   = (CVMObject*)curr;	    CVMAddr        classWord = CVMobjectGetClassWord(currObj);	    CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord);	    CVMUint32      objSize = CVMobjectSizeGivenClass(currObj, currCb);	    if (CVMobjectMarkedOnClassWord(classWord)) {	        CVMUint32* destAddr = (CVMUint32*)		    CVMgenMarkCompactGetForwardingPtr(currObj);	        CVMobjectClearMarkedOnClassWord(classWord);#ifdef CVM_DEBUG	        /* For debugging purposes, make sure the deleted mark is	           reflected in the original copy of the object as well. */	        CVMobjectSetClassWord(currObj, classWord);#endif	        CVMgenMarkCompactCopyDown(destAddr, curr, objSize);#ifdef CVM_JVMPI                if (CVMjvmpiEventObjectMoveIsEnabled()) {                    CVMjvmpiPostObjectMoveEvent(1, curr, 1, destAddr);                }#endif#ifdef CVM_INSPECTOR	        if (CVMglobals.inspector.hasCapturedState) {	            CVMgcHeapStateObjectMoved(currObj, (CVMObject *)destAddr);	        }#endif	        /*	         * First assume that all objects had the default various	         * word. We'll patch the rest shortly.	         * 	         * Note that this clears the GC bits portion. No worries,	         * we won't need that anymore in this generation.	         */	        CVMobjectVariousWord((CVMObject*)destAddr) =		    CVM_OBJECT_DEFAULT_VARIOUS_WORD;	        /* Write the class word whose mark has just been cleared */	        CVMobjectSetClassWord((CVMObject*)destAddr, classWord);	    }	    /* iterate */	    curr += objSize / 4;        }        CVMthreadSchedHook(CVMexecEnv2threadID(ee));     }    CVMassert(curr == top); /* This had better be exact */}/* Gray an object known to be alive. */static voidCVMgenMarkCompactGrayObject(CVMObject** refPtr, void* data){    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)data;    CVMObject* ref = *refPtr;    if (CVMobjectIsInROM(ref)) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?