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 + -
显示快捷键?