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

📄 jsscope.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 4 页
字号:
                    scope->lastProp = overwriting;                } else {                    sprop = GetPropertyTreeChild(cx, sprop, overwriting);                    if (sprop) {                        JS_ASSERT(sprop != overwriting);                        scope->lastProp = sprop;                    }                    overwriting = sprop;                }                break;            }            if (sprop == overwriting)                break;        }        if (overwriting) {            if (scope->table)                SPROP_STORE_PRESERVING_COLLISION(spp, overwriting);            scope->entryCount++;        }        CHECK_ANCESTOR_LINE(scope, JS_TRUE);    }    METER(addFailures);    return NULL;}JSScopeProperty *js_ChangeScopePropertyAttrs(JSContext *cx, JSScope *scope,                            JSScopeProperty *sprop, uintN attrs, uintN mask,                            JSPropertyOp getter, JSPropertyOp setter){    JSScopeProperty child, *newsprop, **spp;    CHECK_ANCESTOR_LINE(scope, JS_TRUE);    /* Allow only shared (slot-less) => unshared (slot-full) transition. */    attrs |= sprop->attrs & mask;    JS_ASSERT(!((attrs ^ sprop->attrs) & JSPROP_SHARED) ||              !(attrs & JSPROP_SHARED));    if (getter == JS_PropertyStub)        getter = NULL;    if (setter == JS_PropertyStub)        setter = NULL;    if (sprop->attrs == attrs &&        sprop->getter == getter &&        sprop->setter == setter) {        return sprop;    }    child.id = sprop->id;    child.getter = getter;    child.setter = setter;    child.slot = sprop->slot;    child.attrs = attrs;    child.flags = sprop->flags;    child.shortid = sprop->shortid;    if (SCOPE_LAST_PROP(scope) == sprop) {        /*         * Optimize the case where the last property added to scope is changed         * to have a different attrs, getter, or setter.  In the last property         * case, we need not fork the property tree.  But since we do not call         * js_AddScopeProperty, we may need to allocate a new slot directly.         */        if ((sprop->attrs & JSPROP_SHARED) && !(attrs & JSPROP_SHARED)) {            JS_ASSERT(child.slot == SPROP_INVALID_SLOT);            if (!js_AllocSlot(cx, scope->object, &child.slot))                return NULL;        }        newsprop = GetPropertyTreeChild(cx, sprop->parent, &child);        if (newsprop) {            spp = js_SearchScope(scope, sprop->id, JS_FALSE);            JS_ASSERT(SPROP_FETCH(spp) == sprop);            if (scope->table)                SPROP_STORE_PRESERVING_COLLISION(spp, newsprop);            scope->lastProp = newsprop;            CHECK_ANCESTOR_LINE(scope, JS_TRUE);        }    } else {        /*         * Let js_AddScopeProperty handle this |overwriting| case, including         * the conservation of sprop->slot (if it's valid).  We must not call         * js_RemoveScopeProperty here, it will free a valid sprop->slot and         * js_AddScopeProperty won't re-allocate it.         */        newsprop = js_AddScopeProperty(cx, scope, child.id,                                       child.getter, child.setter, child.slot,                                       child.attrs, child.flags, child.shortid);    }#ifdef DEBUG_brendan    if (!newsprop)        METER(changeFailures);#endif    return newsprop;}JSBooljs_RemoveScopeProperty(JSContext *cx, JSScope *scope, jsid id){    JSScopeProperty **spp, *stored, *sprop;    uint32 size;    JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));    CHECK_ANCESTOR_LINE(scope, JS_TRUE);    if (SCOPE_IS_SEALED(scope)) {        ReportReadOnlyScope(cx, scope);        return JS_FALSE;    }    METER(removes);    spp = js_SearchScope(scope, id, JS_FALSE);    stored = *spp;    sprop = SPROP_CLEAR_COLLISION(stored);    if (!sprop) {        METER(uselessRemoves);        return JS_TRUE;    }    /* Convert from a list to a hash so we can handle "middle deletes". */    if (!scope->table && sprop != scope->lastProp) {        if (!CreateScopeTable(scope)) {            JS_ReportOutOfMemory(cx);            return JS_FALSE;        }        spp = js_SearchScope(scope, id, JS_FALSE);        stored = *spp;        sprop = SPROP_CLEAR_COLLISION(stored);    }    /* First, if sprop is unshared and not cleared, free its slot number. */    if (SPROP_HAS_VALID_SLOT(sprop, scope))        js_FreeSlot(cx, scope->object, sprop->slot);    /* Next, remove id by setting its entry to a removed or free sentinel. */    if (SPROP_HAD_COLLISION(stored)) {        JS_ASSERT(scope->table);        *spp = SPROP_REMOVED;        scope->removedCount++;    } else {        METER(removeFrees);        if (scope->table)            *spp = NULL;    }    scope->entryCount--;    JS_RUNTIME_UNMETER(cx->runtime, liveScopeProps);    /* Update scope->lastProp directly, or set its deferred update flag. */    if (sprop == SCOPE_LAST_PROP(scope)) {        do {            SCOPE_REMOVE_LAST_PROP(scope);            if (!SCOPE_HAD_MIDDLE_DELETE(scope))                break;            sprop = SCOPE_LAST_PROP(scope);        } while (sprop && !SCOPE_HAS_PROPERTY(scope, sprop));    } else if (!SCOPE_HAD_MIDDLE_DELETE(scope)) {        SCOPE_SET_MIDDLE_DELETE(scope);    }    CHECK_ANCESTOR_LINE(scope, JS_TRUE);    /* Last, consider shrinking scope's table if its load factor is <= .25. */    size = SCOPE_CAPACITY(scope);    if (size > MIN_SCOPE_SIZE && scope->entryCount <= size >> 2) {        METER(shrinks);        (void) ChangeScope(cx, scope, -1);    }    return JS_TRUE;}voidjs_ClearScope(JSContext *cx, JSScope *scope){    CHECK_ANCESTOR_LINE(scope, JS_TRUE);#ifdef DEBUG    JS_LOCK_RUNTIME_VOID(cx->runtime,                         cx->runtime->liveScopeProps -= scope->entryCount);#endif    if (scope->table)        free(scope->table);    SCOPE_CLR_MIDDLE_DELETE(scope);    InitMinimalScope(scope);}#ifdef DEBUG_brendan#include <stdio.h>#include <math.h>uint32 js_nkids_max;uint32 js_nkids_sum;double js_nkids_sqsum;uint32 js_nkids_hist[11];static voidMeterKidCount(uintN nkids){    if (nkids) {        js_nkids_sum += nkids;        js_nkids_sqsum += (double)nkids * nkids;        if (nkids > js_nkids_max)            js_nkids_max = nkids;    }    js_nkids_hist[JS_MIN(nkids, 10)]++;}static voidMeterPropertyTree(JSScopeProperty *node){    uintN i, nkids;    JSScopeProperty *kids, *kid;    PropTreeKidsChunk *chunk;    nkids = 0;    kids = node->kids;    if (kids) {        if (KIDS_IS_CHUNKY(kids)) {            for (chunk = KIDS_TO_CHUNK(kids); chunk; chunk = chunk->next) {                for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {                    kid = chunk->kids[i];                    if (!kid)                        break;                    MeterPropertyTree(kid);                    nkids++;                }            }        } else {            MeterPropertyTree(kids);            nkids = 1;        }    }    MeterKidCount(nkids);}JS_STATIC_DLL_CALLBACK(JSDHashOperator)js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,                     void *arg){    JSPropertyTreeEntry *entry = (JSPropertyTreeEntry *)hdr;    MeterPropertyTree(entry->child);    return JS_DHASH_NEXT;}#endif /* DEBUG_brendan */voidjs_SweepScopeProperties(JSRuntime *rt){    JSArena **ap, *a;    JSScopeProperty *limit, *sprop, *parent, *kids, *kid;    uintN liveCount;    PropTreeKidsChunk *chunk, *nextChunk;    uintN i;#ifdef DEBUG_brendan    uint32 livePropCapacity = 0, totalLiveCount = 0;    static FILE *logfp;    if (!logfp)        logfp = fopen("/tmp/proptree.stats", "a");    MeterKidCount(rt->propertyTreeHash.entryCount);    JS_DHashTableEnumerate(&rt->propertyTreeHash, js_MeterPropertyTree, NULL);    {        double mean = 0., var = 0., sigma = 0.;        double nodesum = rt->livePropTreeNodes;        double kidsum = js_nkids_sum;        if (nodesum > 0 && kidsum >= 0) {            mean = kidsum / nodesum;            var = nodesum * js_nkids_sqsum - kidsum * kidsum;            if (var < 0.0 || nodesum <= 1)                var = 0.0;            else                var /= nodesum * (nodesum - 1);            /* Windows says sqrt(0.0) is "-1.#J" (?!) so we must test. */            sigma = (var != 0.) ? sqrt(var) : 0.;        }        fprintf(logfp,                "props %u nodes %g beta %g meankids %g sigma %g max %u",                rt->liveScopeProps, nodesum, nodesum / rt->liveScopeProps,                mean, sigma, js_nkids_max);    }    fprintf(logfp, " histogram %u %u %u %u %u %u %u %u %u %u %u",            js_nkids_hist[0], js_nkids_hist[1],            js_nkids_hist[2], js_nkids_hist[3],            js_nkids_hist[4], js_nkids_hist[5],            js_nkids_hist[6], js_nkids_hist[7],            js_nkids_hist[8], js_nkids_hist[9],            js_nkids_hist[10]);    js_nkids_sum = js_nkids_max = 0;    js_nkids_sqsum = 0;    memset(js_nkids_hist, 0, sizeof js_nkids_hist);#endif    ap = &rt->propertyArenaPool.first.next;    while ((a = *ap) != NULL) {        limit = (JSScopeProperty *) a->avail;        liveCount = 0;        for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) {            /* If the id is null, sprop is already on the freelist. */            if (sprop->id == JSVAL_NULL)                continue;            /* If the mark bit is set, sprop is alive, so we skip it. */            if (sprop->flags & SPROP_MARK) {                sprop->flags &= ~SPROP_MARK;                liveCount++;                continue;            }            /* Ok, sprop is garbage to collect: unlink it from its parent. */            RemovePropertyTreeChild(rt, sprop);            /* Take care to reparent all sprop's kids to their grandparent. */            kids = sprop->kids;            if (kids) {                sprop->kids = NULL;                parent = sprop->parent;                if (KIDS_IS_CHUNKY(kids)) {                    chunk = KIDS_TO_CHUNK(kids);                    do {                        for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {                            kid = chunk->kids[i];                            if (!kid)                                break;                            JS_ASSERT(kid->parent == sprop);                            InsertPropertyTreeChild(rt, parent, kid);                        }                        nextChunk = chunk->next;                        DestroyPropTreeKidsChunk(rt, chunk);                    } while ((chunk = nextChunk) != NULL);                } else {                    kid = kids;                    InsertPropertyTreeChild(rt, parent, kid);                }            }            /* Clear id so we know (above) that sprop is on the freelist. */            sprop->id = JSVAL_NULL;            FREENODE_INSERT(rt->propertyFreeList, sprop);            JS_RUNTIME_UNMETER(rt, livePropTreeNodes);        }        /* If a contains no live properties, return it to the malloc heap. */        if (liveCount == 0) {            for (sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++)                FREENODE_REMOVE(sprop);            JS_ARENA_DESTROY(&rt->propertyArenaPool, a, ap);        } else {#ifdef DEBUG_brendan            livePropCapacity += limit - (JSScopeProperty *) a->base;            totalLiveCount += liveCount;#endif            ap = &a->next;        }    }#ifdef DEBUG_brendan    fprintf(logfp, " arenautil %g%%\n",            (totalLiveCount * 100.) / livePropCapacity);    fflush(logfp);#endif}JSBooljs_InitPropertyTree(JSRuntime *rt){    if (!JS_DHashTableInit(&rt->propertyTreeHash, &PropertyTreeHashOps, NULL,                           sizeof(JSPropertyTreeEntry), JS_DHASH_MIN_SIZE)) {        rt->propertyTreeHash.ops = NULL;        return JS_FALSE;    }    JS_InitArenaPool(&rt->propertyArenaPool, "properties",                     256 * sizeof(JSScopeProperty), sizeof(void *));    return JS_TRUE;}voidjs_FinishPropertyTree(JSRuntime *rt){    if (rt->propertyTreeHash.ops) {        JS_DHashTableFinish(&rt->propertyTreeHash);        rt->propertyTreeHash.ops = NULL;    }    JS_FinishArenaPool(&rt->propertyArenaPool);}

⌨️ 快捷键说明

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