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

📄 jsgc.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
    uint32 *leakedroots = (uint32 *)arg;    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;    (*leakedroots)++;    fprintf(stderr,            "JS engine warning: leaking GC root \'%s\' at %p\n",            rhe->name ? (char *)rhe->name : "", rhe->root);    return JS_DHASH_NEXT;}static voidCheckLeakedRoots(JSRuntime *rt){    uint32 leakedroots = 0;    /* Warn (but don't assert) debug builds of any remaining roots. */    JS_DHashTableEnumerate(&rt->gcRootsHash, js_root_printer,                           &leakedroots);    if (leakedroots > 0) {        if (leakedroots == 1) {            fprintf(stderr,"JS engine warning: 1 GC root remains after destroying the JSRuntime.\n""                   This root may point to freed memory. Objects reachable\n""                   through it have not been finalized.\n");        } else {            fprintf(stderr,"JS engine warning: %lu GC roots remain after destroying the JSRuntime.\n""                   These roots may point to freed memory. Objects reachable\n""                   through them have not been finalized.\n",                        (unsigned long) leakedroots);        }    }}typedef struct NamedRootDumpArgs {    void (*dump)(const char *name, void *rp, void *data);    void *data;} NamedRootDumpArgs;JS_STATIC_DLL_CALLBACK(JSDHashOperator)js_named_root_dumper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,                     void *arg){    NamedRootDumpArgs *args = (NamedRootDumpArgs *) arg;    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;    if (rhe->name)        args->dump(rhe->name, rhe->root, args->data);    return JS_DHASH_NEXT;}voidjs_DumpNamedRoots(JSRuntime *rt,                  void (*dump)(const char *name, void *rp, void *data),                  void *data){    NamedRootDumpArgs args;    args.dump = dump;    args.data = data;    JS_DHashTableEnumerate(&rt->gcRootsHash, js_named_root_dumper, &args);}#endif /* DEBUG */typedef struct GCRootMapArgs {    JSGCRootMapFun map;    void *data;} GCRootMapArgs;JS_STATIC_DLL_CALLBACK(JSDHashOperator)js_gcroot_mapper(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,                 void *arg){    GCRootMapArgs *args = (GCRootMapArgs *) arg;    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;    intN mapflags;    JSDHashOperator op;    mapflags = args->map(rhe->root, rhe->name, args->data);#if JS_MAP_GCROOT_NEXT == JS_DHASH_NEXT &&                                     \    JS_MAP_GCROOT_STOP == JS_DHASH_STOP &&                                     \    JS_MAP_GCROOT_REMOVE == JS_DHASH_REMOVE    op = (JSDHashOperator)mapflags;#else    op = JS_DHASH_NEXT;    if (mapflags & JS_MAP_GCROOT_STOP)        op |= JS_DHASH_STOP;    if (mapflags & JS_MAP_GCROOT_REMOVE)        op |= JS_DHASH_REMOVE;#endif    return op;}uint32js_MapGCRoots(JSRuntime *rt, JSGCRootMapFun map, void *data){    GCRootMapArgs args;    uint32 rv;    args.map = map;    args.data = data;    JS_LOCK_GC(rt);    rv = JS_DHashTableEnumerate(&rt->gcRootsHash, js_gcroot_mapper, &args);    JS_UNLOCK_GC(rt);    return rv;}JSBooljs_RegisterCloseableIterator(JSContext *cx, JSObject *obj){    JSRuntime *rt;    JSBool ok;    rt = cx->runtime;    JS_ASSERT(!rt->gcRunning);    JS_LOCK_GC(rt);    ok = AddToPtrTable(cx, &rt->gcIteratorTable, &iteratorTableInfo, obj);    JS_UNLOCK_GC(rt);    return ok;}static voidCloseIteratorStates(JSContext *cx){    JSRuntime *rt;    size_t count, newCount, i;    void **array;    JSObject *obj;    rt = cx->runtime;    count = rt->gcIteratorTable.count;    array = rt->gcIteratorTable.array;    newCount = 0;    for (i = 0; i != count; ++i) {        obj = (JSObject *)array[i];        if (js_IsAboutToBeFinalized(cx, obj))            js_CloseIteratorState(cx, obj);        else            array[newCount++] = obj;    }    ShrinkPtrTable(&rt->gcIteratorTable, &iteratorTableInfo, newCount);}#if JS_HAS_GENERATORSvoidjs_RegisterGenerator(JSContext *cx, JSGenerator *gen){    JSRuntime *rt;    rt = cx->runtime;    JS_ASSERT(!rt->gcRunning);    JS_ASSERT(rt->state != JSRTS_LANDING);    JS_ASSERT(gen->state == JSGEN_NEWBORN);    JS_LOCK_GC(rt);    gen->next = rt->gcCloseState.reachableList;    rt->gcCloseState.reachableList = gen;    METER(rt->gcStats.nclose++);    METER(rt->gcStats.maxnclose = JS_MAX(rt->gcStats.maxnclose,                                         rt->gcStats.nclose));    JS_UNLOCK_GC(rt);}/* * We do not run close hooks when the parent scope of the generator instance * becomes unreachable to prevent denial-of-service and resource leakage from * misbehaved generators. * * Called from the GC. */static JSBoolCanScheduleCloseHook(JSGenerator *gen){    JSObject *parent;    JSBool canSchedule;    /* Avoid OBJ_GET_PARENT overhead as we are in GC. */    parent = JSVAL_TO_OBJECT(gen->obj->slots[JSSLOT_PARENT]);    canSchedule = *js_GetGCThingFlags(parent) & GCF_MARK;#ifdef DEBUG_igor    if (!canSchedule) {        fprintf(stderr, "GEN: Kill without schedule, gen=%p parent=%p\n",                (void *)gen, (void *)parent);    }#endif    return canSchedule;}/* * Check if we should delay execution of the close hook. * * Called outside GC or any locks. * * XXX The current implementation is a hack that embeds the knowledge of the * browser embedding pending the resolution of bug 352788. In the browser we * must not close any generators that came from a page that is currently in * the browser history. We detect that using the fact in the browser the scope * is history if scope->outerObject->innerObject != scope. */static JSBoolShouldDeferCloseHook(JSContext *cx, JSGenerator *gen, JSBool *defer){    JSObject *parent, *obj;    JSClass *clasp;    JSExtendedClass *xclasp;    /*     * This is called outside any locks, so use thread-safe macros to access     * parent and  classes.     */    *defer = JS_FALSE;    parent = OBJ_GET_PARENT(cx, gen->obj);    clasp = OBJ_GET_CLASS(cx, parent);    if (clasp->flags & JSCLASS_IS_EXTENDED) {        xclasp = (JSExtendedClass *)clasp;        if (xclasp->outerObject) {            obj = xclasp->outerObject(cx, parent);            if (!obj)                return JS_FALSE;            OBJ_TO_INNER_OBJECT(cx, obj);            if (!obj)                return JS_FALSE;            *defer = obj != parent;        }    }#ifdef DEBUG_igor    if (*defer) {        fprintf(stderr, "GEN: deferring, gen=%p parent=%p\n",                (void *)gen, (void *)parent);    }#endif    return JS_TRUE;}/* * Find all unreachable generators and move them to the todo queue from * rt->gcCloseState.reachableList to execute thier close hooks after the GC * cycle completes. To ensure liveness during the sweep phase we mark all * generators we are going to close later. */static voidFindAndMarkObjectsToClose(JSContext *cx, JSGCInvocationKind gckind,                          JSGenerator **todoQueueTail){    JSRuntime *rt;    JSGenerator *todo, **genp, *gen;    rt = cx->runtime;    todo = NULL;    genp = &rt->gcCloseState.reachableList;    while ((gen = *genp) != NULL) {        if (*js_GetGCThingFlags(gen->obj) & GCF_MARK) {            genp = &gen->next;        } else {            /* Generator must not be executing when it becomes unreachable. */            JS_ASSERT(gen->state == JSGEN_NEWBORN ||                      gen->state == JSGEN_OPEN ||                      gen->state == JSGEN_CLOSED);            *genp = gen->next;            if (gen->state == JSGEN_OPEN &&                js_FindFinallyHandler(gen->frame.script, gen->frame.pc) &&                CanScheduleCloseHook(gen)) {                /*                 * Generator yielded inside a try with a finally block.                 * Schedule it for closing.                 *                 * We keep generators that yielded outside try-with-finally                 * with gen->state == JSGEN_OPEN. The finalizer must deal with                 * open generators as we may skip the close hooks, see below.                 */                gen->next = NULL;                *todoQueueTail = gen;                todoQueueTail = &gen->next;                if (!todo)                    todo = gen;                METER(JS_ASSERT(rt->gcStats.nclose));                METER(rt->gcStats.nclose--);                METER(rt->gcStats.closelater++);                METER(rt->gcStats.maxcloselater                      = JS_MAX(rt->gcStats.maxcloselater,                               rt->gcStats.closelater));            }        }    }    if (gckind == GC_LAST_CONTEXT) {        /*         * Remove scheduled hooks on shutdown as it is too late to run them:         * we do not allow execution of arbitrary scripts at this point.         */        rt->gcCloseState.todoQueue = NULL;    } else {        /*         * Mark just-found unreachable generators *after* we scan the global         * list to prevent a generator that refers to other unreachable         * generators from keeping them on gcCloseState.reachableList.         */        for (gen = todo; gen; gen = gen->next)            GC_MARK(cx, gen->obj, "newly scheduled generator");    }}/* * Mark unreachable generators already scheduled to close and return the tail * pointer to JSGCCloseState.todoQueue. */static JSGenerator **MarkScheduledGenerators(JSContext *cx){    JSRuntime *rt;    JSGenerator **genp, *gen;    rt = cx->runtime;    genp = &rt->gcCloseState.todoQueue;    while ((gen = *genp) != NULL) {        if (CanScheduleCloseHook(gen)) {            GC_MARK(cx, gen->obj, "scheduled generator");            genp = &gen->next;        } else {            /* Discard the generator from the list if its schedule is over. */            *genp = gen->next;            METER(JS_ASSERT(rt->gcStats.closelater > 0));            METER(rt->gcStats.closelater--);        }    }    return genp;}#ifdef JS_THREADSAFE# define GC_RUNNING_CLOSE_HOOKS_PTR(cx)                                       \    (&(cx)->thread->gcRunningCloseHooks)#else# define GC_RUNNING_CLOSE_HOOKS_PTR(cx)                                       \    (&(cx)->runtime->gcCloseState.runningCloseHook)#endiftypedef struct JSTempCloseList {    JSTempValueRooter   tvr;    JSGenerator         *head;} JSTempCloseList;JS_STATIC_DLL_CALLBACK(void)mark_temp_close_list(JSContext *cx, JSTempValueRooter *tvr){    JSTempCloseList *list = (JSTempCloseList *)tvr;    JSGenerator *gen;    for (gen = list->head; gen; gen = gen->next)        GC_MARK(cx, gen->obj, "temp list generator");}#define JS_PUSH_TEMP_CLOSE_LIST(cx, tempList)                                 \    JS_PUSH_TEMP_ROOT_MARKER(cx, mark_temp_close_list, &(tempList)->tvr)#define JS_POP_TEMP_CLOSE_LIST(cx, tempList)                                  \    JS_BEGIN_MACRO                                                            \        JS_ASSERT((tempList)->tvr.u.marker == mark_temp_close_list);          \        JS_POP_TEMP_ROOT(cx, &(tempList)->tvr);                               \    JS_END_MACROJSBooljs_RunCloseHooks(JSContext *cx){    JSRuntime *rt;    JSTempCloseList tempList;    JSStackFrame *fp;    JSGenerator **genp, *gen;    JSBool ok, defer;#if JS_GCMETER    uint32 deferCount;#endif    rt = cx->runtime;    /*     * It is OK to access todoQueue outside the lock here. When many threads     * update the todo list, accessing some older value of todoQueue in the     * worst case just delays the excution of close hooks.     */    if (!rt->gcCloseState.todoQueue)        return JS_TRUE;    /*     * To prevent an infinite loop when a close hook creats more objects with     * close hooks and then triggers GC we ignore recursive invocations of     * js_RunCloseHooks and limit number of hooks to execute to the initial     * size of the list.     */    if (*GC_RUNNING_CLOSE_HOOKS_PTR(cx))        return JS_TRUE;    *GC_RUNNING_CLOSE_HOOKS_PTR(cx) = JS_TRUE;    JS_LOCK_GC(rt);    tempList.head = rt->gcCloseState.todoQueue;    JS_PUSH_TEMP_CLOSE_LIST(cx, &tempList);    rt->gcCloseState.todoQueue = NULL;    METER(rt->gcStats.closelater = 0);    rt->gcPoke = JS_TRUE;    JS_UNLOCK_GC(rt);    /*     * Set aside cx->fp since we do not want a close hook using caller or     * other means to backtrace into whatever stack might be active when     * running the hook. We store the current frame on the dormant list to

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -