gen_edenspill.c

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

C
1,442
字号
/* * @(#)gen_edenspill.c	1.33 06/10/10 * * Copyright  1990-2008 Sun Microsystems, Inc. All Rights Reserved.   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER   *    * This program is free software; you can redistribute it and/or   * modify it under the terms of the GNU General Public License version   * 2 only, as published by the Free Software Foundation.    *    * This program is distributed in the hope that it will be useful, but   * WITHOUT ANY WARRANTY; without even the implied warranty of   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU   * General Public License version 2 for more details (a copy is   * included at /legal/license.txt).    *    * You should have received a copy of the GNU General Public License   * version 2 along with this work; if not, write to the Free Software   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA   * 02110-1301 USA    *    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa   * Clara, CA 95054 or visit www.sun.com if you need additional   * information or have any questions.  * *//* * This file includes the implementation of a copying semispace generation. * This generation can act as a young or an old generation. */#include "javavm/include/defs.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/directmem.h"/* * This file is generated from the GC choice given at build time. */#include "generated/javavm/include/gc_config.h"#include "javavm/include/gc_common.h"#include "javavm/include/gc/gc_impl.h"#include "javavm/include/gc/generational-seg/generational.h"#include "javavm/include/gc/generational-seg/gen_edenspill.h"#include "javavm/include/porting/system.h"#ifdef CVM_JVMTI#include "javavm/include/jvmtiExport.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endifstatic CVMUint32* sweep(CVMGenEdenSpillGeneration* thisGen,       CVMExecEnv* ee,       CVMGCOptions* gcOpts,      CVMUint32* base,       CVMUint32* top) ;static void scanPromotedPointers(CVMGeneration* gen,		     CVMExecEnv* ee, 		     CVMGCOptions* gcOpts,		     CVMRefCallbackFunc callback,		     void* callbackData) ;/* * Range checks */static CVMBoolinSpace(CVMGenSpace* space, CVMObject* ref){    /* Note : Eden-spill gen is faking segmentation so       bounds checking doesnt account for displaced segments    */    CVMUint32* heapPtr = (CVMUint32*)ref;    CVMGenSegment* segBase = (CVMGenSegment*) space->allocBase ;    CVMGenSegment* segTop  = segBase->prevSeg ;    return ((heapPtr >= segBase->allocBase) &&            (heapPtr <  segTop->allocTop));}static CVMBool inGeneration(CVMGeneration* gen, CVMObject* ref){    CVMGenEdenSpillGeneration* thisGen = (CVMGenEdenSpillGeneration*)gen;    return inSpace(thisGen->theSpace, ref);}static CVMBool inThisGeneration(CVMGenEdenSpillGeneration* thisGen, CVMObject* ref){    return inSpace(thisGen->theSpace, ref);}/* * Allocate an eden-spill space */static CVMGenSpace*allocSpace(CVMUint32* heapSpace, CVMUint32 numBytes){    CVMUint32 allocSize = sizeof(CVMGenSpace);    CVMGenSpace* space = (CVMGenSpace*)calloc(1, allocSize);    CVMGenSegment* allocBase = NULL;    CVMGenSegment* allocTop  = NULL;    CVMGenSegment* segCurr   = NULL;    CVMUint32 numSegments = numBytes/CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES;    if (space == NULL) {        return NULL;    }    CVMassert(heapSpace != NULL);    CVMassert(numBytes != 0); /* spillGen only */#if 0    /* numSegments can be 0 if we allow for segment chunks and numBytes to       be less than CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES.  Since this is       currently not the case, this code is unused for the moment. */    if (numSegments == 0) {        /* The only time we have segments that aren't packed to           CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES is when the numBytes is less           than CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES to begin with.  Hence,           we will only have one segment. */        segCurr = CVMgenAllocSegment(&allocBase, &allocTop, heapSpace,                                     numBytes, SEG_TYPE_NORMAL);        CVMassert(segCurr != NULL && allocBase != NULL);    } else #endif    {        /* Otherwise, we should have enough bytes to fill out one or more           properly packed segments. */        CVMassert(numBytes ==                  CVMpackSizeBy(numBytes, CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES));        while (numSegments-- > 0) {	    /* NOTE: We don't actually go ahead and ask for               CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES because we have to account               for misc overhead in setting up the segment.  In this case, we               ask for CVM_GCIMPL_SEGMENT_USABLE_BYTES +               CVM_GCIMPL_SEGMENT_MALLOC_OVERHEAD because we know that the               block of memory is already preallocated as a consecutive block               by the caller.  Hence, we will not need to reserve any space               for the malloc overhead between each segment. Hence, we can               add CVM_GCIMPL_SEGMENT_MALLOC_OVERHEAD back into the usable               space.            */            segCurr = CVMgenAllocSegment(&allocBase, &allocTop, heapSpace,                                         CVM_GCIMPL_SEGMENT_USABLE_BYTES +					 CVM_GCIMPL_SEGMENT_MALLOC_OVERHEAD,                                         SEG_TYPE_NORMAL);            CVMassert(segCurr != NULL && allocBase != NULL);            heapSpace += CVM_GCIMPL_SEGMENT_ALIGNMENT_BYTES / 4;        }    }     CVMassert(allocBase != NULL && allocTop != NULL) ;    space->allocTop  = (CVMUint32*)allocTop;    space->allocPtr  = (CVMUint32*)allocBase;    space->allocBase = (CVMUint32*)allocBase;    return space;}/* * Make sure the allocation pointers of the mark-compact generation * are reflected at the "superclass" level for the shared GC code. */static voidmakeCurrent(CVMGenEdenSpillGeneration* thisGen, CVMGenSpace* thisSpace){    CVMGeneration* super = &thisGen->gen;    super->allocPtr  = thisSpace->allocPtr;    super->allocBase = thisSpace->allocBase;    super->allocTop  = thisSpace->allocTop;    super->allocMark = thisSpace->allocPtr;}static CVMGenSpace*getExtraSpace(CVMGeneration* gen){    return gen->prevGen->getExtraSpace(gen->prevGen);}/* Forward declaration */static CVMBoolcollectGeneration(CVMGeneration* gen,		  CVMExecEnv*    ee, 		  CVMUint32      numBytes, /* collection goal */		  CVMGCOptions*  gcOpts);/* * Given the address of a slot, mark the card table entry */static CVMBoolinYounger(CVMGeneration* gen, CVMObject* ref){    CVMGeneration* prevGen = gen->prevGen;    return prevGen->inGeneration(prevGen, ref);}/* * Scan objects in contiguous range, and do all special handling as well. */static voidscanObjectsInRange(CVMExecEnv* ee, CVMGCOptions* gcOpts,		   CVMUint32* base, CVMUint32* top,		   CVMRefCallbackFunc callback, void* callbackData){    CVMUint32* curr = base;    CVMtraceGcCollect(("GC[MC,full]: "		       "Scanning object range (full) [%x,%x)\n",		       base, top));    while (curr < top) {	CVMObject* currObj = (CVMObject*)curr;	CVMClassBlock* currCb = CVMobjectGetClass(currObj);	CVMUint32  objSize    = CVMobjectSizeGivenClass(currObj, currCb);	CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj, currCb, {	    if (*refPtr != 0) {		(*callback)(refPtr, callbackData);	    }	}, callback, callbackData);	/* iterate */	curr += objSize / 4;    }    CVMassert(curr == top); /* This had better be exact */    return;}/* Forward declartion*/static voidfilteredUpdateRoot(CVMObject** refPtr, void* data);/* * Scan objects in contiguous range, and do all special handling as well. * Ignore unmarked objects. */static voidscanObjectsAndFixPointers(CVMGenEdenSpillGeneration* 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) {	CVMObject* currObj    = (CVMObject*)curr;	/* 	 * member clas and various32 hold a native pointer	 * therefore use type CVMAddr (instead of CVMUint32)	 * which is 64 bit aware	 */	CVMAddr    classWord  = CVMobjectGetClassWord(currObj);	CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord);	CVMUint32  objSize    = CVMobjectSizeGivenClass(currObj, currCb);	if (CVMobjectMarkedOnClassWord(classWord)) {	    CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj,						 classWord, {		if (*refPtr != 0) {		    filteredUpdateRoot(refPtr, thisGen);		}	    }, filteredUpdateRoot, thisGen);	}	/* iterate */	curr += objSize / 4;    }    CVMassert(curr == top); /* This had better be exact */}static void       scanYoungerToOlderPointers(CVMGeneration* gen,			   CVMExecEnv* ee,			   CVMGCOptions* gcOpts,			   CVMRefCallbackFunc callback,			   void* callbackData){    CVMGenSegment* segBase = (CVMGenSegment*)gen->allocBase;    CVMGenSegment* segCurr = segBase;    do {        scanObjectsInRange(ee, gcOpts, segCurr->allocBase, segCurr->allocPtr,                           callback, callbackData);        segCurr = segCurr->nextSeg;    } while (segCurr != segBase);}static void       scanOlderToYoungerPointers(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;}/* * Start and end GC for this generation.  */static voidstartGC(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts){    CVMGenSegment* segBase = (CVMGenSegment*)gen->allocBase ;    CVMGenSegment* segCurr = segBase ;    do {        CHECK_SEGMENT(segCurr) ;        segCurr->rollbackMark = segCurr->allocPtr;        segCurr = segCurr->nextSeg ;    } while (segCurr != segBase) ;    ((CVMGenEdenSpillGeneration*)gen)->promotions = CVM_FALSE;    CVMtraceGcCollect(("GC[MC,%d,full]: Starting GC\n",		       gen->generationNo));}static voidendGC(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts){    CVMtraceGcCollect(("GC[MC,%d,full]: Ending GC\n",                       gen->generationNo));}/* * Return remaining amount of memory */static CVMUint32freeMemory(CVMGeneration* gen, CVMExecEnv* ee){    CVMGenSegment* segBase = (CVMGenSegment*)gen->allocBase;    CVMGenSegment* segCurr = segBase ;    CVMUint32   freeMemorySum = 0 ;    do {	CVMUint32 available = (CVMUint32)((CVMUint8*)segCurr->allocTop -					  (CVMUint8*)segCurr->allocPtr);        freeMemorySum += available ;        segCurr = segCurr->nextSeg ;    } while (segCurr != segBase);    return freeMemorySum;}static CVMUint32totalMemory(CVMGeneration* gen, CVMExecEnv* ee){     CVMGenSegment* segBase = (CVMGenSegment*)gen->allocBase;    CVMGenSegment* segCurr = segBase ;    CVMUint32   totalMemorySum = 0 ;      do {  	CVMUint32 size = (CVMUint32)((CVMUint8*)segCurr->allocTop -				     (CVMUint8*)segCurr->allocBase);        totalMemorySum += size ;         segCurr = segCurr->nextSeg ;    }while (segCurr != segBase) ;     return totalMemorySum; } /* 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 voidscanPromotedPointers(CVMGeneration* gen,		     CVMExecEnv* ee,		     CVMGCOptions* gcOpts,		     CVMRefCallbackFunc callback,		     void* callbackData){    CVMGenEdenSpillGeneration* thisGen = (CVMGenEdenSpillGeneration*)gen;    CVMGeneration* oldGen = gen->nextGen;    CVMGenSegment* segBase = (CVMGenSegment*) gen->allocBase;    CVMGenSegment* segTop  = (CVMGenSegment*) gen->allocTop;    CVMGenSegment* segCurr   = segBase ;    CVMBool scanned          = CVM_FALSE ;     /* Store the allocMark for all the segments before     * scanning. The allocMarks themselves would be used      * for rebuilding the barrier table     */      do {         segCurr->cookie = segCurr->allocMark;	/* Remember what this scan looked like, if work is to be done */	segCurr->logMarkStart = segCurr->allocMark;        segCurr = segCurr->nextSeg ;    } while (segCurr != segBase) ;    do {        CVMUint32* endRange   = segCurr->allocPtr;        scanned = CVM_FALSE ;        CHECK_SEGMENT(segCurr) ;        CVMtraceGcCollect(("GC[MC,full]: "		           "Scanning promoted ptrs [%x,%x)\n",		           segCurr->cookie, segCurr->allocPtr));                /* loop, until promoted object scans result in no more promotions */        while (segCurr->cookie < endRange) {	    scanObjectsInRange(ee, gcOpts, segCurr->cookie,  			       endRange, callback, callbackData);            segCurr->cookie = endRange ; 	    /* segCurr->allocPtr may have been incremented */            endRange = segCurr->allocPtr ;            scanned = CVM_TRUE ;        }         CVMassert(segCurr->cookie == segCurr->allocPtr);        oldGen->scanPromotedPointers(oldGen, ee, gcOpts, 				     callback, callbackData);        if (scanned || thisGen->promotions) {            thisGen->promotions = CVM_FALSE;            segCurr = segBase ;        } else if (segCurr == segTop) {            segCurr = NULL ;        } else {             segCurr = segCurr->nextSeg ;        }           } while (segCurr != NULL) ; #ifdef CVM_DEBUG_ASSERTS    {	CVMGenSegment* oldSegBase = (CVMGenSegment*)oldGen->allocBase;	CVMGenSegment* oldSegCurr = oldSegBase;	do { 	    CVMassert(oldSegCurr->allocMark  == oldSegCurr->allocPtr);	    oldSegCurr = oldSegCurr->nextSeg ;	} while (oldSegCurr != oldSegBase) ;    }#endif     segCurr = segBase ;#ifdef CVM_DEBUG_ASSERTS    do {         CVMassert(segCurr->cookie == segCurr->allocPtr) ;        segCurr = segCurr->nextSeg ;    } while (segCurr != segBase) ;#endif            /* Incremental rebuild of the barrier table */    CVMgenBarrierTableRebuild(gen, ee, gcOpts, CVM_FALSE);    #ifdef CVM_VERIFY_HEAP    segBase = (CVMGenSegment*) gen->allocBase;    segCurr = segBase ;     do { 	if (segCurr->logMarkStart != NULL) {	    CVMgenVerifyObjectRangeForCardSanity(gen, ee, gcOpts,

⌨️ 快捷键说明

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