📄 collector.c
字号:
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 (!ISKEPT((object)[-HEADERSIZE])) { 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; }}#if ENABLE_HEAP_COMPACTIONstatic voidupdateHeapObjects(breakTableStruct *currentTable, cell* endScanPoint){ cell* scanner; for ( scanner = CurrentHeap; scanner < endScanPoint; 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, currentTable); 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, currentTable); } 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, currentTable); } break; case GCT_POINTERLIST: { POINTERLIST list = (POINTERLIST)object; length = list->length; ptr = &list->data[0].cellp; goto markArray; } case GCT_WEAKPOINTERLIST: { WEAKPOINTERLIST list = (WEAKPOINTERLIST)object; length = list->length; ptr = &list->data[0].cellp; goto markArray; } 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, currentTable); length = array->length; ptr = &array->data[0].cellp; /* FALL THROUGH */ } markArray: /* Keep objects in the array alive. */ while (--length >= 0) { updatePointer(ptr, currentTable); ptr++; } break; case GCT_MONITOR: { MONITOR monitor = (MONITOR)object; updatePointer(&monitor->owner, currentTable); updatePointer(&monitor->monitor_waitq, currentTable); updatePointer(&monitor->condvar_waitq, currentTable);#if INCLUDEDEBUGCODE updatePointer(&monitor->object, currentTable);#endif break; } case GCT_THREAD: { THREAD thread = (THREAD)object; updatePointer(&thread->nextAliveThread, currentTable); updatePointer(&thread->nextThread, currentTable); updatePointer(&thread->javaThread, currentTable); updatePointer(&thread->monitor, currentTable); updatePointer(&thread->nextAlarmThread, currentTable); updatePointer(&thread->stack, currentTable);#if ENABLE_JAVA_DEBUGGER { updatePointer(&thread->stepInfo.fp, currentTable); }#endif if (thread->fpStore != NULL) { updateThreadAndStack(thread, currentTable); } break; } case GCT_NOPOINTERS: break; case GCT_EXECSTACK: /* This is handled by the thread that the stack belongs to. */ break; case GCT_METHODTABLE: FOR_EACH_METHOD(thisMethod, ((METHODTABLE)object)) if ((thisMethod->accessFlags & ACC_NATIVE) == 0) { updatePointer(&thisMethod->u.java.code, currentTable); updatePointer(&thisMethod->u.java.handlers, currentTable); } 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 voidupdateMonitor(OBJECT object, breakTableStruct *currentTable){ if (OBJECT_HAS_MONITOR(object)) { /* The monitor slot contains either a MONITOR or a THREAD, * incremented by a small constant, so we will be pointing into the * middle of the first word. * * In this collector, updatePointer() correctly handles pointers into * the middle of an object, so the following code is simpler then it * would be with other collectors. */ void *oldTemp = object->mhc.address; void *newTemp = oldTemp; updatePointer((cell **)&newTemp, currentTable); if (!USESTATIC || (oldTemp != newTemp)) { SET_OBJECT_MHC_ADDRESS(object, (char *)newTemp); } }}static voidupdateThreadAndStack(THREAD thread, breakTableStruct *currentTable){ char map[(MAXIMUM_STACK_AND_LOCALS + 7) >> 3]; long delta; FRAME thisFP; cell* thisSP; BYTE* thisIP; STACK oldStack, newStack, stack; int i; updatePointer(&thread->fpStore, currentTable); updatePointer(&thread->spStore, currentTable); /* Added for KNI */ updatePointer(&thread->nativeLp, currentTable); thisSP = thread->spStore; /* new address */ thisFP = thread->fpStore; /* new address*/ thisIP = thread->ipStore; oldStack = stack = thisFP->stack; updatePointer(&stack, currentTable); newStack = stack; delta = PTR_DELTA(newStack, oldStack); for (;;) { /* thisSP and thisFP are pointers to the current frame * in new space. * oldStack and newStack contain the old and new addresses of the * stack containing the current frame. */ METHOD method = thisFP->thisMethod; cell* localVars = FRAMELOCALS(thisFP); cell *operandStack = (cell*)thisFP + SIZEOF_FRAME; int localsCount = method->frameSize; long realStackSize = thisSP - (cell*)thisFP - SIZEOF_FRAME + 1; unsigned int totalSize = realStackSize + localsCount; FRAME previousFp; /* Mark the possible synchronization object alive */ updatePointer(&thisFP->syncObject, currentTable); if (method == RunCustomCodeMethod) { memset(map, -1, (realStackSize + 7) >> 3); } else { getGCRegisterMask(method, thisIP, map); } for (i = 0; i < totalSize; i++) { if (map[i >> 3] & (1 << (i & 7))) { cell **argP; if (i < localsCount) { argP = (cell **)&localVars[i]; } else { argP = (cell **)&operandStack[i - localsCount]; } updatePointer(argP, currentTable); } } if (INCLUDEDEBUGCODE && thisFP->stack != oldStack) { fatalError(KVM_MSG_BAD_STACK_INFORMATION); } thisFP->stack = newStack; previousFp = thisFP->previousFp; /* old address of previousFP */ if (previousFp == NULL) { break; } else { STACK prevOldStack, prevNewStack; updatePointer(&previousFp, currentTable); prevOldStack = previousFp->stack; /* old address */ if (prevOldStack == oldStack) { thisFP->previousSp = PTR_OFFSET(thisFP->previousSp, delta); thisFP->previousFp = PTR_OFFSET(thisFP->previousFp, delta); } else { updatePointer(&thisFP->previousFp, currentTable); updatePointer(&thisFP->previousSp, currentTable); stack = prevOldStack; updatePointer(&stack, currentTable); prevNewStack = stack; prevNewStack->next = newStack; oldStack = prevOldStack; newStack = prevNewStack; delta = PTR_DELTA(newStack, oldStack); } } /* This frame is now done. Go to the previous one. */ thisSP = thisFP->previousSp; thisIP = thisFP->previousIp; thisFP = thisFP->previousFp; }}#endif /* ENABLE_HEAP_COMPACTION *//*========================================================================= * Deferred objects, as part of markChildren. * * These functions create a queue of objects that are waiting to be * scanned so that their children can be marked. The active part of the * starts at startDeferredObjects and ends just before endDeferredObjects. * This queue is circular. * * The two main functions are putDeferredObject() and getDeferredObject() * which add and remove objects from the queue. putDeferredObject() * correctly handles overflow. getDeferredObject() presumes that the user * has first checked that there is an object to be gotten. *=======================================================================*//*========================================================================= * FUNCTION: initializeDeferredObjectTable * TYPE: scanning the heap * OVERVIEW: Initialize the deferred object table so that it correctly * behaves like a queue. * INTERFACE: * parameters: <none> *=======================================================================*/static void initializeDeferredObjectTable(void) { startDeferredObjects = endDeferredObjects = deferredObjectTable; deferredObjectCount = 0; deferredObjectTableOverflow = FALSE;}/*========================================================================= * FUNCTION: putDeferredObject * TYPE: scanning the heap * OVERVIEW: Add an object to the end of the queue. If the queue is * full, just set the variable deferredObjectTableOverflow * and ignore the request. * INTERFACE: * parameters: value: An object to put on the queue *=======================================================================*/static voidputDeferredObject(cell *value){ if (deferredObjectCount >= DEFERRED_OBJECT_TABLE_SIZE) { deferredObjectTableOverflow = TRUE; } else { if (endDeferredObjects == endDeferredObjectTable) { endDeferredObjects = deferredObjectTable; } *endDeferredObjects++ = value; deferredObjectCount++; }#if ENABLEPROFILING if (deferredObjectCount > MaximumGCDeferrals) { MaximumGCDeferrals = deferredObjectCount; } TotalGCDeferrals++;#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -