gen_markcompact.c

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

C
1,514
字号
        return;    }    /*     * ROM objects should have been filtered out by the time we get here     */    CVMassert(!CVMobjectIsInROM(ref));    /*     * If this object has not been encountered yet, queue it up.     */    if (!CVMobjectMarked(ref)) {        CVMClassBlock *cb = CVMobjectGetClass(ref);	CVMobjectSetMarked(ref);	/* queue it up */	CVMtraceGcCollect(("GC[MC,%d]: Graying object %x\n",			   thisGen->gen.generationNo, ref));        /* If the object is an array of a basic type or if it is an instance           of java.lang.Object, then it contains no references.  Hence, no           need to queue it for further root traversal: */        if (!CVMisArrayOfAnyBasicType(cb) &&            (cb != CVMsystemClass(java_lang_Object))) {            /* If we get here, then the object might contain some refs.  Need               to queue it to check for refs later: */            addToTodo(thisGen, ref);        }    }}static voidCVMgenMarkCompactFilteredUpdateRoot(CVMObject** refPtr, void* data){    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)data;    CVMObject* ref = *refPtr;    if (!CVMgenMarkCompactInGeneration(thisGen, ref)) {	return;    }    /* The forwarding address is valid only for already marked       objects. If the object is not marked, then this slot has already       been 'seen'.    */    CVMassert(CVMobjectMarked(ref));    *refPtr = CVMgenMarkCompactGetForwardingPtr(ref);}typedef struct CVMGenMarkCompactTransitiveScanData {    CVMExecEnv* ee;    CVMGCOptions* gcOpts;    CVMGenMarkCompactGeneration* thisGen;} CVMGenMarkCompactTransitiveScanData;/* Scan and mark the references within an object and add them to the todo   list if necessary. */static voidCVMgenMarkCompactBlackenObject(CVMGenMarkCompactTransitiveScanData* tsd,			       CVMObject* ref, CVMClassBlock* refCb){    CVMGenMarkCompactGeneration* thisGen = tsd->thisGen;    CVMExecEnv* ee = tsd->ee;    CVMGCOptions* gcOpts = tsd->gcOpts;    CVMassert(ref != 0);    CVMtraceGcCollect(("GC[MC,%d,full]: Blacken object %x\n",		       thisGen->gen.generationNo,		       ref));    /*     * We'd better have grayed this object already.     */    CVMassert(CVMobjectMarked(ref));    /*     * Queue up all non-null object references. Handle the class as well.     */    CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, ref, refCb, {	if (*refPtr != 0) {	    CVMgenMarkCompactGrayObject(refPtr, thisGen);	}    }, CVMgenMarkCompactGrayObject, thisGen);}/* Scan all references in the objects that have been placed on the todo list   so that all the children can be scanned and marked as well. */static voidCVMgenMarkCompactFollowRoots(CVMGenMarkCompactGeneration* thisGen,			     CVMGenMarkCompactTransitiveScanData* tsd){    CVMtraceGcCollect(("GC[MC,%d]: Following roots\n",		       thisGen->gen.generationNo));    /* Go through the todo list and blacken each object in it.  To blacken       means to scan the references it contains.  Note that this may cause       more referred objects to be put on the todolist.  We'lll just keep       processing the todo list until all objects in it has been blackened.    */    while (!todoListIsEmpty(thisGen)) {        CVMObject* ref = popFromTodo(thisGen);        CVMClassBlock* refCB = CVMobjectGetClass(ref);	/* Blackening may queue up more objects: */	CVMgenMarkCompactBlackenObject(tsd, ref, refCB);    }}/* Mark the specified object as live and add it to a todo list   so that its children can be scanned and marked as live too. */static voidCVMgenMarkCompactScanTransitively(CVMObject** refPtr, void* data){    CVMGenMarkCompactTransitiveScanData* tsd =	(CVMGenMarkCompactTransitiveScanData*)data;    CVMGenMarkCompactGeneration* thisGen = tsd->thisGen;    CVMassert(refPtr != 0);    CVMassert(*refPtr != 0);    /* Mark the immediate object and put it on the todo list to have its       children scanned as well if necessary: */    CVMgenMarkCompactGrayObject(refPtr, thisGen);    /* Now scan all its children as well by going through the todo list: */    CVMgenMarkCompactFollowRoots(thisGen, tsd);}/* * Test whether a given reference is live or dying. If the reference * does not point to the current generation, answer TRUE. The generation * that does contain the pointer will give the right answer. */static CVMBoolCVMgenMarkCompactRefIsLive(CVMObject** refPtr, void* data){    CVMObject* ref;    CVMassert(refPtr != NULL);    ref = *refPtr;    CVMassert(ref != NULL);#ifdef CVM_INSPECTOR    /* If the VM inspector wants to force all objects to be alive, then we'll       say that the object is alive regardless of whether it is reachable or       not: */    if (CVMglobals.inspector.keepAllObjectsAlive) {        return CVM_TRUE;    }#endif    /*     * ROM objects are always live     */    if (CVMobjectIsInROM(ref)) {	return CVM_TRUE;    }    /* Did somebody else already scan or forward this object? It's live then */    return CVMobjectMarked(ref);}static CVMBoolCVMgenMarkCompactCollect(CVMGeneration* gen,			 CVMExecEnv*    ee, 			 CVMUint32      numBytes, /* collection goal */			 CVMGCOptions*  gcOpts){    CVMGenMarkCompactTransitiveScanData tsd;    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)gen;    CVMBool success;    CVMGenSpace* extraSpace;    CVMUint32* newAllocPtr;    CVMGeneration* youngGen = gen->prevGen;    CVMtraceGcCollect(("GC[MC,%d,full]: Starting GC\n", gen->generationNo));    CVMtraceGcStartStop(("GC[MC,%d,full]: Collecting\n",			 gen->generationNo));    CVMassert(GC_PHASE_RESET == thisGen->gcPhase);    extraSpace = youngGen->getExtraSpace(youngGen);    if (setjmp(thisGen->errorContext) != 0) {        goto handleError;    }    /* Initialize the todoList for use in the "mark" phase of the GC: */    /* Prepare the data structure that preserves original second header       words for use in the TODO stack. */    thisGen->preservedItems = (CVMMCPreservedItem*)extraSpace->allocBase;    thisGen->preservedIdx   = 0;    thisGen->preservedSize  = (CVMUint32)	((CVMMCPreservedItem*)extraSpace->allocTop - 	 (CVMMCPreservedItem*)extraSpace->allocBase);    thisGen->todoList = NULL;	    /*     * Prepare to do transitive scans      */    tsd.ee = ee;    tsd.gcOpts = gcOpts;    tsd.thisGen = thisGen;    /* The mark phase */    thisGen->gcPhase = GC_PHASE_MARK;    gcOpts->discoverWeakReferences = CVM_TRUE;    /*     * Scan all roots that point to this generation. The root callback is     * transitive, so 'children' are aggressively processed.     */    CVMgenScanAllRoots((CVMGeneration*)thisGen,		       ee, gcOpts, CVMgenMarkCompactScanTransitively, &tsd);    CVMthreadSchedHook(CVMexecEnv2threadID(ee));    /*     * Don't discover any more weak references.     */    gcOpts->discoverWeakReferences = CVM_FALSE;    /*     * At this point, we know which objects are live and which are not.     * Do the special objects processing.     */    /* NOTE: ProcessSpecial will call ProcessWeakrefWithLivenessInfo().        However, all transitive scans of weakref related objects will be       done before its FinalizeProcessing().  Hence, we'll be able to       use CVMweakrefCleanUpForGCAbort() to clean up should we encounter       an abort error here because we're guaranteed that we won't encounter       it in FinalizeProcessing() even though it does a transitive scan.       Its transitive scan will always turn up objects that has already       been scanned previously thereby requiring no work that can cause       an abort.           The processing of interned strings can cause some String objects       to be marked.  In an abort situation, this is all cleaned up properly       by the global unmarks() done in the handleError code below.           The processing of unreferencedMonitors will cause those monitors       to be released back into the system.  This side-effect is harmless       and need not be undone.  It's as if we did a partial collection       where we only collected unreferenced monitors.  Since the collection       is only done for objects that are no longer live anyway, the object       cannot be synchronized on.  Hence, it's safe to collect the monitor.           */    gcOpts->isUpdatingObjectPointers = CVM_FALSE;    CVMgcProcessSpecialWithLivenessInfo(ee, gcOpts,					CVMgenMarkCompactRefIsLive, thisGen,					CVMgenMarkCompactScanTransitively,					&tsd);    gcOpts->isUpdatingObjectPointers = CVM_TRUE;    /* Reset the data structure that preserves original second header       words. We are done with the TODO stack, so we can re-use extraSpace. */    thisGen->preservedItems = (CVMMCPreservedItem*)extraSpace->allocBase;    CVMassert(thisGen->preservedIdx == 0);    CVMassert(thisGen->preservedSize == (CVMUint32)	      ((CVMMCPreservedItem*)extraSpace->allocTop - 	       (CVMMCPreservedItem*)extraSpace->allocBase));	    /* The sweep phase. This phase computes the new addresses of each       object and writes it in the second header word. Evacuated       original header words will be kept in the 'preservedItems'       list. */    /* NOTE: If an abort happens here within the sweep phase, no weakref       processing is involved.  Weakref constructs are only updated after       the sweeping action of computing forwarding pointers is completed       at which point no GC abort can occur.  Hence, no cleanup action is       required for weakrefs in the sweep phase.        The same is true for the processing of interned strings.    */    thisGen->gcPhase = GC_PHASE_SWEEP;    newAllocPtr = sweep(ee, thisGen, gen->allocBase, gen->allocPtr);    CVMassert(newAllocPtr <= gen->allocPtr);    /* At this point, the new addresses of each object are written in       the headers of the old. Update all pointers to refer to the new       copies. */    /* Update the roots */    CVMgenScanAllRoots((CVMGeneration*)thisGen, ee, gcOpts,		       CVMgenMarkCompactFilteredUpdateRoot, thisGen);    CVMgcScanSpecial(ee, gcOpts,		     CVMgenMarkCompactFilteredUpdateRoot, thisGen);    /* NOTE: CVMgenScanAllRoots() only scan the tree of GC roots.  Unlike in       the mark phase, the scan is not being done transitively.  Hence, the       objects in the heap are not scanned as part of this traversal.  So,       we must scan the heap objects explicitly here: */    /* Update all interior pointers. */    scanObjectsInYoungGenRange(thisGen, ee, gcOpts,			       youngGen->allocBase, youngGen->allocPtr);    scanObjectsInRangeSkipUnmarked(thisGen,				   ee, gcOpts, gen->allocBase, gen->allocPtr);    /* Unmark: Clear/reset marks on the objects in the youngGen: */    unmark(thisGen, youngGen->allocBase, youngGen->allocPtr);    /* Compact: Move objects and reset marks in the oldGen: */    compact(ee, thisGen, gen->allocBase, gen->allocPtr);    /* Restore the "non-trivial" old header words into the object header words       which were used for storing forwarding addresses: */    restorePreservedHeaderWords(thisGen);    /* Update the allocation pointers: */    gen->allocPtr = newAllocPtr;    gen->allocMark = newAllocPtr;    /*     * Now since we are not in the young generation, we have to     * rebuild the barrier structures.       */    CVMgenClearBarrierTable();    CVMgenMarkCompactRebuildBarrierTable(thisGen, ee, gcOpts,					 gen->allocBase,					 gen->allocPtr);    thisGen->gcPhase = GC_PHASE_RESET;     /* Determine if we succeed or not based on whether we were able to free up        a contiguous chunk of memory of the requested size: */    success = (numBytes/4 <= (CVMUint32)(gen->allocTop - gen->allocPtr));    CVMtraceGcStartStop(("GC[MC,%d,full]: Done, success for %d bytes %s\n",			 gen->generationNo, numBytes,			 success ? "TRUE" : "FALSE"));    CVMtraceGcCollect(("GC[MC,%d,full]: Ending GC\n", gen->generationNo));    /*     * Can we allocate in this space after this GC?     */    return success;handleError:    /* Undo side-effects of work done before error was detected: */    if (thisGen->gcPhase == GC_PHASE_MARK) {        /* Undo the effects of the mark phase: */        /* Restore all the headerwords in the todoList: */        while (!todoListIsEmpty(thisGen)) {            popFromTodo(thisGen);        }        /* Removed all the marks from the objects in both generations: */        unmark(thisGen, youngGen->allocBase, youngGen->allocPtr);        unmark(thisGen, gen->allocBase, gen->allocPtr);    } else if (thisGen->gcPhase == GC_PHASE_SWEEP) {        /* Undo the effects of the sweep phase: */        /* Reset the data structure that preserves original second header           words. We are done with the TODO stack, so we can re-use extraSpace. */        thisGen->preservedItems = (CVMMCPreservedItem*)extraSpace->allocBase;        thisGen->preservedIdx   = 0;        thisGen->preservedSize  = (CVMUint32)            ((CVMMCPreservedItem*)extraSpace->allocTop -              (CVMMCPreservedItem*)extraSpace->allocBase);        unmark(thisGen, youngGen->allocBase, youngGen->allocPtr);        unsweepAndUnmark(thisGen, gen->allocBase, gen->allocPtr);#ifdef CVM_DEBUG    } else {        CVMpanic("Unknown GC phase!");#endif    }    CVMweakrefCleanUpForGCAbort(ee);    thisGen->gcPhase = GC_PHASE_RESET;    return CVM_FALSE;}

⌨️ 快捷键说明

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