⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 collector.c

📁 已经移植好的java虚拟机
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 + -