gen_markcompact.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,514 行 · 第 1/4 页
C
1,514 行
CVMObject* currObj = (CVMObject*)curr; CVMAddr classWord = CVMobjectGetClassWord(currObj); CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); if (CVMobjectMarkedOnClassWord(classWord)) { CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj, classWord, { if (*refPtr != 0) { CVMgenMarkCompactFilteredUpdateRoot(refPtr, thisGen); } }, CVMgenMarkCompactFilteredUpdateRoot, thisGen); } else {#ifdef CVM_JVMPI { extern CVMUint32 liveObjectCount; if (CVMjvmpiEventObjectFreeIsEnabled()) { CVMjvmpiPostObjectFreeEvent(currObj); } liveObjectCount--; }#endif#ifdef CVM_JVMTI { if (CVMjvmtiShouldPostObjectFree()) { CVMjvmtiPostObjectFreeEvent(currObj); } }#endif#ifdef CVM_INSPECTOR /* We only need to report this if there are captured states that need to be updated: */ if (CVMglobals.inspector.hasCapturedState) { CVMgcHeapStateObjectFreed(currObj); }#endif CVMgcReplaceWithPlaceHolderObject(currObj, objSize); } /* iterate */ curr += objSize / 4; } CVMassert(curr == top); /* This had better be exact */}#else#define scanObjectsInYoungGenRange scanObjectsInRangeSkipUnmarked#endif /* CVM_INSPECTOR || CVM_JVMPI || CVM_JVMTI *//* * Scan objects in contiguous range, and do all special handling as well. * Ignore unmarked objects. */static voidscanObjectsInRangeSkipUnmarked(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) { CVMUint32* nextChunk = curr + CHUNK_SIZE; if (nextChunk > top) { nextChunk = top; } while (curr < nextChunk) { CVMObject* currObj = (CVMObject*)curr; CVMAddr classWord = CVMobjectGetClassWord(currObj); CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); if (CVMobjectMarkedOnClassWord(classWord)) { CVMobjectWalkRefsWithSpecialHandling(ee, gcOpts, currObj, classWord, { if (*refPtr != 0) { CVMgenMarkCompactFilteredUpdateRoot(refPtr, thisGen); } }, CVMgenMarkCompactFilteredUpdateRoot, thisGen); } /* iterate */ curr += objSize / 4; } CVMthreadSchedHook(CVMexecEnv2threadID(ee)); } CVMassert(curr == top); /* This had better be exact */}/* * Re-build the old-to-young pointer. */voidCVMgenMarkCompactRebuildBarrierTable(CVMGenMarkCompactGeneration* thisGen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMUint32* startRange, CVMUint32* endRange){ CVMtraceGcCollect(("GC[MC,%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(), so no need to make a record of them in the * barrier records. */ updateCTForRange(thisGen, ee, gcOpts, startRange, endRange); CVMgenBarrierObjectHeadersUpdate((CVMGeneration*)thisGen, ee, gcOpts, startRange, endRange);}static void CVMgenMarkCompactScanOlderToYoungerPointers(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 remaining amount of memory */static CVMUint32CVMgenMarkcompactFreeMemory(CVMGeneration* gen, CVMExecEnv* ee){ return (CVMUint32)((CVMUint8*)gen->allocTop - (CVMUint8*)gen->allocPtr);}/* * Return total amount of memory */static CVMUint32CVMgenMarkcompactTotalMemory(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 voidCVMgenMarkCompactScanPromotedPointers(CVMGeneration* gen, CVMExecEnv* ee, CVMGCOptions* gcOpts, CVMRefCallbackFunc callback, void* callbackData){ CVMUint32* startRange = gen->allocMark; CVMUint32* endRange = gen->allocPtr; CVMtraceGcCollect(("GC[MC,full]: " "Scanning promoted ptrs [%x,%x)\n", startRange, endRange)); /* loop, until promoted object scans result in no more promotions */ do { scanObjectsInRange(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. */ CVMgenMarkCompactRebuildBarrierTable((CVMGenMarkCompactGeneration*)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(CVMgenInGeneration(gen, (CVMObject*)gen->allocPtr) || (gen->allocPtr == gen->allocTop));}#ifdef CVM_DEBUG_ASSERTSstatic CVMGenSpace*CVMgenMarkCompactGetExtraSpace(CVMGeneration* gen){ CVMassert(CVM_FALSE); return NULL;}#endif/* * Copy numBytes from 'source' to 'dest'. Assume word copy, and assume * that the copy regions are disjoint. */static voidCVMgenMarkCompactCopyDisjointWords(CVMUint32* dest, CVMUint32* source, CVMUint32 numBytes){ CVMUint32* d = dest; const CVMUint32* s = source; CVMUint32 n = numBytes / 4; /* numWords to copy */ CVMmemmoveForGC(s, d, n);}/* * Copy numBytes _down_ from 'source' to 'dest'. Assume word copy. */static voidCVMgenMarkCompactCopyDown(CVMUint32* dest, CVMUint32* source, CVMUint32 numBytes){ if (dest == source) { return; } else { CVMUint32* d = dest; const CVMUint32* s = source; CVMUint32 n = numBytes / 4; /* numWords to copy */ CVMassert(d < s); /* Make sure we are copying _down_ */ 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*CVMgenMarkCompactPromoteInto(CVMGeneration* gen, CVMObject* objectToPromote, CVMUint32 objectSize){ CVMObject* dest; CVMgenContiguousSpaceAllocate(gen, objectSize, dest); if (dest != NULL) { CVMgenMarkCompactCopyDisjointWords((CVMUint32*)dest, (CVMUint32*)objectToPromote, objectSize); } CVMtraceGcScan(("GC[MC,%d]: " "Promoted object %x (len %d, class %C), to %x\n", gen->generationNo, objectToPromote, objectSize, CVMobjectGetClass(objectToPromote), dest)); return dest;}/* * Allocate a MarkCompact generation. */CVMGeneration*CVMgenMarkCompactAlloc(CVMUint32* space, CVMUint32 totalNumBytes){ CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*) calloc(sizeof(CVMGenMarkCompactGeneration), 1); CVMUint32 numBytes = totalNumBytes; /* Respect the no. of bytes passed */ if (thisGen == NULL) { return NULL; } /* * Initialize thisGen. */ thisGen->gen.heapTop = &space[numBytes / 4]; thisGen->gen.heapBase = &space[0]; thisGen->gen.allocTop = thisGen->gen.heapTop; thisGen->gen.allocPtr = thisGen->gen.heapBase; thisGen->gen.allocBase = thisGen->gen.heapBase; thisGen->gen.allocMark = thisGen->gen.heapBase; /* * And finally, set the function pointers for this generation */ thisGen->gen.collect = CVMgenMarkCompactCollect; thisGen->gen.scanOlderToYoungerPointers = CVMgenMarkCompactScanOlderToYoungerPointers; thisGen->gen.promoteInto = CVMgenMarkCompactPromoteInto; thisGen->gen.scanPromotedPointers = CVMgenMarkCompactScanPromotedPointers;#ifdef CVM_DEBUG_ASSERTS thisGen->gen.getExtraSpace = CVMgenMarkCompactGetExtraSpace;#endif thisGen->gen.freeMemory = CVMgenMarkcompactFreeMemory; thisGen->gen.totalMemory = CVMgenMarkcompactTotalMemory;#if defined(CVM_DEBUG) CVMgenMarkCompactDumpSysInfo(thisGen);#endif /* CVM_DEBUG */ return (CVMGeneration*)thisGen;}#if defined(CVM_DEBUG) || defined(CVM_INSPECTOR)/* Dumps info about the configuration of the markcompact generation. */void CVMgenMarkCompactDumpSysInfo(CVMGenMarkCompactGeneration* thisGen){ CVMUint32 numBytes; numBytes = (thisGen->gen.heapTop - thisGen->gen.heapBase) * sizeof(CVMUint32); CVMconsolePrintf("GC[MC]: Initialized mark-compact gen " "for generational GC\n"); CVMconsolePrintf("\tSize of the space in bytes=%d\n" "\tLimits of generation = [0x%x,0x%x)\n", numBytes, thisGen->gen.allocBase, thisGen->gen.allocTop);}#endif /* CVM_DEBUG || CVM_INSPECTOR *//* * Free all the memory associated with the current mark-compact generation */voidCVMgenMarkCompactFree(CVMGenMarkCompactGeneration* thisGen){ free(thisGen);}static CVMObject*CVMgenMarkCompactGetForwardingPtr(CVMObject* ref){ CVMAddr forwardingAddress = CVMobjectVariousWord(ref); CVMassert(CVMobjectMarked(ref)); return (CVMObject*)forwardingAddress;}#ifdef MAX_STACK_DEPTHSstatic CVMUint32 preservedIdxMax = 0;#endifstatic voidpreserveHeaderWord(CVMGenMarkCompactGeneration* thisGen, CVMObject* movedRef, CVMAddr originalWord);/* NOTE: The todoList behaves like a stack. We add to it by pushing an item on to it. We remove from it by popping an item off. Because the add and remove is ordered in a stack fashion, we can get efficient memory usage of the preservedItems database without having to maintain a free list.*//* Adds an item to the todoList. */static voidaddToTodo(CVMGenMarkCompactGeneration* thisGen, CVMObject* ref){ volatile CVMAddr *headerAddr = &CVMobjectVariousWord(ref); CVMAddr originalWord = *headerAddr; CVMAddr next = (CVMAddr)thisGen->todoList; if (!CVMobjectTrivialHeaderWord(originalWord)) { /* Preserve the old header word with the new address of object, but only if it is non-trivial. */ preserveHeaderWord(thisGen, ref, originalWord); next |= 0x1; } /* Add the object to the todoList: */ *headerAddr = next; thisGen->todoList = ref;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?