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