📄 collector.c
字号:
#endif}/*========================================================================= * FUNCTION: markChildren() * TYPE: private garbage collection operation * OVERVIEW: Scan the contents of an individual object, * recursively marking all those objects that * are reachable from it. * INTERFACE: * parameters: child: an object pointer * limit: the current location of the scanner in * markNonRootObjects * depth: The number of times further for which this function * can recurse, before we start adding objects to * the deferral queue. * returns: <nothing> * * This function tries >>very<< hard not to be recursive. It uses several * tricks: * 1) It will only recursively mark objects whose location in the heap * is less than the value "limit". It marks but doesn't recurse on * objects "above the limit" because markNonRootObjects() will * eventually get to them. * * 2) The variable nextObject is set in those cases in which we think, or * hope that only a single child of the current node needs to be * followed. In these cases, we iterate (making explicit the tail * recursion), rather than calling ourselves recursively * * 3) We only allow the stack to get to a limited depth. If the depth * gets beyond that, we save the sub object on a "deferred object" * queue, and then iterate on these deferred objects once the depth * gets back down to zero. * * 4) If the deferred object queue overflows, we just throw up our * hands, and scan the stack multiple times. We're guaranteed to make * some progress in each pass through the stack. It's hard to * create a case that needs more than one pass through the stack. *=======================================================================*/static voidmarkChildren(cell* object, cell* limit, int remainingDepth){ cell *heapSpace = CurrentHeap; cell *heapSpaceEnd = CurrentHeapEnd;/* Call this macro to mark a child, when we don't think that there is * any useful reason to try for tail recursion (i.e. there's something * later in the object that's better to tail recurse on. */#define MARK_AND_RECURSE(child) \ if (inHeapSpaceFast(child)) { \ cell _tmp_ = OBJECT_HEADER(child); \ if (!ISKEPT(_tmp_)) { \ OBJECT_HEADER(child) = _tmp_ | MARKBIT; \ if ((cell*)child < limit) { \ RECURSE((cell *)child); \ } \ } \ }/* Call this macro to mark a child, when we think tail recursion might * be useful on this field. * This macro does the right thing, even if we might have already picked * another child on which to tail recurse. * * [We use this macro when looking at elements of an array, or fields of * an instance, since we want to tail recurse on one of the children. * We just don't know which ones will be good to recurse on */#define MARK_AND_TAIL_RECURSE(child) \ if (inHeapSpaceFast(child)) { \ cell _tmp_ = OBJECT_HEADER(child); \ if (!ISKEPT(_tmp_)) { \ OBJECT_HEADER(child) = _tmp_ | MARKBIT; \ if ((cell*)child < limit) { \ if (nextObject != NULL) { \ RECURSE(nextObject); \ } \ nextObject = (cell *)(child); \ } \ } \ }/* This is the same as MARK_AND_TAIL_RECURSE, except we only call it when we * absolutely know that we have not yet called MARK_AND_TAIL_RECURSE, so * we know that we have not yet picked a child upon which to tail recurse. */#define MARK_AND_TAIL_RECURSEX(child) \ if (inHeapSpaceFast(child)) { \ cell _tmp_ = OBJECT_HEADER(child); \ if (!ISKEPT(_tmp_)) { \ OBJECT_HEADER(child) = _tmp_ | MARKBIT; \ if ((cell*)child < limit) { \ nextObject = (cell *)(child); \ } \ } \ }/* Used only in the macros above. Either recurse on the child, or * save it in the deferred items list. * * Note that remainingDepth will have already been decremented from the value * that it originally had when the function was called */#define RECURSE(child) \ if (remainingDepth < 0) { \ putDeferredObject(child); \ } else { \ markChildren(child, limit, remainingDepth); \ } /* If non-NULL, then it holds the value of object for the next iteration * through the loop. Used to implement tail recursion. */ cell *nextObject = NULL; remainingDepth -= 1; /* remaining depth for any subcalls */ for(;;) { cell *header = object - HEADERSIZE; GCT_ObjectType gctype = TYPE(*header);#if INCLUDEDEBUGCODE if (tracegarbagecollectionverbose) { fprintf(stdout, "GC Mark: "); printObject(object); }#endif 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; /* Mark the possible monitor object alive */ checkMonitorAndMark((OBJECT)instance); while (clazz) { /* This is the tough part: walk through all the fields */ /* of the object and see if they contain pointers */ FOR_EACH_FIELD(thisField, clazz->fieldTable) /* Is this a non-static pointer field? */ if ((thisField->accessFlags & (ACC_POINTER | ACC_STATIC)) == ACC_POINTER) { int offset = thisField->u.offset; cell *subobject = instance->data[offset].cellp; MARK_AND_TAIL_RECURSE(subobject); } END_FOR_EACH_FIELD clazz = clazz->superClass; } break; } case GCT_ARRAY: /* The object is a Java array with primitive values. */ checkMonitorAndMark((OBJECT)object); break; case GCT_POINTERLIST: { POINTERLIST list = (POINTERLIST)object; length = list->length; ptr = &list->data[0].cellp; goto markArray; } case GCT_WEAKPOINTERLIST: /* don't mark children, we only want to update the pointers * if the objects are marked because of other references */ /* 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. */ checkMonitorAndMark((OBJECT)object); length = ((ARRAY)object)->length; ptr = &((ARRAY)object)->data[0].cellp; /* FALL THROUGH */ markArray: /* Keep objects in the array alive. */ while (--length >= 0) { cell *subobject = *ptr++; MARK_AND_TAIL_RECURSE(subobject); } break; case GCT_METHODTABLE: FOR_EACH_METHOD(thisMethod, ((METHODTABLE)object)) if ((thisMethod->accessFlags & ACC_NATIVE) == 0) { MARK_OBJECT(thisMethod->u.java.code); MARK_OBJECT_IF_NON_NULL(thisMethod->u.java.handlers); } END_FOR_EACH_METHOD break; case GCT_MONITOR: /* The only pointers in a monitor will get handled elsewhere */ break; case GCT_NOPOINTERS: /* The object does not have any pointers in it */ break; case GCT_EXECSTACK: /* Scanning of executing stack is done as part of the root set */ break; case GCT_THREAD: /* Scanning of all live threads is done as part of the root set */ 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 */ fatalVMError(KVM_MSG_BAD_DYNAMIC_HEAP_OBJECTS_FOUND); } /* End of switch statement */ if (nextObject != NULL) { /* We can perform a tail recursive call. */ object = nextObject; nextObject = NULL; /* continue */ } else if (remainingDepth == MAX_GC_DEPTH - 1 && deferredObjectCount > 0) { /* We're at the outer level of recursion and there is a deferred * object for us to look up. Note that remainingDepth has * already been decremented, so we don't compare against * MAX_GC_DEPTH */ object = getDeferredObject(); /* continue */ } else { break; /* finish "for" loop. */ } } /* end of for(ever) loop */}/*========================================================================= * FUNCTION: markThreadStack * TYPE: private garbage collection operation * OVERVIEW: Scan the execution stack of the given thread, and * mark all the objects that are reachable from it. * INTERFACE: * parameters: pointer to the thread whose stack is to be scanned. * returns: <nothing> *=======================================================================*/static voidmarkThreadStack(THREAD thisThread){ /* Perform a complete stack trace, looking for pointers */ /* inside the stack and marking the corresponding objects. */ cell *heapSpace = CurrentHeap; cell *heapSpaceEnd = CurrentHeapEnd; FRAME thisFP = thisThread->fpStore; cell* thisSP = thisThread->spStore; BYTE* thisIP = thisThread->ipStore; char map[(MAXIMUM_STACK_AND_LOCALS + 7) >> 3]; long i; STACK stack = thisThread->stack; if (thisFP == NULL) { MARK_OBJECT_IF_NON_NULL(stack); return; } thisFP->stack->next = NULL; /* we're the end of the stack chain. */ while (thisFP != NULL) { /* Get a pointer to the method of 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; /* Mark the possible synchronization object alive */ MARK_OBJECT_IF_NON_NULL(thisFP->syncObject); MARK_OBJECT_IF_NON_NULL(thisFP->stack); if (method == RunCustomCodeMethod) { memset(map, -1, (realStackSize + 7) >> 3); } else { unsigned int expectedStackSize = getGCRegisterMask(method, thisIP, map); if ((unsigned int)realStackSize > expectedStackSize) { /* If the garbage collector gets called from */ /* inside KNI method calls, the execution stack */ /* may contain more elements than the stack map */ /* indicates => normalize the stack size for */ /* this situation */ totalSize = expectedStackSize + localsCount; } } for (i = 0; i < totalSize; i++) { if (map[i >> 3] & (1 << (i & 7))) { cell *arg; if (i < localsCount) { arg = *(cell **)&localVars[i]; } else { arg = *(cell **)&operandStack[i - localsCount]; } if (INCLUDEDEBUGCODE && method != RunCustomCodeMethod) { checkValidHeapPointer(arg); } MARK_OBJECT_IF_NON_NULL(arg); } } /* This frame is now done. Go to the previous one */ /* using the same algorithm as in 'popFrame()'. */ thisSP = thisFP->previousSp; thisIP = thisFP->previousIp; thisFP = thisFP->previousFp; }}static void checkMonitorAndMark(OBJECT object){ /* We only need to mark real monitors. We don't need to mark threads' * in the monitor/hashcode slot since they will be marked elsewhere */ if (OBJECT_HAS_REAL_MONITOR(object)) { cell *heapSpace = CurrentHeap; cell *heapSpaceEnd = CurrentHeapEnd; MONITOR monitor = OBJECT_MHC_MONITOR(object); /* A monitor doesn't contain any subobjects that won't be marked * elsewhere */ MARK_OBJECT(monitor); }}static voidmarkWeakPointerLists(){ WEAKPOINTERLIST list; /* save the current native method pointer */ cell* currentNativeLp;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -