зеркало из https://github.com/mozilla/gecko-dev.git
Backout bug 473228 and its follow-up, temporarily, to attempt a clean merge of other stuff.
This commit is contained in:
Коммит
efc9136a43
|
@ -1618,11 +1618,15 @@ JS_ResolveStandardClass(JSContext *cx, JSObject *obj, jsval id,
|
||||||
static JSBool
|
static JSBool
|
||||||
AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
|
AlreadyHasOwnProperty(JSContext *cx, JSObject *obj, JSAtom *atom)
|
||||||
{
|
{
|
||||||
|
JSScopeProperty *sprop;
|
||||||
|
JSScope *scope;
|
||||||
|
|
||||||
|
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||||
JS_LOCK_OBJ(cx, obj);
|
JS_LOCK_OBJ(cx, obj);
|
||||||
JSScope *scope = OBJ_SCOPE(obj);
|
scope = OBJ_SCOPE(obj);
|
||||||
bool found = scope->hasProperty(ATOM_TO_JSID(atom));
|
sprop = scope->lookup(ATOM_TO_JSID(atom));
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
return found;
|
return sprop != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(JSBool)
|
JS_PUBLIC_API(JSBool)
|
||||||
|
@ -3398,7 +3402,7 @@ AlreadyHasOwnPropertyHelper(JSContext *cx, JSObject *obj, jsid id,
|
||||||
|
|
||||||
JS_LOCK_OBJ(cx, obj);
|
JS_LOCK_OBJ(cx, obj);
|
||||||
scope = OBJ_SCOPE(obj);
|
scope = OBJ_SCOPE(obj);
|
||||||
*foundp = scope->hasProperty(id);
|
*foundp = (scope->lookup(id) != NULL);
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
return JS_TRUE;
|
return JS_TRUE;
|
||||||
}
|
}
|
||||||
|
@ -4082,7 +4086,7 @@ JS_NewPropertyIterator(JSContext *cx, JSObject *obj)
|
||||||
if (OBJ_IS_NATIVE(obj)) {
|
if (OBJ_IS_NATIVE(obj)) {
|
||||||
/* Native case: start with the last property in obj's own scope. */
|
/* Native case: start with the last property in obj's own scope. */
|
||||||
scope = OBJ_SCOPE(obj);
|
scope = OBJ_SCOPE(obj);
|
||||||
pdata = scope->lastProperty();
|
pdata = scope->lastProp;
|
||||||
index = -1;
|
index = -1;
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
|
@ -4125,12 +4129,15 @@ JS_NextProperty(JSContext *cx, JSObject *iterobj, jsid *idp)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the next property mapped by scope in the property tree ancestor
|
* If the next property mapped by scope in the property tree ancestor
|
||||||
* line is not enumerable, or it's an alias, skip it and keep on trying
|
* line is not enumerable, or it's an alias, or one or more properties
|
||||||
* to find an enumerable property that is still in scope.
|
* were deleted from the "middle" of the scope-mapped ancestor line
|
||||||
|
* and the next property was among those deleted, skip it and keep on
|
||||||
|
* trying to find an enumerable property that is still in scope.
|
||||||
*/
|
*/
|
||||||
while (sprop &&
|
while (sprop &&
|
||||||
(!(sprop->attrs & JSPROP_ENUMERATE) ||
|
(!(sprop->attrs & JSPROP_ENUMERATE) ||
|
||||||
(sprop->flags & SPROP_IS_ALIAS))) {
|
(sprop->flags & SPROP_IS_ALIAS) ||
|
||||||
|
(scope->hadMiddleDelete() && !scope->has(sprop)))) {
|
||||||
sprop = sprop->parent;
|
sprop = sprop->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1327,8 +1327,8 @@ js_MakeArraySlow(JSContext *cx, JSObject *obj)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprop = scope->addDataProperty(cx, id, JS_INITIAL_NSLOTS + i,
|
sprop = scope->add(cx, id, NULL, NULL, i + JS_INITIAL_NSLOTS,
|
||||||
JSPROP_ENUMERATE);
|
JSPROP_ENUMERATE, 0, 0);
|
||||||
if (!sprop)
|
if (!sprop)
|
||||||
goto out_bad;
|
goto out_bad;
|
||||||
}
|
}
|
||||||
|
|
|
@ -231,22 +231,21 @@ JS_DEFINE_CALLINFO_2(extern, INT32, js_StringToInt32, CONTEXT, STRING, 1, 1)
|
||||||
JSBool FASTCALL
|
JSBool FASTCALL
|
||||||
js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(OBJ_IS_NATIVE(obj));
|
||||||
JS_LOCK_OBJ(cx, obj);
|
JS_LOCK_OBJ(cx, obj);
|
||||||
|
|
||||||
uint32 slot = sprop->slot;
|
|
||||||
JSScope* scope = OBJ_SCOPE(obj);
|
JSScope* scope = OBJ_SCOPE(obj);
|
||||||
JS_ASSERT(slot == scope->freeslot);
|
uint32 slot;
|
||||||
JS_ASSERT(sprop->parent == scope->lastProperty());
|
|
||||||
|
|
||||||
if (scope->owned()) {
|
if (scope->owned()) {
|
||||||
JS_ASSERT(!scope->hasProperty(sprop));
|
JS_ASSERT(!scope->has(sprop));
|
||||||
} else {
|
} else {
|
||||||
scope = js_GetMutableScope(cx, obj);
|
scope = js_GetMutableScope(cx, obj);
|
||||||
if (!scope)
|
if (!scope)
|
||||||
goto exit_trace;
|
goto exit_trace;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!scope->table) {
|
slot = sprop->slot;
|
||||||
|
if (!scope->table && sprop->parent == scope->lastProp && slot == scope->freeslot) {
|
||||||
if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
|
if (slot < STOBJ_NSLOTS(obj) && !OBJ_GET_CLASS(cx, obj)->reserveSlots) {
|
||||||
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot)));
|
JS_ASSERT(JSVAL_IS_VOID(STOBJ_GET_SLOT(obj, scope->freeslot)));
|
||||||
++scope->freeslot;
|
++scope->freeslot;
|
||||||
|
@ -262,9 +261,10 @@ js_AddProperty(JSContext* cx, JSObject* obj, JSScopeProperty* sprop)
|
||||||
|
|
||||||
scope->extend(cx, sprop);
|
scope->extend(cx, sprop);
|
||||||
} else {
|
} else {
|
||||||
JSScopeProperty *sprop2 =
|
JSScopeProperty *sprop2 = scope->add(cx, sprop->id,
|
||||||
scope->addProperty(cx, sprop->id, sprop->getter, sprop->setter, SPROP_INVALID_SLOT,
|
sprop->getter, sprop->setter,
|
||||||
sprop->attrs, sprop->flags, sprop->shortid);
|
SPROP_INVALID_SLOT, sprop->attrs,
|
||||||
|
sprop->flags, sprop->shortid);
|
||||||
if (sprop2 != sprop)
|
if (sprop2 != sprop)
|
||||||
goto exit_trace;
|
goto exit_trace;
|
||||||
}
|
}
|
||||||
|
|
|
@ -820,7 +820,7 @@ struct JSRuntime {
|
||||||
JSBasicStats loopStats;
|
JSBasicStats loopStats;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEBUG
|
#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
|
||||||
/* Function invocation metering. */
|
/* Function invocation metering. */
|
||||||
jsrefcount inlineCalls;
|
jsrefcount inlineCalls;
|
||||||
jsrefcount nativeCalls;
|
jsrefcount nativeCalls;
|
||||||
|
@ -842,6 +842,7 @@ struct JSRuntime {
|
||||||
jsrefcount duplicatePropTreeNodes;
|
jsrefcount duplicatePropTreeNodes;
|
||||||
jsrefcount totalPropTreeNodes;
|
jsrefcount totalPropTreeNodes;
|
||||||
jsrefcount propTreeKidsChunks;
|
jsrefcount propTreeKidsChunks;
|
||||||
|
jsrefcount middleDeleteFixups;
|
||||||
|
|
||||||
/* String instrumentation. */
|
/* String instrumentation. */
|
||||||
jsrefcount liveStrings;
|
jsrefcount liveStrings;
|
||||||
|
@ -859,7 +860,7 @@ struct JSRuntime {
|
||||||
jsrefcount totalScripts;
|
jsrefcount totalScripts;
|
||||||
jsrefcount liveEmptyScripts;
|
jsrefcount liveEmptyScripts;
|
||||||
jsrefcount totalEmptyScripts;
|
jsrefcount totalEmptyScripts;
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG || JS_DUMP_PROPTREE_STATS */
|
||||||
|
|
||||||
#ifdef JS_SCOPE_DEPTH_METER
|
#ifdef JS_SCOPE_DEPTH_METER
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -64,7 +64,6 @@
|
||||||
#include "jsstr.h"
|
#include "jsstr.h"
|
||||||
|
|
||||||
#include "jsatominlines.h"
|
#include "jsatominlines.h"
|
||||||
#include "jsscopeinlines.h"
|
|
||||||
|
|
||||||
#include "jsautooplen.h"
|
#include "jsautooplen.h"
|
||||||
|
|
||||||
|
@ -423,16 +422,13 @@ typedef struct JSWatchPoint {
|
||||||
#define JSWP_LIVE 0x1 /* live because set and not cleared */
|
#define JSWP_LIVE 0x1 /* live because set and not cleared */
|
||||||
#define JSWP_HELD 0x2 /* held while running handler/setter */
|
#define JSWP_HELD 0x2 /* held while running handler/setter */
|
||||||
|
|
||||||
static bool
|
|
||||||
IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
|
* NB: DropWatchPointAndUnlock releases cx->runtime->debuggerLock in all cases.
|
||||||
*/
|
*/
|
||||||
static JSBool
|
static JSBool
|
||||||
DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
|
DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
|
||||||
{
|
{
|
||||||
JSBool ok;
|
JSBool ok, found;
|
||||||
JSScopeProperty *sprop;
|
JSScopeProperty *sprop;
|
||||||
JSScope *scope;
|
JSScope *scope;
|
||||||
JSPropertyOp setter;
|
JSPropertyOp setter;
|
||||||
|
@ -463,22 +459,20 @@ DropWatchPointAndUnlock(JSContext *cx, JSWatchPoint *wp, uintN flag)
|
||||||
if (!setter) {
|
if (!setter) {
|
||||||
JS_LOCK_OBJ(cx, wp->object);
|
JS_LOCK_OBJ(cx, wp->object);
|
||||||
scope = OBJ_SCOPE(wp->object);
|
scope = OBJ_SCOPE(wp->object);
|
||||||
|
found = (scope->lookup(sprop->id) != NULL);
|
||||||
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the property wasn't found on wp->object, or it isn't still being
|
* If the property wasn't found on wp->object or didn't exist, then
|
||||||
* watched, then someone else must have deleted or unwatched it, and we
|
* someone else has dealt with this sprop, and we don't need to change
|
||||||
* don't need to change the property attributes.
|
* the property attributes.
|
||||||
*/
|
*/
|
||||||
JSScopeProperty *wprop = scope->lookup(sprop->id);
|
if (found) {
|
||||||
if (wprop &&
|
sprop = scope->change(cx, sprop, 0, sprop->attrs,
|
||||||
((wprop->attrs ^ sprop->attrs) & JSPROP_SETTER) == 0 &&
|
sprop->getter, wp->setter);
|
||||||
IsWatchedProperty(cx, wprop)) {
|
|
||||||
sprop = scope->changeProperty(cx, wprop, 0, wprop->attrs,
|
|
||||||
wprop->getter, wp->setter);
|
|
||||||
if (!sprop)
|
if (!sprop)
|
||||||
ok = JS_FALSE;
|
ok = JS_FALSE;
|
||||||
}
|
}
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cx->free(wp);
|
cx->free(wp);
|
||||||
|
@ -768,18 +762,6 @@ js_watch_set_wrapper(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
|
||||||
return js_watch_set(cx, obj, userid, rval);
|
return js_watch_set(cx, obj, userid, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
|
||||||
IsWatchedProperty(JSContext *cx, JSScopeProperty *sprop)
|
|
||||||
{
|
|
||||||
if (sprop->attrs & JSPROP_SETTER) {
|
|
||||||
JSObject *funobj = js_CastAsObject(sprop->setter);
|
|
||||||
JSFunction *fun = GET_FUNCTION_PRIVATE(cx, funobj);
|
|
||||||
|
|
||||||
return FUN_NATIVE(fun) == js_watch_set_wrapper;
|
|
||||||
}
|
|
||||||
return sprop->setter == js_watch_set;
|
|
||||||
}
|
|
||||||
|
|
||||||
JSPropertyOp
|
JSPropertyOp
|
||||||
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
js_WrapWatchedSetter(JSContext *cx, jsid id, uintN attrs, JSPropertyOp setter)
|
||||||
{
|
{
|
||||||
|
@ -1450,7 +1432,16 @@ JS_PropertyIterator(JSObject *obj, JSScopeProperty **iteratorp)
|
||||||
scope = OBJ_SCOPE(obj);
|
scope = OBJ_SCOPE(obj);
|
||||||
|
|
||||||
/* XXXbe minor(?) incompatibility: iterate in reverse definition order */
|
/* XXXbe minor(?) incompatibility: iterate in reverse definition order */
|
||||||
sprop = sprop ? sprop->parent : scope->lastProperty();
|
if (!sprop) {
|
||||||
|
sprop = SCOPE_LAST_PROP(scope);
|
||||||
|
} else {
|
||||||
|
while ((sprop = sprop->parent) != NULL) {
|
||||||
|
if (!scope->hadMiddleDelete())
|
||||||
|
break;
|
||||||
|
if (scope->has(sprop))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
*iteratorp = sprop;
|
*iteratorp = sprop;
|
||||||
return sprop;
|
return sprop;
|
||||||
}
|
}
|
||||||
|
@ -1499,7 +1490,7 @@ JS_GetPropertyDesc(JSContext *cx, JSObject *obj, JSScopeProperty *sprop,
|
||||||
JSScope *scope = OBJ_SCOPE(obj);
|
JSScope *scope = OBJ_SCOPE(obj);
|
||||||
if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
if (SPROP_HAS_VALID_SLOT(sprop, scope)) {
|
||||||
JSScopeProperty *aprop;
|
JSScopeProperty *aprop;
|
||||||
for (aprop = scope->lastProperty(); aprop; aprop = aprop->parent) {
|
for (aprop = SCOPE_LAST_PROP(scope); aprop; aprop = aprop->parent) {
|
||||||
if (aprop != sprop && aprop->slot == sprop->slot) {
|
if (aprop != sprop && aprop->slot == sprop->slot) {
|
||||||
pd->alias = ID_TO_VALUE(aprop->id);
|
pd->alias = ID_TO_VALUE(aprop->id);
|
||||||
break;
|
break;
|
||||||
|
@ -1540,7 +1531,9 @@ JS_GetPropertyDescArray(JSContext *cx, JSObject *obj, JSPropertyDescArray *pda)
|
||||||
if (!pd)
|
if (!pd)
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
i = 0;
|
i = 0;
|
||||||
for (sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
for (sprop = SCOPE_LAST_PROP(scope); sprop; sprop = sprop->parent) {
|
||||||
|
if (scope->hadMiddleDelete() && !scope->has(sprop))
|
||||||
|
continue;
|
||||||
if (!js_AddRoot(cx, &pd[i].id, NULL))
|
if (!js_AddRoot(cx, &pd[i].id, NULL))
|
||||||
goto bad;
|
goto bad;
|
||||||
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
if (!js_AddRoot(cx, &pd[i].value, NULL))
|
||||||
|
|
|
@ -122,7 +122,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj,
|
||||||
* from pobj's scope (via unwatch or delete, e.g.).
|
* from pobj's scope (via unwatch or delete, e.g.).
|
||||||
*/
|
*/
|
||||||
scope = OBJ_SCOPE(pobj);
|
scope = OBJ_SCOPE(pobj);
|
||||||
if (!scope->hasProperty(sprop)) {
|
if (!scope->has(sprop)) {
|
||||||
PCMETER(cache->oddfills++);
|
PCMETER(cache->oddfills++);
|
||||||
return JS_NO_PROP_CACHE_FILL;
|
return JS_NO_PROP_CACHE_FILL;
|
||||||
}
|
}
|
||||||
|
@ -132,8 +132,8 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj,
|
||||||
* and setter hooks can change the prototype chain using JS_SetPrototype
|
* and setter hooks can change the prototype chain using JS_SetPrototype
|
||||||
* after js_LookupPropertyWithFlags has returned the nominal protoIndex,
|
* after js_LookupPropertyWithFlags has returned the nominal protoIndex,
|
||||||
* we have to validate protoIndex if it is non-zero. If it is zero, then
|
* we have to validate protoIndex if it is non-zero. If it is zero, then
|
||||||
* we know thanks to the scope->hasProperty test above, combined with the
|
* we know thanks to the scope->has test above, combined with the fact that
|
||||||
* fact that obj == pobj, that protoIndex is invariant.
|
* obj == pobj, that protoIndex is invariant.
|
||||||
*
|
*
|
||||||
* The scopeIndex can't be wrong. We require JS_SetParent calls to happen
|
* The scopeIndex can't be wrong. We require JS_SetParent calls to happen
|
||||||
* before any running script might consult a parent-linked scope chain. If
|
* before any running script might consult a parent-linked scope chain. If
|
||||||
|
@ -251,7 +251,7 @@ js_FillPropertyCache(JSContext *cx, JSObject *obj,
|
||||||
/* Best we can do is to cache sprop (still a nice speedup). */
|
/* Best we can do is to cache sprop (still a nice speedup). */
|
||||||
vword = SPROP_TO_PCVAL(sprop);
|
vword = SPROP_TO_PCVAL(sprop);
|
||||||
if (adding &&
|
if (adding &&
|
||||||
sprop == scope->lastProperty() &&
|
sprop == scope->lastProp &&
|
||||||
scope->shape == sprop->shape) {
|
scope->shape == sprop->shape) {
|
||||||
/*
|
/*
|
||||||
* Our caller added a new property. We also know that a setter
|
* Our caller added a new property. We also know that a setter
|
||||||
|
|
|
@ -2958,7 +2958,7 @@ js_XDRBlockObject(JSXDRState *xdr, JSObject **objp)
|
||||||
/* Find a property to XDR. */
|
/* Find a property to XDR. */
|
||||||
do {
|
do {
|
||||||
/* If sprop is NULL, this is the first property. */
|
/* If sprop is NULL, this is the first property. */
|
||||||
sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProperty();
|
sprop = sprop ? sprop->parent : OBJ_SCOPE(obj)->lastProp;
|
||||||
} while (!(sprop->flags & SPROP_HAS_SHORTID));
|
} while (!(sprop->flags & SPROP_HAS_SHORTID));
|
||||||
|
|
||||||
JS_ASSERT(sprop->getter == block_getProperty);
|
JS_ASSERT(sprop->getter == block_getProperty);
|
||||||
|
@ -3726,7 +3726,7 @@ js_AddNativeProperty(JSContext *cx, JSObject *obj, jsid id,
|
||||||
} else {
|
} else {
|
||||||
/* Convert string indices to integers if appropriate. */
|
/* Convert string indices to integers if appropriate. */
|
||||||
id = js_CheckForStringIndex(id);
|
id = js_CheckForStringIndex(id);
|
||||||
sprop = scope->putProperty(cx, id, getter, setter, slot, attrs, flags, shortid);
|
sprop = scope->add(cx, id, getter, setter, slot, attrs, flags, shortid);
|
||||||
}
|
}
|
||||||
JS_UNLOCK_OBJ(cx, obj);
|
JS_UNLOCK_OBJ(cx, obj);
|
||||||
return sprop;
|
return sprop;
|
||||||
|
@ -3744,7 +3744,7 @@ js_ChangeNativePropertyAttrs(JSContext *cx, JSObject *obj,
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
sprop = NULL;
|
sprop = NULL;
|
||||||
} else {
|
} else {
|
||||||
sprop = scope->changeProperty(cx, sprop, attrs, mask, getter, setter);
|
sprop = scope->change(cx, sprop, attrs, mask, getter, setter);
|
||||||
}
|
}
|
||||||
JS_UNLOCK_OBJ(cx, obj);
|
JS_UNLOCK_OBJ(cx, obj);
|
||||||
return sprop;
|
return sprop;
|
||||||
|
@ -3823,7 +3823,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||||
if (sprop &&
|
if (sprop &&
|
||||||
pobj == obj &&
|
pobj == obj &&
|
||||||
(sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
|
(sprop->attrs & (JSPROP_GETTER | JSPROP_SETTER))) {
|
||||||
sprop = OBJ_SCOPE(obj)->changeProperty(cx, sprop, attrs,
|
sprop = OBJ_SCOPE(obj)->change(cx, sprop, attrs,
|
||||||
JSPROP_GETTER | JSPROP_SETTER,
|
JSPROP_GETTER | JSPROP_SETTER,
|
||||||
(attrs & JSPROP_GETTER)
|
(attrs & JSPROP_GETTER)
|
||||||
? getter
|
? getter
|
||||||
|
@ -3896,9 +3896,9 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
added = !scope->hasProperty(id);
|
added = !scope->lookup(id);
|
||||||
sprop = scope->putProperty(cx, id, getter, setter, SPROP_INVALID_SLOT,
|
sprop = scope->add(cx, id, getter, setter, SPROP_INVALID_SLOT, attrs,
|
||||||
attrs, flags, shortid);
|
flags, shortid);
|
||||||
if (!sprop)
|
if (!sprop)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
@ -3909,7 +3909,7 @@ js_DefineNativeProperty(JSContext *cx, JSObject *obj, jsid id, jsval value,
|
||||||
|
|
||||||
/* XXXbe called with lock held */
|
/* XXXbe called with lock held */
|
||||||
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, &value)) {
|
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, &value)) {
|
||||||
scope->removeProperty(cx, id);
|
scope->remove(cx, id);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4330,7 +4330,7 @@ js_NativeGet(JSContext *cx, JSObject *obj, JSObject *pobj,
|
||||||
JS_LOCK_SCOPE(cx, scope);
|
JS_LOCK_SCOPE(cx, scope);
|
||||||
if (SLOT_IN_SCOPE(slot, scope) &&
|
if (SLOT_IN_SCOPE(slot, scope) &&
|
||||||
(JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
|
(JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
|
||||||
scope->hasProperty(sprop))) {
|
scope->has(sprop))) {
|
||||||
jsval v = *vp;
|
jsval v = *vp;
|
||||||
if (!scope->methodWriteBarrier(cx, sprop, v)) {
|
if (!scope->methodWriteBarrier(cx, sprop, v)) {
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
|
@ -4392,7 +4392,7 @@ js_NativeSet(JSContext *cx, JSObject *obj, JSScopeProperty *sprop, bool added,
|
||||||
JS_LOCK_SCOPE(cx, scope);
|
JS_LOCK_SCOPE(cx, scope);
|
||||||
if (SLOT_IN_SCOPE(slot, scope) &&
|
if (SLOT_IN_SCOPE(slot, scope) &&
|
||||||
(JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
|
(JS_LIKELY(cx->runtime->propertyRemovals == sample) ||
|
||||||
scope->hasProperty(sprop))) {
|
scope->has(sprop))) {
|
||||||
jsval v = *vp;
|
jsval v = *vp;
|
||||||
if (!added && !scope->methodWriteBarrier(cx, sprop, v)) {
|
if (!added && !scope->methodWriteBarrier(cx, sprop, v)) {
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
|
@ -4760,8 +4760,8 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sprop = scope->addProperty(cx, id, getter, setter, SPROP_INVALID_SLOT,
|
sprop = scope->add(cx, id, getter, setter, SPROP_INVALID_SLOT, attrs,
|
||||||
attrs, flags, shortid);
|
flags, shortid);
|
||||||
if (!sprop) {
|
if (!sprop) {
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
|
@ -4777,7 +4777,7 @@ js_SetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, uintN defineHow,
|
||||||
|
|
||||||
/* XXXbe called with obj locked */
|
/* XXXbe called with obj locked */
|
||||||
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, vp)) {
|
if (!AddPropertyHelper(cx, clasp, obj, scope, sprop, vp)) {
|
||||||
scope->removeProperty(cx, id);
|
scope->remove(cx, id);
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
return JS_FALSE;
|
return JS_FALSE;
|
||||||
}
|
}
|
||||||
|
@ -4924,7 +4924,7 @@ js_DeleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *rval)
|
||||||
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
if (SPROP_HAS_VALID_SLOT(sprop, scope))
|
||||||
GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
|
GC_POKE(cx, LOCKED_OBJ_GET_SLOT(obj, sprop->slot));
|
||||||
|
|
||||||
ok = scope->removeProperty(cx, id);
|
ok = scope->remove(cx, id);
|
||||||
obj->dropProperty(cx, prop);
|
obj->dropProperty(cx, prop);
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
@ -5159,9 +5159,12 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||||
/* Count all enumerable properties in object's scope. */
|
/* Count all enumerable properties in object's scope. */
|
||||||
JSScope *scope = OBJ_SCOPE(obj);
|
JSScope *scope = OBJ_SCOPE(obj);
|
||||||
length = 0;
|
length = 0;
|
||||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope);
|
||||||
|
sprop;
|
||||||
|
sprop = sprop->parent) {
|
||||||
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
||||||
!(sprop->flags & SPROP_IS_ALIAS)) {
|
!(sprop->flags & SPROP_IS_ALIAS) &&
|
||||||
|
(!scope->hadMiddleDelete() || scope->has(sprop))) {
|
||||||
length++;
|
length++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5192,9 +5195,12 @@ js_Enumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op,
|
||||||
ne->shape = shape;
|
ne->shape = shape;
|
||||||
|
|
||||||
jsid *ids = ne->ids;
|
jsid *ids = ne->ids;
|
||||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope);
|
||||||
|
sprop;
|
||||||
|
sprop = sprop->parent) {
|
||||||
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
if ((sprop->attrs & JSPROP_ENUMERATE) &&
|
||||||
!(sprop->flags & SPROP_IS_ALIAS)) {
|
!(sprop->flags & SPROP_IS_ALIAS) &&
|
||||||
|
(!scope->hadMiddleDelete() || scope->has(sprop))) {
|
||||||
JS_ASSERT(ids < ne->ids + length);
|
JS_ASSERT(ids < ne->ids + length);
|
||||||
*ids++ = sprop->id;
|
*ids++ = sprop->id;
|
||||||
}
|
}
|
||||||
|
@ -5863,7 +5869,7 @@ js_PrintObjectSlotName(JSTracer *trc, char *buf, size_t bufsize)
|
||||||
JSScopeProperty *sprop;
|
JSScopeProperty *sprop;
|
||||||
if (OBJ_IS_NATIVE(obj)) {
|
if (OBJ_IS_NATIVE(obj)) {
|
||||||
JSScope *scope = OBJ_SCOPE(obj);
|
JSScope *scope = OBJ_SCOPE(obj);
|
||||||
sprop = scope->lastProperty();
|
sprop = SCOPE_LAST_PROP(scope);
|
||||||
while (sprop && sprop->slot != slot)
|
while (sprop && sprop->slot != slot)
|
||||||
sprop = sprop->parent;
|
sprop = sprop->parent;
|
||||||
} else {
|
} else {
|
||||||
|
@ -6294,8 +6300,9 @@ js_DumpObject(JSObject *obj)
|
||||||
fprintf(stderr, "sealed\n");
|
fprintf(stderr, "sealed\n");
|
||||||
|
|
||||||
fprintf(stderr, "properties:\n");
|
fprintf(stderr, "properties:\n");
|
||||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop;
|
for (JSScopeProperty *sprop = SCOPE_LAST_PROP(scope); sprop;
|
||||||
sprop = sprop->parent) {
|
sprop = sprop->parent) {
|
||||||
|
if (!scope->hadMiddleDelete() || scope->has(sprop))
|
||||||
dumpScopeProp(sprop);
|
dumpScopeProp(sprop);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -277,7 +277,7 @@ ToDisassemblySource(JSContext *cx, jsval v)
|
||||||
|
|
||||||
if (clasp == &js_BlockClass) {
|
if (clasp == &js_BlockClass) {
|
||||||
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
|
char *source = JS_sprintf_append(NULL, "depth %d {", OBJ_BLOCK_DEPTH(cx, obj));
|
||||||
for (JSScopeProperty *sprop = OBJ_SCOPE(obj)->lastProperty();
|
for (JSScopeProperty *sprop = OBJ_SCOPE(obj)->lastProp;
|
||||||
sprop;
|
sprop;
|
||||||
sprop = sprop->parent) {
|
sprop = sprop->parent) {
|
||||||
const char *bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id));
|
const char *bytes = js_AtomToPrintableString(cx, JSID_TO_ATOM(sprop->id));
|
||||||
|
@ -1316,7 +1316,7 @@ GetLocal(SprintStack *ss, jsint i)
|
||||||
}
|
}
|
||||||
|
|
||||||
i -= depth;
|
i -= depth;
|
||||||
for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop; sprop = sprop->parent) {
|
for (sprop = OBJ_SCOPE(obj)->lastProp; sprop; sprop = sprop->parent) {
|
||||||
if (sprop->shortid == i)
|
if (sprop->shortid == i)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2634,7 +2634,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
|
||||||
MUST_FLOW_THROUGH("enterblock_out");
|
MUST_FLOW_THROUGH("enterblock_out");
|
||||||
#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
|
#define LOCAL_ASSERT_OUT(expr) LOCAL_ASSERT_CUSTOM(expr, ok = JS_FALSE; \
|
||||||
goto enterblock_out)
|
goto enterblock_out)
|
||||||
for (sprop = OBJ_SCOPE(obj)->lastProperty(); sprop;
|
for (sprop = OBJ_SCOPE(obj)->lastProp; sprop;
|
||||||
sprop = sprop->parent) {
|
sprop = sprop->parent) {
|
||||||
if (!(sprop->flags & SPROP_HAS_SHORTID))
|
if (!(sprop->flags & SPROP_HAS_SHORTID))
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -1756,7 +1756,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||||
/* The cache entry doesn't apply. vshape mismatch. */
|
/* The cache entry doesn't apply. vshape mismatch. */
|
||||||
checkForAdd = false;
|
checkForAdd = false;
|
||||||
} else if (scope->owned()) {
|
} else if (scope->owned()) {
|
||||||
if (sprop == scope->lastProperty() || scope->hasProperty(sprop)) {
|
if (sprop == scope->lastProp || scope->has(sprop)) {
|
||||||
fast_set_propcache_hit:
|
fast_set_propcache_hit:
|
||||||
PCMETER(cache->pchits++);
|
PCMETER(cache->pchits++);
|
||||||
PCMETER(cache->setpchits++);
|
PCMETER(cache->setpchits++);
|
||||||
|
@ -1766,7 +1766,8 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||||
}
|
}
|
||||||
checkForAdd =
|
checkForAdd =
|
||||||
!(sprop->attrs & JSPROP_SHARED) &&
|
!(sprop->attrs & JSPROP_SHARED) &&
|
||||||
sprop->parent == scope->lastProperty();
|
sprop->parent == scope->lastProp &&
|
||||||
|
!scope->hadMiddleDelete();
|
||||||
} else {
|
} else {
|
||||||
scope = js_GetMutableScope(cx, obj);
|
scope = js_GetMutableScope(cx, obj);
|
||||||
if (!scope) {
|
if (!scope) {
|
||||||
|
@ -1813,7 +1814,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||||
/*
|
/*
|
||||||
* If this obj's number of reserved slots differed, or
|
* If this obj's number of reserved slots differed, or
|
||||||
* if something created a hash table for scope, we must
|
* if something created a hash table for scope, we must
|
||||||
* pay the price of JSScope::putProperty.
|
* pay the price of JSScope::add.
|
||||||
*
|
*
|
||||||
* If slot does not match the cached sprop's slot,
|
* If slot does not match the cached sprop's slot,
|
||||||
* update the cache entry in the hope that obj and
|
* update the cache entry in the hope that obj and
|
||||||
|
@ -1822,7 +1823,7 @@ BEGIN_CASE(JSOP_SETMETHOD)
|
||||||
*/
|
*/
|
||||||
if (slot != sprop->slot || scope->table) {
|
if (slot != sprop->slot || scope->table) {
|
||||||
JSScopeProperty *sprop2 =
|
JSScopeProperty *sprop2 =
|
||||||
scope->putProperty(cx, sprop->id,
|
scope->add(cx, sprop->id,
|
||||||
sprop->getter, sprop->setter,
|
sprop->getter, sprop->setter,
|
||||||
slot, sprop->attrs,
|
slot, sprop->attrs,
|
||||||
sprop->flags, sprop->shortid);
|
sprop->flags, sprop->shortid);
|
||||||
|
@ -3536,10 +3537,10 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect a repeated property name and force a miss to share the
|
* Detect a repeated property name and force a miss to share the
|
||||||
* strict warning code and consolidate all the complexity managed
|
* strict warning code and cope with complexity managed by
|
||||||
* by JSScope::addProperty.
|
* JSScope::add.
|
||||||
*/
|
*/
|
||||||
if (sprop->parent != scope->lastProperty())
|
if (sprop->parent != scope->lastProp)
|
||||||
goto do_initprop_miss;
|
goto do_initprop_miss;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -3547,8 +3548,8 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
||||||
* proto-property, and there cannot have been any deletions of
|
* proto-property, and there cannot have been any deletions of
|
||||||
* prior properties.
|
* prior properties.
|
||||||
*/
|
*/
|
||||||
JS_ASSERT(!scope->inDictionaryMode());
|
JS_ASSERT(!scope->hadMiddleDelete());
|
||||||
JS_ASSERT_IF(scope->table, !scope->hasProperty(sprop));
|
JS_ASSERT_IF(scope->table, !scope->has(sprop));
|
||||||
|
|
||||||
slot = sprop->slot;
|
slot = sprop->slot;
|
||||||
JS_ASSERT(slot == scope->freeslot);
|
JS_ASSERT(slot == scope->freeslot);
|
||||||
|
@ -3562,11 +3563,14 @@ BEGIN_CASE(JSOP_INITMETHOD)
|
||||||
JS_ASSERT(slot == sprop->slot);
|
JS_ASSERT(slot == sprop->slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_ASSERT(!scope->lastProperty() ||
|
JS_ASSERT(!scope->lastProp ||
|
||||||
scope->shape == scope->lastProperty()->shape);
|
scope->shape == scope->lastProp->shape);
|
||||||
if (scope->table) {
|
if (scope->table) {
|
||||||
JSScopeProperty *sprop2 =
|
JSScopeProperty *sprop2 =
|
||||||
scope->addDataProperty(cx, sprop->id, slot, sprop->attrs);
|
scope->add(cx, sprop->id,
|
||||||
|
sprop->getter, sprop->setter,
|
||||||
|
slot, sprop->attrs,
|
||||||
|
sprop->flags, sprop->shortid);
|
||||||
if (!sprop2) {
|
if (!sprop2) {
|
||||||
js_FreeSlot(cx, obj, slot);
|
js_FreeSlot(cx, obj, slot);
|
||||||
JS_UNLOCK_SCOPE(cx, scope);
|
JS_UNLOCK_SCOPE(cx, scope);
|
||||||
|
|
|
@ -3262,7 +3262,7 @@ PopStatement(JSTreeContext *tc)
|
||||||
JSScope *scope = OBJ_SCOPE(obj);
|
JSScope *scope = OBJ_SCOPE(obj);
|
||||||
JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj));
|
JS_ASSERT(!OBJ_IS_CLONED_BLOCK(obj));
|
||||||
|
|
||||||
for (JSScopeProperty *sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
for (JSScopeProperty *sprop = scope->lastProp; sprop; sprop = sprop->parent) {
|
||||||
JSAtom *atom = JSID_TO_ATOM(sprop->id);
|
JSAtom *atom = JSID_TO_ATOM(sprop->id);
|
||||||
|
|
||||||
/* Beware the empty destructuring dummy. */
|
/* Beware the empty destructuring dummy. */
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
212
js/src/jsscope.h
212
js/src/jsscope.h
|
@ -114,10 +114,10 @@ JS_BEGIN_EXTERN_C
|
||||||
* skipping nodes that lack entries.
|
* skipping nodes that lack entries.
|
||||||
*
|
*
|
||||||
* What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
|
* What if we add Y again? X->Y->Z->Y is wrong and we'll enumerate Y twice.
|
||||||
* Therefore we must fork in such a case if not earlier, or do something else.
|
* Therefore we must fork in such a case, if not earlier. Because delete is
|
||||||
* We used to fork on the theory that set after delete is rare, but the Web is
|
* "bursty", we should not fork eagerly. Delaying a fork till we are at risk
|
||||||
* a harsh mistress, and we now convert the scope to a "dictionary" on first
|
* of adding Y after it was deleted already requires a flag in the JSScope, to
|
||||||
* delete, to avoid O(n^2) growth in the property tree.
|
* wit, SCOPE_MIDDLE_DELETE.
|
||||||
*
|
*
|
||||||
* What about thread safety? If the property tree operations done by requests
|
* What about thread safety? If the property tree operations done by requests
|
||||||
* are find-node and insert-node, then the only hazard is duplicate insertion.
|
* are find-node and insert-node, then the only hazard is duplicate insertion.
|
||||||
|
@ -195,15 +195,13 @@ JS_BEGIN_EXTERN_C
|
||||||
* in Mozilla is < 5, with a large standard deviation (~8). Instead of always
|
* in Mozilla is < 5, with a large standard deviation (~8). Instead of always
|
||||||
* allocating scope->table, we leave it null while initializing all the other
|
* allocating scope->table, we leave it null while initializing all the other
|
||||||
* scope members as if it were non-null and minimal-length. Until a property
|
* scope members as if it were non-null and minimal-length. Until a property
|
||||||
* is added that crosses the threshold of 6 or more entries for hashing, we use
|
* is added that crosses the threshold of 6 or more entries for hashing, or
|
||||||
* linear search from scope->lastProp to find a given id, and save on the space
|
* until a "middle delete" occurs, we use linear search from scope->lastProp
|
||||||
* overhead of a hash table.
|
* to find a given id, and save on the space overhead of a hash table.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct JSEmptyScope;
|
struct JSEmptyScope;
|
||||||
|
|
||||||
#define SPROP_INVALID_SLOT 0xffffffff
|
|
||||||
|
|
||||||
struct JSScope : public JSObjectMap
|
struct JSScope : public JSObjectMap
|
||||||
{
|
{
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
|
@ -220,44 +218,9 @@ struct JSScope : public JSObjectMap
|
||||||
uint32 entryCount; /* number of entries in table */
|
uint32 entryCount; /* number of entries in table */
|
||||||
uint32 removedCount; /* removed entry sentinels in table */
|
uint32 removedCount; /* removed entry sentinels in table */
|
||||||
JSScopeProperty **table; /* table of ptrs to shared tree nodes */
|
JSScopeProperty **table; /* table of ptrs to shared tree nodes */
|
||||||
|
JSScopeProperty *lastProp; /* pointer to last property added */
|
||||||
/*
|
|
||||||
* A little information hiding for scope->lastProp, in case it ever becomes
|
|
||||||
* a tagged pointer again.
|
|
||||||
*/
|
|
||||||
inline JSScopeProperty *lastProperty() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
JSScopeProperty *getChildProperty(JSContext *cx, JSScopeProperty *parent,
|
|
||||||
JSScopeProperty &child);
|
|
||||||
|
|
||||||
JSScopeProperty *newDictionaryProperty(JSContext *cx, const JSScopeProperty &child,
|
|
||||||
JSScopeProperty **childp);
|
|
||||||
|
|
||||||
bool toDictionaryMode(JSContext *cx, JSScopeProperty *&aprop);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Private pointer to the last added property and methods to manipulate the
|
|
||||||
* list it links among properties in this scope. The {remove,insert} pair
|
|
||||||
* for DictionaryProperties assert that the scope is in dictionary mode and
|
|
||||||
* any reachable properties are flagged as dictionary properties.
|
|
||||||
*
|
|
||||||
* NB: these private methods do *not* update this scope's shape to track
|
|
||||||
* lastProp->shape after they finish updating the linked list in the case
|
|
||||||
* where lastProp is updated. It is up to calling code in jsscope.cpp to
|
|
||||||
* call updateShape(cx) after updating lastProp.
|
|
||||||
*/
|
|
||||||
JSScopeProperty *lastProp;
|
|
||||||
|
|
||||||
/* These four inline methods are defined further below in this .h file. */
|
|
||||||
inline void setLastProperty(JSScopeProperty *sprop);
|
|
||||||
inline void removeLastProperty();
|
|
||||||
inline void removeDictionaryProperty(JSScopeProperty *sprop);
|
|
||||||
inline void insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **childp);
|
|
||||||
|
|
||||||
/* Defined in jsscopeinlines.h to avoid including implementation dependencies here. */
|
|
||||||
inline void updateShape(JSContext *cx);
|
|
||||||
|
|
||||||
void initMinimal(JSContext *cx, uint32 newShape);
|
void initMinimal(JSContext *cx, uint32 newShape);
|
||||||
bool createTable(JSContext *cx, bool report);
|
bool createTable(JSContext *cx, bool report);
|
||||||
bool changeTable(JSContext *cx, int change);
|
bool changeTable(JSContext *cx, int change);
|
||||||
|
@ -267,12 +230,6 @@ struct JSScope : public JSObjectMap
|
||||||
inline JSScopeProperty **search(jsid id, bool adding);
|
inline JSScopeProperty **search(jsid id, bool adding);
|
||||||
JSEmptyScope *createEmptyScope(JSContext *cx, JSClass *clasp);
|
JSEmptyScope *createEmptyScope(JSContext *cx, JSClass *clasp);
|
||||||
|
|
||||||
JSScopeProperty *addPropertyHelper(JSContext *cx, jsid id,
|
|
||||||
JSPropertyOp getter, JSPropertyOp setter,
|
|
||||||
uint32 slot, uintN attrs,
|
|
||||||
uintN flags, intN shortid,
|
|
||||||
JSScopeProperty **spp);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit JSScope(const JSObjectOps *ops, JSObject *obj = NULL)
|
explicit JSScope(const JSObjectOps *ops, JSObject *obj = NULL)
|
||||||
: JSObjectMap(ops, 0), object(obj) {}
|
: JSObjectMap(ops, 0), object(obj) {}
|
||||||
|
@ -298,46 +255,25 @@ struct JSScope : public JSObjectMap
|
||||||
inline bool canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp);
|
inline bool canProvideEmptyScope(JSObjectOps *ops, JSClass *clasp);
|
||||||
|
|
||||||
JSScopeProperty *lookup(jsid id);
|
JSScopeProperty *lookup(jsid id);
|
||||||
|
bool has(JSScopeProperty *sprop);
|
||||||
|
|
||||||
inline bool hasProperty(jsid id) { return lookup(id) != NULL; }
|
JSScopeProperty *add(JSContext *cx, jsid id,
|
||||||
inline bool hasProperty(JSScopeProperty *sprop);
|
|
||||||
|
|
||||||
/* Add a property whose id is not yet in this scope. */
|
|
||||||
JSScopeProperty *addProperty(JSContext *cx, jsid id,
|
|
||||||
JSPropertyOp getter, JSPropertyOp setter,
|
JSPropertyOp getter, JSPropertyOp setter,
|
||||||
uint32 slot, uintN attrs,
|
uint32 slot, uintN attrs,
|
||||||
uintN flags, intN shortid);
|
uintN flags, intN shortid);
|
||||||
|
|
||||||
/* Add a data property whose id is not yet in this scope. */
|
JSScopeProperty *change(JSContext *cx, JSScopeProperty *sprop,
|
||||||
JSScopeProperty *addDataProperty(JSContext *cx, jsid id, uint32 slot, uintN attrs) {
|
|
||||||
JS_ASSERT(!(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
|
|
||||||
return addProperty(cx, id, NULL, NULL, slot, attrs, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Add or overwrite a property for id in this scope. */
|
|
||||||
JSScopeProperty *putProperty(JSContext *cx, jsid id,
|
|
||||||
JSPropertyOp getter, JSPropertyOp setter,
|
|
||||||
uint32 slot, uintN attrs,
|
|
||||||
uintN flags, intN shortid);
|
|
||||||
|
|
||||||
/* Change the given property into a sibling with the same id in this scope. */
|
|
||||||
JSScopeProperty *changeProperty(JSContext *cx, JSScopeProperty *sprop,
|
|
||||||
uintN attrs, uintN mask,
|
uintN attrs, uintN mask,
|
||||||
JSPropertyOp getter, JSPropertyOp setter);
|
JSPropertyOp getter, JSPropertyOp setter);
|
||||||
|
|
||||||
/* Remove id from this scope. */
|
bool remove(JSContext *cx, jsid id);
|
||||||
bool removeProperty(JSContext *cx, jsid id);
|
|
||||||
|
|
||||||
/* Clear the scope, making it empty. */
|
|
||||||
void clear(JSContext *cx);
|
void clear(JSContext *cx);
|
||||||
|
|
||||||
/* Extend this scope to have sprop as its last-added property. */
|
|
||||||
void extend(JSContext *cx, JSScopeProperty *sprop);
|
void extend(JSContext *cx, JSScopeProperty *sprop);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read barrier to clone a joined function object stored as a method.
|
* Read barrier to clone a joined function object stored as a method.
|
||||||
* Defined in jsscopeinlines.h, but not declared inline per standard style
|
* Defined inline further below.
|
||||||
* in order to avoid gcc warnings.
|
|
||||||
*/
|
*/
|
||||||
bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp);
|
bool methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp);
|
||||||
|
|
||||||
|
@ -358,6 +294,7 @@ struct JSScope : public JSObjectMap
|
||||||
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval);
|
bool methodShapeChange(JSContext *cx, JSScopeProperty *sprop, jsval toval);
|
||||||
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
|
bool methodShapeChange(JSContext *cx, uint32 slot, jsval toval);
|
||||||
void protoShapeChange(JSContext *cx);
|
void protoShapeChange(JSContext *cx);
|
||||||
|
void replacingShapeChange(JSContext *cx, JSScopeProperty *sprop, JSScopeProperty *newsprop);
|
||||||
void sealingShapeChange(JSContext *cx);
|
void sealingShapeChange(JSContext *cx);
|
||||||
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
|
void shadowingShapeChange(JSContext *cx, JSScopeProperty *sprop);
|
||||||
|
|
||||||
|
@ -365,7 +302,7 @@ struct JSScope : public JSObjectMap
|
||||||
#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
|
#define SCOPE_CAPACITY(scope) JS_BIT(JS_DHASH_BITS-(scope)->hashShift)
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
DICTIONARY_MODE = 0x0001,
|
MIDDLE_DELETE = 0x0001,
|
||||||
SEALED = 0x0002,
|
SEALED = 0x0002,
|
||||||
BRANDED = 0x0004,
|
BRANDED = 0x0004,
|
||||||
INDEXED_PROPERTIES = 0x0008,
|
INDEXED_PROPERTIES = 0x0008,
|
||||||
|
@ -379,9 +316,9 @@ struct JSScope : public JSObjectMap
|
||||||
SHAPE_REGEN = 0x0040
|
SHAPE_REGEN = 0x0040
|
||||||
};
|
};
|
||||||
|
|
||||||
bool inDictionaryMode() { return flags & DICTIONARY_MODE; }
|
bool hadMiddleDelete() { return flags & MIDDLE_DELETE; }
|
||||||
void setDictionaryMode() { flags |= DICTIONARY_MODE; }
|
void setMiddleDelete() { flags |= MIDDLE_DELETE; }
|
||||||
void clearDictionaryMode() { flags &= ~DICTIONARY_MODE; }
|
void clearMiddleDelete() { flags &= ~MIDDLE_DELETE; }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Don't define clearSealed, as it can't be done safely because JS_LOCK_OBJ
|
* Don't define clearSealed, as it can't be done safely because JS_LOCK_OBJ
|
||||||
|
@ -404,7 +341,6 @@ struct JSScope : public JSObjectMap
|
||||||
|
|
||||||
bool hasOwnShape() { return flags & OWN_SHAPE; }
|
bool hasOwnShape() { return flags & OWN_SHAPE; }
|
||||||
void setOwnShape() { flags |= OWN_SHAPE; }
|
void setOwnShape() { flags |= OWN_SHAPE; }
|
||||||
void clearOwnShape() { flags &= ~OWN_SHAPE; }
|
|
||||||
|
|
||||||
bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; }
|
bool hasRegenFlag(uint8 regenFlag) { return (flags & SHAPE_REGEN) == regenFlag; }
|
||||||
|
|
||||||
|
@ -491,6 +427,18 @@ OBJ_SHAPE(JSObject *obj)
|
||||||
return obj->map->shape;
|
return obj->map->shape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A little information hiding for scope->lastProp, in case it ever becomes
|
||||||
|
* a tagged pointer again.
|
||||||
|
*/
|
||||||
|
#define SCOPE_LAST_PROP(scope) \
|
||||||
|
(JS_ASSERT_IF((scope)->lastProp, !JSVAL_IS_NULL((scope)->lastProp->id)), \
|
||||||
|
(scope)->lastProp)
|
||||||
|
#define SCOPE_REMOVE_LAST_PROP(scope) \
|
||||||
|
(JS_ASSERT_IF((scope)->lastProp->parent, \
|
||||||
|
!JSVAL_IS_NULL((scope)->lastProp->parent->id)), \
|
||||||
|
(scope)->lastProp = (scope)->lastProp->parent)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
|
* Helpers for reinterpreting JSPropertyOp as JSObject* for scripted getters
|
||||||
* and setters.
|
* and setters.
|
||||||
|
@ -523,14 +471,8 @@ struct JSScopeProperty {
|
||||||
uint8 flags; /* flags, see below for defines */
|
uint8 flags; /* flags, see below for defines */
|
||||||
int16 shortid; /* tinyid, or local arg/var index */
|
int16 shortid; /* tinyid, or local arg/var index */
|
||||||
JSScopeProperty *parent; /* parent node, reverse for..in order */
|
JSScopeProperty *parent; /* parent node, reverse for..in order */
|
||||||
union {
|
|
||||||
JSScopeProperty *kids; /* null, single child, or a tagged ptr
|
JSScopeProperty *kids; /* null, single child, or a tagged ptr
|
||||||
to many-kids data structure */
|
to many-kids data structure */
|
||||||
JSScopeProperty **childp; /* dictionary list starting at lastProp
|
|
||||||
has a double-indirect back pointer,
|
|
||||||
either to sprop->parent if not last,
|
|
||||||
else to scope->lastProp */
|
|
||||||
};
|
|
||||||
uint32 shape; /* property cache shape identifier */
|
uint32 shape; /* property cache shape identifier */
|
||||||
|
|
||||||
/* Bits stored in sprop->flags. */
|
/* Bits stored in sprop->flags. */
|
||||||
|
@ -539,7 +481,6 @@ struct JSScopeProperty {
|
||||||
#define SPROP_HAS_SHORTID 0x04
|
#define SPROP_HAS_SHORTID 0x04
|
||||||
#define SPROP_FLAG_SHAPE_REGEN 0x08
|
#define SPROP_FLAG_SHAPE_REGEN 0x08
|
||||||
#define SPROP_IS_METHOD 0x10
|
#define SPROP_IS_METHOD 0x10
|
||||||
#define SPROP_IN_DICTIONARY 0x20
|
|
||||||
|
|
||||||
bool isMethod() const {
|
bool isMethod() const {
|
||||||
return flags & SPROP_IS_METHOD;
|
return flags & SPROP_IS_METHOD;
|
||||||
|
@ -610,85 +551,11 @@ JSScope::lookup(jsid id)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
JSScope::hasProperty(JSScopeProperty *sprop)
|
JSScope::has(JSScopeProperty *sprop)
|
||||||
{
|
{
|
||||||
return lookup(sprop->id) == sprop;
|
return lookup(sprop->id) == sprop;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline JSScopeProperty *
|
|
||||||
JSScope::lastProperty() const
|
|
||||||
{
|
|
||||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
|
||||||
return lastProp;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Note that sprop must not be null, as emptying a scope requires extra work
|
|
||||||
* done only by methods in jsscope.cpp.
|
|
||||||
*/
|
|
||||||
inline void
|
|
||||||
JSScope::setLastProperty(JSScopeProperty *sprop)
|
|
||||||
{
|
|
||||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
|
||||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
|
||||||
|
|
||||||
lastProp = sprop;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
JSScope::removeLastProperty()
|
|
||||||
{
|
|
||||||
JS_ASSERT(!inDictionaryMode());
|
|
||||||
JS_ASSERT_IF(lastProp->parent, !JSVAL_IS_NULL(lastProp->parent->id));
|
|
||||||
|
|
||||||
lastProp = lastProp->parent;
|
|
||||||
--entryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
JSScope::removeDictionaryProperty(JSScopeProperty *sprop)
|
|
||||||
{
|
|
||||||
JS_ASSERT(inDictionaryMode());
|
|
||||||
JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY);
|
|
||||||
JS_ASSERT(sprop->childp);
|
|
||||||
JS_ASSERT(!JSVAL_IS_NULL(sprop->id));
|
|
||||||
|
|
||||||
JS_ASSERT(lastProp->flags & SPROP_IN_DICTIONARY);
|
|
||||||
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));
|
|
||||||
|
|
||||||
if (sprop->parent)
|
|
||||||
sprop->parent->childp = sprop->childp;
|
|
||||||
*sprop->childp = sprop->parent;
|
|
||||||
--entryCount;
|
|
||||||
sprop->childp = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **childp)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Don't assert inDictionaryMode() here because we may be called from
|
|
||||||
* toDictionaryMode via newDictionaryProperty.
|
|
||||||
*/
|
|
||||||
JS_ASSERT(sprop->flags & SPROP_IN_DICTIONARY);
|
|
||||||
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(lastProp, lastProp->childp == &lastProp);
|
|
||||||
JS_ASSERT_IF(lastProp, !JSVAL_IS_NULL(lastProp->id));
|
|
||||||
|
|
||||||
sprop->parent = *childp;
|
|
||||||
*childp = sprop;
|
|
||||||
if (sprop->parent)
|
|
||||||
sprop->parent->childp = &sprop->parent;
|
|
||||||
sprop->childp = childp;
|
|
||||||
++entryCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
|
* If SPROP_HAS_SHORTID is set in sprop->flags, we use sprop->shortid rather
|
||||||
* than id when calling sprop's getter or setter.
|
* than id when calling sprop's getter or setter.
|
||||||
|
@ -697,6 +564,8 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
||||||
(((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
|
(((sprop)->flags & SPROP_HAS_SHORTID) ? INT_TO_JSVAL((sprop)->shortid) \
|
||||||
: ID_TO_VALUE((sprop)->id))
|
: ID_TO_VALUE((sprop)->id))
|
||||||
|
|
||||||
|
#define SPROP_INVALID_SLOT 0xffffffff
|
||||||
|
|
||||||
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
|
#define SLOT_IN_SCOPE(slot,scope) ((slot) < (scope)->freeslot)
|
||||||
#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
|
#define SPROP_HAS_VALID_SLOT(sprop,scope) SLOT_IN_SCOPE((sprop)->slot, scope)
|
||||||
|
|
||||||
|
@ -713,7 +582,7 @@ JSScope::insertDictionaryProperty(JSScopeProperty *sprop, JSScopeProperty **chil
|
||||||
extern uint32
|
extern uint32
|
||||||
js_GenerateShape(JSContext *cx, bool gcLocked);
|
js_GenerateShape(JSContext *cx, bool gcLocked);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef JS_DUMP_PROPTREE_STATS
|
||||||
struct JSScopeStats {
|
struct JSScopeStats {
|
||||||
jsrefcount searches;
|
jsrefcount searches;
|
||||||
jsrefcount hits;
|
jsrefcount hits;
|
||||||
|
@ -722,16 +591,10 @@ struct JSScopeStats {
|
||||||
jsrefcount steps;
|
jsrefcount steps;
|
||||||
jsrefcount stepHits;
|
jsrefcount stepHits;
|
||||||
jsrefcount stepMisses;
|
jsrefcount stepMisses;
|
||||||
jsrefcount tableAllocFails;
|
|
||||||
jsrefcount toDictFails;
|
|
||||||
jsrefcount wrapWatchFails;
|
|
||||||
jsrefcount adds;
|
jsrefcount adds;
|
||||||
jsrefcount addFails;
|
jsrefcount redundantAdds;
|
||||||
jsrefcount puts;
|
jsrefcount addFailures;
|
||||||
jsrefcount redundantPuts;
|
jsrefcount changeFailures;
|
||||||
jsrefcount putFails;
|
|
||||||
jsrefcount changes;
|
|
||||||
jsrefcount changeFails;
|
|
||||||
jsrefcount compresses;
|
jsrefcount compresses;
|
||||||
jsrefcount grows;
|
jsrefcount grows;
|
||||||
jsrefcount removes;
|
jsrefcount removes;
|
||||||
|
@ -755,6 +618,7 @@ JSScope::search(jsid id, bool adding)
|
||||||
METER(searches);
|
METER(searches);
|
||||||
if (!table) {
|
if (!table) {
|
||||||
/* Not enough properties to justify hashing: search from lastProp. */
|
/* Not enough properties to justify hashing: search from lastProp. */
|
||||||
|
JS_ASSERT(!hadMiddleDelete());
|
||||||
for (spp = &lastProp; (sprop = *spp); spp = &sprop->parent) {
|
for (spp = &lastProp; (sprop = *spp); spp = &sprop->parent) {
|
||||||
if (sprop->id == id) {
|
if (sprop->id == id) {
|
||||||
METER(hits);
|
METER(hits);
|
||||||
|
|
|
@ -41,26 +41,20 @@
|
||||||
#define jsscopeinlines_h___
|
#define jsscopeinlines_h___
|
||||||
|
|
||||||
#include "jscntxt.h"
|
#include "jscntxt.h"
|
||||||
#include "jsdbgapi.h"
|
|
||||||
#include "jsfun.h"
|
#include "jsfun.h"
|
||||||
|
#include "jsinterp.h"
|
||||||
#include "jsobj.h"
|
#include "jsobj.h"
|
||||||
#include "jsscope.h"
|
#include "jsscope.h"
|
||||||
|
|
||||||
inline void
|
|
||||||
JSScope::updateShape(JSContext *cx)
|
|
||||||
{
|
|
||||||
JS_ASSERT(object);
|
|
||||||
js_LeaveTraceIfGlobalObject(cx, object);
|
|
||||||
|
|
||||||
shape = (hasOwnShape() || !lastProp) ? js_GenerateShape(cx, false) : lastProp->shape;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
JSScope::extend(JSContext *cx, JSScopeProperty *sprop)
|
JSScope::extend(JSContext *cx, JSScopeProperty *sprop)
|
||||||
{
|
{
|
||||||
|
js_LeaveTraceIfGlobalObject(cx, object);
|
||||||
|
shape = (!lastProp || shape == lastProp->shape)
|
||||||
|
? sprop->shape
|
||||||
|
: js_GenerateShape(cx, false);
|
||||||
++entryCount;
|
++entryCount;
|
||||||
setLastProperty(sprop);
|
lastProp = sprop;
|
||||||
updateShape(cx);
|
|
||||||
|
|
||||||
jsuint index;
|
jsuint index;
|
||||||
if (js_IdIsIndex(sprop->id, &index))
|
if (js_IdIsIndex(sprop->id, &index))
|
||||||
|
@ -78,7 +72,7 @@ inline bool
|
||||||
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp)
|
JSScope::methodReadBarrier(JSContext *cx, JSScopeProperty *sprop, jsval *vp)
|
||||||
{
|
{
|
||||||
JS_ASSERT(hasMethodBarrier());
|
JS_ASSERT(hasMethodBarrier());
|
||||||
JS_ASSERT(hasProperty(sprop));
|
JS_ASSERT(has(sprop));
|
||||||
JS_ASSERT(sprop->isMethod());
|
JS_ASSERT(sprop->isMethod());
|
||||||
JS_ASSERT(sprop->methodValue() == *vp);
|
JS_ASSERT(sprop->methodValue() == *vp);
|
||||||
JS_ASSERT(object->getClass() == &js_ObjectClass);
|
JS_ASSERT(object->getClass() == &js_ObjectClass);
|
||||||
|
@ -154,10 +148,12 @@ JSScope::trace(JSTracer *trc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (sprop) {
|
if (sprop) {
|
||||||
JS_ASSERT(hasProperty(sprop));
|
JS_ASSERT(has(sprop));
|
||||||
|
|
||||||
/* Trace scope's property tree ancestor line. */
|
/* Trace scope's property tree ancestor line. */
|
||||||
do {
|
do {
|
||||||
|
if (hadMiddleDelete() && !has(sprop))
|
||||||
|
continue;
|
||||||
sprop->trace(trc);
|
sprop->trace(trc);
|
||||||
} while ((sprop = sprop->parent) != NULL);
|
} while ((sprop = sprop->parent) != NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -5482,7 +5482,7 @@ Utf8ToOneUcs4Char(const uint8 *utf8Buffer, int utf8Length)
|
||||||
return ucs4Char;
|
return ucs4Char;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#if defined DEBUG || defined JS_DUMP_PROPTREE_STATS
|
||||||
|
|
||||||
JS_FRIEND_API(size_t)
|
JS_FRIEND_API(size_t)
|
||||||
js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
|
js_PutEscapedStringImpl(char *buffer, size_t bufferSize, FILE *fp,
|
||||||
|
|
|
@ -9002,7 +9002,7 @@ DumpShape(JSObject* obj, const char* prefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(shapefp, "\n%s: shape %u flags %x\n", prefix, scope->shape, scope->flags);
|
fprintf(shapefp, "\n%s: shape %u flags %x\n", prefix, scope->shape, scope->flags);
|
||||||
for (JSScopeProperty* sprop = scope->lastProperty(); sprop; sprop = sprop->parent) {
|
for (JSScopeProperty* sprop = scope->lastProp; sprop; sprop = sprop->parent) {
|
||||||
if (JSID_IS_ATOM(sprop->id)) {
|
if (JSID_IS_ATOM(sprop->id)) {
|
||||||
fprintf(shapefp, " %s", JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(sprop->id))));
|
fprintf(shapefp, " %s", JS_GetStringBytes(JSVAL_TO_STRING(ID_TO_VALUE(sprop->id))));
|
||||||
} else {
|
} else {
|
||||||
|
@ -11215,7 +11215,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop
|
||||||
LIns* obj_ins = get(&l);
|
LIns* obj_ins = get(&l);
|
||||||
JSScope* scope = OBJ_SCOPE(obj);
|
JSScope* scope = OBJ_SCOPE(obj);
|
||||||
|
|
||||||
JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->hasProperty(sprop));
|
JS_ASSERT_IF(entry->vcap == PCVCAP_MAKE(entry->kshape, 0, 0), scope->has(sprop));
|
||||||
|
|
||||||
// Fast path for CallClass. This is about 20% faster than the general case.
|
// Fast path for CallClass. This is about 20% faster than the general case.
|
||||||
v_ins = get(&v);
|
v_ins = get(&v);
|
||||||
|
@ -11237,7 +11237,7 @@ TraceRecorder::setProp(jsval &l, JSPropCacheEntry* entry, JSScopeProperty* sprop
|
||||||
jsuword pcval;
|
jsuword pcval;
|
||||||
CHECK_STATUS(guardPropertyCacheHit(obj_ins, map_ins, obj, obj2, entry, pcval));
|
CHECK_STATUS(guardPropertyCacheHit(obj_ins, map_ins, obj, obj2, entry, pcval));
|
||||||
JS_ASSERT(scope->object == obj2);
|
JS_ASSERT(scope->object == obj2);
|
||||||
JS_ASSERT(scope->hasProperty(sprop));
|
JS_ASSERT(scope->has(sprop));
|
||||||
JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED);
|
JS_ASSERT_IF(obj2 != obj, sprop->attrs & JSPROP_SHARED);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -12543,7 +12543,7 @@ TraceRecorder::prop(JSObject* obj, LIns* obj_ins, uint32 *slotp, LIns** v_insp,
|
||||||
|
|
||||||
if (PCVAL_IS_SPROP(pcval)) {
|
if (PCVAL_IS_SPROP(pcval)) {
|
||||||
sprop = PCVAL_TO_SPROP(pcval);
|
sprop = PCVAL_TO_SPROP(pcval);
|
||||||
JS_ASSERT(OBJ_SCOPE(obj2)->hasProperty(sprop));
|
JS_ASSERT(OBJ_SCOPE(obj2)->has(sprop));
|
||||||
|
|
||||||
if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
|
if (setflags && !SPROP_HAS_STUB_SETTER(sprop))
|
||||||
RETURN_STOP_A("non-stub setter");
|
RETURN_STOP_A("non-stub setter");
|
||||||
|
|
Загрузка…
Ссылка в новой задаче