Address bug 638316 and bug 694247 review comments, r=luke.

This commit is contained in:
Brian Hackett 2011-11-09 09:52:59 -08:00
parent 708b16abe9
commit 831cd84d89
24 changed files with 157 additions and 156 deletions

View File

@ -48,7 +48,6 @@
#include "nsJSUtils.h"
#include "jsapi.h"
#include "jsdbgapi.h"
#include "jsfriendapi.h"
#include "prprf.h"
#include "nsIScriptContext.h"
#include "nsIScriptObjectOwner.h"
@ -107,7 +106,7 @@ nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
if (!glob)
return nsnull;
glob = js::GetObjectGlobal(glob);
glob = JS_GetGlobalForObject(aContext, glob);
NS_ABORT_IF_FALSE(glob, "Infallible returns null");
clazz = JS_GET_CLASS(aContext, glob);

View File

@ -3071,6 +3071,7 @@ JS_SetPrototype(JSContext *cx, JSObject *obj, JSObject *proto)
JS_PUBLIC_API(JSObject *)
JS_GetParent(JSContext *cx, JSObject *obj)
{
JS_ASSERT(!obj->isInternalScope());
assertSameCompartment(cx, obj);
return obj->getParent();
}
@ -3079,7 +3080,7 @@ JS_PUBLIC_API(JSBool)
JS_SetParent(JSContext *cx, JSObject *obj, JSObject *parent)
{
CHECK_REQUEST(cx);
JS_ASSERT(!obj->isScope());
JS_ASSERT(!obj->isInternalScope());
JS_ASSERT(parent || !obj->getParent());
assertSameCompartment(cx, obj, parent);
return obj->setParent(cx, parent);
@ -4357,7 +4358,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent)
JSMSG_BAD_CLONE_FUNOBJ_SCOPE);
return NULL;
}
obj = obj->getParentOrScopeChain();
obj = obj->scopeChain();
}
Value v;

View File

@ -180,19 +180,13 @@ AutoSwitchCompartment::~AutoSwitchCompartment()
JS_FRIEND_API(bool)
js::IsScopeObject(const JSObject *obj)
{
return obj->isScope();
return obj->isInternalScope();
}
JS_FRIEND_API(JSObject *)
js::GetObjectParentMaybeScope(const JSObject *obj)
{
return obj->getParentOrScopeChain();
}
JS_FRIEND_API(JSObject *)
js::GetObjectGlobal(JSObject *obj)
{
return obj->getGlobal();
return obj->scopeChain();
}
JS_FRIEND_API(uint32)

View File

@ -283,9 +283,6 @@ GetObjectParent(const JSObject *obj)
JS_FRIEND_API(JSObject *)
GetObjectParentMaybeScope(const JSObject *obj);
JS_FRIEND_API(JSObject *)
GetObjectGlobal(JSObject *obj);
JS_FRIEND_API(bool)
IsOriginalScriptFunction(JSFunction *fun);

View File

@ -718,7 +718,7 @@ NewDeclEnvObject(JSContext *cx, StackFrame *fp)
envobj->initialize(emptyDeclEnvShape, type, NULL);
envobj->setPrivate(fp);
if (!envobj->setScopeChain(cx, &fp->scopeChain()))
if (!envobj->setInternalScopeChain(cx, &fp->scopeChain()))
return NULL;
return envobj;
@ -861,7 +861,7 @@ js_PutCallObject(StackFrame *fp)
/* Clear private pointers to fp, which is about to go away. */
if (js_IsNamedLambda(fun)) {
JSObject *env = callobj.scopeChain();
JSObject *env = callobj.internalScopeChain();
JS_ASSERT(env->isDeclEnv());
JS_ASSERT(env->getPrivate() == fp);

View File

@ -328,8 +328,8 @@ SkipScopeParent(JSObject *parent)
{
if (!parent)
return NULL;
while (parent->isScope())
parent = parent->getParentMaybeScope();
while (parent->isInternalScope())
parent = parent->scopeChain();
return parent;
}

View File

@ -694,7 +694,7 @@ ScanObject(GCMarker *gcmarker, JSObject *obj)
types::TypeObject *type = obj->typeFromGC();
PushMarkStack(gcmarker, type);
if (JSObject *parent = obj->getParentMaybeScope())
if (JSObject *parent = obj->getParent())
PushMarkStack(gcmarker, parent);
/*
@ -763,7 +763,7 @@ MarkChildren(JSTracer *trc, JSObject *obj)
MarkTypeObject(trc, obj->typeFromGC(), "type");
/* Trace universal (ops-independent) members. */
if (JSObject *parent = obj->getParentMaybeScope())
if (JSObject *parent = obj->getParent())
MarkObject(trc, *parent, "parent");
Class *clasp = obj->getClass();

View File

@ -5162,7 +5162,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
* the script is nested inside.
*/
while (!scope->isCall())
scope = scope->scopeChain();
scope = scope->internalScopeChain();
CallObject &call = scope->asCall();
@ -5195,7 +5195,7 @@ TypeScript::SetScope(JSContext *cx, JSScript *script, JSObject *scope)
if (!parent->ensureHasTypes(cx))
return false;
if (!parent->types->hasScope()) {
if (!SetScope(cx, parent, scope->scopeChain()))
if (!SetScope(cx, parent, scope->internalScopeChain()))
return false;
parent->nesting()->activeCall = scope;
parent->nesting()->argArray = call.argArray();
@ -5290,7 +5290,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
JS_ASSERT(parent);
while (!scope->isCall() || scope->asCall().getCalleeFunction()->script() != parent)
scope = scope->scopeChain();
scope = scope->internalScopeChain();
if (scope != parent->nesting()->activeCall) {
parent->reentrantOuterFunction = true;
@ -5305,7 +5305,7 @@ CheckNestingParent(JSContext *cx, JSObject *scope, JSScript *script)
* parent.
*/
if (parent->nesting()->parent) {
scope = scope->scopeChain();
scope = scope->internalScopeChain();
script = parent;
goto restart;
}

View File

@ -299,7 +299,7 @@ GetScopeChainFull(JSContext *cx, StackFrame *fp, JSObject *blockChain)
*/
limitClone = &fp->scopeChain();
while (limitClone->isWith())
limitClone = limitClone->scopeChain();
limitClone = limitClone->internalScopeChain();
JS_ASSERT(limitClone);
/*
@ -357,11 +357,11 @@ GetScopeChainFull(JSContext *cx, StackFrame *fp, JSObject *blockChain)
if (!clone)
return NULL;
if (!newChild->setScopeChain(cx, clone))
if (!newChild->setInternalScopeChain(cx, clone))
return NULL;
newChild = clone;
}
if (!newChild->setScopeChain(cx, &fp->scopeChain()))
if (!newChild->setInternalScopeChain(cx, &fp->scopeChain()))
return NULL;
@ -1215,7 +1215,7 @@ LeaveWith(JSContext *cx)
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp()));
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
withobj->setPrivate(NULL);
cx->fp()->setScopeChainNoCallObj(*withobj->scopeChain());
cx->fp()->setScopeChainNoCallObj(*withobj->internalScopeChain());
}
bool
@ -2139,7 +2139,7 @@ BEGIN_CASE(JSOP_POPN)
JS_ASSERT_IF(obj,
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
<= (size_t) (regs.sp - regs.fp()->base()));
for (obj = &regs.fp()->scopeChain(); obj; obj = obj->getParentOrScopeChain()) {
for (obj = &regs.fp()->scopeChain(); obj; obj = obj->scopeChain()) {
if (!obj->isBlock() || !obj->isWith())
continue;
if (obj->getPrivate() != js_FloatingFrameIfGenerator(cx, regs.fp()))
@ -5440,13 +5440,13 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
*/
JSObject *obj2 = &regs.fp()->scopeChain();
while (obj2->isWith())
obj2 = obj2->scopeChain();
obj2 = obj2->internalScopeChain();
if (obj2->isBlock() &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, regs.fp())) {
JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock());
JSObject *parent = obj;
while ((parent = parent->getParentOrScopeChain()) != youngestProto)
while ((parent = parent->scopeChain()) != youngestProto)
JS_ASSERT(parent);
}
#endif

View File

@ -962,7 +962,7 @@ static void
AssertInnerizedScopeChain(JSContext *cx, JSObject &scopeobj)
{
#ifdef DEBUG
for (JSObject *o = &scopeobj; o; o = o->getParentOrScopeChain()) {
for (JSObject *o = &scopeobj; o; o = o->scopeChain()) {
if (JSObjectOp op = o->getClass()->ext.innerObject)
JS_ASSERT(op(cx, o) == o);
}
@ -3604,7 +3604,7 @@ js_NewWithObject(JSContext *cx, JSObject *proto, JSObject *parent, jsint depth)
obj->initialize(emptyWithShape, type, NULL);
OBJ_SET_BLOCK_DEPTH(cx, obj, depth);
if (!obj->setScopeChain(cx, parent))
if (!obj->setInternalScopeChain(cx, parent))
return NULL;
obj->setPrivate(priv);
@ -3664,8 +3664,8 @@ js_CloneBlockObject(JSContext *cx, JSObject *proto, StackFrame *fp)
/* Set the parent if necessary, as for call objects. */
JSObject *global = priv->scopeChain().getGlobal();
if (global != clone->getParentMaybeScope()) {
JS_ASSERT(clone->getParentMaybeScope() == NULL);
if (global != clone->getParent()) {
JS_ASSERT(clone->getParent() == NULL);
if (!clone->setParent(cx, global))
return NULL;
}
@ -3711,7 +3711,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
/* We must clear the private slot even with errors. */
obj->setPrivate(NULL);
fp->setScopeChainNoCallObj(*obj->scopeChain());
fp->setScopeChainNoCallObj(*obj->internalScopeChain());
return normalUnwind;
}
@ -5303,7 +5303,7 @@ js_PurgeScopeChainHelper(JSContext *cx, JSObject *obj, jsid id)
* may gain such properties via eval introducing new vars; see bug 490364.
*/
if (obj->isCall()) {
while ((obj = obj->getParentOrScopeChain()) != NULL) {
while ((obj = obj->scopeChain()) != NULL) {
if (!PurgeProtoChain(cx, obj, id))
return false;
}
@ -5748,7 +5748,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
/* Scan entries on the scope chain that we can cache across. */
entry = JS_NO_PROP_CACHE_FILL;
obj = scopeChain;
parent = obj->getParentOrScopeChain();
parent = obj->scopeChain();
for (scopeIndex = 0;
parent
? IsCacheableNonGlobalScope(obj)
@ -5794,7 +5794,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
goto out;
}
obj = parent;
parent = obj->getParentOrScopeChain();
parent = obj->scopeChain();
}
for (;;) {
@ -5809,7 +5809,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, bool cacheResult, bool global,
* We conservatively assume that a resolve hook could mutate the scope
* chain during JSObject::lookupGeneric. So we read parent here again.
*/
parent = obj->getParentOrScopeChain();
parent = obj->scopeChain();
if (!parent) {
pobj = NULL;
break;
@ -5868,14 +5868,14 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
JS_ASSERT(obj->isGlobal());
return obj;
}
JS_ASSERT_IF(obj->isScope(), pobj->getClass() == obj->getClass());
JS_ASSERT_IF(obj->isInternalScope(), pobj->getClass() == obj->getClass());
DebugOnly<PropertyCacheEntry*> entry =
JS_PROPERTY_CACHE(cx).fill(cx, scopeChain, scopeIndex, pobj, (Shape *) prop);
JS_ASSERT(entry);
return obj;
}
JSObject *parent = obj->getParentOrScopeChain();
JSObject *parent = obj->scopeChain();
if (!parent)
return obj;
obj = parent;
@ -5895,7 +5895,7 @@ js_FindIdentifierBase(JSContext *cx, JSObject *scopeChain, jsid id)
* chain during JSObject::lookupGeneric. So we must check if parent is
* not null here even if it wasn't before the lookup.
*/
JSObject *parent = obj->getParentOrScopeChain();
JSObject *parent = obj->scopeChain();
if (!parent)
break;
obj = parent;
@ -7471,7 +7471,7 @@ js_DumpObject(JSObject *obj)
fputc('\n', stderr);
fprintf(stderr, "parent ");
dumpValue(ObjectOrNullValue(obj->getParentMaybeScope()));
dumpValue(ObjectOrNullValue(obj->getParent()));
fputc('\n', stderr);
if (clasp->flags & JSCLASS_HAS_PRIVATE)

View File

@ -851,32 +851,63 @@ struct JSObject : js::gc::Cell
return type_->proto;
}
/*
* Parents and scope chains.
*
* All script-accessible objects with a NULL parent are global objects,
* and all global objects have a NULL parent. Some builtin objects which
* are not script-accessible also have a NULL parent, such as parser
* created functions for non-compileAndGo scripts.
*
* Except for the non-script-accessible builtins, the global with which an
* object is associated can be reached by following parent links to that
* global (see getGlobal()).
*
* The scope chain of an object is the link in the search path when a
* script does a name lookup on a scope object. For JS internal scope
* objects --- Call, Block, DeclEnv and With --- the chain is stored in
* the first fixed slot of the object, and the object's parent is the
* associated global. For other scope objects, the chain is stored in the
* object's parent.
*
* In compileAndGo code, scope chains can contain only internal scope
* objects with a global object at the root as the scope of the outermost
* non-function script. In non-compileAndGo code, the scope of the
* outermost non-function script might not be a global object, and can have
* a mix of other objects above it before the global object is reached.
*/
/* Access the parent link of an object. */
inline JSObject *getParent() const;
bool setParent(JSContext *cx, JSObject *newParent);
/* Get the scope chain of an arbitrary scope object. */
inline JSObject *scopeChain() const;
inline bool isGlobal() const;
inline js::GlobalObject *asGlobal();
inline js::GlobalObject *getGlobal() const;
inline bool isInternalScope() const;
/* Access the scope chain of an internal scope object. */
inline JSObject *internalScopeChain() const;
inline bool setInternalScopeChain(JSContext *cx, JSObject *obj);
static inline size_t offsetOfInternalScopeChain();
/*
* Information for non-global scope chain objects (call/with/etc.). All
* objects on a scope chain are either isScope() or isGlobal(). isScope()
* objects do not escape to script and only appear on scope chains.
* Access the scope chain of a static block object. These do not appear
* on scope chains but mirror their structure, and can have a NULL
* scope chain.
*/
inline bool isScope() const;
inline JSObject *scopeChain() const;
inline bool setScopeChain(JSContext *cx, JSObject *obj);
static inline size_t offsetOfScopeChain();
inline JSObject *getParentOrScopeChain() const;
inline JSObject *getParentMaybeScope() const;
inline JSObject *getStaticBlockScopeChain() const;
inline void setStaticBlockScopeChain(JSObject *obj);
/* Common fixed slot for the scope chain of internal scope objects. */
static const uint32 SCOPE_CHAIN_SLOT = 0;
/* Private data accessors. */
inline bool hasPrivate() const;
inline void *getPrivate() const;
inline void setPrivate(void *data);

View File

@ -274,74 +274,56 @@ JSObject::finalize(JSContext *cx, bool background)
inline JSObject *
JSObject::getParent() const
{
JS_ASSERT(!isScope());
return lastProperty()->getObjectParent();
}
inline bool
JSObject::isScope() const
JSObject::isInternalScope() const
{
return isCall() || isDeclEnv() || isBlock() || isWith();
}
inline JSObject *
JSObject::scopeChain() const
JSObject::internalScopeChain() const
{
JS_ASSERT(isScope());
return &getFixedSlot(0).toObject();
JS_ASSERT(isInternalScope());
return &getFixedSlot(SCOPE_CHAIN_SLOT).toObject();
}
inline bool
JSObject::setInternalScopeChain(JSContext *cx, JSObject *obj)
{
JS_ASSERT(isInternalScope());
if (!obj->setDelegate(cx))
return false;
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectValue(*obj));
return true;
}
/*static*/ inline size_t
JSObject::offsetOfInternalScopeChain()
{
return getFixedSlotOffset(SCOPE_CHAIN_SLOT);
}
inline JSObject *
JSObject::getParentOrScopeChain() const
JSObject::scopeChain() const
{
return isScope() ? scopeChain() : getParent();
return isInternalScope() ? internalScopeChain() : getParent();
}
inline JSObject *
JSObject::getStaticBlockScopeChain() const
{
/*
* Unlike other scope objects, static blocks not nested in one another
* do not have a scope chain.
*/
JS_ASSERT(isStaticBlock());
return getFixedSlot(0).isObject() ? &getFixedSlot(0).toObject() : NULL;
return getFixedSlot(SCOPE_CHAIN_SLOT).toObjectOrNull();
}
inline void
JSObject::setStaticBlockScopeChain(JSObject *obj)
{
/*
* Static blocks may have a block chain set and then overwritten with NULL.
* XXX bug 700799 this should not be able to happen.
*/
JS_ASSERT(isStaticBlock());
if (obj)
setFixedSlot(0, js::ObjectValue(*obj));
else
setFixedSlot(0, js::UndefinedValue());
}
inline JSObject *
JSObject::getParentMaybeScope() const
{
return lastProperty()->getObjectParent();
}
inline bool
JSObject::setScopeChain(JSContext *cx, JSObject *obj)
{
JS_ASSERT(isScope());
if (!obj->setDelegate(cx))
return false;
setFixedSlot(0, JS::ObjectValue(*obj));
return true;
}
/*static*/ inline size_t
JSObject::offsetOfScopeChain()
{
return getFixedSlotOffset(0);
setFixedSlot(SCOPE_CHAIN_SLOT, JS::ObjectOrNullValue(obj));
}
/*
@ -453,11 +435,11 @@ inline bool
JSObject::canRemoveLastProperty()
{
/*
* Some information stored in shapes describes the object itself, and can
* be changed via replaceLastProperty without converting to a dictionary.
* Parent shapes in the property tree may not have this information set,
* and we need to ensure when unwinding properties that the per-object
* information is not accidentally reset.
* Check that the information about the object stored in the last
* property's base shape is consistent with that stored in the previous
* shape. If not consistent, then the last property cannot be removed as it
* will induce a change in the object itself, and the object must be
* converted to dictionary mode instead. See BaseShape comment in jsscope.h
*/
JS_ASSERT(!inDictionaryMode());
const js::Shape *previous = lastProperty()->previous();
@ -1281,7 +1263,7 @@ inline js::GlobalObject *
JSObject::getGlobal() const
{
JSObject *obj = const_cast<JSObject *>(this);
while (JSObject *parent = obj->getParentMaybeScope())
while (JSObject *parent = obj->getParent())
obj = parent;
return obj->asGlobal();
}

View File

@ -81,7 +81,7 @@ PropertyCache::fill(JSContext *cx, JSObject *obj, uintN scopeIndex, JSObject *po
JSObject *tmp = obj;
for (uintN i = 0; i != scopeIndex; i++)
tmp = tmp->scopeChain();
tmp = tmp->internalScopeChain();
uintN protoIndex = 0;
while (tmp != pobj) {
@ -224,7 +224,7 @@ PropertyCache::fullTest(JSContext *cx, jsbytecode *pc, JSObject **objp, JSObject
if (JOF_MODE(cs.format) == JOF_NAME) {
while (vindex & (PCINDEX_SCOPEMASK << PCINDEX_PROTOBITS)) {
tmp = pobj->scopeChain();
tmp = pobj->internalScopeChain();
if (!tmp || !tmp->isNative())
break;
pobj = tmp;

View File

@ -341,13 +341,18 @@ Shape::getChildBinding(JSContext *cx, const js::Shape &child, Shape **lastBindin
}
/* static */ bool
Shape::replaceLastProperty(JSContext *cx, const js::Shape &child, Shape **lastp)
Shape::replaceLastProperty(JSContext *cx, const BaseShape &base, Shape **lastp)
{
Shape *shape = *lastp;
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
return false;
JS_ASSERT(!child.inDictionary());
Shape *shape = *lastp;
JS_ASSERT(!shape->inDictionary());
Shape child(shape);
child.base_ = nbase;
Shape *newShape;
if (shape->parent) {
newShape = JS_PROPERTY_TREE(cx).getChild(cx, shape->parent, child);
@ -645,7 +650,7 @@ JSObject::addPropertyInternal(JSContext *cx, jsid id,
/* Find or create a property tree node labeled by our arguments. */
Shape *shape;
{
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
attrs, getter, setter);
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
@ -744,7 +749,7 @@ JSObject::putProperty(JSContext *cx, jsid id,
UnownedBaseShape *nbase;
{
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
attrs, getter, setter);
nbase = BaseShape::lookup(cx, base);
if (!nbase)
@ -824,7 +829,7 @@ JSObject::putProperty(JSContext *cx, jsid id,
* If any shape in the tree has a property hashtable, it is shared and
* immutable too, therefore we must not update *spp.
*/
BaseShape base(getClass(), getParentMaybeScope(), lastProperty()->getObjectFlags(),
BaseShape base(getClass(), getParent(), lastProperty()->getObjectFlags(),
attrs, getter, setter);
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
@ -1160,14 +1165,8 @@ Shape::setObjectParent(JSContext *cx, JSObject *parent, Shape **listp)
BaseShape base(*(*listp)->base()->unowned());
base.setParent(parent);
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
return false;
Shape child(*listp);
child.base_ = nbase;
return replaceLastProperty(cx, child, listp);
return replaceLastProperty(cx, base, listp);
}
bool
@ -1219,14 +1218,8 @@ Shape::setObjectFlag(JSContext *cx, BaseShape::Flag flag, Shape **listp)
BaseShape base(*(*listp)->base()->unowned());
base.flags |= flag;
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
return false;
Shape child(*listp);
child.base_ = nbase;
return replaceLastProperty(cx, child, listp);
return replaceLastProperty(cx, base, listp);
}
/* static */ inline HashNumber
@ -1368,14 +1361,8 @@ Shape::setExtensibleParents(JSContext *cx, Shape **listp)
BaseShape base(*shape->base()->unowned());
base.flags |= BaseShape::EXTENSIBLE_PARENTS;
BaseShape *nbase = BaseShape::lookup(cx, base);
if (!nbase)
return NULL;
Shape child(shape);
child.base_ = nbase;
return replaceLastProperty(cx, child, listp);
return replaceLastProperty(cx, base, listp);
}
bool

View File

@ -328,6 +328,16 @@ class PropertyTree;
* Unowned Shape, Unowned BaseShape:
*
* Property in the property tree which does not have a property table.
*
* BaseShapes additionally encode some information about the referring object
* itself. This includes the object's class, parent and various flags that may
* be set for the object. Except for the class, this information is mutable and
* may change when the object has an established property lineage. On such
* changes the entire property lineage is not updated, but rather only the
* last property (and its base shape). This works because only the object's
* last property is used to query information about the object. Care must be
* taken to call JSObject::canRemoveLastProperty when unwinding an object to
* an earlier property, however.
*/
class UnownedBaseShape;
@ -565,8 +575,8 @@ struct Shape : public js::gc::Cell
js::Shape *getChildBinding(JSContext *cx, const js::Shape &child, js::Shape **lastBinding);
/* Replace the last shape in a non-dictionary lineage with child. */
static bool replaceLastProperty(JSContext *cx, const js::Shape &child, Shape **lastp);
/* Replace the base shape of the last shape in a non-dictionary lineage with base. */
static bool replaceLastProperty(JSContext *cx, const BaseShape &base, Shape **lastp);
bool hashify(JSContext *cx);
void handoffTableTo(Shape *newShape);

View File

@ -175,7 +175,7 @@ BaseShape::adoptUnowned(UnownedBaseShape *other)
uint32 span = slotSpan();
PropertyTable *table = &this->table();
*this = *static_cast<BaseShape *>(other);
*this = *other;
setOwned(other);
this->parent = parent;
this->flags |= flags;

View File

@ -7548,7 +7548,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
return false;
obj = NULL;
for (tmp = scopeChain; tmp; tmp = tmp->getParentOrScopeChain()) {
for (tmp = scopeChain; tmp; tmp = tmp->scopeChain()) {
Class *clasp = tmp->getClass();
if (clasp == &BlockClass || clasp == &WithClass)
continue;
@ -7746,7 +7746,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
return JS_TRUE;
}
}
} while ((obj = obj->getParentOrScopeChain()) != NULL);
} while ((obj = obj->scopeChain()) != NULL);
JSAutoByteString printable;
JSString *str = ConvertQNameToString(cx, nameobj);

View File

@ -1377,10 +1377,10 @@ class ScopeNameCompiler : public PICStubCompiler
return error();
/* Load the next link in the scope chain. */
Address parent(pic.objReg, JSObject::offsetOfScopeChain());
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
masm.loadPayload(parent, pic.objReg);
tobj = tobj->scopeChain();
tobj = tobj->internalScopeChain();
}
if (tobj != getprop.holder)
@ -1759,7 +1759,7 @@ class BindNameCompiler : public PICStubCompiler
/* Walk up the scope chain. */
JSObject *tobj = scopeChain;
Address parent(pic.objReg, JSObject::offsetOfScopeChain());
Address parent(pic.objReg, JSObject::offsetOfInternalScopeChain());
while (tobj && tobj != obj) {
if (!IsCacheableNonGlobalScope(tobj))
return disable("non-cacheable obj in scope chain");
@ -1769,7 +1769,7 @@ class BindNameCompiler : public PICStubCompiler
ImmPtr(tobj->lastProperty()));
if (!fails.append(shapeTest))
return error();
tobj = tobj->scopeChain();
tobj = tobj->internalScopeChain();
}
if (tobj != obj)
return disable("indirect hit");

View File

@ -1859,13 +1859,13 @@ stubs::EnterBlock(VMFrame &f, JSObject *obj)
*/
JSObject *obj2 = &fp->scopeChain();
while (obj2->isWith())
obj2 = obj2->scopeChain();
obj2 = obj2->internalScopeChain();
if (obj2->isBlock() &&
obj2->getPrivate() == js_FloatingFrameIfGenerator(cx, fp)) {
JSObject *youngestProto = obj2->getProto();
JS_ASSERT(youngestProto->isStaticBlock());
JSObject *parent = obj;
while ((parent = parent->getParentOrScopeChain()) != youngestProto)
while ((parent = parent->scopeChain()) != youngestProto)
JS_ASSERT(parent);
}
#endif

View File

@ -77,8 +77,8 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
* to be updated dynamically.
*/
JSObject *global = scopeChain.getGlobal();
if (global != obj->getParentMaybeScope()) {
JS_ASSERT(obj->getParentMaybeScope() == NULL);
if (global != obj->getParent()) {
JS_ASSERT(obj->getParent() == NULL);
if (!obj->setParent(cx, global))
return NULL;
}
@ -96,7 +96,7 @@ CallObject::create(JSContext *cx, JSScript *script, JSObject &scopeChain, JSObje
JS_ASSERT(obj->isCall());
JS_ASSERT(!obj->inDictionaryMode());
if (!obj->setScopeChain(cx, &scopeChain))
if (!obj->setInternalScopeChain(cx, &scopeChain))
return NULL;
/*

View File

@ -84,7 +84,7 @@ StackFrame::varObj()
{
JSObject *obj = &scopeChain();
while (!obj->isVarObj())
obj = obj->getParentOrScopeChain();
obj = obj->getParent();
return *obj;
}
@ -376,10 +376,10 @@ StackFrame::setScopeChainNoCallObj(JSObject &obj)
if (hasCallObj()) {
JSObject *pobj = &obj;
while (pobj && pobj->getPrivate() != this)
pobj = pobj->getParentOrScopeChain();
pobj = pobj->scopeChain();
JS_ASSERT(pobj);
} else {
for (JSObject *pobj = &obj; pobj->isScope(); pobj = pobj->getParentOrScopeChain())
for (JSObject *pobj = &obj; pobj->isInternalScope(); pobj = pobj->scopeChain())
JS_ASSERT_IF(pobj->isCall(), pobj->getPrivate() != this);
}
}
@ -404,7 +404,7 @@ StackFrame::callObj() const
JSObject *pobj = &scopeChain();
while (JS_UNLIKELY(!pobj->isCall()))
pobj = pobj->getParentOrScopeChain();
pobj = pobj->scopeChain();
return pobj->asCall();
}
@ -476,7 +476,7 @@ StackFrame::markFunctionEpilogueDone()
*/
scopeChain_ = isFunctionFrame()
? callee().toFunction()->environment()
: scopeChain_->scopeChain();
: scopeChain_->internalScopeChain();
flags_ &= ~HAS_CALL_OBJ;
}
}

View File

@ -151,7 +151,7 @@ StackFrame::stealFrameAndSlots(Value *vp, StackFrame *otherfp,
obj.setPrivate(this);
otherfp->flags_ &= ~HAS_CALL_OBJ;
if (js_IsNamedLambda(fun())) {
JSObject *env = obj.scopeChain();
JSObject *env = obj.internalScopeChain();
JS_ASSERT(env->isDeclEnv());
env->setPrivate(this);
}

View File

@ -273,7 +273,7 @@ bool
ListBase<LC>::instanceIsListObject(JSContext *cx, JSObject *obj, JSObject *callee)
{
if (XPCWrapper::IsSecurityWrapper(obj)) {
if (callee && js::GetObjectGlobal(obj) == js::GetObjectGlobal(callee)) {
if (callee && JS_GetGlobalForObject(cx, obj) == JS_GetGlobalForObject(cx, callee)) {
obj = js::UnwrapObject(obj);
} else {
obj = XPCWrapper::Unwrap(cx, obj);

View File

@ -808,7 +808,7 @@ nsXPConnect::Traverse(void *p, nsCycleCollectionTraversalCallback &cb)
}
if(traceKind == JSTRACE_OBJECT) {
JSObject *global = js::GetObjectGlobal(static_cast<JSObject*>(p));
JSObject *global = JS_GetGlobalForObject(NULL, static_cast<JSObject*>(p));
char fullname[100];
JS_snprintf(fullname, sizeof(fullname),
"%s (global=%p)", name, global);