gen_markcompact.c

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

C
1,514
字号
	CVMObject* currObj    = (CVMObject*)curr;	CVMAddr    classWord  = CVMobjectGetClassWord(currObj);	CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord);	CVMUint32  objSize    = CVMobjectSizeGivenClass(currObj, currCb);	if (CVMobjectMarkedOnClassWord(classWord)) {	    CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj,						 classWord, {		if (*refPtr != 0) {		    CVMgenMarkCompactFilteredUpdateRoot(refPtr, thisGen);		}	    }, CVMgenMarkCompactFilteredUpdateRoot, thisGen);	} 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	    CVMgcReplaceWithPlaceHolderObject(currObj, objSize);	}	/* iterate */	curr += objSize / 4;    }    CVMassert(curr == top); /* This had better be exact */}#else#define scanObjectsInYoungGenRange scanObjectsInRangeSkipUnmarked#endif /* CVM_INSPECTOR || CVM_JVMPI || CVM_JVMTI *//* * Scan objects in contiguous range, and do all special handling as well. * Ignore unmarked objects. */static voidscanObjectsInRangeSkipUnmarked(CVMGenMarkCompactGeneration* thisGen,			       CVMExecEnv* ee, CVMGCOptions* gcOpts,			       CVMUint32* base, CVMUint32* top){    CVMUint32* curr = base;    CVMtraceGcCollect(("GC[MC,full]: "		       "Scanning object range (skip unmarked) [%x,%x)\n",		       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)) {	        CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj,						     classWord, {		    if (*refPtr != 0) {		        CVMgenMarkCompactFilteredUpdateRoot(refPtr, thisGen);		    }	        }, CVMgenMarkCompactFilteredUpdateRoot, thisGen);	    }	    /* iterate */	    curr += objSize / 4;        }        CVMthreadSchedHook(CVMexecEnv2threadID(ee));    }    CVMassert(curr == top); /* This had better be exact */}/* * Re-build the old-to-young pointer.  */voidCVMgenMarkCompactRebuildBarrierTable(CVMGenMarkCompactGeneration* thisGen,				     CVMExecEnv* ee,				     CVMGCOptions* gcOpts,				     CVMUint32* startRange,				     CVMUint32* endRange){    CVMtraceGcCollect(("GC[MC,%d,full]: "		       "Rebuilding barrier table for range [%x,%x)\n",		       thisGen->gen.generationNo,		       startRange, endRange));    /*     * No need to look at classes here. They are scanned separately in     * CVMgenScanAllRoots(), so no need to make a record of them in the     * barrier records.     */    updateCTForRange(thisGen, ee, gcOpts, startRange, endRange);    CVMgenBarrierObjectHeadersUpdate((CVMGeneration*)thisGen,				     ee, gcOpts, startRange, endRange);}static void       CVMgenMarkCompactScanOlderToYoungerPointers(CVMGeneration* gen,					  CVMExecEnv* ee,					  CVMGCOptions* gcOpts,					  CVMRefCallbackFunc callback,					  void* callbackData){    CVMtraceGcCollect(("GC[MC,%d,full]: "		       "Scanning older to younger ptrs\n",		       gen->generationNo));    /*     * To get all older to younger pointers, traverse the records in     * the write barrier tables.     */    CVMgenBarrierPointersTraverse(gen, ee, gcOpts, callback, callbackData);}/* * Return remaining amount of memory */static CVMUint32CVMgenMarkcompactFreeMemory(CVMGeneration* gen, CVMExecEnv* ee){    return (CVMUint32)((CVMUint8*)gen->allocTop - (CVMUint8*)gen->allocPtr);}/* * Return total amount of memory */static CVMUint32CVMgenMarkcompactTotalMemory(CVMGeneration* gen, CVMExecEnv* ee){    return (CVMUint32)((CVMUint8*)gen->allocTop - (CVMUint8*)gen->allocBase);}/* Iterate over promoted pointers in a generation. A young space   collection accummulates promoted objects in an older   generation. These objects need to be scanned for pointers into   the young generation.      At the start of a GC, the current allocation pointer of each   generation is marked. Therefore the promoted objects to scan are those   starting from 'allocMark' to the current 'allocPtr'.  */static voidCVMgenMarkCompactScanPromotedPointers(CVMGeneration* gen,				      CVMExecEnv* ee,				      CVMGCOptions* gcOpts,				      CVMRefCallbackFunc callback,				      void* callbackData){    CVMUint32* startRange = gen->allocMark;    CVMUint32* endRange   = gen->allocPtr;    CVMtraceGcCollect(("GC[MC,full]: "		       "Scanning promoted ptrs [%x,%x)\n",		       startRange, endRange));    /* loop, until promoted object scans result in no more promotions */    do {	scanObjectsInRange(ee, gcOpts, startRange, endRange,			   callback, callbackData);	startRange = endRange;	/* gen->allocPtr may have been incremented */	endRange = gen->allocPtr;     } while (startRange < endRange);    CVMassert(endRange == gen->allocPtr);    /*     * Remember these pointers for further young space collections.     * Don't forget to clear class marks again, since we need to be     * able to traverse already scanned classes again, in order to     * build barrier tables.     */    CVMgenMarkCompactRebuildBarrierTable((CVMGenMarkCompactGeneration*)gen,					 ee, gcOpts,					 gen->allocMark, gen->allocPtr);    gen->allocMark = gen->allocPtr; /* Advance mark for the next batch				       of promotions */    /*     * Make sure that gen->allocPtr and gen->fromSpace->allocPtr are     * in agreement (i.e. in the same space).     */    CVMassert(CVMgenInGeneration(gen, (CVMObject*)gen->allocPtr) ||	      (gen->allocPtr == gen->allocTop));}#ifdef CVM_DEBUG_ASSERTSstatic CVMGenSpace*CVMgenMarkCompactGetExtraSpace(CVMGeneration* gen){    CVMassert(CVM_FALSE);    return NULL;}#endif/* * Copy numBytes from 'source' to 'dest'. Assume word copy, and assume * that the copy regions are disjoint.   */static voidCVMgenMarkCompactCopyDisjointWords(CVMUint32* dest, CVMUint32* source, 				   CVMUint32 numBytes){    CVMUint32*       d = dest;    const CVMUint32* s = source;    CVMUint32        n = numBytes / 4; /* numWords to copy */    CVMmemmoveForGC(s, d, n);}/* * Copy numBytes _down_ from 'source' to 'dest'. Assume word copy. */static voidCVMgenMarkCompactCopyDown(CVMUint32* dest, CVMUint32* source,			  CVMUint32 numBytes){    if (dest == source) {	return;    } else {        CVMUint32*       d = dest;	const CVMUint32* s = source;	CVMUint32        n = numBytes / 4; /* numWords to copy */		CVMassert(d < s); /* Make sure we are copying _down_ */        CVMmemmoveForGC(s, d, n);    }}/* Promote 'objectToPromote' into the current generation. Returns   the new address of the object, or NULL if the promotion failed. */static CVMObject*CVMgenMarkCompactPromoteInto(CVMGeneration* gen,			     CVMObject* objectToPromote,			     CVMUint32  objectSize){    CVMObject* dest;    CVMgenContiguousSpaceAllocate(gen, objectSize, dest);    if (dest != NULL) {	CVMgenMarkCompactCopyDisjointWords((CVMUint32*)dest,					 (CVMUint32*)objectToPromote,					 objectSize);    }    CVMtraceGcScan(("GC[MC,%d]: "		    "Promoted object %x (len %d, class %C), to %x\n",		    gen->generationNo,		    objectToPromote, objectSize,		    CVMobjectGetClass(objectToPromote),		    dest));    return dest;}/* * Allocate a MarkCompact generation. */CVMGeneration*CVMgenMarkCompactAlloc(CVMUint32* space, CVMUint32 totalNumBytes){    CVMGenMarkCompactGeneration* thisGen  = (CVMGenMarkCompactGeneration*)	calloc(sizeof(CVMGenMarkCompactGeneration), 1);    CVMUint32 numBytes = totalNumBytes; /* Respect the no. of bytes passed */    if (thisGen == NULL) {	return NULL;    }    /*     * Initialize thisGen.      */    thisGen->gen.heapTop = &space[numBytes / 4];    thisGen->gen.heapBase = &space[0];    thisGen->gen.allocTop = thisGen->gen.heapTop;    thisGen->gen.allocPtr = thisGen->gen.heapBase;    thisGen->gen.allocBase = thisGen->gen.heapBase;    thisGen->gen.allocMark = thisGen->gen.heapBase;    /*      * And finally, set the function pointers for this generation     */    thisGen->gen.collect = CVMgenMarkCompactCollect;    thisGen->gen.scanOlderToYoungerPointers =	CVMgenMarkCompactScanOlderToYoungerPointers;    thisGen->gen.promoteInto = 	CVMgenMarkCompactPromoteInto;    thisGen->gen.scanPromotedPointers =	CVMgenMarkCompactScanPromotedPointers;#ifdef CVM_DEBUG_ASSERTS    thisGen->gen.getExtraSpace = CVMgenMarkCompactGetExtraSpace;#endif    thisGen->gen.freeMemory = CVMgenMarkcompactFreeMemory;    thisGen->gen.totalMemory = CVMgenMarkcompactTotalMemory;#if defined(CVM_DEBUG)    CVMgenMarkCompactDumpSysInfo(thisGen);#endif /* CVM_DEBUG */    return (CVMGeneration*)thisGen;}#if defined(CVM_DEBUG) || defined(CVM_INSPECTOR)/* Dumps info about the configuration of the markcompact generation. */void CVMgenMarkCompactDumpSysInfo(CVMGenMarkCompactGeneration* thisGen){    CVMUint32 numBytes;    numBytes = (thisGen->gen.heapTop - thisGen->gen.heapBase) *	       sizeof(CVMUint32);    CVMconsolePrintf("GC[MC]: Initialized mark-compact gen "		     "for generational GC\n");    CVMconsolePrintf("\tSize of the space in bytes=%d\n"		     "\tLimits of generation = [0x%x,0x%x)\n",		     numBytes, thisGen->gen.allocBase, thisGen->gen.allocTop);}#endif /* CVM_DEBUG || CVM_INSPECTOR *//* * Free all the memory associated with the current mark-compact generation */voidCVMgenMarkCompactFree(CVMGenMarkCompactGeneration* thisGen){    free(thisGen);}static CVMObject*CVMgenMarkCompactGetForwardingPtr(CVMObject* ref){    CVMAddr  forwardingAddress = CVMobjectVariousWord(ref);    CVMassert(CVMobjectMarked(ref));    return (CVMObject*)forwardingAddress;}#ifdef MAX_STACK_DEPTHSstatic CVMUint32 preservedIdxMax = 0;#endifstatic voidpreserveHeaderWord(CVMGenMarkCompactGeneration* thisGen,                   CVMObject* movedRef, CVMAddr originalWord);/* NOTE: The todoList behaves like a stack.  We add to it by pushing an item   on to it.  We remove from it by popping an item off.  Because the add and   remove is ordered in a stack fashion, we can get efficient memory usage   of the preservedItems database without having to maintain a free list.*//* Adds an item to the todoList. */static voidaddToTodo(CVMGenMarkCompactGeneration* thisGen, CVMObject* ref){    volatile CVMAddr *headerAddr = &CVMobjectVariousWord(ref);    CVMAddr originalWord = *headerAddr;    CVMAddr next = (CVMAddr)thisGen->todoList;    if (!CVMobjectTrivialHeaderWord(originalWord)) {        /* Preserve the old header word with the new address           of object, but only if it is non-trivial. */        preserveHeaderWord(thisGen, ref, originalWord);        next |= 0x1;    }    /* Add the object to the todoList: */    *headerAddr = next;    thisGen->todoList = ref;}

⌨️ 快捷键说明

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