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

📄 jsscope.c

📁 Swfdec still is development software, but has also followed a rigid no-crashes-allowed policy. I b
💻 C
📖 第 1 页 / 共 4 页
字号:
}#define SPROP_MATCH(sprop, child)                                             \    SPROP_MATCH_PARAMS(sprop, (child)->id, (child)->getter, (child)->setter,  \                       (child)->slot, (child)->attrs, (child)->flags,         \                       (child)->shortid)#define SPROP_MATCH_PARAMS(sprop, aid, agetter, asetter, aslot, aattrs,       \                           aflags, ashortid)                                  \    ((sprop)->id == (aid) &&                                                  \     SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs,      \                                 aflags, ashortid))#define SPROP_MATCH_PARAMS_AFTER_ID(sprop, agetter, asetter, aslot, aattrs,   \                                    aflags, ashortid)                         \    ((sprop)->getter == (agetter) &&                                          \     (sprop)->setter == (asetter) &&                                          \     (sprop)->slot == (aslot) &&                                              \     (sprop)->attrs == (aattrs) &&                                            \     (((sprop)->flags ^ (aflags)) & ~SPROP_FLAGS_NOT_MATCHED) == 0 &&         \     (sprop)->shortid == (ashortid))JS_STATIC_DLL_CALLBACK(JSBool)js_MatchScopeProperty(JSDHashTable *table,                      const JSDHashEntryHdr *hdr,                      const void *key){    const JSPropertyTreeEntry *entry = (const JSPropertyTreeEntry *)hdr;    const JSScopeProperty *sprop = entry->child;    const JSScopeProperty *kprop = (const JSScopeProperty *)key;    return SPROP_MATCH(sprop, kprop);}static const JSDHashTableOps PropertyTreeHashOps = {    JS_DHashAllocTable,    JS_DHashFreeTable,    JS_DHashGetKeyStub,    js_HashScopeProperty,    js_MatchScopeProperty,    JS_DHashMoveEntryStub,    JS_DHashClearEntryStub,    JS_DHashFinalizeStub,    NULL};/* * A property tree node on rt->propertyFreeList overlays the following prefix * struct on JSScopeProperty. */typedef struct FreeNode {    jsid                id;    JSScopeProperty     *next;    JSScopeProperty     **prevp;} FreeNode;#define FREENODE(sprop) ((FreeNode *) (sprop))#define FREENODE_INSERT(list, sprop)                                          \    JS_BEGIN_MACRO                                                            \        FREENODE(sprop)->next = (list);                                       \        FREENODE(sprop)->prevp = &(list);                                     \        if (list)                                                             \            FREENODE(list)->prevp = &FREENODE(sprop)->next;                   \        (list) = (sprop);                                                     \    JS_END_MACRO#define FREENODE_REMOVE(sprop)                                                \    JS_BEGIN_MACRO                                                            \        *FREENODE(sprop)->prevp = FREENODE(sprop)->next;                      \        if (FREENODE(sprop)->next)                                            \            FREENODE(FREENODE(sprop)->next)->prevp = FREENODE(sprop)->prevp;  \    JS_END_MACRO/* NB: Called with the runtime lock held. */static JSScopeProperty *NewScopeProperty(JSRuntime *rt){    JSScopeProperty *sprop;    sprop = rt->propertyFreeList;    if (sprop) {        FREENODE_REMOVE(sprop);    } else {        JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *,                               &rt->propertyArenaPool,                               sizeof(JSScopeProperty));        if (!sprop)            return NULL;    }    JS_RUNTIME_METER(rt, livePropTreeNodes);    JS_RUNTIME_METER(rt, totalPropTreeNodes);    return sprop;}#define CHUNKY_KIDS_TAG         ((jsuword)1)#define KIDS_IS_CHUNKY(kids)    ((jsuword)(kids) & CHUNKY_KIDS_TAG)#define KIDS_TO_CHUNK(kids)     ((PropTreeKidsChunk *)                        \                                 ((jsuword)(kids) & ~CHUNKY_KIDS_TAG))#define CHUNK_TO_KIDS(chunk)    ((JSScopeProperty *)                          \                                 ((jsuword)(chunk) | CHUNKY_KIDS_TAG))#define MAX_KIDS_PER_CHUNK      10typedef struct PropTreeKidsChunk PropTreeKidsChunk;struct PropTreeKidsChunk {    JSScopeProperty     *kids[MAX_KIDS_PER_CHUNK];    PropTreeKidsChunk   *next;};static PropTreeKidsChunk *NewPropTreeKidsChunk(JSRuntime *rt){    PropTreeKidsChunk *chunk;    chunk = calloc(1, sizeof *chunk);    if (!chunk)        return NULL;    JS_ASSERT(((jsuword)chunk & CHUNKY_KIDS_TAG) == 0);    JS_RUNTIME_METER(rt, propTreeKidsChunks);    return chunk;}static voidDestroyPropTreeKidsChunk(JSRuntime *rt, PropTreeKidsChunk *chunk){    JS_RUNTIME_UNMETER(rt, propTreeKidsChunks);    free(chunk);}/* NB: Called with the runtime lock held. */static JSBoolInsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,                        JSScopeProperty *child){    JSPropertyTreeEntry *entry;    JSScopeProperty **childp, *kids, *sprop;    PropTreeKidsChunk *chunk, **chunkp;    uintN i;    JS_ASSERT(!parent || child->parent != parent);    if (!parent) {        entry = (JSPropertyTreeEntry *)            JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD);        if (!entry)            return JS_FALSE;        childp = &entry->child;        sprop = *childp;        if (!sprop) {            *childp = child;        } else {            /*             * A "Duplicate child" case.             *             * We can't do away with child, as at least one live scope entry             * still points at it.  What's more, that scope's lastProp chains             * through an ancestor line to reach child, and js_Enumerate and             * others count on this linkage.  We must leave child out of the             * hash table, and not require it to be there when we eventually             * GC it (see RemovePropertyTreeChild, below).             *             * It is necessary to leave the duplicate child out of the hash             * table to preserve entry uniqueness.  It is safe to leave the             * child out of the hash table (unlike the duplicate child cases             * below), because the child's parent link will be null, which             * can't dangle.             */            JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));            JS_RUNTIME_METER(rt, duplicatePropTreeNodes);        }    } else {        childp = &parent->kids;        kids = *childp;        if (kids) {            if (KIDS_IS_CHUNKY(kids)) {                chunk = KIDS_TO_CHUNK(kids);                do {                    for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {                        childp = &chunk->kids[i];                        sprop = *childp;                        if (!sprop)                            goto insert;                        JS_ASSERT(sprop != child);                        if (SPROP_MATCH(sprop, child)) {                            /*                             * Duplicate child, see comment above.  In this                             * case, we must let the duplicate be inserted at                             * this level in the tree, so we keep iterating,                             * looking for an empty slot in which to insert.                             */                            JS_ASSERT(sprop != child);                            JS_RUNTIME_METER(rt, duplicatePropTreeNodes);                        }                    }                    chunkp = &chunk->next;                } while ((chunk = *chunkp) != NULL);                chunk = NewPropTreeKidsChunk(rt);                if (!chunk)                    return JS_FALSE;                *chunkp = chunk;                childp = &chunk->kids[0];            } else {                sprop = kids;                JS_ASSERT(sprop != child);                if (SPROP_MATCH(sprop, child)) {                    /*                     * Duplicate child, see comment above.  Once again, we                     * must let duplicates created by deletion pile up in a                     * kids-chunk-list, in order to find them when sweeping                     * and thereby avoid dangling parent pointers.                     */                    JS_RUNTIME_METER(rt, duplicatePropTreeNodes);                }                chunk = NewPropTreeKidsChunk(rt);                if (!chunk)                    return JS_FALSE;                parent->kids = CHUNK_TO_KIDS(chunk);                chunk->kids[0] = sprop;                childp = &chunk->kids[1];            }        }    insert:        *childp = child;    }    child->parent = parent;    return JS_TRUE;}/* NB: Called with the runtime lock held. */static voidRemovePropertyTreeChild(JSRuntime *rt, JSScopeProperty *child){    JSPropertyTreeEntry *entry;    JSScopeProperty *parent, *kids, *kid;    PropTreeKidsChunk *list, *chunk, **chunkp, *lastChunk;    uintN i, j;    parent = child->parent;    if (!parent) {        /*         * Don't remove child if it is not in rt->propertyTreeHash, but only         * matches a root child in the table that has compatible members. See         * the "Duplicate child" comments in InsertPropertyTreeChild, above.         */        entry = (JSPropertyTreeEntry *)            JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_LOOKUP);        if (entry->child == child)            JS_DHashTableRawRemove(&rt->propertyTreeHash, &entry->hdr);    } else {        kids = parent->kids;        if (KIDS_IS_CHUNKY(kids)) {            list = chunk = KIDS_TO_CHUNK(kids);            chunkp = &list;            do {                for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {                    if (chunk->kids[i] == child) {                        lastChunk = chunk;                        if (!lastChunk->next) {                            j = i + 1;                        } else {                            j = 0;                            do {                                chunkp = &lastChunk->next;                                lastChunk = *chunkp;                            } while (lastChunk->next);                        }                        for (; j < MAX_KIDS_PER_CHUNK; j++) {                            if (!lastChunk->kids[j])                                break;                        }                        --j;                        if (chunk != lastChunk || j > i)                            chunk->kids[i] = lastChunk->kids[j];                        lastChunk->kids[j] = NULL;                        if (j == 0) {                            *chunkp = NULL;                            if (!list)                                parent->kids = NULL;                            DestroyPropTreeKidsChunk(rt, lastChunk);                        }                        return;                    }                }                chunkp = &chunk->next;            } while ((chunk = *chunkp) != NULL);        } else {            kid = kids;            if (kid == child)                parent->kids = NULL;        }    }}/* * Called *without* the runtime lock held, this function acquires that lock * only when inserting a new child.  Thus there may be races to find or add * a node that result in duplicates.  We expect such races to be rare! */static JSScopeProperty *GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,                     JSScopeProperty *child){    JSRuntime *rt;    JSPropertyTreeEntry *entry;    JSScopeProperty *sprop;    PropTreeKidsChunk *chunk;    uintN i;    rt = cx->runtime;    if (!parent) {        JS_LOCK_RUNTIME(rt);        entry = (JSPropertyTreeEntry *)            JS_DHashTableOperate(&rt->propertyTreeHash, child, JS_DHASH_ADD);        if (!entry)            goto out_of_memory;        sprop = entry->child;        if (sprop)            goto out;    } else {        /*         * Because chunks are appended at the end and never deleted except by         * the GC, we can search without taking the runtime lock.  We may miss         * a matching sprop added by another thread, and make a duplicate one,         * but that is an unlikely, therefore small, cost.  The property tree         * has extremely low fan-out below its root in popular embeddings with         * real-world workloads.         *         * If workload changes so as to increase fan-out significantly below         * the property tree root, we'll want to add another tag bit stored in         * parent->kids that indicates a JSDHashTable pointer.         */        entry = NULL;        sprop = parent->kids;        if (sprop) {            if (KIDS_IS_CHUNKY(sprop)) {                chunk = KIDS_TO_CHUNK(sprop);                do {                    for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {                        sprop = chunk->kids[i];                        if (!sprop)                            goto not_found;                        if (SPROP_MATCH(sprop, child))                            return sprop;                    }                } while ((chunk = chunk->next) != NULL);            } else {                if (SPROP_MATCH(sprop, child))                    return sprop;            }        }    not_found:        JS_LOCK_RUNTIME(rt);    }    sprop = NewScopeProperty(rt);    if (!sprop)        goto out_of_memory;    sprop->id = child->id;    sprop->getter = child->getter;    sprop->setter = child->setter;    sprop->slot = child->slot;    sprop->attrs = child->attrs;    sprop->flags = child->flags;    sprop->shortid = child->shortid;    sprop->parent = sprop->kids = NULL;    if (!parent) {        entry->child = sprop;    } else {        if (!InsertPropertyTreeChild(rt, parent, sprop))            goto out_of_memory;    }out:    JS_UNLOCK_RUNTIME(rt);    return sprop;out_of_memory:    JS_UNLOCK_RUNTIME(rt);    JS_ReportOutOfMemory(cx);    return NULL;}

⌨️ 快捷键说明

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