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

📄 jsgc.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 4 页
字号:
        break;      }      case GCX_STRING:      case GCX_MUTABLE_STRING: {        JSString *str = (JSString *)thing;        if (JSSTRING_IS_DEPENDENT(str)) {            JS_snprintf(depbuf, sizeof depbuf, "start:%u, length:%u",                        JSSTRDEP_START(str), JSSTRDEP_LENGTH(str));            className = depbuf;        } else {            className = "string";        }        break;      }      case GCX_DOUBLE:        className = "double";        break;    }    return className;}static voidgc_dump_thing(JSGCThing *thing, uint8 flags, GCMarkNode *prev, FILE *fp){    GCMarkNode *next = NULL;    char *path = NULL;    while (prev) {        next = prev;        prev = prev->prev;    }    while (next) {        path = JS_sprintf_append(path, "%s(%s).",                                 next->name,                                 gc_object_class_name(next->thing));        next = next->next;    }    if (!path)        return;    fprintf(fp, "%08lx ", (long)thing);    switch (flags & GCF_TYPEMASK) {      case GCX_OBJECT:      {        JSObject  *obj = (JSObject *)thing;        jsval     privateValue = obj->slots[JSSLOT_PRIVATE];        void      *privateThing = JSVAL_IS_VOID(privateValue)                                  ? NULL                                  : JSVAL_TO_PRIVATE(privateValue);        const char *className = gc_object_class_name(thing);        fprintf(fp, "object %8p %s", privateThing, className);        break;      }      case GCX_DOUBLE:        fprintf(fp, "double %g", *(jsdouble *)thing);        break;      default:        fprintf(fp, "string %s", JS_GetStringBytes((JSString *)thing));        break;    }    fprintf(fp, " via %s\n", path);    free(path);}#endif /* !GC_MARK_DEBUG */static voidgc_mark_atom_key_thing(void *thing, void *arg){    JSContext *cx = (JSContext *) arg;    GC_MARK(cx, thing, "atom", NULL);}voidjs_MarkAtom(JSContext *cx, JSAtom *atom, void *arg){    jsval key;    if (atom->flags & ATOM_MARK)        return;    atom->flags |= ATOM_MARK;    key = ATOM_KEY(atom);    if (JSVAL_IS_GCTHING(key)) {#ifdef GC_MARK_DEBUG        char name[32];        if (JSVAL_IS_STRING(key)) {            JS_snprintf(name, sizeof name, "'%s'",                        JS_GetStringBytes(JSVAL_TO_STRING(key)));        } else {            JS_snprintf(name, sizeof name, "<%x>", key);        }#endif        GC_MARK(cx, JSVAL_TO_GCTHING(key), name, arg);    }}voidjs_MarkGCThing(JSContext *cx, void *thing, void *arg){    uint8 flags, *flagp;    JSRuntime *rt;    JSObject *obj;    uint32 nslots;    jsval v, *vp, *end;    JSString *str;#ifdef GC_MARK_DEBUG    JSScope *scope;    JSScopeProperty *sprop;#endif    if (!thing)        return;    flagp = js_GetGCThingFlags(thing);    flags = *flagp;    JS_ASSERT(flags != GCF_FINAL);#ifdef GC_MARK_DEBUG    if (js_LiveThingToFind == thing)        gc_dump_thing(thing, flags, arg, stderr);#endif    if (flags & GCF_MARK)        return;    *flagp |= GCF_MARK;    rt = cx->runtime;    METER(if (++rt->gcStats.depth > rt->gcStats.maxdepth)              rt->gcStats.maxdepth = rt->gcStats.depth);#ifdef GC_MARK_DEBUG    if (!js_DumpGCHeap)      js_DumpGCHeap = stderr;    gc_dump_thing(thing, flags, arg, js_DumpGCHeap);#endif    switch (flags & GCF_TYPEMASK) {      case GCX_OBJECT:        obj = (JSObject *) thing;        vp = obj->slots;        if (!vp) {            /* If obj->slots is null, obj must be a newborn. */            JS_ASSERT(!obj->map);            goto out;        }        nslots = (obj->map->ops->mark)                 ? obj->map->ops->mark(cx, obj, arg)                 : JS_MIN(obj->map->freeslot, obj->map->nslots);#ifdef GC_MARK_DEBUG        scope = OBJ_IS_NATIVE(obj) ? OBJ_SCOPE(obj) : NULL;#endif        for (end = vp + nslots; vp < end; vp++) {            v = *vp;            if (JSVAL_IS_GCTHING(v)) {#ifdef GC_MARK_DEBUG                char name[32];                if (scope) {                    uint32 slot;                    jsval nval;                    slot = vp - obj->slots;                    for (sprop = SCOPE_LAST_PROP(scope); ;                         sprop = sprop->parent) {                        if (!sprop) {                            switch (slot) {                              case JSSLOT_PROTO:                                strcpy(name, "__proto__");                                break;                              case JSSLOT_PARENT:                                strcpy(name, "__parent__");                                break;                              case JSSLOT_PRIVATE:                                strcpy(name, "__private__");                                break;                              default:                                JS_snprintf(name, sizeof name,                                            "**UNKNOWN SLOT %ld**",                                            (long)slot);                                break;                            }                            break;                        }                        if (sprop->slot == slot) {                            nval = ID_TO_VALUE(sprop->id);                            if (JSVAL_IS_INT(nval)) {                                JS_snprintf(name, sizeof name, "%ld",                                            (long)JSVAL_TO_INT(nval));                            } else if (JSVAL_IS_STRING(nval)) {                                JS_snprintf(name, sizeof name, "%s",                                  JS_GetStringBytes(JSVAL_TO_STRING(nval)));                            } else {                                strcpy(name, "**FINALIZED ATOM KEY**");                            }                            break;                        }                    }                } else {                    strcpy(name, "**UNKNOWN OBJECT MAP ENTRY**");                }#endif                GC_MARK(cx, JSVAL_TO_GCTHING(v), name, arg);            }        }        break;#ifdef DEBUG      case GCX_STRING:        str = (JSString *)thing;        JS_ASSERT(!JSSTRING_IS_DEPENDENT(str));        break;#endif      case GCX_MUTABLE_STRING:        str = (JSString *)thing;        if (JSSTRING_IS_DEPENDENT(str))            GC_MARK(cx, JSSTRDEP_BASE(str), "base", arg);        break;    }out:    METER(rt->gcStats.depth--);}JS_STATIC_DLL_CALLBACK(JSDHashOperator)gc_root_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg){    JSGCRootHashEntry *rhe = (JSGCRootHashEntry *)hdr;    jsval *rp = (jsval *)rhe->root;    jsval v = *rp;    /* Ignore null object and scalar values. */    if (!JSVAL_IS_NULL(v) && JSVAL_IS_GCTHING(v)) {        JSContext *cx = (JSContext *)arg;#ifdef DEBUG        JSArena *a;        jsuword firstpage;        JSBool root_points_to_gcArenaPool = JS_FALSE;        void *thing = JSVAL_TO_GCTHING(v);        for (a = cx->runtime->gcArenaPool.first.next; a; a = a->next) {            firstpage = FIRST_THING_PAGE(a);            if (JS_UPTRDIFF(thing, firstpage) < a->avail - firstpage) {                root_points_to_gcArenaPool = JS_TRUE;                break;            }        }        if (!root_points_to_gcArenaPool && rhe->name) {            fprintf(stderr,"JS API usage error: the address passed to JS_AddNamedRoot currently holds an\n""invalid jsval.  This is usually caused by a missing call to JS_RemoveRoot.\n""The root's name is \"%s\".\n",                    rhe->name);        }        JS_ASSERT(root_points_to_gcArenaPool);#endif        GC_MARK(cx, JSVAL_TO_GCTHING(v), rhe->name ? rhe->name : "root", NULL);    }    return JS_DHASH_NEXT;}JS_STATIC_DLL_CALLBACK(JSDHashOperator)gc_lock_marker(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 num, void *arg){    JSGCLockHashEntry *lhe = (JSGCLockHashEntry *)hdr;    void *thing = (void *)lhe->thing;    JSContext *cx = (JSContext *)arg;    GC_MARK(cx, thing, "locked object", NULL);    return JS_DHASH_NEXT;}voidjs_ForceGC(JSContext *cx, uintN gcflags){    uintN i;    for (i = 0; i < GCX_NTYPES; i++)        cx->newborn[i] = NULL;    cx->lastAtom = NULL;    cx->runtime->gcPoke = JS_TRUE;    js_GC(cx, gcflags);    JS_ArenaFinish();}#define GC_MARK_JSVALS(cx, len, vec, name)                                    \    JS_BEGIN_MACRO                                                            \        jsval _v, *_vp, *_end;                                                \                                                                              \        for (_vp = vec, _end = _vp + len; _vp < _end; _vp++) {                \            _v = *_vp;                                                        \            if (JSVAL_IS_GCTHING(_v))                                         \                GC_MARK(cx, JSVAL_TO_GCTHING(_v), name, NULL);                \        }                                                                     \    JS_END_MACROvoidjs_GC(JSContext *cx, uintN gcflags){    JSRuntime *rt;    JSContext *iter, *acx;    JSStackFrame *fp, *chain;    uintN i, depth, nslots, type;    JSStackHeader *sh;    JSArena *a, **ap;    uint8 flags, *flagp, *split;    JSGCThing *thing, *limit, **flp, **oflp;    GCFinalizeOp finalizer;    JSBool all_clear;#ifdef JS_THREADSAFE    jsword currentThread;    uint32 requestDebit;#endif    rt = cx->runtime;#ifdef JS_THREADSAFE    /* Avoid deadlock. */    JS_ASSERT(!JS_IS_RUNTIME_LOCKED(rt));#endif    /*     * Don't collect garbage if the runtime isn't up, and cx is not the last     * context in the runtime.  The last context must force a GC, and nothing     * should suppress that final collection or there may be shutdown leaks,     * or runtime bloat until the next context is created.     */    if (rt->state != JSRTS_UP && !(gcflags & GC_LAST_CONTEXT))        return;    /*     * Let the API user decide to defer a GC if it wants to (unless this     * is the last context).  Invoke the callback regardless.     */    if (rt->gcCallback) {        if (!rt->gcCallback(cx, JSGC_BEGIN) && !(gcflags & GC_LAST_CONTEXT))            return;    }    /* Lock out other GC allocator and collector invocations. */    if (!(gcflags & GC_ALREADY_LOCKED))        JS_LOCK_GC(rt);    /* Do nothing if no assignment has executed since the last GC. */    if (!rt->gcPoke) {        METER(rt->gcStats.nopoke++);        if (!(gcflags & GC_ALREADY_LOCKED))            JS_UNLOCK_GC(rt);        return;    }    METER(rt->gcStats.poke++);#ifdef JS_THREADSAFE

⌨️ 快捷键说明

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