📄 collector.c
字号:
} return result;#else /* ENABLE_HEAP_COMPACTION */ result = callocObject(size, GCT_NOPOINTERS); OBJECT_HEADER(result) |= STATICBIT; return result;#endif /* ENABLE_HEAP_COMPACTION */}/*========================================================================= * Garbage collection operations *=======================================================================*/voidgarbageCollectForReal(int realSize){ CHUNK firstFreeChunk; long maximumFreeSize; markRootObjects(); markNonRootObjects(); markWeakPointerLists(); firstFreeChunk = sweepTheHeap(&maximumFreeSize);#if ENABLE_HEAP_COMPACTION if (realSize > maximumFreeSize) { /* We need to compact the heap. */ breakTableStruct currentTable; cell* freeStart = compactTheHeap(¤tTable, firstFreeChunk); if (currentTable.length > 0) { updateRootObjects(¤tTable); updateHeapObjects(¤tTable, freeStart); } if (freeStart < CurrentHeapEnd - 1) { firstFreeChunk = (CHUNK)freeStart; firstFreeChunk->size = (CurrentHeapEnd - freeStart - HEADERSIZE) << TYPEBITS; firstFreeChunk->next = NULL; } else { /* We are so utterly hosed. * Memory is completely full, and there is no free space whatsoever. */ firstFreeChunk = NULL; } }#endif FirstFreeChunk = firstFreeChunk;}/*========================================================================= * FUNCTION: markRootObjects * TYPE: private garbage collection operation * OVERVIEW: Marks the root objects of garbage collection * INTERFACE: * parameters: none * returns: none *=======================================================================*/static voidmarkRootObjects(void){ cell *heapSpace = CurrentHeap; cell *heapSpaceEnd = CurrentHeapEnd; cellOrPointer *ptr, *endptr; HASHTABLE stringTable; THREAD thread; ptr = &GlobalRoots[0]; endptr = ptr + GlobalRootsLength; for ( ; ptr < endptr; ptr++) { MARK_OBJECT_IF_NON_NULL(*(ptr->cellpp)); } ptr = &TemporaryRoots[0]; endptr = ptr + TemporaryRootsLength; for ( ; ptr < endptr; ptr++) { cellOrPointer location = *ptr; if (location.cell == -1) { /* Actual Location is ptr[1], base is ptr[2] */ MARK_OBJECT_IF_NON_NULL(ptr[2].cellpp); ptr += 2; } else { MARK_OBJECT_IF_NON_NULL(*(location.cellpp)); } }#if ASYNCHRONOUS_NATIVE_FUNCTIONS{ int i; for (i = 0 ; i < ASYNC_IOCB_COUNT ; i++) { ASYNCIOCB *aiocb = &IocbRoots[i]; MARK_OBJECT_IF_NON_NULL(aiocb->thread); MARK_OBJECT_IF_NON_NULL(aiocb->instance); MARK_OBJECT_IF_NON_NULL(aiocb->array); }}#endif#if ROMIZING { /* In RELOCATABLE_ROM builds, we have a pointer to the static data. * In !RELOCATABLE_ROM builds, we have the actual array. */#if RELOCATABLE_ROM long *staticPtr = KVM_staticDataPtr;#else long *staticPtr = KVM_staticData;#endif int refCount = staticPtr[0]; for( ; refCount > 0; refCount--) { MARK_OBJECT_IF_NON_NULL((cell *)staticPtr[refCount]); } }#endif stringTable = InternStringTable; if (ROMIZING || stringTable != NULL) { int count = stringTable->bucketCount; while (--count >= 0) { INTERNED_STRING_INSTANCE instance = (INTERNED_STRING_INSTANCE)stringTable->bucket[count]; for ( ; instance != NULL; instance = instance->next) { checkMonitorAndMark((OBJECT)instance); } } } if (ROMIZING || ClassTable != NULL) { FOR_ALL_CLASSES(clazz) checkMonitorAndMark((OBJECT)clazz); if (!IS_ARRAY_CLASS(clazz)) { INSTANCE_CLASS iclazz = (INSTANCE_CLASS)clazz; POINTERLIST statics = iclazz->staticFields; METHODTABLE methodTable = iclazz->methodTable; MARK_OBJECT_IF_NON_NULL(iclazz->initThread); if (clazz->accessFlags & ACC_ROM_CLASS) { continue; } if (USESTATIC) { MARK_OBJECT_IF_NON_NULL(iclazz->constPool); MARK_OBJECT_IF_NON_NULL(iclazz->ifaceTable); MARK_OBJECT_IF_NON_NULL(iclazz->fieldTable); MARK_OBJECT_IF_NON_NULL(iclazz->methodTable); } if (statics != NULL) { int count = statics->length; while (--count >= 0) { MARK_OBJECT_IF_NON_NULL(statics->data[count].cellp); } } if (iclazz->status == CLASS_VERIFIED) { continue; } FOR_EACH_METHOD(thisMethod, methodTable) /* Mark the bytecode object alive for non-native methods */ if (!(thisMethod->accessFlags & ACC_NATIVE)) { checkValidHeapPointer((cell *) thisMethod->u.java.stackMaps.verifierMap); MARK_OBJECT_IF_NON_NULL(thisMethod->u.java.stackMaps.verifierMap); } END_FOR_EACH_METHOD } END_FOR_ALL_CLASSES } for (thread = AllThreads; thread != NULL; thread = thread->nextAliveThread){ MARK_OBJECT(thread); if (thread->javaThread != NULL) { MARK_OBJECT(thread->javaThread); } if (thread->stack != NULL) { markThreadStack(thread); } }}#if ENABLE_HEAP_COMPACTIONstatic voidupdateRootObjects(breakTableStruct *currentTable){ HASHTABLE stringTable; cellOrPointer *ptr, *endptr; ptr = &GlobalRoots[0]; endptr = ptr + GlobalRootsLength; for ( ; ptr < endptr; ptr++) { updatePointer(ptr->cellpp, currentTable); } ptr = &TemporaryRoots[0]; endptr = ptr + TemporaryRootsLength; for ( ; ptr < endptr; ptr++) { cellOrPointer location = *ptr; if (location.cell == -1) { /* Actual Location is ptr[1], base is ptr[2] */ long offset = *(ptr[1].charpp) - ptr[2].charp; updatePointer(&ptr[2], currentTable); *(ptr[1].charpp) = ptr[2].charp + offset; ptr += 2; } else { updatePointer(location.cellpp, currentTable); } }#if ASYNCHRONOUS_NATIVE_FUNCTIONS{ int i; for (i = 0 ; i < ASYNC_IOCB_COUNT ; i++) { ASYNCIOCB *aiocb = &IocbRoots[i]; updatePointer(&aiocb->thread, currentTable); updatePointer(&aiocb->instance, currentTable); updatePointer(&aiocb->array, currentTable); }}#endif#if ROMIZING { /* In RELOCATABLE_ROM builds, we have a pointer to the static data. * In !RELOCATABLE_ROM builds, we have the actual array. */#if RELOCATABLE_ROM long *staticPtr = KVM_staticDataPtr;#else long *staticPtr = KVM_staticData;#endif int refCount = staticPtr[0]; for( ; refCount > 0; refCount--) { updatePointer(&staticPtr[refCount], currentTable); } }#endif /* ROMIZING */ stringTable = InternStringTable; if (ROMIZING || stringTable != NULL) { int count = stringTable->bucketCount; while (--count >= 0) { INTERNED_STRING_INSTANCE instance = (INTERNED_STRING_INSTANCE)stringTable->bucket[count]; for ( ; instance != NULL; instance = instance->next) { updateMonitor((OBJECT)instance, currentTable); } } } if (ROMIZING || ClassTable != NULL) { FOR_ALL_CLASSES(clazz) updateMonitor((OBJECT)clazz, currentTable); if (!IS_ARRAY_CLASS(clazz)) { INSTANCE_CLASS iclazz = (INSTANCE_CLASS)clazz; POINTERLIST statics = iclazz->staticFields; THREAD initThread = iclazz->initThread; if (initThread != NULL) { updatePointer(&initThread, currentTable); setClassInitialThread(iclazz, initThread); } if (clazz->accessFlags & ACC_ROM_CLASS) { continue; } if (USESTATIC) { updatePointer(&iclazz->constPool, currentTable); updatePointer(&iclazz->ifaceTable, currentTable); updatePointer(&iclazz->fieldTable, currentTable); updatePointer(&iclazz->methodTable, currentTable); } if (statics != NULL) { int count = statics->length; while (--count >= 0) { updatePointer(&statics->data[count].cellp, currentTable); } } if (iclazz->status == CLASS_VERIFIED) { continue; } FOR_EACH_METHOD(thisMethod, iclazz->methodTable) if (!(thisMethod->accessFlags & ACC_NATIVE)) { if (!USESTATIC || inCurrentHeap(thisMethod)) { updatePointer(&thisMethod->u.java.stackMaps.verifierMap, currentTable); } else { POINTERLIST oldValue = thisMethod->u.java.stackMaps.verifierMap; POINTERLIST newValue = oldValue; updatePointer(&newValue, currentTable); if (oldValue != newValue) { CONSTANTPOOL cp = iclazz->constPool; int offset = (char *)&thisMethod->u.java.stackMaps.pointerMap - (char *)cp; modifyStaticMemory(cp, offset, &newValue, sizeof(POINTERLIST)); } } } END_FOR_EACH_METHOD } END_FOR_ALL_CLASSES }}#endif /* ENABLE_HEAP_COMPACTION *//*========================================================================= * FUNCTION: markNonRootObjects * TYPE: private garbage collection operation * OVERVIEW: Scan the heap looking for objects that are reachable only * from other heap objects. * INTERFACE: * parameters: None * returns: <nothing> * COMMENTS: This code >>tries<< to do all its work in a single pass * through the heap. For each live object in the heap, it * calls the function markChildren(). This latter function * sets the variable deferredObjectTableOverflow if it was * ever unable to completely following the children of an * object because of recursion overflow. In this rare case, * we just rescan the heap. We're guaranteed to get further * to completion on each pass. *=======================================================================*/#define MAX_GC_DEPTH 4static voidmarkNonRootObjects(void) { /* Scan the entire heap, looking for badly formed headers */ cell* scanner; cell* endScanPoint = CurrentHeapEnd; int scans = 0; do { WeakPointers = NULL; initializeDeferredObjectTable(); for (scanner = CurrentHeap; scanner < endScanPoint; scanner += SIZE(*scanner) + HEADERSIZE) { if (ISMARKED(*scanner)) { cell *object = scanner + 1; /* See markChildren() for comments on the arguments */ markChildren(object, object, MAX_GC_DEPTH); } } if (ENABLEPROFILING) { scans++; } /* This loop runs exactly once in almost all cases */ } while (deferredObjectTableOverflow);#if ENABLEPROFILING GarbageCollectionRescans += (scans - 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -