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

📄 jsscope.c

📁 java script test programing source code
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sw=4 et tw=78: * * ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is Mozilla Communicator client code, released * March 31, 1998. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** *//* * JS symbol tables. */#include "jsstddef.h"#include <stdlib.h>#include <string.h>#include "jstypes.h"#include "jsarena.h"#include "jsbit.h"#include "jsclist.h"#include "jsdhash.h"#include "jsutil.h" /* Added by JSIFY */#include "jsapi.h"#include "jsatom.h"#include "jscntxt.h"#include "jsdbgapi.h"#include "jslock.h"#include "jsnum.h"#include "jsscope.h"#include "jsstr.h"JSScope *js_GetMutableScope(JSContext *cx, JSObject *obj){    JSScope *scope, *newscope;    scope = OBJ_SCOPE(obj);    JS_ASSERT(JS_IS_SCOPE_LOCKED(cx, scope));    if (scope->object == obj)        return scope;    newscope = js_NewScope(cx, 0, scope->map.ops, LOCKED_OBJ_GET_CLASS(obj),                           obj);    if (!newscope)        return NULL;    JS_LOCK_SCOPE(cx, newscope);    obj->map = js_HoldObjectMap(cx, &newscope->map);    scope = (JSScope *) js_DropObjectMap(cx, &scope->map, obj);    JS_TRANSFER_SCOPE_LOCK(cx, scope, newscope);    return newscope;}/* * JSScope uses multiplicative hashing, _a la_ jsdhash.[ch], but specialized * to minimize footprint.  But if a scope has fewer than SCOPE_HASH_THRESHOLD * entries, we use linear search and avoid allocating scope->table. */#define SCOPE_HASH_THRESHOLD    6#define MIN_SCOPE_SIZE_LOG2     4#define MIN_SCOPE_SIZE          JS_BIT(MIN_SCOPE_SIZE_LOG2)#define SCOPE_TABLE_NBYTES(n)   ((n) * sizeof(JSScopeProperty *))static voidInitMinimalScope(JSScope *scope){    scope->hashShift = JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2;    scope->entryCount = scope->removedCount = 0;    scope->table = NULL;    scope->lastProp = NULL;}static JSBoolCreateScopeTable(JSContext *cx, JSScope *scope, JSBool report){    int sizeLog2;    JSScopeProperty *sprop, **spp;    JS_ASSERT(!scope->table);    JS_ASSERT(scope->lastProp);    if (scope->entryCount > SCOPE_HASH_THRESHOLD) {        /*         * Ouch: calloc failed at least once already -- let's try again,         * overallocating to hold at least twice the current population.         */        sizeLog2 = JS_CeilingLog2(2 * scope->entryCount);        scope->hashShift = JS_DHASH_BITS - sizeLog2;    } else {        JS_ASSERT(scope->hashShift == JS_DHASH_BITS - MIN_SCOPE_SIZE_LOG2);        sizeLog2 = MIN_SCOPE_SIZE_LOG2;    }    scope->table = (JSScopeProperty **)        calloc(JS_BIT(sizeLog2), sizeof(JSScopeProperty *));    if (!scope->table) {        if (report)            JS_ReportOutOfMemory(cx);        return JS_FALSE;    }    js_UpdateMallocCounter(cx, JS_BIT(sizeLog2) * sizeof(JSScopeProperty *));    scope->hashShift = JS_DHASH_BITS - sizeLog2;    for (sprop = scope->lastProp; sprop; sprop = sprop->parent) {        spp = js_SearchScope(scope, sprop->id, JS_TRUE);        SPROP_STORE_PRESERVING_COLLISION(spp, sprop);    }    return JS_TRUE;}JSScope *js_NewScope(JSContext *cx, jsrefcount nrefs, JSObjectOps *ops, JSClass *clasp,            JSObject *obj){    JSScope *scope;    scope = (JSScope *) JS_malloc(cx, sizeof(JSScope));    if (!scope)        return NULL;    js_InitObjectMap(&scope->map, nrefs, ops, clasp);    scope->object = obj;    scope->flags = 0;    InitMinimalScope(scope);#ifdef JS_THREADSAFE    scope->ownercx = cx;    memset(&scope->lock, 0, sizeof scope->lock);    /*     * Set u.link = NULL, not u.count = 0, in case the target architecture's     * null pointer has a non-zero integer representation.     */    scope->u.link = NULL;#ifdef DEBUG    scope->file[0] = scope->file[1] = scope->file[2] = scope->file[3] = NULL;    scope->line[0] = scope->line[1] = scope->line[2] = scope->line[3] = 0;#endif#endif    JS_RUNTIME_METER(cx->runtime, liveScopes);    JS_RUNTIME_METER(cx->runtime, totalScopes);    return scope;}#ifdef DEBUG_SCOPE_COUNTextern voidjs_unlog_scope(JSScope *scope);#endifvoidjs_DestroyScope(JSContext *cx, JSScope *scope){#ifdef DEBUG_SCOPE_COUNT    js_unlog_scope(scope);#endif#ifdef JS_THREADSAFE    /* Scope must be single-threaded at this point, so set scope->ownercx. */    JS_ASSERT(scope->u.count == 0);    scope->ownercx = cx;    js_FinishLock(&scope->lock);#endif    if (scope->table)        JS_free(cx, scope->table);#ifdef DEBUG    JS_LOCK_RUNTIME_VOID(cx->runtime,                         cx->runtime->liveScopeProps -= scope->entryCount);#endif    JS_RUNTIME_UNMETER(cx->runtime, liveScopes);    JS_free(cx, scope);}#ifdef DUMP_SCOPE_STATStypedef struct JSScopeStats {    jsrefcount          searches;    jsrefcount          steps;    jsrefcount          hits;    jsrefcount          misses;    jsrefcount          stepHits;    jsrefcount          stepMisses;    jsrefcount          adds;    jsrefcount          redundantAdds;    jsrefcount          addFailures;    jsrefcount          changeFailures;    jsrefcount          compresses;    jsrefcount          grows;    jsrefcount          removes;    jsrefcount          removeFrees;    jsrefcount          uselessRemoves;    jsrefcount          shrinks;} JSScopeStats;JS_FRIEND_DATA(JSScopeStats) js_scope_stats;# define METER(x)       JS_ATOMIC_INCREMENT(&js_scope_stats.x)#else# define METER(x)       /* nothing */#endif/* * Double hashing needs the second hash code to be relatively prime to table * size, so we simply make hash2 odd.  The inputs to multiplicative hash are * the golden ratio, expressed as a fixed-point 32 bit fraction, and the int * property index or named property's atom number (observe that most objects * have either no indexed properties, or almost all indexed and a few names, * so collisions between index and atom number are unlikely). */#define SCOPE_HASH0(id)                 (HASH_ID(id) * JS_GOLDEN_RATIO)#define SCOPE_HASH1(hash0,shift)        ((hash0) >> (shift))#define SCOPE_HASH2(hash0,log2,shift)   ((((hash0) << (log2)) >> (shift)) | 1)JS_FRIEND_API(JSScopeProperty **)js_SearchScope(JSScope *scope, jsid id, JSBool adding){    JSHashNumber hash0, hash1, hash2;    int hashShift, sizeLog2;    JSScopeProperty *stored, *sprop, **spp, **firstRemoved;    uint32 sizeMask;    METER(searches);    if (!scope->table) {        /* Not enough properties to justify hashing: search from lastProp. */        JS_ASSERT(!SCOPE_HAD_MIDDLE_DELETE(scope));        for (spp = &scope->lastProp; (sprop = *spp); spp = &sprop->parent) {            if (sprop->id == id) {                METER(hits);                return spp;            }        }        METER(misses);        return spp;    }    /* Compute the primary hash address. */    hash0 = SCOPE_HASH0(id);    hashShift = scope->hashShift;    hash1 = SCOPE_HASH1(hash0, hashShift);    spp = scope->table + hash1;    /* Miss: return space for a new entry. */    stored = *spp;    if (SPROP_IS_FREE(stored)) {        METER(misses);        return spp;    }    /* Hit: return entry. */    sprop = SPROP_CLEAR_COLLISION(stored);    if (sprop && sprop->id == id) {        METER(hits);        return spp;    }    /* Collision: double hash. */    sizeLog2 = JS_DHASH_BITS - hashShift;    hash2 = SCOPE_HASH2(hash0, sizeLog2, hashShift);    sizeMask = JS_BITMASK(sizeLog2);    /* Save the first removed entry pointer so we can recycle it if adding. */    if (SPROP_IS_REMOVED(stored)) {        firstRemoved = spp;    } else {        firstRemoved = NULL;        if (adding && !SPROP_HAD_COLLISION(stored))            SPROP_FLAG_COLLISION(spp, sprop);    }    for (;;) {        METER(steps);        hash1 -= hash2;        hash1 &= sizeMask;        spp = scope->table + hash1;        stored = *spp;        if (SPROP_IS_FREE(stored)) {            METER(stepMisses);            return (adding && firstRemoved) ? firstRemoved : spp;        }        sprop = SPROP_CLEAR_COLLISION(stored);        if (sprop && sprop->id == id) {            METER(stepHits);            return spp;        }        if (SPROP_IS_REMOVED(stored)) {            if (!firstRemoved)                firstRemoved = spp;        } else {            if (adding && !SPROP_HAD_COLLISION(stored))                SPROP_FLAG_COLLISION(spp, sprop);        }    }    /* NOTREACHED */    return NULL;}static JSBoolChangeScope(JSContext *cx, JSScope *scope, int change){    int oldlog2, newlog2;    uint32 oldsize, newsize, nbytes;    JSScopeProperty **table, **oldtable, **spp, **oldspp, *sprop;    /* Grow, shrink, or compress by changing scope->table. */    oldlog2 = JS_DHASH_BITS - scope->hashShift;    newlog2 = oldlog2 + change;    oldsize = JS_BIT(oldlog2);    newsize = JS_BIT(newlog2);    nbytes = SCOPE_TABLE_NBYTES(newsize);    table = (JSScopeProperty **) calloc(nbytes, 1);    if (!table) {        JS_ReportOutOfMemory(cx);        return JS_FALSE;    }    /* Now that we have a new table allocated, update scope members. */    scope->hashShift = JS_DHASH_BITS - newlog2;    scope->removedCount = 0;    oldtable = scope->table;    scope->table = table;    /* Treat the above calloc as a JS_malloc, to match CreateScopeTable. */    cx->runtime->gcMallocBytes += nbytes;

⌨️ 快捷键说明

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