gen_semispace.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,610 行 · 第 1/4 页
C
1,610 行
/* * 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/generational.h"#include "javavm/include/gc/generational/gen_semispace.h"#include "javavm/include/gc/generational/gen_markcompact.h"#ifdef CVM_JVMTI#include "javavm/include/jvmtiExport.h"#endif#ifdef CVM_JVMPI#include "javavm/include/jvmpi_impl.h"#endif/* NOTE: The following symbol is not defined for this implementation because the semispace generation is only used as the youngGen in this generational GC. However, the code is intentionally left here for reference but is #ifdef'ed out. */#undef CVM_SEMISPACE_AS_OLDGEN/* * Range checks */static CVMBoolCVMgenSemispaceInSpace(CVMGenSpace* space, CVMObject* ref){ CVMUint32* heapPtr = (CVMUint32*)ref; return ((heapPtr >= space->allocBase) && (heapPtr < space->allocTop));}static CVMBool CVMgenSemispaceInOld(CVMGenSemispaceGeneration* thisGen, CVMObject* ref){ return CVMgenSemispaceInSpace(thisGen->fromSpace, ref);}/* * Allocate a semispace for the current semispaces generation */static CVMGenSpace*CVMgenOneSemispaceAlloc(CVMUint32* heapSpace, CVMUint32 numBytes){ CVMUint32 allocSize = sizeof(CVMGenSpace); CVMGenSpace* space = (CVMGenSpace*)calloc(1, allocSize); CVMUint32 numWords = numBytes / 4; if (space != NULL) { space->allocTop = &heapSpace[numWords]; space->allocPtr = &heapSpace[0]; space->allocBase = &heapSpace[0]; } return space;}/* * Make a semispace the current semispace of the generation. */static voidCVMgenSemispaceMakeCurrent(CVMGenSemispaceGeneration* thisGen, CVMGenSpace* thisSpace){ CVMGeneration* super = &thisGen->gen; super->allocPtr = thisSpace->allocPtr; super->allocBase = thisSpace->allocBase; super->allocTop = thisSpace->allocTop; super->allocMark = thisSpace->allocPtr;}/* Forward declaration */static CVMBoolCVMgenSemispaceCollect(CVMGeneration* gen, CVMExecEnv* ee, CVMUint32 numBytes, /* collection goal */ CVMGCOptions* gcOpts);#ifdef CVM_SEMISPACE_AS_OLDGEN/* * Scan objects in contiguous range, without doing any special handling. */static voidscanObjectsInRangePartial(CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMUint32* base, CVMUint32* top, CVMRefCallbackFunc callback, void* callbackData){ CVMUint32* curr = base; CVMtraceGcCollect(("GC[SS,full]: " "Scanning object range (partial) [%x,%x)\n", base, top)); while (curr < top) { CVMObject* currObj = (CVMObject*)curr; CVMClassBlock* currCb = CVMobjectGetClass(currObj); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); CVMobjectWalkRefs(ee, gcOpts, currObj, currCb, { if (*refPtr != 0) { (*callback)(refPtr, callbackData); } }); /* iterate */ curr += objSize / 4; } CVMassert(curr == top); /* This had better be exact */}static voidCVMgenSemispaceUpdateTableForObjectSlot(CVMObject** refPtr, void* data){ CVMGenSemispaceGeneration* thisGen = (CVMGenSemispaceGeneration*)data; CVMObject* ref = *refPtr; if ((ref != NULL) && !CVMgenSemispaceInOld(thisGen, ref) && !CVMobjectIsInROM(ref)) { CVMassert(!CVMgenInGeneration((CVMGeneration*)thisGen, ref)); *CARD_TABLE_SLOT_ADDRESS_FOR(refPtr) = CARD_DIRTY_BYTE; }}static CVMBoolCVMgenSemispaceIsYoung(CVMGenSemispaceGeneration* thisGen){ return thisGen->gen.generationNo == 0;}#endif#ifdef CVM_SEMISPACE_AS_OLDGEN/* * Scan objects in contiguous range, and do all special handling as well. */static voidscanObjectsInRangeFull(CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMUint32* base, CVMUint32* top, CVMRefCallbackFunc callback, void* callbackData){ CVMUint32* curr = base; CVMtraceGcCollect(("GC[SS,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 */}/* * Re-build the old-to-young pointer tables after an old generation is * done. */static voidCVMgenSemispaceRebuildBarrierTable(CVMGenSemispaceGeneration* thisGen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMUint32* startRange, CVMUint32* endRange){ CVMassert(!CVMgenSemispaceIsYoung(thisGen)); /* Do this only for old */ CVMtraceGcCollect(("GC[SS,%d,full]: " "Rebuilding barrier table for range [%x,%x)\n", thisGen->gen.generationNo, startRange, endRange)); /* * No need to look at classes here. They are scanned separately in * CVMgenScanAllRoots(). */ scanObjectsInRangePartial(ee, gcOpts, startRange, endRange, CVMgenSemispaceUpdateTableForObjectSlot, thisGen); CVMgenBarrierObjectHeadersUpdate((CVMGeneration*)thisGen, ee, gcOpts, startRange, endRange);}#endif#if defined(CVM_SEMISPACE_AS_OLDGEN) || defined(CVM_DEBUG_ASSERTS)static void CVMgenSemispaceScanOlderToYoungerPointers(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMRefCallbackFunc callback, void* callbackData){#ifdef CVM_SEMISPACE_AS_OLDGEN CVMtraceGcCollect(("GC[SS,%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);#else CVMassert(CVM_FALSE);#endif}#endif /* defined(CVM_SEMISPACE_AS_OLDGEN) || defined(CVM_DEBUG_ASSERTS) *//* * Return remaining amount of memory */static CVMUint32CVMgenSemispaceFreeMemory(CVMGeneration* gen, CVMExecEnv* ee){ return (CVMUint32)((CVMUint8*)gen->allocTop - (CVMUint8*)gen->allocPtr);}/* * Return total amount of memory */static CVMUint32CVMgenSemispaceTotalMemory(CVMGeneration* gen, CVMExecEnv* ee){ return (CVMUint32)((CVMUint8*)gen->allocTop - (CVMUint8*)gen->allocBase);}/* 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 voidCVMgenSemispaceScanPromotedPointers(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMRefCallbackFunc callback, void* callbackData){#ifdef CVM_SEMISPACE_AS_OLDGEN CVMUint32* startRange = gen->allocMark; CVMUint32* endRange = gen->allocPtr; CVMtraceGcCollect(("GC[SS,full]: " "Scanning promoted ptrs [%x,%x)\n", startRange, endRange)); /* loop, until promoted object scans result in no more promotions */ /* * First clear class marks, since we want to be able to iterate over * classes scanned before promotion. */ do { scanObjectsInRangeFull(ee, gcOpts, startRange, endRange, callback, callbackData); startRange = endRange; /* gen->allocPtr may have been incremented */ endRange = gen->allocPtr; } while (startRange < endRange); CVMassert(endRange == gen->allocPtr); /* * Remember these pointers for further young space collections. * Don't forget to clear class marks again, since we need to be * able to traverse already scanned classes again, in order to * build barrier tables. */ CVMgenSemispaceRebuildBarrierTable((CVMGenSemispaceGeneration*)gen, ee, gcOpts, gen->allocMark, gen->allocPtr); gen->allocMark = gen->allocPtr; /* Advance mark for the next batch of promotions */ /* * Make sure that gen->allocPtr and gen->fromSpace->allocPtr are * in agreement (i.e. in the same space). */ CVMassert(CVMgenSemispaceInOld((CVMGenSemispaceGeneration*)gen, (CVMObject*)gen->allocPtr) || (gen->allocPtr == gen->allocTop)); /* * This is the observable fromSpace pointer. We can probably * get away with not committing this pointer. */ ((CVMGenSemispaceGeneration*)gen)->fromSpace->allocPtr = gen->allocPtr;#else CVMassert(CVM_FALSE); /* Should never get here. */#endif}/* * Copy numBytes from 'source' to 'dest'. Assume word copy, and assume * that the copy regions are disjoint. */static voidCVMgenSemispaceCopyDisjointWords(CVMUint32* dest, CVMUint32* source, CVMUint32 numBytes){ CVMUint32* d = dest; CVMUint32* s = source; CVMUint32 n = numBytes / 4; /* numWords to copy */ CVMmemmoveForGC(s, d, n);}/* Promote 'objectToPromote' into the current generation. Returns the new address of the object, or NULL if the promotion failed. */static CVMObject*CVMgenSemispacePromoteInto(CVMGeneration* gen, CVMObject* objectToPromote, CVMUint32 objectSize){#ifdef CVM_SEMISPACE_AS_OLDGEN CVMObject* dest; CVMgenContiguousSpaceAllocate(gen, objectSize, dest); if (dest != NULL) { CVMgenSemispaceCopyDisjointWords((CVMUint32*)dest, (CVMUint32*)objectToPromote, objectSize); } CVMtraceGcScan(("GC[SS,%d]: " "Promoted object %x (len %d, class %C), to %x\n", gen->generationNo, objectToPromote, objectSize, CVMobjectGetClass(objectToPromote), dest)); return dest;#else CVMassert(CVM_FALSE); /* Should never get here. */ return NULL;#endif}static CVMGenSpace*CVMgenSemispaceGetExtraSpace(CVMGeneration* gen){ CVMGenSemispaceGeneration* thisGen = (CVMGenSemispaceGeneration*)gen; /* * Make sure it is unused */ CVMassert(gen->allocBase != thisGen->toSpace->allocBase); return thisGen->toSpace;}/* * Allocate a semispaces generation. This includes the actual semispaces * as well as all the supporting data structures. */CVMGeneration*CVMgenSemispaceAlloc(CVMUint32* space, CVMUint32 totalNumBytes){ CVMGenSemispaceGeneration* thisGen = (CVMGenSemispaceGeneration*) calloc(sizeof(CVMGenSemispaceGeneration), 1); CVMUint32 numBytes = totalNumBytes / 2; /* Two equal-sized semispaces */ CVMGenSpace* fromSpace; CVMGenSpace* toSpace; if (thisGen == NULL) { return NULL; } fromSpace = CVMgenOneSemispaceAlloc(space, numBytes); toSpace = CVMgenOneSemispaceAlloc(space + numBytes / 4, numBytes); if ((fromSpace == NULL) || (toSpace == NULL)) { free(thisGen);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?