зеркало из https://github.com/mozilla/gecko-dev.git
Bug 539829 - Encapsulate JSScope::flags. r=Waldo.
--HG-- extra : rebase_source : ced4f057e715075d8e4eff343e824d8934152a7e
This commit is contained in:
Родитель
da6fb77bda
Коммит
99f75d684d
|
@ -2964,7 +2964,7 @@ JS_DefineProperties(JSContext *cx, JSObject *obj, JSPropertySpec *ps)
|
|||
for (ok = JS_TRUE; ps->name; ps++) {
|
||||
ok = DefineProperty(cx, obj, ps->name, JSVAL_VOID,
|
||||
ps->getter, ps->setter, ps->flags,
|
||||
SPROP_HAS_SHORTID, ps->tinyid);
|
||||
JSScopeProperty::HAS_SHORTID, ps->tinyid);
|
||||
if (!ok)
|
||||
break;
|
||||
}
|
||||
|
@ -2995,7 +2995,7 @@ JS_DefinePropertyWithTinyId(JSContext *cx, JSObject *obj, const char *name,
|
|||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return DefineProperty(cx, obj, name, value, getter, setter, attrs,
|
||||
SPROP_HAS_SHORTID, tinyid);
|
||||
JSScopeProperty::HAS_SHORTID, tinyid);
|
||||
}
|
||||
|
||||
static JSBool
|
||||
|
@ -3062,7 +3062,7 @@ JS_AliasProperty(JSContext *cx, JSObject *obj, const char *name,
|
|||
sprop = (JSScopeProperty *)prop;
|
||||
ok = (js_AddNativeProperty(cx, obj, ATOM_TO_JSID(atom),
|
||||
sprop->getter, sprop->setter, sprop->slot,
|
||||
sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
|
||||
sprop->attrs, sprop->getFlags() | JSScopeProperty::ALIAS,
|
||||
sprop->shortid)
|
||||
!= NULL);
|
||||
}
|
||||
|
@ -3564,7 +3564,7 @@ JS_DefineUCPropertyWithTinyId(JSContext *cx, JSObject *obj,
|
|||
{
|
||||
CHECK_REQUEST(cx);
|
||||
return DefineUCProperty(cx, obj, name, namelen, value, getter, setter,
|
||||
attrs, SPROP_HAS_SHORTID, tinyid);
|
||||
attrs, JSScopeProperty::HAS_SHORTID, tinyid);
|
||||
}
|
||||
|
||||
JS_PUBLIC_API(JSBool)
|
||||
|
@ -3735,7 +3735,7 @@ JS_AliasElement(JSContext *cx, JSObject *obj, const char *name, jsint alias)
|
|||
sprop = (JSScopeProperty *)prop;
|
||||
ok = (js_AddNativeProperty(cx, obj, INT_TO_JSID(alias),
|
||||
sprop->getter, sprop->setter, sprop->slot,
|
||||
sprop->attrs, sprop->flags | SPROP_IS_ALIAS,
|
||||
sprop->attrs, sprop->getFlags() | JSScopeProperty::ALIAS,
|
||||
sprop->shortid)
|
||||
!= NULL);
|
||||
obj->dropProperty(cx, prop);
|
||||
|
@ -4008,11 +4008,8 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
|
|||
* line is not enumerable, or it's an alias, skip it and keep on trying
|
||||
* to find an enumerable property that is still in scope.
|
||||
*/
|
||||
while (sprop &&
|
||||
(!(sprop->attrs & JSPROP_ENUMERATE) ||
|
||||
(sprop->flags & SPROP_IS_ALIAS))) {
|
||||
while (sprop && (!sprop->enumerable() || sprop->isAlias()))
|
||||
sprop = sprop->parent;
|
||||
}
|
||||
|
||||
if (!sprop) {
|
||||
*idp = JSVAL_VOID;
|
||||
|
|
|
@ -266,7 +266,7 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
|||
} else {
|
||||
JSScopeProperty *sprop2 =
|
||||
scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
|
||||
sprop->attrs, sprop->flags, sprop->shortid);
|
||||
sprop->attrs, sprop->getFlags(), sprop->shortid);
|
||||
if (sprop2 != sprop)
|
||||
goto exit_trace;
|
||||
}
|
||||
|
|
|
@ -623,9 +623,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
|
|||
|
||||
JS_LOCK_OBJ(cx, obj);
|
||||
propid = ID_TO_VALUE(sprop->id);
|
||||
userid = (sprop->flags & SPROP_HAS_SHORTID)
|
||||
? INT_TO_JSVAL(sprop->shortid)
|
||||
: propid;
|
||||
userid = SPROP_USERID(sprop);
|
||||
scope = OBJ_SCOPE(obj);
|
||||
JS_UNLOCK_OBJ(cx, obj);
|
||||
|
||||
|
@ -880,7 +878,7 @@ JS_SetWatchPoint(JSContext *cx, JSObject *obj, jsval idval,
|
|||
getter = sprop->getter;
|
||||
setter = sprop->setter;
|
||||
attrs = sprop->attrs;
|
||||
flags = sprop->flags;
|
||||
flags = sprop->getFlags();
|
||||
shortid = sprop->shortid;
|
||||
} else {
|
||||
if (!pobj->getProperty(cx, propid, &value) ||
|
||||
|
|
|
@ -1590,7 +1590,7 @@ js_LexicalLookup(JSTreeContext *tc, JSAtom *atom, jsint *slotp, JSStmtInfo *stmt
|
|||
scope = OBJ_SCOPE(obj);
|
||||
sprop = scope->lookup(ATOM_TO_JSID(atom));
|
||||
if (sprop) {
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
if (slotp) {
|
||||
JS_ASSERT(JSVAL_IS_INT(obj->fslots[JSSLOT_BLOCK_DEPTH]));
|
||||
|
|
|
@ -1207,7 +1207,7 @@ call_resolve(JSContext *cx, JSObject *obj, jsval idval, uintN flags,
|
|||
}
|
||||
}
|
||||
if (!js_DefineNativeProperty(cx, obj, id, JSVAL_VOID, getter, setter,
|
||||
attrs, SPROP_HAS_SHORTID, (int16) slot,
|
||||
attrs, JSScopeProperty::HAS_SHORTID, (int16) slot,
|
||||
NULL, JSDNP_DONT_PURGE)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
@ -1506,7 +1506,7 @@ fun_resolve(JSContext *cx, JSObject *obj, jsval id, uintN flags,
|
|||
if (!js_DefineNativeProperty(cx, obj,
|
||||
ATOM_TO_JSID(atom), JSVAL_VOID,
|
||||
fun_getProperty, JS_PropertyStub,
|
||||
lfp->attrs, SPROP_HAS_SHORTID,
|
||||
lfp->attrs, JSScopeProperty::HAS_SHORTID,
|
||||
lfp->tinyid, NULL)) {
|
||||
return JS_FALSE;
|
||||
}
|
||||
|
|
|
@ -3555,7 +3555,7 @@ js_DefineBlockVariable(JSContext *cx, JSObject *obj, jsid id, intN index)
|
|||
return js_DefineNativeProperty(cx, obj, id, JSVAL_VOID,
|
||||
block_getProperty, block_setProperty,
|
||||
JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_SHARED,
|
||||
SPROP_HAS_SHORTID, index, NULL);
|
||||
JSScopeProperty::HAS_SHORTID, index, NULL);
|
||||
}
|
||||
|
||||
#if JS_HAS_XDR
|
||||
|
@ -3658,7 +3658,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
|
|||
do {
|
||||
/* If sprop is NULL, this is the first property. */
|
||||
sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProperty();
|
||||
} while (!(sprop->flags & SPROP_HAS_SHORTID));
|
||||
} while (!sprop->hasShortID());
|
||||
|
||||
JS_ASSERT(sprop->getter == block_getProperty);
|
||||
propid = sprop->id;
|
||||
|
@ -4401,7 +4401,7 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
|
|||
JSScope *scope;
|
||||
JSScopeProperty *sprop;
|
||||
|
||||
JS_ASSERT(!(flags & SPROP_IS_METHOD));
|
||||
JS_ASSERT(!(flags & JSScopeProperty::METHOD));
|
||||
|
||||
/*
|
||||
* Purge the property cache of now-shadowed id in obj's scope chain. Do
|
||||
|
@ -4582,7 +4582,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
|||
|
||||
JSObject *funobj = JSVAL_TO_OBJECT(value);
|
||||
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
|
||||
flags |= SPROP_IS_METHOD;
|
||||
flags |= JSScopeProperty::METHOD;
|
||||
getter = js_CastAsPropertyOp(funobj);
|
||||
}
|
||||
}
|
||||
|
@ -5398,8 +5398,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
|||
* shortid, not id, when they are called on the shadow we are
|
||||
* about to create in obj's scope.
|
||||
*/
|
||||
if (sprop->flags & SPROP_HAS_SHORTID) {
|
||||
flags = SPROP_HAS_SHORTID;
|
||||
if (sprop->hasShortID()) {
|
||||
flags = JSScopeProperty::HAS_SHORTID;
|
||||
shortid = sprop->shortid;
|
||||
getter = sprop->getter;
|
||||
setter = sprop->setter;
|
||||
|
@ -5447,7 +5447,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
|||
|
||||
JSObject *funobj = JSVAL_TO_OBJECT(*vp);
|
||||
if (FUN_OBJECT(GET_FUNCTION_PRIVATE(cx, funobj)) == funobj) {
|
||||
flags |= SPROP_IS_METHOD;
|
||||
flags |= JSScopeProperty::METHOD;
|
||||
getter = js_CastAsPropertyOp(funobj);
|
||||
}
|
||||
}
|
||||
|
@ -5852,11 +5852,9 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
|||
JSScope *scope = OBJ_SCOPE(obj);
|
||||
length = 0;
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
||||
!(sprop->flags & SPROP_IS_ALIAS)) {
|
||||
if (sprop->enumerable() && !sprop->isAlias())
|
||||
length++;
|
||||
}
|
||||
}
|
||||
if (length == 0) {
|
||||
/*
|
||||
* Cache the scope without enumerable properties unless its
|
||||
|
@ -5885,8 +5883,7 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
|||
|
||||
jsid *ids = ne->ids;
|
||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
||||
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
||||
!(sprop->flags & SPROP_IS_ALIAS)) {
|
||||
if (sprop->enumerable() && !sprop->isAlias()) {
|
||||
JS_ASSERT(ids < ne->ids + length);
|
||||
*ids++ = sprop->id;
|
||||
}
|
||||
|
@ -6947,7 +6944,7 @@ dumpScopeProp(JSScopeProperty *sprop)
|
|||
if (attrs & JSPROP_GETTER) fprintf(stderr, "getter ");
|
||||
if (attrs & JSPROP_SETTER) fprintf(stderr, "setter ");
|
||||
if (attrs & JSPROP_SHARED) fprintf(stderr, "shared ");
|
||||
if (sprop->flags & SPROP_IS_ALIAS) fprintf(stderr, "alias ");
|
||||
if (sprop->isAlias()) fprintf(stderr, "alias ");
|
||||
if (JSID_IS_ATOM(id))
|
||||
dumpString(JSVAL_TO_STRING(ID_TO_VALUE(id)));
|
||||
else if (JSID_IS_INT(id))
|
||||
|
|
|
@ -836,8 +836,8 @@ js_DefineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
|||
const uintN JSDNP_CACHE_RESULT = 1; /* an interpreter call from JSOP_INITPROP */
|
||||
const uintN JSDNP_DONT_PURGE = 2; /* suppress js_PurgeScopeChain */
|
||||
const uintN JSDNP_SET_METHOD = 4; /* js_{DefineNativeProperty,SetPropertyHelper}
|
||||
must pass the SPROP_IS_METHOD flag on to
|
||||
js_AddScopeProperty */
|
||||
must pass the JSScopeProperty::METHOD
|
||||
flag on to js_AddScopeProperty */
|
||||
|
||||
/*
|
||||
* On error, return false. On success, if propp is non-null, return true with
|
||||
|
|
|
@ -2639,7 +2639,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
|||
goto enterblock_out)
|
||||
for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop;
|
||||
sprop = sprop->parent) {
|
||||
if (!(sprop->flags & SPROP_HAS_SHORTID))
|
||||
if (!sprop->hasShortID())
|
||||
continue;
|
||||
LOCAL_ASSERT_OUT(sprop->shortid < argc);
|
||||
atomv[sprop->shortid] = JSID_TO_ATOM(sprop->id);
|
||||
|
|
|
@ -1837,7 +1837,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
|||
scope->putProperty(cx, sprop->id,
|
||||
sprop->getter, sprop->setter,
|
||||
slot, sprop->attrs,
|
||||
sprop->flags, sprop->shortid);
|
||||
sprop->getFlags(), sprop->shortid);
|
||||
if (!sprop2) {
|
||||
js_FreeSlot(cx, obj, slot);
|
||||
goto error;
|
||||
|
@ -3474,7 +3474,7 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
|||
if (scope->table) {
|
||||
JSScopeProperty *sprop2 =
|
||||
scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, slot,
|
||||
sprop->attrs, sprop->flags, sprop->shortid);
|
||||
sprop->attrs, sprop->getFlags(), sprop->shortid);
|
||||
if (!sprop2) {
|
||||
js_FreeSlot(cx, obj, slot);
|
||||
goto error;
|
||||
|
|
|
@ -3996,7 +3996,7 @@ CheckDestructuring(JSContext *cx, BindData *data,
|
|||
JSPROP_ENUMERATE |
|
||||
JSPROP_PERMANENT |
|
||||
JSPROP_SHARED,
|
||||
SPROP_HAS_SHORTID, 0, NULL);
|
||||
JSScopeProperty::HAS_SHORTID, 0, NULL);
|
||||
if (!ok)
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -452,60 +452,13 @@ JSScope::changeTable(JSContext *cx, int change)
|
|||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take care to exclude the mark bits in case we're called from the GC.
|
||||
*/
|
||||
#define SPROP_FLAGS_NOT_MATCHED (SPROP_MARK | SPROP_FLAG_SHAPE_REGEN)
|
||||
|
||||
static JSDHashNumber
|
||||
js_HashScopeProperty(JSDHashTable *table, const void *key)
|
||||
{
|
||||
const JSScopeProperty *sprop = (const JSScopeProperty *)key;
|
||||
JSDHashNumber hash;
|
||||
JSPropertyOp gsop;
|
||||
|
||||
/* Accumulate from least to most random so the low bits are most random. */
|
||||
hash = 0;
|
||||
JS_ASSERT_IF(sprop->isMethod(),
|
||||
!sprop->setter || sprop->setter == js_watch_set);
|
||||
gsop = sprop->getter;
|
||||
if (gsop)
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsword(gsop);
|
||||
gsop = sprop->setter;
|
||||
if (gsop)
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsword(gsop);
|
||||
|
||||
hash = JS_ROTATE_LEFT32(hash, 4)
|
||||
^ (sprop->flags & ~SPROP_FLAGS_NOT_MATCHED);
|
||||
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->attrs;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->shortid;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->slot;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ sprop->id;
|
||||
return hash;
|
||||
return sprop->hash();
|
||||
}
|
||||
|
||||
#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) \
|
||||
(JS_ASSERT(!JSVAL_IS_NULL((sprop)->id)), JS_ASSERT(!JSVAL_IS_NULL(aid)), \
|
||||
(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))
|
||||
|
||||
static JSBool
|
||||
js_MatchScopeProperty(JSDHashTable *table,
|
||||
const JSDHashEntryHdr *hdr,
|
||||
|
@ -515,7 +468,7 @@ js_MatchScopeProperty(JSDHashTable *table,
|
|||
const JSScopeProperty *sprop = entry->child;
|
||||
const JSScopeProperty *kprop = (const JSScopeProperty *)key;
|
||||
|
||||
return SPROP_MATCH(sprop, kprop);
|
||||
return sprop->matches(kprop);
|
||||
}
|
||||
|
||||
static const JSDHashTableOps PropertyTreeHashOps = {
|
||||
|
@ -659,7 +612,7 @@ InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
|
|||
* below), because the child's parent link will be null, which
|
||||
* can't dangle.
|
||||
*/
|
||||
JS_ASSERT(sprop != child && SPROP_MATCH(sprop, child));
|
||||
JS_ASSERT(sprop != child && sprop->matches(child));
|
||||
JS_RUNTIME_METER(rt, duplicatePropTreeNodes);
|
||||
}
|
||||
} else {
|
||||
|
@ -699,7 +652,7 @@ InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
|
|||
goto insert;
|
||||
|
||||
JS_ASSERT(sprop != child);
|
||||
if (SPROP_MATCH(sprop, child)) {
|
||||
if (sprop->matches(child)) {
|
||||
/*
|
||||
* Duplicate child, see comment above. In this
|
||||
* case, we must let the duplicate be inserted at
|
||||
|
@ -726,7 +679,7 @@ InsertPropertyTreeChild(JSRuntime *rt, JSScopeProperty *parent,
|
|||
} else {
|
||||
sprop = kids;
|
||||
JS_ASSERT(sprop != child);
|
||||
if (SPROP_MATCH(sprop, child)) {
|
||||
if (sprop->matches(child)) {
|
||||
/*
|
||||
* Duplicate child, see comment above. Once again, we
|
||||
* must let duplicates created by deletion pile up in a
|
||||
|
@ -869,8 +822,8 @@ HashChunks(PropTreeKidsChunk *chunk, uintN n)
|
|||
* We use rt->gcLock, not rt->rtLock, to avoid nesting the former inside the
|
||||
* latter in js_GenerateShape below.
|
||||
*/
|
||||
static JSScopeProperty *
|
||||
GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
|
||||
JSScopeProperty *
|
||||
js_GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
|
||||
const JSScopeProperty &child)
|
||||
{
|
||||
JSRuntime *rt;
|
||||
|
@ -949,13 +902,13 @@ GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
|
|||
goto not_found;
|
||||
}
|
||||
|
||||
if (SPROP_MATCH(sprop, &child))
|
||||
if (sprop->matches(&child))
|
||||
return sprop;
|
||||
}
|
||||
n += MAX_KIDS_PER_CHUNK;
|
||||
} while ((chunk = chunk->next) != NULL);
|
||||
} else {
|
||||
if (SPROP_MATCH(sprop, &child))
|
||||
if (sprop->matches(&child))
|
||||
return sprop;
|
||||
}
|
||||
}
|
||||
|
@ -1006,6 +959,7 @@ JSScope::getChildProperty(JSContext *cx, JSScopeProperty *parent,
|
|||
JSScopeProperty &child)
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(child.id));
|
||||
JS_ASSERT(!child.inDictionary());
|
||||
|
||||
/*
|
||||
* Aliases share another property's slot, passed in the |slot| parameter.
|
||||
|
@ -1013,7 +967,7 @@ JSScope::getChildProperty(JSContext *cx, JSScopeProperty *parent,
|
|||
* another property's slot allocate a slot here, but may lose it due to a
|
||||
* JS_ClearScope call.
|
||||
*/
|
||||
if (!(child.flags & SPROP_IS_ALIAS)) {
|
||||
if (!child.isAlias()) {
|
||||
if (child.attrs & JSPROP_SHARED) {
|
||||
child.slot = SPROP_INVALID_SLOT;
|
||||
} else {
|
||||
|
@ -1039,8 +993,7 @@ JSScope::getChildProperty(JSContext *cx, JSScopeProperty *parent,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
child.flags &= ~SPROP_IN_DICTIONARY;
|
||||
JSScopeProperty *sprop = GetPropertyTreeChild(cx, parent, child);
|
||||
JSScopeProperty *sprop = js_GetPropertyTreeChild(cx, parent, child);
|
||||
if (sprop) {
|
||||
JS_ASSERT(sprop->parent == parent);
|
||||
if (parent == lastProp) {
|
||||
|
@ -1155,7 +1108,7 @@ JSScope::newDictionaryProperty(JSContext *cx, const JSScopeProperty &child,
|
|||
dprop->setter = child.setter;
|
||||
dprop->slot = child.slot;
|
||||
dprop->attrs = child.attrs;
|
||||
dprop->flags = child.flags | SPROP_IN_DICTIONARY;
|
||||
dprop->flags = child.flags | JSScopeProperty::IN_DICTIONARY;
|
||||
dprop->shortid = child.shortid;
|
||||
dprop->shape = js_GenerateShape(cx, false);
|
||||
|
||||
|
@ -1284,7 +1237,7 @@ NormalizeGetterAndSetter(JSContext *cx, JSScope *scope,
|
|||
{
|
||||
if (setter == JS_PropertyStub)
|
||||
setter = NULL;
|
||||
if (flags & SPROP_IS_METHOD) {
|
||||
if (flags & JSScopeProperty::METHOD) {
|
||||
/* Here, getter is the method, a function object reference. */
|
||||
JS_ASSERT(getter);
|
||||
JS_ASSERT(!setter || setter == js_watch_set);
|
||||
|
@ -1423,8 +1376,7 @@ JSScope::putProperty(JSContext *cx, jsid id,
|
|||
SPROP_HAS_VALID_SLOT(sprop, this)) {
|
||||
slot = sprop->slot;
|
||||
}
|
||||
if (SPROP_MATCH_PARAMS_AFTER_ID(sprop, getter, setter, slot, attrs,
|
||||
flags, shortid)) {
|
||||
if (sprop->matchesParamsAfterId(getter, setter, slot, attrs, flags, shortid)) {
|
||||
METER(redundantPuts);
|
||||
return sprop;
|
||||
}
|
||||
|
@ -1517,7 +1469,7 @@ JSScope::changeProperty(JSContext *cx, JSScopeProperty *sprop,
|
|||
!(attrs & JSPROP_SHARED));
|
||||
|
||||
/* Don't allow method properties to be changed to accessor properties. */
|
||||
JS_ASSERT(!(sprop->flags & SPROP_IS_METHOD));
|
||||
JS_ASSERT(!sprop->isMethod());
|
||||
|
||||
if (getter == JS_PropertyStub)
|
||||
getter = NULL;
|
||||
|
@ -1720,12 +1672,13 @@ JSScope::methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval)
|
|||
|
||||
/*
|
||||
* Pass null to make a stub getter, but pass along sprop->setter to
|
||||
* preserve watchpoints. Clear SPROP_IS_METHOD from flags as we are
|
||||
* despecializing from a method memoized in the property tree to a
|
||||
* preserve watchpoints. Clear JSScopeProperty::METHOD from flags as we
|
||||
* are despecializing from a method memoized in the property tree to a
|
||||
* plain old function-valued property.
|
||||
*/
|
||||
sprop = putProperty(cx, sprop->id, NULL, sprop->setter, sprop->slot,
|
||||
sprop->attrs, sprop->flags & ~SPROP_IS_METHOD,
|
||||
sprop->attrs,
|
||||
sprop->getFlags() & ~JSScopeProperty::METHOD,
|
||||
sprop->shortid);
|
||||
if (!sprop)
|
||||
return false;
|
||||
|
@ -1828,7 +1781,7 @@ void
|
|||
JSScopeProperty::trace(JSTracer *trc)
|
||||
{
|
||||
if (IS_GC_MARKING_TRACER(trc))
|
||||
flags |= SPROP_MARK;
|
||||
mark();
|
||||
js_TraceId(trc, id);
|
||||
|
||||
#if JS_HAS_GETTER_SETTER
|
||||
|
@ -1852,8 +1805,6 @@ JSScopeProperty::trace(JSTracer *trc)
|
|||
|
||||
#ifdef DEBUG
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static void
|
||||
MeterKidCount(JSBasicStats *bs, uintN nkids)
|
||||
{
|
||||
|
@ -1901,26 +1852,21 @@ js_MeterPropertyTree(JSDHashTable *table, JSDHashEntryHdr *hdr, uint32 number,
|
|||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static void
|
||||
DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp)
|
||||
void
|
||||
JSScopeProperty::dump(JSContext *cx, FILE *fp)
|
||||
{
|
||||
jsval v;
|
||||
JSString *str;
|
||||
JSScopeProperty *kids, *kid;
|
||||
PropTreeKidsChunk *chunk;
|
||||
uintN i;
|
||||
JS_ASSERT(!JSVAL_IS_NULL(id));
|
||||
|
||||
fprintf(fp, "%*sid ", level, "");
|
||||
v = ID_TO_VALUE(sprop->id);
|
||||
JS_ASSERT(!JSVAL_IS_NULL(v));
|
||||
if (JSID_IS_INT(sprop->id)) {
|
||||
fprintf(fp, "%d", JSVAL_TO_INT(v));
|
||||
jsval idval = ID_TO_VALUE(id);
|
||||
if (JSVAL_IS_INT(idval)) {
|
||||
fprintf(fp, "[%ld]", (long) JSVAL_TO_INT(idval));
|
||||
} else {
|
||||
if (JSID_IS_ATOM(sprop->id)) {
|
||||
str = JSVAL_TO_STRING(v);
|
||||
JSString *str;
|
||||
if (JSVAL_IS_STRING(idval)) {
|
||||
str = JSVAL_TO_STRING(idval);
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_OBJECT(sprop->id));
|
||||
str = js_ValueToString(cx, v);
|
||||
JS_ASSERT(JSVAL_IS_OBJECT(idval));
|
||||
str = js_ValueToString(cx, idval);
|
||||
fputs("object ", fp);
|
||||
}
|
||||
if (!str)
|
||||
|
@ -1929,27 +1875,65 @@ DumpSubtree(JSContext *cx, JSScopeProperty *sprop, int level, FILE *fp)
|
|||
js_FileEscapedString(fp, str, '"');
|
||||
}
|
||||
|
||||
fprintf(fp, " g/s %p/%p slot %u attrs %x flags %x shortid %d\n",
|
||||
JS_FUNC_TO_DATA_PTR(void *, sprop->getter),
|
||||
JS_FUNC_TO_DATA_PTR(void *, sprop->setter),
|
||||
sprop->slot, sprop->attrs, sprop->flags, sprop->shortid);
|
||||
kids = sprop->kids;
|
||||
fprintf(fp, " g/s %p/%p slot %u attrs %x ",
|
||||
JS_FUNC_TO_DATA_PTR(void *, getter),
|
||||
JS_FUNC_TO_DATA_PTR(void *, setter),
|
||||
slot, attrs);
|
||||
if (attrs) {
|
||||
int first = 1;
|
||||
fputs("(", fp);
|
||||
#define DUMP_ATTR(name, display) if (attrs & JSPROP_##name) fputs(" " #display + first, fp), first = 0
|
||||
DUMP_ATTR(ENUMERATE, enumerate);
|
||||
DUMP_ATTR(READONLY, readonly);
|
||||
DUMP_ATTR(PERMANENT, permanent);
|
||||
DUMP_ATTR(GETTER, getter);
|
||||
DUMP_ATTR(SETTER, setter);
|
||||
DUMP_ATTR(SHARED, shared);
|
||||
#undef DUMP_ATTR
|
||||
fputs(") ", fp);
|
||||
}
|
||||
|
||||
fprintf(fp, "flags %x ", flags);
|
||||
if (flags) {
|
||||
int first = 1;
|
||||
fputs("(", fp);
|
||||
#define DUMP_FLAG(name, display) if (flags & name) fputs(" " #display + first, fp), first = 0
|
||||
DUMP_FLAG(ALIAS, alias);
|
||||
DUMP_FLAG(HAS_SHORTID, has_shortid);
|
||||
DUMP_FLAG(METHOD, method);
|
||||
DUMP_FLAG(MARK, mark);
|
||||
DUMP_FLAG(SHAPE_REGEN, shape_regen);
|
||||
DUMP_FLAG(IN_DICTIONARY, in_dictionary);
|
||||
#undef DUMP_FLAG
|
||||
fputs(") ", fp);
|
||||
}
|
||||
|
||||
fprintf(fp, "shortid %d\n", shortid);
|
||||
}
|
||||
|
||||
void
|
||||
JSScopeProperty::dumpSubtree(JSContext *cx, int level, FILE *fp)
|
||||
{
|
||||
fprintf(fp, "%*sid ", level, "");
|
||||
dump(cx, fp);
|
||||
|
||||
if (kids) {
|
||||
++level;
|
||||
if (KIDS_IS_CHUNKY(kids)) {
|
||||
chunk = KIDS_TO_CHUNK(kids);
|
||||
PropTreeKidsChunk *chunk = KIDS_TO_CHUNK(kids);
|
||||
do {
|
||||
for (i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
||||
kid = chunk->kids[i];
|
||||
for (uintN i = 0; i < MAX_KIDS_PER_CHUNK; i++) {
|
||||
JSScopeProperty *kid = chunk->kids[i];
|
||||
if (!kid)
|
||||
break;
|
||||
JS_ASSERT(kid->parent == sprop);
|
||||
DumpSubtree(cx, kid, level, fp);
|
||||
JS_ASSERT(kid->parent == this);
|
||||
kid->dumpSubtree(cx, level, fp);
|
||||
}
|
||||
} while ((chunk = chunk->next) != NULL);
|
||||
} else {
|
||||
kid = kids;
|
||||
DumpSubtree(cx, kid, level, fp);
|
||||
JSScopeProperty *kid = kids;
|
||||
JS_ASSERT(kid->parent == this);
|
||||
kid->dumpSubtree(cx, level, fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2012,11 +1996,11 @@ js_SweepScopeProperties(JSContext *cx)
|
|||
* during the mark phase, when live scopes' lastProp members are
|
||||
* followed to update both scope->shape and lastProp->shape.
|
||||
*/
|
||||
if (sprop->flags & SPROP_MARK) {
|
||||
sprop->flags &= ~SPROP_MARK;
|
||||
if (sprop->marked()) {
|
||||
sprop->clearMark();
|
||||
if (rt->gcRegenShapes) {
|
||||
if (sprop->flags & SPROP_FLAG_SHAPE_REGEN)
|
||||
sprop->flags &= ~SPROP_FLAG_SHAPE_REGEN;
|
||||
if (sprop->hasRegenFlag())
|
||||
sprop->clearRegenFlag();
|
||||
else
|
||||
sprop->shape = js_RegenerateShapeForGC(cx);
|
||||
}
|
||||
|
@ -2024,7 +2008,7 @@ js_SweepScopeProperties(JSContext *cx)
|
|||
continue;
|
||||
}
|
||||
|
||||
if (!(sprop->flags & SPROP_IN_DICTIONARY)) {
|
||||
if (!sprop->inDictionary()) {
|
||||
/* Ok, sprop is garbage to collect: unlink it from its parent. */
|
||||
freeChunk = RemovePropertyTreeChild(rt, sprop);
|
||||
|
||||
|
@ -2212,7 +2196,7 @@ js_SweepScopeProperties(JSContext *cx)
|
|||
end = pte + JS_DHASH_TABLE_SIZE(&rt->propertyTreeHash);
|
||||
while (pte < end) {
|
||||
if (pte->child)
|
||||
DumpSubtree(cx, pte->child, 0, dumpfp);
|
||||
pte->child->dumpSubtree(cx, 0, dumpfp);
|
||||
pte++;
|
||||
}
|
||||
fclose(dumpfp);
|
||||
|
|
|
@ -43,6 +43,10 @@
|
|||
/*
|
||||
* JS symbol tables.
|
||||
*/
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "jstypes.h"
|
||||
#include "jslock.h"
|
||||
#include "jsobj.h"
|
||||
|
@ -549,13 +553,20 @@ js_CastAsObjectJSVal(JSPropertyOp op)
|
|||
}
|
||||
|
||||
struct JSScopeProperty {
|
||||
friend class JSScope;
|
||||
friend void js_SweepScopeProperties(JSContext *cx);
|
||||
friend JSScopeProperty * js_GetPropertyTreeChild(JSContext *cx, JSScopeProperty *parent,
|
||||
const JSScopeProperty &child);
|
||||
|
||||
jsid id; /* int-tagged jsval/untagged JSAtom* */
|
||||
JSPropertyOp getter; /* getter and setter hooks or objects */
|
||||
JSPropertyOp setter; /* getter is JSObject* and setter is 0
|
||||
if sprop->isMethod() */
|
||||
uint32 slot; /* abstract index in object slots */
|
||||
uint8 attrs; /* attributes, see jsapi.h JSPROP_* */
|
||||
private:
|
||||
uint8 flags; /* flags, see below for defines */
|
||||
public:
|
||||
int16 shortid; /* tinyid, or local arg/var index */
|
||||
JSScopeProperty *parent; /* parent node, reverse for..in order */
|
||||
union {
|
||||
|
@ -568,17 +579,47 @@ struct JSScopeProperty {
|
|||
};
|
||||
uint32 shape; /* property cache shape identifier */
|
||||
|
||||
/* Bits stored in sprop->flags. */
|
||||
#define SPROP_MARK 0x01
|
||||
#define SPROP_IS_ALIAS 0x02
|
||||
#define SPROP_HAS_SHORTID 0x04
|
||||
#define SPROP_FLAG_SHAPE_REGEN 0x08
|
||||
#define SPROP_IS_METHOD 0x10
|
||||
#define SPROP_IN_DICTIONARY 0x20
|
||||
private:
|
||||
/* Implementation-private bits stored in sprop->flags. */
|
||||
enum {
|
||||
/* GC mark flag. */
|
||||
MARK = 0x01,
|
||||
|
||||
/*
|
||||
* Set during a shape-regenerating GC if the shape has already been
|
||||
* regenerated. Unlike JSScope::SHAPE_REGEN, this does not toggle with
|
||||
* each GC. js_SweepScopeProperties clears it.
|
||||
*/
|
||||
SHAPE_REGEN = 0x08,
|
||||
|
||||
/* Property stored in per-object dictionary, not shared property tree. */
|
||||
IN_DICTIONARY = 0x20
|
||||
};
|
||||
|
||||
bool marked() const { return (flags & MARK) != 0; }
|
||||
void mark() { flags |= MARK; }
|
||||
void clearMark() { flags &= ~MARK; }
|
||||
|
||||
bool hasRegenFlag() const { return (flags & SHAPE_REGEN) != 0; }
|
||||
void setRegenFlag() { flags |= SHAPE_REGEN; }
|
||||
void clearRegenFlag() { flags &= ~SHAPE_REGEN; }
|
||||
|
||||
bool inDictionary() const { return (flags & IN_DICTIONARY) != 0; }
|
||||
|
||||
public:
|
||||
/* Public bits stored in sprop->flags. */
|
||||
enum {
|
||||
ALIAS = 0x02,
|
||||
HAS_SHORTID = 0x04,
|
||||
METHOD = 0x10,
|
||||
PUBLIC_FLAGS = ALIAS | HAS_SHORTID | METHOD
|
||||
};
|
||||
|
||||
uintN getFlags() const { return flags & PUBLIC_FLAGS; }
|
||||
bool isAlias() const { return (flags & ALIAS) != 0; }
|
||||
bool hasShortID() const { return (flags & HAS_SHORTID) != 0; }
|
||||
bool isMethod() const { return (flags & METHOD) != 0; }
|
||||
|
||||
bool isMethod() const {
|
||||
return flags & SPROP_IS_METHOD;
|
||||
}
|
||||
JSObject *methodObject() const {
|
||||
JS_ASSERT(isMethod());
|
||||
return js_CastAsObject(getter);
|
||||
|
@ -610,6 +651,11 @@ struct JSScopeProperty {
|
|||
return setterVal;
|
||||
}
|
||||
|
||||
inline JSDHashNumber hash() const;
|
||||
inline bool matches(const JSScopeProperty *p) const;
|
||||
inline bool matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot,
|
||||
uintN aattrs, uintN aflags, intN ashortid) const;
|
||||
|
||||
bool get(JSContext* cx, JSObject* obj, JSObject *pobj, jsval* vp);
|
||||
bool set(JSContext* cx, JSObject* obj, jsval* vp);
|
||||
|
||||
|
@ -625,6 +671,11 @@ struct JSScopeProperty {
|
|||
bool isAccessorDescriptor() {
|
||||
return (attrs & (JSPROP_SETTER | JSPROP_GETTER)) != 0;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump(JSContext *cx, FILE *fp);
|
||||
void dumpSubtree(JSContext *cx, int level, FILE *fp);
|
||||
#endif
|
||||
};
|
||||
|
||||
/* JSScopeProperty pointer tag bit indicating a collision. */
|
||||
|
@ -693,11 +744,11 @@ inline void
|
|||
JSScope::removeDictionaryProperty(JSScopeProperty *sprop)
|
||||
{
|
||||
JS_ASSERT(inDictionaryMode());
|
||||
JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY);
|
||||
JS_ASSERT(sprop->inDictionary());
|
||||
JS_ASSERT(sprop->childp);
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
|
||||
JS_ASSERT(lastProp->flags & SPROP_IN_DICTIONARY);
|
||||
JS_ASSERT(lastProp->inDictionary());
|
||||
JS_ASSERT(lastProp->childp == &lastProp);
|
||||
JS_ASSERT_IF(lastProp != sprop, !JSVAL_IS_NULL(lastProp->id));
|
||||
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id));
|
||||
|
@ -716,12 +767,12 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
|||
* Don't assert inDictionaryMode() here because we may be called from
|
||||
* toDictionaryMode via newDictionaryProperty.
|
||||
*/
|
||||
JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY);
|
||||
JS_ASSERT(sprop->inDictionary());
|
||||
JS_ASSERT(!sprop->childp);
|
||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
||||
|
||||
JS_ASSERT_IF(*childp, (*childp)->flags & SPROP_IN_DICTIONARY);
|
||||
JS_ASSERT_IF(lastProp, lastProp->flags & SPROP_IN_DICTIONARY);
|
||||
JS_ASSERT_IF(*childp, (*childp)->inDictionary());
|
||||
JS_ASSERT_IF(lastProp, lastProp->inDictionary());
|
||||
JS_ASSERT_IF(lastProp, lastProp->childp == &lastProp);
|
||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
||||
|
||||
|
@ -734,11 +785,11 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
|||
}
|
||||
|
||||
/*
|
||||
* If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
|
||||
* If SHORTID is set in sprop->flags, we use sprop->shortid rather
|
||||
* than id when calling sprop's getter or setter.
|
||||
*/
|
||||
#define SPROP_USERID(sprop) \
|
||||
(((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
|
||||
((sprop)->hasShortID() ? INT_TO_JSVAL((sprop)->shortid) \
|
||||
: ID_TO_VALUE((sprop)->id))
|
||||
|
||||
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
|
||||
|
|
|
@ -171,9 +171,9 @@ JSScope::trace(JSTracer *trc)
|
|||
uint32 newShape;
|
||||
|
||||
if (sprop) {
|
||||
if (!(sprop->flags & SPROP_FLAG_SHAPE_REGEN)) {
|
||||
if (!sprop->hasRegenFlag()) {
|
||||
sprop->shape = js_RegenerateShapeForGC(cx);
|
||||
sprop->flags |= SPROP_FLAG_SHAPE_REGEN;
|
||||
sprop->setRegenFlag();
|
||||
}
|
||||
newShape = sprop->shape;
|
||||
}
|
||||
|
@ -202,4 +202,45 @@ JSScope::trace(JSTracer *trc)
|
|||
}
|
||||
}
|
||||
|
||||
inline JSDHashNumber
|
||||
JSScopeProperty::hash() const
|
||||
{
|
||||
JSDHashNumber hash = 0;
|
||||
|
||||
/* Accumulate from least to most random so the low bits are most random. */
|
||||
JS_ASSERT_IF(isMethod(), !setter || setter == js_watch_set);
|
||||
if (getter)
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(getter);
|
||||
if (setter)
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(setter);
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS);
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ slot;
|
||||
hash = JS_ROTATE_LEFT32(hash, 4) ^ id;
|
||||
return hash;
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScopeProperty::matches(const JSScopeProperty *p) const
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(id));
|
||||
JS_ASSERT(!JSVAL_IS_NULL(p->id));
|
||||
return id == p->id &&
|
||||
matchesParamsAfterId(p->getter, p->setter, p->slot, p->attrs, p->flags, p->shortid);
|
||||
}
|
||||
|
||||
inline bool
|
||||
JSScopeProperty::matchesParamsAfterId(JSPropertyOp agetter, JSPropertyOp asetter, uint32 aslot,
|
||||
uintN aattrs, uintN aflags, intN ashortid) const
|
||||
{
|
||||
JS_ASSERT(!JSVAL_IS_NULL(id));
|
||||
return getter == agetter &&
|
||||
setter == asetter &&
|
||||
slot == aslot &&
|
||||
attrs == aattrs &&
|
||||
((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
|
||||
shortid == ashortid;
|
||||
}
|
||||
|
||||
#endif /* jsscopeinlines_h___ */
|
||||
|
|
|
@ -7883,7 +7883,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp,
|
|||
}
|
||||
|
||||
// Now assert that our use of sprop->shortid was in fact kosher.
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
if (frameIfInRange(obj)) {
|
||||
// At this point we are guaranteed to be looking at an active call oject
|
||||
|
@ -7932,7 +7932,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp,
|
|||
}
|
||||
|
||||
// Now assert that our use of sprop->shortid was in fact kosher.
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
LIns* base = lir->insLoad(LIR_ldp, obj_ins, offsetof(JSObject, dslots));
|
||||
LIns* val_ins = lir->insLoad(LIR_ldp, base, dslot_index * sizeof(jsval));
|
||||
|
@ -7962,7 +7962,7 @@ TraceRecorder::callProp(JSObject* obj, JSProperty* prop, jsid id, jsval*& vp,
|
|||
}
|
||||
|
||||
// Now assert that our use of sprop->shortid was in fact kosher.
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
call_ins = lir->insCall(ci, args);
|
||||
|
||||
|
@ -11346,14 +11346,14 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty
|
|||
JSStackFrame *fp = frameIfInRange(callobj);
|
||||
if (fp) {
|
||||
if (sprop->setter == SetCallArg) {
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
uintN slot = uint16(sprop->shortid);
|
||||
jsval *vp2 = &fp->argv[slot];
|
||||
set(vp2, v_ins);
|
||||
return RECORD_CONTINUE;
|
||||
}
|
||||
if (sprop->setter == SetCallVar) {
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
uintN slot = uint16(sprop->shortid);
|
||||
jsval *vp2 = &fp->slots[slot];
|
||||
set(vp2, v_ins);
|
||||
|
@ -11382,7 +11382,7 @@ TraceRecorder::setCallProp(JSObject *callobj, LIns *callobj_ins, JSScopeProperty
|
|||
// Now assert that the shortid get we did above was ok. Have to do it
|
||||
// after the RETURN_STOP above, since in that case we may in fact not
|
||||
// have a valid shortid; but we don't use it in that case anyway.
|
||||
JS_ASSERT(sprop->flags & SPROP_HAS_SHORTID);
|
||||
JS_ASSERT(sprop->hasShortID());
|
||||
|
||||
LIns* base = lir->insLoad(LIR_ldp, callobj_ins, offsetof(JSObject, dslots));
|
||||
lir->insStorei(box_jsval(v, v_ins), base, dslot_index * sizeof(jsval));
|
||||
|
|
|
@ -2013,42 +2013,10 @@ Tracing(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
|
|||
static void
|
||||
DumpScope(JSContext *cx, JSObject *obj, FILE *fp)
|
||||
{
|
||||
uintN i;
|
||||
JSScopeProperty *sprop;
|
||||
jsval v;
|
||||
JSString *str;
|
||||
|
||||
i = 0;
|
||||
sprop = NULL;
|
||||
while (JS_PropertyIterator(obj, &sprop)) {
|
||||
fprintf(fp, "%3u %p ", i, (void *)sprop);
|
||||
|
||||
v = ID_TO_VALUE(sprop->id);
|
||||
if (JSID_IS_INT(sprop->id)) {
|
||||
fprintf(fp, "[%ld]", (long)JSVAL_TO_INT(v));
|
||||
} else {
|
||||
if (JSID_IS_ATOM(sprop->id)) {
|
||||
str = JSVAL_TO_STRING(v);
|
||||
} else {
|
||||
JS_ASSERT(JSID_IS_OBJECT(sprop->id));
|
||||
str = js_ValueToString(cx, v);
|
||||
fputs("object ", fp);
|
||||
}
|
||||
if (!str)
|
||||
fputs("<error>", fp);
|
||||
else
|
||||
js_FileEscapedString(fp, str, '"');
|
||||
}
|
||||
#define DUMP_ATTR(name) if (sprop->attrs & JSPROP_##name) fputs(" " #name, fp)
|
||||
DUMP_ATTR(ENUMERATE);
|
||||
DUMP_ATTR(READONLY);
|
||||
DUMP_ATTR(PERMANENT);
|
||||
DUMP_ATTR(GETTER);
|
||||
DUMP_ATTR(SETTER);
|
||||
#undef DUMP_ATTR
|
||||
|
||||
fprintf(fp, " slot %lu flags %x shortid %d\n",
|
||||
(unsigned long)sprop->slot, sprop->flags, sprop->shortid);
|
||||
uintN i = 0;
|
||||
for (JSScopeProperty *sprop = NULL; JS_PropertyIterator(obj, &sprop);) {
|
||||
fprintf(fp, "%3u %p ", i++, (void *) sprop);
|
||||
sprop->dump(cx, fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче