gen_semispace.c

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

C
1,610
字号
	if (fromSpace != NULL) {	    free(fromSpace);	}	if (toSpace != NULL) {	    free(toSpace);	}	return NULL;    }    /*     * Initialize thisGen.      */    thisGen->fromSpace = fromSpace;    thisGen->toSpace   = toSpace;    thisGen->gen.heapBase = space;    thisGen->gen.heapTop = space + totalNumBytes / 4;    /*     * Start the world on fromSpace     */    CVMgenSemispaceMakeCurrent(thisGen, fromSpace);    /*      * And finally, set the function pointers for this generation     */    thisGen->gen.collect = CVMgenSemispaceCollect;#if defined(CVM_SEMISPACE_AS_OLDGEN) || defined(CVM_DEBUG_ASSERTS)    thisGen->gen.scanOlderToYoungerPointers =	CVMgenSemispaceScanOlderToYoungerPointers;#endif    thisGen->gen.promoteInto = 	CVMgenSemispacePromoteInto;    thisGen->gen.scanPromotedPointers =	CVMgenSemispaceScanPromotedPointers;    thisGen->gen.getExtraSpace = CVMgenSemispaceGetExtraSpace;    thisGen->gen.freeMemory = CVMgenSemispaceFreeMemory;    thisGen->gen.totalMemory = CVMgenSemispaceTotalMemory;#if defined(CVM_DEBUG)    CVMgenSemispaceDumpSysInfo(thisGen);#endif /* CVM_DEBUG */    return (CVMGeneration*)thisGen;}#if defined(CVM_DEBUG) || defined(CVM_INSPECTOR)/* Dumps info about the configuration of the semispace generation. */void CVMgenSemispaceDumpSysInfo(CVMGenSemispaceGeneration* thisGen){    CVMUint32 numBytes;    CVMGenSpace* fromSpace = thisGen->fromSpace;    CVMGenSpace* toSpace = thisGen->toSpace;    CVMGenSpace* firstSpace;    CVMGenSpace* secondSpace;    firstSpace = (fromSpace->allocBase < toSpace->allocBase) ?	         fromSpace : toSpace;    secondSpace = (fromSpace->allocBase > toSpace->allocBase) ?	          fromSpace : toSpace;    numBytes = (firstSpace->allocTop - firstSpace->allocBase) *               sizeof(CVMUint32);    CVMconsolePrintf("GC[SS]: Initialized semi-space gen for generational GC\n");    CVMconsolePrintf("\tSize of *each* semispace in bytes=%d\n"		     "\tLimits of generation = [0x%x,0x%x)\n" 		     "\tFirst semispace      = [0x%x,0x%x)\n" 		     "\tSecond semispace     = [0x%x,0x%x)\n"		     "\tCurrent semispace    = %s semispace\n",		     numBytes, firstSpace->allocBase, secondSpace->allocTop,		     firstSpace->allocBase, firstSpace->allocTop,		     secondSpace->allocBase, secondSpace->allocTop,		     ((fromSpace == firstSpace) ?"First":"Second"));}#endif /* CVM_DEBUG || CVM_INSPECTOR *//* * Free all the memory associated with the current semispaces generation */voidCVMgenSemispaceFree(CVMGenSemispaceGeneration* thisGen){    free(thisGen->fromSpace);    free(thisGen->toSpace);    thisGen->fromSpace = NULL;    thisGen->toSpace   = NULL;    free(thisGen);}static voidCVMgenSemispaceSetupCopying(CVMGenSemispaceGeneration* thisGen){    CVMUint32 spaceSize = (CVMUint32)	(thisGen->toSpace->allocTop - thisGen->toSpace->allocBase);    /* Always copy from 'fromSpace' to 'toSpace' */    thisGen->copyBase = thisGen->toSpace->allocBase;    thisGen->copyTop  = thisGen->copyBase;    thisGen->copyThreshold = thisGen->toSpace->allocTop - spaceSize / 4;}/* * GC done. Flip the semispaces. */static voidCVMgenSemispaceFlip(CVMGenSemispaceGeneration* thisGen){    /* Flip the spaces: */    CVMGenSpace* newCurrent = thisGen->toSpace;    thisGen->toSpace = thisGen->fromSpace;    thisGen->fromSpace = newCurrent;     /* Update the alloc ptrs in this gen and the new current space: */    newCurrent->allocPtr = thisGen->copyTop;    CVMgenSemispaceMakeCurrent(thisGen, newCurrent);}/* * Copy object, leave forwarding pointer behind */static CVMObject*CVMgenSemispaceForwardOrPromoteObject(CVMGenSemispaceGeneration* thisGen,				      CVMObject* ref, CVMAddr classWord){    CVMClassBlock*  objCb      = CVMobjectGetClassFromClassWord(classWord);    CVMUint32       objSize    = CVMobjectSizeGivenClass(ref, objCb);    CVMUint32*      copyTop    = thisGen->copyTop;    CVMObject* ret;    CVMBool copyIntoToSpace;    /*      * If this is the old generation, copy into to-space unconditionally.     *     * If it is not the old generation, try promotions as well.  Copy     * into to-space if object age below the desired threshold. If     * above the threshold, try promotion. If promotion fails, copy     * into to-space anyway.       */#ifdef CVM_SEMISPACE_AS_OLDGEN    if (!CVMgenSemispaceIsYoung(thisGen)) {	ret = NULL;	copyIntoToSpace = CVM_TRUE;    } else#endif    if (CVMobjGcBitsPlusPlusCompare(ref, CVM_GEN_PROMOTION_THRESHOLD)) {	ret = NULL;	copyIntoToSpace = CVM_TRUE;    } else {	/* Try promotion */	ret = thisGen->gen.nextGen->promoteInto(thisGen->gen.nextGen,						ref, objSize);	if (ret == NULL) {            thisGen->hasFailedPromotion = CVM_TRUE;	    copyIntoToSpace = CVM_TRUE;	} else {	    copyIntoToSpace = CVM_FALSE;	}    }    if (copyIntoToSpace) {	CVMUint32*      newCopyTop = copyTop + objSize / 4;	CVMtraceGcCollect(("GC[SS,%d]: "			   "Forwarding object %x (len %d, class %C), to %x\n",			   thisGen->gen.generationNo,			   ref, objSize, objCb, thisGen->copyTop));	CVMgenSemispaceCopyDisjointWords(copyTop, (CVMUint32*)ref, objSize);	thisGen->copyTop = newCopyTop;	ret = (CVMObject*)copyTop;    }    CVMassert(ret != NULL);#ifdef CVM_JVMPI    if (CVMjvmpiEventObjectMoveIsEnabled()) {        CVMjvmpiPostObjectMoveEvent(1, ref, 1, ret);    }#endif#ifdef CVM_INSPECTOR    if (CVMglobals.inspector.hasCapturedState) {        CVMgcHeapStateObjectMoved(ref, ret);    }#endif    /*     * Set forwarding pointer     */    {	CVMAddr newClassWord = (CVMAddr)ret;	/* Mark as forwarded */	CVMobjectSetMarkedOnClassWord(newClassWord);	/* ... and forward to the new copy */	CVMobjectSetClassWord(ref, newClassWord);    }        return ret;}/* * Gray an object known to be in the old semispace */static voidCVMgenSemispaceGrayObject(CVMGenSemispaceGeneration* thisGen,			  CVMObject** refPtr, CVMObject *ref){    CVMAddr  classWord = CVMobjectGetClassWord(ref);    CVMtraceGcCollect(("GC[SS,%d]: Graying object %x\n",		       thisGen->gen.generationNo,		       ref));    /*     * ROM objects should have been filtered out by the time we get here     */    CVMassert(!CVMobjectIsInROM(ref));    /*     * Also, all objects that don't belong to this generation need to have     * been filtered out by now.     */    CVMassert(CVMgenSemispaceInOld(thisGen, ref));    /*     * If the object is in old space it might already be     * forwarded. Check that. If it has been forwarded, set the slot     * to refer to the new copy. If it has not been forwarded, copy     * the object, and set the forwarding pointer.     */    if (CVMobjectMarkedOnClassWord(classWord)) {	/* Get the forwarding pointer */	*refPtr = (CVMObject*)CVMobjectClearMarkedOnClassWord(classWord);	CVMtraceGcCollect(("GC[SS,%d]: Object already forwarded: %x -> %x\n",			   thisGen->gen.generationNo,			   ref, *refPtr));    } else {	*refPtr = CVMgenSemispaceForwardOrPromoteObject(thisGen, ref,							classWord);    }}/* * Gray a slot if it points into this generation. */static voidCVMgenSemispaceFilteredGrayObject(CVMGenSemispaceGeneration* thisGen,				  CVMObject** refPtr,				  CVMObject*  ref){    /*     * Gray only if the slot points to this generation's from space.      *     * Make sure we don't scan roots twice!     */    CVMassert(CVMobjectIsInROM(ref) ||	      !CVMgenInGeneration((CVMGeneration*)thisGen, ref) ||	      CVMgenSemispaceInOld(thisGen, ref));    if (CVMgenSemispaceInOld(thisGen, ref)) {        CVMgenSemispaceGrayObject(thisGen, refPtr, ref);    }}/*  * A version of the above where multiple scans of the same slot are allowed. * Used for CVMgenSemispaceScanTransitively() only. */static voidCVMgenSemispaceFilteredGrayObjectWithMS(CVMGenSemispaceGeneration* thisGen,					CVMObject** refPtr,					CVMObject*  ref){    /*     * Gray only if the slot points to this generation's from space.      */    if (CVMgenSemispaceInOld(thisGen, ref)) {	CVMgenSemispaceGrayObject(thisGen, refPtr, ref);    }}/* * Scan a non-NULL reference into this generation. Make sure to * handle the case that the slot has already been scanned -- the * root scan should allow for such a case. */static voidCVMgenSemispaceFilteredHandleRoot(CVMObject** refPtr, void* data){    CVMGenSemispaceGeneration* thisGen = (CVMGenSemispaceGeneration*)data;    CVMObject* ref = *refPtr;    CVMassert(refPtr != 0);    CVMassert(ref != 0);    CVMtraceGcCollect(("GC[SS,%d]: Handling external reference: [%x] = %x\n",		       thisGen->gen.generationNo,		       refPtr, ref));    CVMgenSemispaceFilteredGrayObject(thisGen, refPtr, ref);}typedef struct CVMGenSemispaceTransitiveScanData {    CVMExecEnv* ee;    CVMGCOptions* gcOpts;    CVMGenSemispaceGeneration* thisGen;} CVMGenSemispaceTransitiveScanData;#ifndef BREADTH_FIRST_SCAN/* NOTE: The following CVMObjectIterator code is based on the   CVMobjectWalkRefsAux() macro, and is supposed to achieve the equivalent   scanning of objects.  The difference being that CVMObjectIterator allows   for a depth-first scan algorithm at the cost of a slightly higher   overhead, while CVMobjectWalkRefsAux() enforces breadth-first scanning.*/typedef struct CVMObjectIterator CVMObjectIterator;struct CVMObjectIterator{    CVMObject *ref;    CVMObject *forwardedRef;    CVMAddr offset;    CVMAddr map;    CVMObject **refPtr;    CVMAddr flags;    /* For arrays only: */    CVMObject **arrEnd;    /* For Big GC maps only: */    CVMAddr *mapPtr;    CVMAddr *mapEnd;    CVMObject** otherRefPtr;};/* Initializes the iterator to walk the references in the given object. */static voidCVMobjectIteratorInit(CVMExecEnv *ee, CVMGCOptions *gcOpts,		      CVMObjectIterator *iter, CVMObject *obj,		      CVMObject *forwardedObj){    CVMClassBlock *cb;    CVMAddr map;    CVMObject **refPtr;    CVMAddr flags;    CVMBool handleWeakReferences = CVM_TRUE;    iter->ref = obj;    iter->forwardedRef = forwardedObj;    iter->offset = 0;    cb = CVMobjectGetClass(forwardedObj);    map = CVMcbGcMap(cb).map;    flags = map & CVM_GCMAP_FLAGS_MASK;    iter->map = map;    iter->flags = flags;    if (map == CVM_GCMAP_NOREFS) {	return;    }    refPtr = (CVMObject **)&(forwardedObj)->fields[0];    if (flags == CVM_GCMAP_SHORTGCMAP_FLAG) {	/* First skip the flags */	map >>= CVM_GCMAP_NUM_FLAGS;	if (handleWeakReferences &&	    gcOpts->discoverWeakReferences) {	    if (CVMcbIs(cb, REFERENCE)) {		/* Skip referent, next in case we just discovered		   a new active weak reference object. */		if (CVMweakrefField(forwardedObj, next) == NULL) {		    CVMweakrefDiscover(ee, forwardedObj);		    map >>= CVM_GCMAP_NUM_WEAKREF_FIELDS;		    refPtr += CVM_GCMAP_NUM_WEAKREF_FIELDS;		}	    }	}    } else if (flags == CVM_GCMAP_ALLREFS_FLAG) {	CVMArrayOfRef *arrRefs = (CVMArrayOfRef *)forwardedObj;	CVMJavaInt arrLen = CVMD_arrayGetLength(arrRefs);	refPtr = (CVMObject **) &arrRefs->elems[0];	iter->arrEnd = (CVMObject **) &arrRefs->elems[arrLen];    } else {	/* object with "big" GC map */	/*	 * CVMGCBitMap is a union of the scalar 'map' and the	 * pointer 'bigmap'. So it's best to	 * use the pointer if we need the pointer	 */	CVMBigGCBitMap *bigmap = (CVMBigGCBitMap *)	                            ((CVMAddr)(CVMcbGcMap(cb).bigmap) &				      ~CVM_GCMAP_FLAGS_MASK);	CVMUint32 mapLen = bigmap->maplen;	/*	 * Make 'mapPtr' and 'mapEnd' pointers to the type of 'map'	 * in 'CVMBigGCBitMap'.	 */	CVMAddr *mapPtr = bigmap->map;	CVMAddr *mapEnd = mapPtr + mapLen;	CVMObject** otherRefPtr = refPtr;	CVMassert(flags == CVM_GCMAP_LONGGCMAP_FLAG);	/* Make sure there is something to do. */	CVMassert(mapPtr < mapEnd);	map = *mapPtr;	if (handleWeakReferences &&			    gcOpts->discoverWeakReferences) {

⌨️ 快捷键说明

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