gen_markcompact.c

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

C
1,830
字号
/* * @(#)gen_markcompact.c	1.56 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_markcompact.h"#include "javavm/include/porting/system.h"#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endifstatic CVMUint32* sweep(CVMGenMarkCompactGeneration* thisGen,       CVMExecEnv* ee,       CVMGCOptions* gcOpts,      CVMUint32* base,       CVMUint32* top) ;static void scanPromotedPointers(CVMGeneration* gen,		     CVMExecEnv* ee, 		     CVMGCOptions* gcOpts,		     CVMRefCallbackFunc callback,		     void* callbackData) ;/* * Range checks */#if 0   /* inSpace() is very expensive for multiple segments. See below. */static CVMBoolinSpace(CVMGenSpace* space, CVMObject* ref){    CVMUint32* heapPtr = (CVMUint32*)ref;    CVMGenSegment* segBase = (CVMGenSegment*) space->allocBase ;    CVMGenSegment* segCurr = segBase ;    do {        if (heapPtr >= segCurr->allocBase &&            heapPtr <  segCurr->allocTop) {            return CVM_TRUE;        }         segCurr = segCurr->nextSeg ;    } while (segCurr != segBase) ;    return CVM_FALSE;}#endifstatic CVMBool inGeneration(CVMGeneration* gen, CVMObject* ref){    /* Using negation to determine ref is in this gen since the     * inSpace doesn't scale as the number of segments increases */    CVMGeneration* youngestGen = gen->prevGen->prevGen;    CVMGeneration* youngerGen  = gen->prevGen;        /* Assume for now that this generation can only be instantiated as       generation #2. Otherwise it would have to iterate. */   CVMassert(gen->generationNo == 2);   return (!CVMobjectIsInROM(ref) &&	   !youngestGen->inGeneration(youngestGen, ref) &&	   !youngerGen->inGeneration(youngerGen, ref));}static CVMBool inThisGeneration(CVMGenMarkCompactGeneration* thisGen, CVMObject* ref){    return inGeneration(&thisGen->gen, ref);}/* * Allocate a MarkCompact for the current semispaces generation */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(numSegments != 0);#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, NULL,                                     numBytes, SEG_TYPE_NORMAL);        if (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.            */            segCurr = CVMgenAllocSegment(&allocBase, &allocTop, NULL,                                         CVM_GCIMPL_SEGMENT_USABLE_BYTES,                                         SEG_TYPE_NORMAL);            if (segCurr == NULL) {                allocBase = NULL;                break;            }        }    }    if (allocBase == NULL || allocTop == NULL) {        free(space);        return 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(CVMGenMarkCompactGeneration* thisGen, CVMGenSpace* thisSpace){    CVMGeneration* super = &thisGen->gen;    super->allocPtr  = thisSpace->allocPtr;    super->allocBase = thisSpace->allocBase;    super->allocTop  = thisSpace->allocTop;    {        CVMGenSegment* segBase = (CVMGenSegment*) thisSpace->allocBase ;        CVMGenSegment* segCurr = segBase ;        do {            segCurr->allocMark = segCurr->allocPtr ;            segCurr = segCurr->nextSeg ;        } while (segCurr != segBase) ;    }}/* Forward declaration */static CVMBoolcollectGeneration(CVMGeneration* gen,		  CVMExecEnv*    ee, 		  CVMUint32      numBytes, /* collection goal */		  CVMGCOptions*  gcOpts);static CVMBoolinYounger(CVMGeneration* gen, CVMObject* ref){    /* The pointer is either in the previous generation, or is       younger than that */    return gen->prevGen->inGeneration(gen->prevGen, ref) ||	gen->prevGen->inYounger(gen->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(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) {	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){    CVMassert(CVM_FALSE); /* this generation can only be oldest */}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) ;    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));#if defined(CVM_DEBUG_ASSERTS) && defined(CVM_CVM_SEGMENTED_HEAP)    {	CVMGenSegment* segBase = (CVMGenSegment*)gen->allocBase ;	CVMGenSegment* segCurr = segBase ;	do {	    CVMassert(segCurr->nextHotSeg == NULL) ;	    segCurr = segCurr->nextSeg ;	} while (segCurr != segBase) ;    }#endif    }/* * Return remaining amount of memory */static CVMUint32freeMemory(CVMGeneration* gen, CVMExecEnv* ee){    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)gen;    CVMGenSegment* segBase = (CVMGenSegment*)thisGen->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) ;    if (thisGen->cacheBase == NULL)        return freeMemorySum ;    segCurr = segBase = thisGen->cacheBase ;    do {	CVMUint32 available = (CVMUint32)((CVMUint8*)segCurr->allocTop -					  (CVMUint8*)segCurr->allocPtr);        freeMemorySum += available ;        segCurr = segCurr->nextSeg ;    } while (segCurr != segBase) ;    return freeMemorySum ;}/* * Return total amount of memory */static CVMUint32totalMemory(CVMGeneration* gen, CVMExecEnv* ee){    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)gen;    CVMGenSegment* segBase = (CVMGenSegment*)thisGen->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) ;    if (thisGen->cacheBase == NULL)        return totalMemorySum ;     segCurr = segBase = thisGen->cacheBase ;    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){    CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)gen;    CVMGenSegment* segBase = (CVMGenSegment*) thisGen->hotBase;    CVMGenSegment* segTop  = (CVMGenSegment*) thisGen->hotTop;    CVMGenSegment* segCurr   = segBase ;    CVMBool scanned          = CVM_FALSE ;    if (thisGen->hotBase == NULL) {       /* Nothing to do */       return ;    }    /* 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 */

⌨️ 快捷键说明

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