gen_markcompact.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 1,514 行 · 第 1/4 页
C
1,514 行
/* Pops an item and removes it from the todoList. */static CVMObject *popFromTodo(CVMGenMarkCompactGeneration* thisGen){ CVMObject* ref = thisGen->todoList; volatile CVMAddr *headerAddr = &CVMobjectVariousWord(ref); CVMAddr next = *headerAddr; thisGen->todoList = (CVMObject *)(next & ~0x1); /* Restore the header various word that we used to store the next pointer of the todoList: */ if ((next & 0x1) != 0) { CVMInt32 idx = --thisGen->preservedIdx; CVMMCPreservedItem* item = &thisGen->preservedItems[idx]; CVMassert(idx >= 0); CVMassert(item->movedRef == ref); CVMassert(!CVMobjectTrivialHeaderWord(item->originalWord)); *headerAddr = item->originalWord; CVMtraceGcScan(("GC[MC,%d]: " "Restoring header %x for obj 0x%x at i=%d\n", thisGen->gen.generationNo, item->originalWord, ref, idx)); } else { /* NOTE: popFromTodo can be used to handle objects in the youngGen as well. For those, we want to ensure that their GC age is at least 1. This is because we must have at least gone through one youngGen GC before getting here. If we simply reset the header word to CVM_OBJECT_DEFAULT_VARIOUS_WORD, then the age will be reset to 0 thereby causing the object to stay longer in the youngGen then it should. Setting the age to 1 does not guarantee that we have the proper age of the object, but it is at least closer to the real age than an age of 0. */ *headerAddr = CVM_OBJECT_DEFAULT_VARIOUS_WORD | (1 << CVM_GC_SHIFT); } return ref;}/* Checks to see if the todoList is empty. *//* static CVMBool todoListIsEmpty(CVMGenMarkCompactGeneration* thisGen); */#define todoListIsEmpty(thisGen) ((thisGen)->todoList == NULL)/* * Restore all preserved header words. */static voidrestorePreservedHeaderWords(CVMGenMarkCompactGeneration* thisGen){ CVMInt32 idx; CVMtraceGcScan(("GC[MC,%d]: Restoring %d preserved headers\n", thisGen->gen.generationNo, thisGen->preservedIdx)); while ((idx = --thisGen->preservedIdx) >= 0) { CVMMCPreservedItem* item = &thisGen->preservedItems[idx]; CVMObject* movedRef = item->movedRef; /* * Make sure that the object we are looking at now has the default * various word set up for now */ CVMassert(CVMobjectTrivialHeaderWord(CVMobjectVariousWord(movedRef))); /* * And also, that we did not evacuate this word for nothing */ CVMassert(!CVMobjectTrivialHeaderWord(item->originalWord)); CVMobjectVariousWord(movedRef) = item->originalWord; CVMtraceGcScan(("GC[MC,%d]: " "Restoring header %x for obj 0x%x at i=%d\n", thisGen->gen.generationNo, item->originalWord, movedRef, idx)); }}/* * Preserve a header word for an object in its new address. */static voidpreserveHeaderWord(CVMGenMarkCompactGeneration* thisGen, CVMObject* movedRef, CVMAddr originalWord){ CVMMCPreservedItem* item = &thisGen->preservedItems[thisGen->preservedIdx]; if (thisGen->preservedIdx >= thisGen->preservedSize) { thisGen->lastProcessedRef = movedRef; gcError(thisGen); } /* Write out the new item: */ item->movedRef = movedRef; item->originalWord = originalWord; CVMtraceGcScan(("GC[MC,%d]: Preserving header %x for obj 0x%x at i=%d\n", thisGen->gen.generationNo, originalWord, movedRef, thisGen->preservedIdx)); thisGen->preservedIdx++;#ifdef MAX_STACK_DEPTHS if (thisGen->preservedIdx >= preservedIdxMax) { preservedIdxMax = thisGen->preservedIdx; CVMconsolePrintf("**** preserved: max depth=%d\n", preservedIdxMax); }#endif /* MAX_STACK_DEPTHS */}/* Sweep the heap, compute the compacted addresses, write them into the original object headers, and return the new allocPtr of this space. */static CVMUint32*sweep(CVMExecEnv* ee, CVMGenMarkCompactGeneration* thisGen, CVMUint32* base, CVMUint32* top){ CVMUint32* forwardingAddress = base; CVMUint32* curr = base; CVMtraceGcCollect(("GC[MC,%d]: Sweeping object range [%x,%x)\n", thisGen->gen.generationNo, 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)) { volatile CVMAddr* headerAddr = &CVMobjectVariousWord(currObj); CVMAddr originalWord = *headerAddr; CVMtraceGcScan(("GC[MC,%d]: obj 0x%x -> 0x%x\n", thisGen->gen.generationNo, curr, forwardingAddress)); if (!CVMobjectTrivialHeaderWord(originalWord)) { /* Preserve the old header word with the new address of object, but only if it is non-trivial. */ preserveHeaderWord(thisGen, (CVMObject *)forwardingAddress, originalWord); } /* Set forwardingAddress in header */ *headerAddr = (CVMAddr)forwardingAddress; /* Pretend to have copied this live object! */ forwardingAddress += objSize / 4; } 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 } /* iterate */ curr += objSize / 4; } CVMthreadSchedHook(CVMexecEnv2threadID(ee)); } CVMassert(curr == top); /* This had better be exact */ CVMtraceGcCollect(("GC[MC,%d]: Swept object range [%x,%x) -> 0x%x\n", thisGen->gen.generationNo, base, top, forwardingAddress)); return forwardingAddress;}static void unmark(CVMGenMarkCompactGeneration* thisGen, CVMUint32* base, CVMUint32* top){ CVMUint32* curr = base; CVMtraceGcCollect(("GC[MC,%d]: Unmarking object range [%x,%x)\n", thisGen->gen.generationNo, base, top)); while (curr < top) { CVMObject* currObj = (CVMObject*)curr; CVMAddr classWord = CVMobjectGetClassWord(currObj); CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); if (CVMobjectMarkedOnClassWord(classWord)) { CVMobjectClearMarkedOnClassWord(classWord); CVMobjectSetClassWord(currObj, classWord); } /* iterate */ curr += objSize / 4; } CVMassert(curr == top); /* This had better be exact */}/* Purpose: Get the header words that were saved away by preservedHeaderWord. This should only be called by unsweepAndUnmark() below. Since unsweepAndUnmark() scans the heap in exactly the same order as sweep(), we should be getting the objects in exactly the same order as was preserved by preservedHeaderWords. This should allow us to restore the original words to the objects. NOTE: We cannot use restorePreservedHeaderWords() to restore the header words because it assumes that the objects has been moved and does its restoration based on forwarded pointers. We want to restore the original objects because we're aborting the GC before the object motion in the compact phase.*/static CVMAddrgetHeaderWord(CVMGenMarkCompactGeneration* thisGen, CVMObject* ref, CVMObject* forwardedRef){ CVMAddr result = CVM_OBJECT_DEFAULT_VARIOUS_WORD; /* We only do restorations when we encountered an error due to having exhausted the preservedSize. So, we only have preserved words for the case when we haven't exhausted the preservedSize yet. */ if (thisGen->lastProcessedRef != NULL) { if (thisGen->lastProcessedRef == forwardedRef) { /* We have reached the last of the list of objects that were swept: */ /* NOTE: The lastProcessedRef points to the next object that would have been swept if we had not run out of scratch space. Hence, it's header word is still intact. Nothing needs to be done to restore it. */ thisGen->lastProcessedRef = NULL; /* Indicate we're done. */ goto noMoreSweptObjects; } else { CVMMCPreservedItem* item; CVMassert(thisGen->preservedIdx <= thisGen->preservedSize); item = &thisGen->preservedItems[thisGen->preservedIdx]; /* If the forwarding address in the object's header matches the current preserved item in the list, then the original word must have been preserved in the preserved item. Restore this word and increment the preserved index. Otherwise, the original word must have been the default various word value (i.e. CVM_OBJECT_DEFAULT_VARIOUS_WORD) or equivalent. The only difference may be the GC age, but that information is inconsequential for objects in the old generation. Hence, we simply restore it to the default word. */ if (item->movedRef == forwardedRef) { result = item->originalWord; thisGen->preservedIdx++; } } } else {noMoreSweptObjects: /* This object's header wasn't changed. Just return the original word in the object header: */ result = CVMobjectVariousWord(ref); } return result;}/* Purpose: Restore the objects header words modified by the sweep phase. */static voidunsweepAndUnmark(CVMGenMarkCompactGeneration* thisGen, CVMUint32* base, CVMUint32* top){ CVMUint32* forwardingAddress = base; CVMUint32* curr = base; while (curr < top) { CVMObject* currObj = (CVMObject*)curr; CVMAddr classWord = CVMobjectGetClassWord(currObj); CVMClassBlock* currCb = CVMobjectGetClassFromClassWord(classWord); CVMUint32 objSize = CVMobjectSizeGivenClass(currObj, currCb); if (CVMobjectMarkedOnClassWord(classWord)) { if (thisGen->lastProcessedRef != NULL) { volatile CVMAddr* headerAddr = &CVMobjectVariousWord(currObj); CVMAddr originalWord; originalWord = getHeaderWord(thisGen, currObj, (CVMObject *)forwardingAddress); *headerAddr = originalWord; /* Pretend to have copied this live object! */ forwardingAddress += objSize / 4; } /* Deleted mark in the object. */ /* NOTE: The sweep phase would leave the mark on the object intact. It's the compact phase that unmarks it. But in this case, we are already iterating the heap to undo the sweep effects in an abort operation. Hence, we'll take this opportunity to unmark the objects too. */ CVMobjectClearMarkedOnClassWord(classWord); CVMobjectSetClassWord(currObj, classWord); } /* iterate */ curr += objSize / 4; } CVMassert(curr == top); /* This had better be exact */}/* Finally we can move objects, reset marks, and restore original header words. */static void compact(CVMExecEnv* ee, CVMGenMarkCompactGeneration* thisGen, CVMUint32* base, CVMUint32* top){ CVMUint32* curr = base; CVMtraceGcCollect(("GC[MC,%d]: Compacting object range [%x,%x)\n", thisGen->gen.generationNo, 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)) { CVMUint32* destAddr = (CVMUint32*) CVMgenMarkCompactGetForwardingPtr(currObj); CVMobjectClearMarkedOnClassWord(classWord);#ifdef CVM_DEBUG /* For debugging purposes, make sure the deleted mark is reflected in the original copy of the object as well. */ CVMobjectSetClassWord(currObj, classWord);#endif CVMgenMarkCompactCopyDown(destAddr, curr, objSize);#ifdef CVM_JVMPI if (CVMjvmpiEventObjectMoveIsEnabled()) { CVMjvmpiPostObjectMoveEvent(1, curr, 1, destAddr); }#endif#ifdef CVM_INSPECTOR if (CVMglobals.inspector.hasCapturedState) { CVMgcHeapStateObjectMoved(currObj, (CVMObject *)destAddr); }#endif /* * First assume that all objects had the default various * word. We'll patch the rest shortly. * * Note that this clears the GC bits portion. No worries, * we won't need that anymore in this generation. */ CVMobjectVariousWord((CVMObject*)destAddr) = CVM_OBJECT_DEFAULT_VARIOUS_WORD; /* Write the class word whose mark has just been cleared */ CVMobjectSetClassWord((CVMObject*)destAddr, classWord); } /* iterate */ curr += objSize / 4; } CVMthreadSchedHook(CVMexecEnv2threadID(ee)); } CVMassert(curr == top); /* This had better be exact */}/* Gray an object known to be alive. */static voidCVMgenMarkCompactGrayObject(CVMObject** refPtr, void* data){ CVMGenMarkCompactGeneration* thisGen = (CVMGenMarkCompactGeneration*)data; CVMObject* ref = *refPtr; if (CVMobjectIsInROM(ref)) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?