📄 collectordebug.c
字号:
garbageCollect(-1); } else { /* We've already garbage collected, so we can't compact the * heap any more */ fatalError(KVM_MSG_UNABLE_TO_EXPAND_PERMANENT_MEMORY); } } else { /* We're currently allocating into HeapSpace 1 */ if (CurrentHeapFreePtr < newPermanentSpace) { /* Let's put a fake object to fill up the space between * the old pointer and the new, just in case we decide to * scan memory */ int delta = (CurrentHeap - newHeapSpace1); *(newHeapSpace1) = (GCT_NOPOINTERS << 2) + ((delta - 1) << TYPEBITS); CurrentHeap = newHeapSpace1; CurrentHeapEnd = newPermanentSpace; break; } else { garbageCollect(0); } } } /* Zero then new memory */ memset((char *)newPermanentSpace, 0, PTR_DELTA(PermanentSpace, newPermanentSpace)); nHeapSize = newHeapSize; PermanentSpace = newPermanentSpace;#else fatalError(KVM_MSG_UNABLE_TO_EXPAND_PERMANENT_MEMORY);#endif /* CHENEY_TWO_SPACE */}static voidcopyRootObjects(void){ cellOrPointer *ptr, *endptr; HASHTABLE stringTable; ptr = &GlobalRoots[0]; endptr = ptr + GlobalRootsLength; for ( ; ptr < endptr; ptr++) { updatePointer(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] */ long offset = *(ptr[1].charpp) - ptr[2].charp; updatePointer(&ptr[2]); *(ptr[1].charpp) = ptr[2].charp + offset; ptr += 2; } else { updatePointer(location.cellpp); } }#if ASYNCHRONOUS_NATIVE_FUNCTIONS{ int i; for (i = 0 ; i < ASYNC_IOCB_COUNT ; i++) { ASYNCIOCB *aiocb = &IocbRoots[i]; updatePointer(&aiocb->thread); updatePointer(&aiocb->instance); updatePointer(&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 cell **staticPtrData = (cell **)KVM_staticDataPtr;#else cell **staticPtrData = (cell **)KVM_staticData;#endif int refCount = ((int *)staticPtrData)[0]; cell **staticPtr = staticPtrData + 1; cell **lastStaticPtr = staticPtr + refCount; while (staticPtr < lastStaticPtr) { updatePointer(staticPtr); staticPtr++; } }#endif /* ROMIZING */ if (ROMIZING || ClassTable != NULL) { FOR_ALL_CLASSES(clazz) updateMonitor((OBJECT)clazz); if (!IS_ARRAY_CLASS(clazz)) { INSTANCE_CLASS iclazz = (INSTANCE_CLASS)clazz; POINTERLIST statics = iclazz->staticFields; THREAD initThread = iclazz->initThread; if (initThread != NULL) { updatePointer(&initThread); setClassInitialThread(iclazz, initThread); } if (clazz->accessFlags & ACC_ROM_CLASS) { continue; } if (USESTATIC) { updatePointer(&iclazz->constPool); updatePointer(&iclazz->ifaceTable); updatePointer(&iclazz->fieldTable); updatePointer(&iclazz->methodTable); } if (statics != NULL) { int count = statics->length; while (--count >= 0) { updatePointer(&statics->data[count].cellp); } } if (iclazz->status == CLASS_VERIFIED) { continue; } FOR_EACH_METHOD(thisMethod, iclazz->methodTable) /* Mark the bytecode object alive for non-native methods */ if (!(thisMethod->accessFlags & ACC_NATIVE)) { if (!USESTATIC || inTargetSpace(thisMethod)) { updatePointer(&thisMethod->u.java.stackMaps.verifierMap); } else { POINTERLIST oldValue = thisMethod->u.java.stackMaps.verifierMap; POINTERLIST newValue = oldValue; updatePointer(&newValue); if (oldValue != newValue) { CONSTANTPOOL cp = iclazz->constPool; int offset = PTR_DELTA( &thisMethod->u.java.stackMaps.pointerMap, cp); modifyStaticMemory(cp, offset, &newValue, sizeof(POINTERLIST)); } } } END_FOR_EACH_METHOD } END_FOR_ALL_CLASSES } 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); } } }}static voidcopyNonRootObjects(){ cell* scanner; for ( scanner = TargetSpace; scanner < TargetSpaceFreePtr; scanner += SIZE(*scanner) + HEADERSIZE) { cell *header = scanner; cell *object = scanner + 1; GCT_ObjectType gctype = TYPE(*header); switch (gctype) { int length; cell **ptr; case GCT_INSTANCE: { /* The object is a Java object instance. Mark pointer fields */ INSTANCE instance = (INSTANCE)object; INSTANCE_CLASS clazz = instance->ofClass; updateMonitor((OBJECT)instance); while (clazz) { FOR_EACH_FIELD(thisField, clazz->fieldTable) /* Is this a non-static pointer field? */ if ((thisField->accessFlags & (ACC_POINTER | ACC_STATIC)) == ACC_POINTER) { updatePointer(&instance->data[thisField->u.offset].cellp); } END_FOR_EACH_FIELD clazz = clazz->superClass; } break; } case GCT_ARRAY: { /* The object is a Java array with primitive values. */ /* Only the possible monitor will have to be marked alive. */ updateMonitor((OBJECT)object); } break; case GCT_POINTERLIST: { POINTERLIST list = (POINTERLIST)object; length = list->length; ptr = &list->data[0].cellp; goto markArray; } case GCT_WEAKPOINTERLIST: /* Push this object onto the linked list of weak pointers */ ((WEAKPOINTERLIST)object)->gcReserved = WeakPointers; WeakPointers = (WEAKPOINTERLIST)object; break; case GCT_OBJECTARRAY: { /* The object is a Java array with object references. */ /* The contents of the array and the possible monitor */ /* will have to be scanned. */ ARRAY array = (ARRAY)object; updateMonitor((OBJECT)array); length = array->length; ptr = &array->data[0].cellp; /* FALL THROUGH */ } markArray: /* Keep objects in the array alive. */ while (--length >= 0) { updatePointer(ptr); ptr++; } break; case GCT_MONITOR: { MONITOR monitor = (MONITOR)object; updatePointer(&monitor->owner); updatePointer(&monitor->monitor_waitq); updatePointer(&monitor->condvar_waitq);#if INCLUDEDEBUGCODE updatePointer(&monitor->object);#endif break; } case GCT_THREAD: { THREAD thread = (THREAD)object; updatePointer(&thread->nextAliveThread); updatePointer(&thread->nextThread); updatePointer(&thread->javaThread); updatePointer(&thread->monitor); updatePointer(&thread->nextAlarmThread); updatePointer(&thread->stack); if (thread->fpStore != NULL) { updateThreadAndStack(thread); } break; } case GCT_NOPOINTERS: break; case GCT_EXECSTACK: /* This is ugly, but it gets handled by GCT_THREAD; */ break; case GCT_METHODTABLE: FOR_EACH_METHOD(thisMethod, ((METHODTABLE)object)) if ((thisMethod->accessFlags & ACC_NATIVE) == 0) { updatePointer(&thisMethod->u.java.code); updatePointer(&thisMethod->u.java.handlers); } END_FOR_EACH_METHOD break; default: /* We should never get here as isValidHeapPointer should */ /* guarantee that the header tag of this object is in the */ /* range GCT_FIRSTVALIDTAG && GCT_LASTVALIDTAG */ fatalError(KVM_MSG_BAD_DYNAMIC_HEAP_OBJECTS_FOUND); } /* End of switch statement */ } /* End of for statement */}static voidcopyWeakPointerLists(){ WEAKPOINTERLIST list; /* save the current native method pointer */ cell* currentNativeLp; if (CurrentThread) { currentNativeLp = CurrentThread->nativeLp; } for (list = WeakPointers; list != NULL; list = list->gcReserved) { void (*finalizer)(INSTANCE_HANDLE) = list->finalizer; cellOrPointer *ptr = &list->data[0]; cellOrPointer *endPtr = ptr + list->length; for (; ptr < endPtr; ptr++) { cell* object = ptr->cellp; if (object != NULL) { if (ISMARKED((object)[-HEADERSIZE])) { ptr->cellp = (cell *)(((object)[-HEADERSIZE]) & ~MARKBIT); } else { ptr->cellp = NULL; if (finalizer) { /* In KVM, making the 'this' pointer available */ /* in native finalizers is rather painful. */ /* KVM doesn't create stack frames for native */ /* methods, and therefore the stack may not */ /* contain anything to which 'nativeLp' could */ /* point to create access to the 'this' pointer. */ /* Therefore, it is necessary to set 'nativeLp' */ /* to point to a 'fake' location each time we */ /* need to call a native finalizer. */ if (CurrentThread) { CurrentThread->nativeLp = (cell *)&object; } /* In KVM 1.0.4, we pass the object to */ /* the finalizer as a handle. This makes */ /* it possible to define native finalizers */ /* as KNI functions that take a 'jobject' */ /* parameter. */ finalizer((INSTANCE_HANDLE)&object); } } } } } /* Restore the original 'nativeLp' */ if (CurrentThread) { CurrentThread->nativeLp = currentNativeLp; }}static void updateThreadAndStack(THREAD thread) { /* Note that when this is called, some (or all) of the thread stacks * may have already been copied into new space. However none of the * stacks, themselves, have been scanned.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -