Put JSStackFrame.scopeChain/blockChain behind an interface, bug 586533. r=lw

This commit is contained in:
Brian Hackett 2010-08-13 00:08:37 -04:00
parent 58398dc6a8
commit a416b05f95
14 changed files with 218 additions and 180 deletions

View File

@ -1823,7 +1823,7 @@ JS_GetGlobalForScopeChain(JSContext *cx)
VOUCH_DOES_NOT_REQUIRE_STACK();
if (cx->fp)
return cx->fp->scopeChain->getGlobal();
return cx->fp->getScopeChain()->getGlobal();
JSObject *scope = cx->globalObject;
if (!scope) {

View File

@ -351,7 +351,7 @@ js_PopInterpFrame(JSContext* cx, TracerState* state)
return JS_FALSE;
if (fp->imacpc)
return JS_FALSE;
if (fp->blockChain)
if (fp->hasBlockChain())
return JS_FALSE;
fp->putActivationObjects(cx);

View File

@ -685,7 +685,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsid id, Value *vp)
fp->script = script;
fp->fun = fun;
fp->argv = vp + 2;
fp->scopeChain = closure->getParent();
fp->setScopeChain(closure->getParent());
fp->setArgsObj(NULL);
/* Initialize regs. */
@ -1204,7 +1204,7 @@ JS_IsNativeFrame(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(JSObject *)
JS_GetFrameObject(JSContext *cx, JSStackFrame *fp)
{
return fp->scopeChain;
return fp->maybeScopeChain();
}
JS_PUBLIC_API(JSObject *)
@ -1564,7 +1564,7 @@ SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs &regs, JSObj
PodZero(fp);
fp->fun = fun;
fp->argv = vp + 2;
fp->scopeChain = scopeobj->getGlobal();
fp->setScopeChain(scopeobj->getGlobal());
regs.pc = NULL;
regs.sp = fp->slots();

View File

@ -215,7 +215,7 @@ js_GetArgsObject(JSContext *cx, JSStackFrame *fp)
return fp->getArgsObj();
/* Compute the arguments object's parent slot from fp's scope chain. */
JSObject *global = fp->scopeChain->getGlobal();
JSObject *global = fp->getScopeChain()->getGlobal();
JSObject *argsobj = NewArguments(cx, global, fp->argc, &fp->argv[-2].toObject());
if (!argsobj)
return argsobj;
@ -763,7 +763,7 @@ NewDeclEnvObject(JSContext *cx, JSStackFrame *fp)
return NULL;
/* Init immediately to avoid GC seeing a half-init'ed object. */
envobj->init(&js_DeclEnvClass, NULL, fp->scopeChain, PrivateValue(fp));
envobj->init(&js_DeclEnvClass, NULL, fp->maybeScopeChain(), PrivateValue(fp));
envobj->map = cx->runtime->emptyDeclEnvScope->hold();
return envobj;
}
@ -778,11 +778,11 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
#ifdef DEBUG
/* A call object should be a frame's outermost scope chain element. */
Class *classp = fp->scopeChain->getClass();
Class *classp = fp->getScopeChain()->getClass();
if (classp == &js_WithClass || classp == &js_BlockClass)
JS_ASSERT(fp->scopeChain->getPrivate() != js_FloatingFrameIfGenerator(cx, fp));
JS_ASSERT(fp->getScopeChain()->getPrivate() != js_FloatingFrameIfGenerator(cx, fp));
else if (classp == &js_CallClass)
JS_ASSERT(fp->scopeChain->getPrivate() != fp);
JS_ASSERT(fp->getScopeChain()->getPrivate() != fp);
#endif
/*
@ -798,9 +798,9 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
return NULL;
/* Root envobj before js_DefineNativeProperty (-> JSClass.addProperty). */
fp->scopeChain = envobj;
fp->setScopeChain(envobj);
JS_ASSERT(fp->argv);
if (!js_DefineNativeProperty(cx, fp->scopeChain, ATOM_TO_JSID(lambdaName),
if (!js_DefineNativeProperty(cx, fp->getScopeChain(), ATOM_TO_JSID(lambdaName),
fp->calleeValue(),
CalleeGetter, NULL,
JSPROP_PERMANENT | JSPROP_READONLY,
@ -809,7 +809,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
}
}
JSObject *callobj = NewCallObject(cx, fp->fun, fp->scopeChain);
JSObject *callobj = NewCallObject(cx, fp->fun, fp->getScopeChain());
if (!callobj)
return NULL;
@ -823,7 +823,7 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp)
* Push callobj on the top of the scope chain, and make it the
* variables object.
*/
fp->scopeChain = callobj;
fp->setScopeChain(callobj);
return callobj;
}

View File

@ -2260,8 +2260,8 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */
MarkValue(trc, fp->thisv, "this");
MarkValue(trc, fp->rval, "rval");
if (fp->scopeChain)
JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain");
if (fp->hasScopeChain())
JS_CALL_OBJECT_TRACER(trc, fp->getScopeChain(), "scope chain");
}
void

View File

@ -103,7 +103,7 @@ jsbytecode *const JSStackFrame::sInvalidPC = (jsbytecode *)0xbeef;
JSObject *
js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
{
JSObject *sharedBlock = fp->blockChain;
JSObject *sharedBlock = fp->maybeBlockChain();
if (!sharedBlock) {
/*
@ -113,8 +113,8 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
JS_ASSERT(!fp->fun ||
!(fp->fun->flags & JSFUN_HEAVYWEIGHT) ||
fp->hasCallObj());
JS_ASSERT(fp->scopeChain);
return fp->scopeChain;
JS_ASSERT(fp->hasScopeChain());
return fp->getScopeChain();
}
/* We don't handle cloning blocks on trace. */
@ -129,8 +129,8 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
*/
JSObject *limitBlock, *limitClone;
if (fp->fun && !fp->hasCallObj()) {
JS_ASSERT_IF(fp->scopeChain->getClass() == &js_BlockClass,
fp->scopeChain->getPrivate() != js_FloatingFrameIfGenerator(cx, fp));
JS_ASSERT_IF(fp->getScopeChain()->getClass() == &js_BlockClass,
fp->getScopeChain()->getPrivate() != js_FloatingFrameIfGenerator(cx, fp));
if (!js_GetCallObject(cx, fp))
return NULL;
@ -143,7 +143,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
* prototype should appear on blockChain; we'll clone blockChain up
* to, but not including, that prototype.
*/
limitClone = fp->scopeChain;
limitClone = fp->getScopeChain();
while (limitClone->getClass() == &js_WithClass)
limitClone = limitClone->getParent();
JS_ASSERT(limitClone);
@ -170,7 +170,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
/* If the innermost block has already been cloned, we are done. */
if (limitBlock == sharedBlock)
return fp->scopeChain;
return fp->getScopeChain();
}
/*
@ -206,7 +206,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
newChild->setParent(clone);
newChild = clone;
}
newChild->setParent(fp->scopeChain);
newChild->setParent(fp->getScopeChain());
/*
@ -219,7 +219,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp)
sharedBlock);
/* Place our newly cloned blocks at the head of the scope chain. */
fp->scopeChain = innermostNewChild;
fp->setScopeChain(innermostNewChild);
return innermostNewChild;
}
@ -507,8 +507,8 @@ InvokeCommon(JSContext *cx, JSFunction *fun, JSScript *script, T native,
fp->argv = args.argv();
fp->rval = (flags & JSINVOKE_CONSTRUCT) ? fp->thisv : UndefinedValue();
fp->annotation = NULL;
fp->scopeChain = NULL;
fp->blockChain = NULL;
fp->setScopeChain(NULL);
fp->setBlockChain(NULL);
fp->imacpc = NULL;
fp->flags = flags;
@ -530,14 +530,14 @@ InvokeCommon(JSContext *cx, JSFunction *fun, JSScript *script, T native,
if (native) {
/* Slow natives and call ops expect the caller's scopeChain as their scopeChain. */
if (JSStackFrame *down = fp->down)
fp->scopeChain = down->scopeChain;
fp->setScopeChain(down->maybeScopeChain());
/* Ensure that we have a scope chain. */
if (!fp->scopeChain)
fp->scopeChain = parent;
if (!fp->hasScopeChain())
fp->setScopeChain(parent);
} else {
/* Use parent scope so js_GetCallObject can find the right "Call". */
fp->scopeChain = parent;
fp->setScopeChain(parent);
if (fun->isHeavyweight() && !js_GetCallObject(cx, fp))
return false;
}
@ -824,7 +824,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
fp->argc = down->argc;
fp->argv = down->argv;
fp->annotation = down->annotation;
fp->scopeChain = chain;
fp->setScopeChain(chain);
/*
* We want to call |down->varobj()|, but this requires knowing the
@ -850,7 +850,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
OBJ_TO_INNER_OBJECT(cx, innerizedChain);
if (!innerizedChain)
return false;
fp->scopeChain = innerizedChain;
fp->setScopeChain(innerizedChain);
initialVarObj = (cx->options & JSOPTION_VAROBJFIX)
? chain->getGlobal()
@ -861,7 +861,7 @@ Execute(JSContext *cx, JSObject *chain, JSScript *script,
fp->script = script;
fp->imacpc = NULL;
fp->rval.setUndefined();
fp->blockChain = NULL;
fp->setBlockChain(NULL);
/* Initialize regs. */
regs.pc = script->code;
@ -1245,7 +1245,7 @@ js_EnterWith(JSContext *cx, jsint stackIndex)
if (!withobj)
return JS_FALSE;
fp->scopeChain = withobj;
fp->setScopeChain(withobj);
return JS_TRUE;
}
@ -1254,11 +1254,11 @@ js_LeaveWith(JSContext *cx)
{
JSObject *withobj;
withobj = cx->fp->scopeChain;
withobj = cx->fp->getScopeChain();
JS_ASSERT(withobj->getClass() == &js_WithClass);
JS_ASSERT(withobj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp));
JS_ASSERT(OBJ_BLOCK_DEPTH(cx, withobj) >= 0);
cx->fp->scopeChain = withobj->getParent();
cx->fp->setScopeChain(withobj->getParent());
withobj->setPrivate(NULL);
}
@ -1290,15 +1290,15 @@ js_UnwindScope(JSContext *cx, jsint stackDepth, JSBool normalUnwind)
JS_ASSERT(cx->fp->base() + stackDepth <= cx->regs->sp);
JSStackFrame *fp = cx->fp;
for (obj = fp->blockChain; obj; obj = obj->getParent()) {
for (obj = fp->maybeBlockChain(); obj; obj = obj->getParent()) {
JS_ASSERT(obj->getClass() == &js_BlockClass);
if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth)
break;
}
fp->blockChain = obj;
fp->setBlockChain(obj);
for (;;) {
obj = fp->scopeChain;
obj = fp->getScopeChain();
clasp = js_IsActiveWithOrBlock(cx, obj, stackDepth);
if (!clasp)
break;
@ -2525,11 +2525,11 @@ BEGIN_CASE(JSOP_POPN)
regs.sp -= GET_UINT16(regs.pc);
#ifdef DEBUG
JS_ASSERT(fp->base() <= regs.sp);
JSObject *obj = fp->blockChain;
JSObject *obj = fp->maybeBlockChain();
JS_ASSERT_IF(obj,
OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj)
<= (size_t) (regs.sp - fp->base()));
for (obj = fp->scopeChain; obj; obj = obj->getParent()) {
for (obj = fp->maybeScopeChain(); obj; obj = obj->getParent()) {
Class *clasp = obj->getClass();
if (clasp != &js_BlockClass && clasp != &js_WithClass)
continue;
@ -2564,11 +2564,11 @@ BEGIN_CASE(JSOP_ENTERWITH)
* We set sp[-1] to the current "with" object to help asserting the
* enter/leave balance in [leavewith].
*/
regs.sp[-1].setObject(*fp->scopeChain);
regs.sp[-1].setObject(*fp->getScopeChain());
END_CASE(JSOP_ENTERWITH)
BEGIN_CASE(JSOP_LEAVEWITH)
JS_ASSERT(&regs.sp[-1].toObject() == fp->scopeChain);
JS_ASSERT(&regs.sp[-1].toObject() == fp->getScopeChain());
regs.sp--;
js_LeaveWith(cx);
END_CASE(JSOP_LEAVEWITH)
@ -2609,8 +2609,8 @@ BEGIN_CASE(JSOP_STOP)
if (inlineCallCount)
inline_return:
{
JS_ASSERT(!fp->blockChain);
JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
JS_ASSERT(!fp->hasBlockChain());
JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->getScopeChain(), 0));
void *hookData = fp->hookData;
if (JS_UNLIKELY(hookData != NULL)) {
@ -3136,7 +3136,7 @@ BEGIN_CASE(JSOP_BINDNAME)
* the rhs. We desire such resolve hook equivalence between the two
* forms.
*/
obj = fp->scopeChain;
obj = fp->getScopeChain();
if (!obj->getParent())
break;
@ -3150,7 +3150,7 @@ BEGIN_CASE(JSOP_BINDNAME)
}
jsid id = ATOM_TO_JSID(atom);
obj = js_FindIdentifierBase(cx, fp->scopeChain, id);
obj = js_FindIdentifierBase(cx, fp->getScopeChain(), id);
if (!obj)
goto error;
} while (0);
@ -3705,7 +3705,7 @@ BEGIN_CASE(JSOP_DECNAME)
BEGIN_CASE(JSOP_NAMEINC)
BEGIN_CASE(JSOP_NAMEDEC)
{
obj = fp->scopeChain;
obj = fp->getScopeChain();
JSObject *obj2;
PropertyCacheEntry *entry;
@ -4617,9 +4617,9 @@ BEGIN_CASE(JSOP_APPLY)
newfp->argv = vp + 2;
newfp->rval.setUndefined();
newfp->annotation = NULL;
newfp->scopeChain = obj->getParent();
newfp->setScopeChain(obj->getParent());
newfp->flags = flags;
newfp->blockChain = NULL;
newfp->setBlockChain(NULL);
JS_ASSERT(!JSFUN_BOUND_METHOD_TEST(fun->flags));
newfp->thisv = vp[1];
newfp->imacpc = NULL;
@ -4734,7 +4734,7 @@ END_CASE(JSOP_SETCALL)
BEGIN_CASE(JSOP_NAME)
BEGIN_CASE(JSOP_CALLNAME)
{
JSObject *obj = fp->scopeChain;
JSObject *obj = fp->getScopeChain();
JSScopeProperty *sprop;
Value rval;
@ -4874,7 +4874,7 @@ BEGIN_CASE(JSOP_REGEXP)
*/
jsatomid index = GET_FULL_INDEX(0);
JSObject *proto;
if (!js_GetClassPrototype(cx, fp->scopeChain, JSProto_RegExp, &proto))
if (!js_GetClassPrototype(cx, fp->getScopeChain(), JSProto_RegExp, &proto))
goto error;
JS_ASSERT(proto);
JSObject *obj = js_CloneRegExpObject(cx, script->getRegExp(index), proto);
@ -5393,7 +5393,7 @@ BEGIN_CASE(JSOP_DEFFUN)
* FIXME: bug 476950, although debugger users may also demand some kind
* of scope link for debugger-assisted eval-in-frame.
*/
obj2 = fp->scopeChain;
obj2 = fp->getScopeChain();
} else {
JS_ASSERT(!FUN_FLAT_CLOSURE(fun));
@ -5401,8 +5401,8 @@ BEGIN_CASE(JSOP_DEFFUN)
* Inline js_GetScopeChain a bit to optimize for the case of a
* top-level function.
*/
if (!fp->blockChain) {
obj2 = fp->scopeChain;
if (!fp->hasBlockChain()) {
obj2 = fp->getScopeChain();
} else {
obj2 = js_GetScopeChain(cx, fp);
if (!obj2)
@ -5431,7 +5431,7 @@ BEGIN_CASE(JSOP_DEFFUN)
* fp->scopeChain code below the parent->defineProperty call.
*/
MUST_FLOW_THROUGH("restore_scope");
fp->scopeChain = obj;
fp->setScopeChain(obj);
Value rval = ObjectValue(*obj);
@ -5501,7 +5501,7 @@ BEGIN_CASE(JSOP_DEFFUN)
restore_scope:
/* Restore fp->scopeChain now that obj is defined in fp->callobj. */
fp->scopeChain = obj2;
fp->setScopeChain(obj2);
if (!ok)
goto error;
}
@ -5556,7 +5556,7 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
JSObject *obj = FUN_OBJECT(fun);
if (FUN_NULL_CLOSURE(fun)) {
obj = CloneFunctionObject(cx, fun, fp->scopeChain);
obj = CloneFunctionObject(cx, fun, fp->getScopeChain());
if (!obj)
goto error;
} else {
@ -5623,7 +5623,7 @@ BEGIN_CASE(JSOP_LAMBDA)
do {
JSObject *parent;
if (FUN_NULL_CLOSURE(fun)) {
parent = fp->scopeChain;
parent = fp->getScopeChain();
if (obj->getParent() == parent) {
jsbytecode *pc2 = regs.pc + JSOP_LAMBDA_LENGTH;
@ -6624,7 +6624,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
regs.sp = vp;
#ifdef DEBUG
JS_ASSERT(fp->blockChain == obj->getParent());
JS_ASSERT(fp->maybeBlockChain() == obj->getParent());
/*
* The young end of fp->scopeChain may omit blocks if we haven't closed
@ -6633,7 +6633,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
* anything else we should have popped off fp->scopeChain when we left its
* static scope.
*/
JSObject *obj2 = fp->scopeChain;
JSObject *obj2 = fp->getScopeChain();
Class *clasp;
while ((clasp = obj2->getClass()) == &js_WithClass)
obj2 = obj2->getParent();
@ -6647,7 +6647,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK)
}
#endif
fp->blockChain = obj;
fp->setBlockChain(obj);
}
END_CASE(JSOP_ENTERBLOCK)
@ -6655,8 +6655,8 @@ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR)
BEGIN_CASE(JSOP_LEAVEBLOCK)
{
#ifdef DEBUG
JS_ASSERT(fp->blockChain->getClass() == &js_BlockClass);
uintN blockDepth = OBJ_BLOCK_DEPTH(cx, fp->blockChain);
JS_ASSERT(fp->getBlockChain()->getClass() == &js_BlockClass);
uintN blockDepth = OBJ_BLOCK_DEPTH(cx, fp->getBlockChain());
JS_ASSERT(blockDepth <= StackDepth(script));
#endif
@ -6665,15 +6665,15 @@ BEGIN_CASE(JSOP_LEAVEBLOCK)
* cloned onto fp->scopeChain, clear its private data, move its locals from
* the stack into the clone, and pop it off the chain.
*/
JSObject *obj = fp->scopeChain;
if (obj->getProto() == fp->blockChain) {
JSObject *obj = fp->getScopeChain();
if (obj->getProto() == fp->getBlockChain()) {
JS_ASSERT(obj->getClass() == &js_BlockClass);
if (!js_PutBlockObject(cx, JS_TRUE))
goto error;
}
/* Pop the block chain, too. */
fp->blockChain = fp->blockChain->getParent();
fp->setBlockChain(fp->getBlockChain()->getParent());
/* Move the result of the expression to the new topmost stack slot. */
Value *vp = NULL; /* silence GCC warnings */
@ -7006,8 +7006,8 @@ END_CASE(JSOP_ARRAYPUSH)
AbortRecording(cx, "recording out of Interpret");
#endif
JS_ASSERT_IF(!fp->isGenerator(), !fp->blockChain);
JS_ASSERT_IF(!fp->isGenerator(), !js_IsActiveWithOrBlock(cx, fp->scopeChain, 0));
JS_ASSERT_IF(!fp->isGenerator(), !fp->hasBlockChain());
JS_ASSERT_IF(!fp->isGenerator(), !js_IsActiveWithOrBlock(cx, fp->getScopeChain(), 0));
/* Undo the remaining effects committed on entry to Interpret. */
if (cx->version == currentVersion && currentVersion != originalVersion)

View File

@ -86,6 +86,8 @@ struct JSStackFrame
private:
JSObject *callobj; /* lazily created Call object */
JSObject *argsobj; /* lazily created arguments object */
JSObject *scopeChain; /* current scope chain */
JSObject *blockChain; /* current static block */
public:
jsbytecode *imacpc; /* null or interpreter macro call pc */
@ -105,45 +107,6 @@ struct JSStackFrame
static jsbytecode *const sInvalidPC;
#endif
/*
* We can't determine in advance which local variables can live on
* the stack and be freed when their dynamic scope ends, and which
* will be closed over and need to live in the heap. So we place
* variables on the stack initially, note when they are closed
* over, and copy those that are out to the heap when we leave
* their dynamic scope.
*
* The bytecode compiler produces a tree of block objects
* accompanying each JSScript representing those lexical blocks in
* the script that have let-bound variables associated with them.
* These block objects are never modified, and never become part
* of any function's scope chain. Their parent slots point to the
* innermost block that encloses them, or are NULL in the
* outermost blocks within a function or in eval or global code.
*
* When we are in the static scope of such a block, blockChain
* points to its compiler-allocated block object; otherwise, it is
* NULL.
*
* scopeChain is the current scope chain, including 'call' and
* 'block' objects for those function calls and lexical blocks
* whose static scope we are currently executing in, and 'with'
* objects for with statements; the chain is typically terminated
* by a global object. However, as an optimization, the young end
* of the chain omits block objects we have not yet cloned. To
* create a closure, we clone the missing blocks from blockChain
* (which is always current), place them at the head of
* scopeChain, and use that for the closure's scope chain. If we
* never close over a lexical block, we never place a mutable
* clone of it on scopeChain.
*
* This lazy cloning is implemented in js_GetScopeChain, which is
* also used in some other cases --- entering 'with' blocks, for
* example.
*/
JSObject *scopeChain;
JSObject *blockChain;
uint32 flags; /* frame flags -- see below */
/* Members only needed for inline calls. */
@ -217,6 +180,89 @@ struct JSStackFrame
return offsetof(JSStackFrame, argsobj);
}
/*
* We can't determine in advance which local variables can live on
* the stack and be freed when their dynamic scope ends, and which
* will be closed over and need to live in the heap. So we place
* variables on the stack initially, note when they are closed
* over, and copy those that are out to the heap when we leave
* their dynamic scope.
*
* The bytecode compiler produces a tree of block objects
* accompanying each JSScript representing those lexical blocks in
* the script that have let-bound variables associated with them.
* These block objects are never modified, and never become part
* of any function's scope chain. Their parent slots point to the
* innermost block that encloses them, or are NULL in the
* outermost blocks within a function or in eval or global code.
*
* When we are in the static scope of such a block, blockChain
* points to its compiler-allocated block object; otherwise, it is
* NULL.
*
* scopeChain is the current scope chain, including 'call' and
* 'block' objects for those function calls and lexical blocks
* whose static scope we are currently executing in, and 'with'
* objects for with statements; the chain is typically terminated
* by a global object. However, as an optimization, the young end
* of the chain omits block objects we have not yet cloned. To
* create a closure, we clone the missing blocks from blockChain
* (which is always current), place them at the head of
* scopeChain, and use that for the closure's scope chain. If we
* never close over a lexical block, we never place a mutable
* clone of it on scopeChain.
*
* This lazy cloning is implemented in js_GetScopeChain, which is
* also used in some other cases --- entering 'with' blocks, for
* example.
*/
/* Scope chain accessors */
bool hasScopeChain() const {
return scopeChain != NULL;
}
JSObject* getScopeChain() const {
JS_ASSERT(hasScopeChain());
return scopeChain;
}
JSObject* maybeScopeChain() const {
return scopeChain;
}
void setScopeChain(JSObject *obj) {
scopeChain = obj;
}
JSObject** addressScopeChain() {
return &scopeChain;
}
static size_t offsetScopeChain() {
return offsetof(JSStackFrame, scopeChain);
}
/* Block chain accessors */
bool hasBlockChain() const {
return blockChain != NULL;
}
JSObject* getBlockChain() const {
JS_ASSERT(hasBlockChain());
return blockChain;
}
JSObject* maybeBlockChain() const {
return blockChain;
}
void setBlockChain(JSObject *obj) {
blockChain = obj;
}
/* Other accessors */
void putActivationObjects(JSContext *cx) {

View File

@ -1144,9 +1144,9 @@ js_NewGenerator(JSContext *cx)
newfp->argv = vp + 2;
newfp->rval = fp->rval;
newfp->annotation = NULL;
newfp->scopeChain = fp->scopeChain;
JS_ASSERT(!fp->blockChain);
newfp->blockChain = NULL;
newfp->setScopeChain(fp->maybeScopeChain());
JS_ASSERT(!fp->hasBlockChain());
newfp->setBlockChain(NULL);
newfp->flags = fp->flags | JSFRAME_GENERATOR | JSFRAME_FLOATING_GENERATOR;
/* Copy in arguments and slots. */

View File

@ -2967,7 +2967,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
JS_STATIC_ASSERT(JS_INITIAL_NSLOTS == JSSLOT_BLOCK_DEPTH + 2);
JSStackFrame *const fp = cx->fp;
JSObject *obj = fp->scopeChain;
JSObject *obj = fp->getScopeChain();
JS_ASSERT(obj->getClass() == &js_BlockClass);
JS_ASSERT(obj->getPrivate() == js_FloatingFrameIfGenerator(cx, cx->fp));
JS_ASSERT(OBJ_IS_CLONED_BLOCK(obj));
@ -3001,7 +3001,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
/* We must clear the private slot even with errors. */
obj->setPrivate(NULL);
fp->scopeChain = obj->getParent();
fp->setScopeChain(obj->getParent());
return normalUnwind;
}
@ -3750,7 +3750,7 @@ js_FindClassObject(JSContext *cx, JSObject *start, JSProtoKey protoKey,
*/
VOUCH_DOES_NOT_REQUIRE_STACK();
if (!start && (fp = cx->fp) != NULL)
start = fp->scopeChain;
start = fp->maybeScopeChain();
if (start) {
/* Find the topmost object in the scope chain. */
@ -4469,7 +4469,7 @@ js_FindPropertyHelper(JSContext *cx, jsid id, JSBool cacheResult,
JSProperty *prop;
JS_ASSERT_IF(cacheResult, !JS_ON_TRACE(cx));
scopeChain = js_GetTopStackFrame(cx)->scopeChain;
scopeChain = js_GetTopStackFrame(cx)->getScopeChain();
/* Scan entries on the scope chain that we can cache across. */
entry = JS_NO_PROP_CACHE_FILL;
@ -5575,7 +5575,7 @@ js_GetClassPrototype(JSContext *cx, JSObject *scope, JSProtoKey protoKey,
if (protoKey != JSProto_Null) {
if (!scope) {
if (cx->fp)
scope = cx->fp->scopeChain;
scope = cx->fp->maybeScopeChain();
if (!scope) {
scope = cx->globalObject;
if (!scope) {
@ -6440,10 +6440,10 @@ js_DumpStackFrame(JSContext *cx, JSStackFrame *start)
fprintf(stderr, " overridden_args");
fputc('\n', stderr);
if (fp->scopeChain)
fprintf(stderr, " scopeChain: (JSObject *) %p\n", (void *) fp->scopeChain);
if (fp->blockChain)
fprintf(stderr, " blockChain: (JSObject *) %p\n", (void *) fp->blockChain);
if (fp->hasScopeChain())
fprintf(stderr, " scopeChain: (JSObject *) %p\n", (void *) fp->getScopeChain());
if (fp->hasBlockChain())
fprintf(stderr, " blockChain: (JSObject *) %p\n", (void *) fp->getBlockChain());
fputc('\n', stderr);
}

View File

@ -611,7 +611,7 @@ NewBuiltinClassInstance(JSContext *cx, Class *clasp)
if (!global)
return NULL;
} else {
global = cx->fp->scopeChain->getGlobal();
global = cx->fp->getScopeChain()->getGlobal();
}
JS_ASSERT(global->getClass()->flags & JSCLASS_IS_GLOBAL);

View File

@ -186,7 +186,7 @@ TraceRecorder::downSnapshot(FrameInfo* downFrame)
exit->numStackSlotsBelowCurrentFrame = cx->fp->down->argv ?
nativeStackOffset(&cx->fp->argv[-2]) / sizeof(double) : 0;
exit->exitType = UNSTABLE_LOOP_EXIT;
exit->block = cx->fp->down->blockChain;
exit->block = cx->fp->down->maybeBlockChain();
exit->pc = downFrame->pc + JSOP_CALL_LENGTH;
exit->imacpc = NULL;
exit->sp_adj = ((downPostSlots + 1) * sizeof(double)) - tree->nativeStackBase;
@ -596,7 +596,7 @@ TraceRecorder::slurpDownFrames(jsbytecode* return_pc)
/* argsobj */
slurpFrameObjPtrSlot(fp_ins, JSStackFrame::offsetArgsObj(), fp->addressArgsObj(), &info);
/* scopeChain */
slurpFrameObjPtrSlot(fp_ins, offsetof(JSStackFrame, scopeChain), &fp->scopeChain, &info);
slurpFrameObjPtrSlot(fp_ins, JSStackFrame::offsetScopeChain(), fp->addressScopeChain(), &info);
/* vars */
LIns* slots_ins = addName(lir->ins2(LIR_addp, fp_ins, INS_CONSTWORD(sizeof(JSStackFrame))),
"slots");

View File

@ -1201,7 +1201,7 @@ GlobalSlotHash(JSContext* cx, unsigned slot)
fp = fp->down;
HashAccum(h, uintptr_t(fp->script), ORACLE_MASK);
HashAccum(h, uintptr_t(fp->scopeChain->getGlobal()->shape()), ORACLE_MASK);
HashAccum(h, uintptr_t(fp->getScopeChain()->getGlobal()->shape()), ORACLE_MASK);
HashAccum(h, uintptr_t(slot), ORACLE_MASK);
return int(h);
}
@ -1821,7 +1821,7 @@ VisitFrameSlots(Visitor &visitor, JSContext *cx, unsigned depth,
// requires type |Value|. But the bits are the same, so we can import
// it with a cast and the (identity function) unboxing will be OK.
visitor.setStackSlotKind("scopeChain");
if (!visitor.visitFrameObjPtr(&fp->scopeChain, fp))
if (!visitor.visitFrameObjPtr(fp->addressScopeChain(), fp))
return false;
visitor.setStackSlotKind("var");
if (!visitor.visitStackSlots(fp->slots(), fp->script->nfixed, fp))
@ -1873,7 +1873,7 @@ template <typename Visitor>
static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitGlobalSlots(Visitor &visitor, JSContext *cx, SlotList &gslots)
{
VisitGlobalSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
VisitGlobalSlots(visitor, cx, cx->fp->getScopeChain()->getGlobal(),
gslots.length(), gslots.data());
}
@ -1892,7 +1892,7 @@ static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitSlots(Visitor& visitor, JSContext* cx, unsigned callDepth,
unsigned ngslots, uint16* gslots)
{
VisitSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
VisitSlots(visitor, cx, cx->fp->getScopeChain()->getGlobal(),
callDepth, ngslots, gslots);
}
@ -1910,7 +1910,7 @@ static JS_REQUIRES_STACK JS_ALWAYS_INLINE void
VisitSlots(Visitor &visitor, JSContext *cx, unsigned callDepth,
const SlotList& slots)
{
VisitSlots(visitor, cx, cx->fp->scopeChain->getGlobal(),
VisitSlots(visitor, cx, cx->fp->getScopeChain()->getGlobal(),
callDepth, slots.length(), slots.data());
}
@ -2224,7 +2224,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
globalObj(tree->globalObj),
outer(outer),
outerArgc(outerArgc),
lexicalBlock(cx->fp->blockChain),
lexicalBlock(cx->fp->maybeBlockChain()),
anchor(anchor),
lir(NULL),
cx_ins(NULL),
@ -2255,7 +2255,7 @@ TraceRecorder::TraceRecorder(JSContext* cx, VMSideExit* anchor, VMFragment* frag
generatedSpecializedNative(),
tempTypeMap(cx)
{
JS_ASSERT(globalObj == cx->fp->scopeChain->getGlobal());
JS_ASSERT(globalObj == cx->fp->getScopeChain()->getGlobal());
JS_ASSERT(globalObj->scope()->hasOwnShape());
JS_ASSERT(cx->regs->pc == (jsbytecode*)fragment->ip);
@ -3461,15 +3461,15 @@ FlushNativeStackFrame(JSContext* cx, unsigned callDepth, const JSValueType* mp,
// Iff these fields are NULL, then |fp| was synthesized on trace exit, so
// we need to update the frame fields.
if (!fp->hasCallObj())
fp->setCallObj(fp->scopeChain);
fp->setCallObj(fp->getScopeChain());
// Iff scope chain's private is NULL, then |fp->scopeChain| was created
// on trace for a call, so we set the private field now. (Call objects
// that correspond to returned frames also have a NULL private, but such
// a call object would not occur as the |scopeChain| member of a frame,
// so we cannot be in that case here.)
if (!fp->scopeChain->getPrivate())
fp->scopeChain->setPrivate(fp);
if (!fp->getScopeChain()->getPrivate())
fp->getScopeChain()->setPrivate(fp);
}
fp->thisv = fp->argv[-1];
if (fp->flags & JSFRAME_CONSTRUCTING) // constructors always compute 'this'
@ -3863,7 +3863,7 @@ TraceRecorder::isValidFrameObjPtr(JSObject **p)
{
JSStackFrame *fp = cx->fp;
for (; fp; fp = fp->down) {
if (&fp->scopeChain == p || fp->addressArgsObj() == p)
if (fp->addressScopeChain() == p || fp->addressArgsObj() == p)
return true;
}
return false;
@ -4273,9 +4273,9 @@ TraceRecorder::snapshot(ExitType exitType)
nativeStackOffset(&cx->fp->argv[-2]) / sizeof(double) :
0;
exit->exitType = exitType;
exit->block = fp->blockChain;
if (fp->blockChain)
tree->gcthings.addUnique(ObjectValue(*fp->blockChain));
exit->block = fp->maybeBlockChain();
if (fp->hasBlockChain())
tree->gcthings.addUnique(ObjectValue(*fp->getBlockChain()));
exit->pc = pc;
exit->imacpc = fp->imacpc;
exit->sp_adj = (stackSlots * sizeof(double)) - tree->nativeStackBase;
@ -5671,14 +5671,7 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee)
cx->regs->sp = sp;
cx->regs->pc = fi.pc;
fp->imacpc = fi.imacpc;
fp->blockChain = fi.block;
fp->blockChain = fi.block;
#ifdef DEBUG
if (fi.block != fp->blockChain) {
for (JSObject* obj = fi.block; obj != fp->blockChain; obj = obj->getParent())
JS_ASSERT(obj);
}
#endif
fp->setBlockChain(fi.block);
/*
* Get pointer to new frame/slots, without changing global state.
@ -5716,9 +5709,9 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee)
#endif
newfp->rval = UndefinedValue();
newfp->annotation = NULL;
newfp->scopeChain = NULL; // will be updated in FlushNativeStackFrame
newfp->setScopeChain(NULL); // will be updated in FlushNativeStackFrame
newfp->flags = fi.is_constructing() ? JSFRAME_CONSTRUCTING : 0;
newfp->blockChain = NULL;
newfp->setBlockChain(NULL);
newfp->thisv.setNull(); // will be updated in FlushNativeStackFrame
newfp->imacpc = NULL;
@ -5788,9 +5781,8 @@ SynthesizeSlowNativeFrame(TracerState& state, JSContext *cx, VMSideExit *exit)
fp->fun = GET_FUNCTION_PRIVATE(cx, fp->callee());
fp->rval = UndefinedValue();
fp->annotation = NULL;
JS_ASSERT(cx->fp->scopeChain);
fp->scopeChain = cx->fp->scopeChain;
fp->blockChain = NULL;
fp->setScopeChain(cx->fp->maybeScopeChain());
fp->setBlockChain(NULL);
fp->flags = exit->constructing() ? JSFRAME_CONSTRUCTING : 0;
state.bailedSlowNativeRegs = *cx->regs;
@ -6157,7 +6149,7 @@ TraceRecorder::recordLoopEdge(JSContext* cx, TraceRecorder* r, uintN& inlineCall
* Make sure the shape of the global object still matches (this might flush
* the JIT cache).
*/
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
JSObject* globalObj = cx->fp->getScopeChain()->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
if (!CheckGlobalObjectShape(cx, tm, globalObj, &globalShape, &globalSlots)) {
@ -6663,7 +6655,7 @@ ExecuteTrace(JSContext* cx, Fragment* f, TracerState& state)
static JS_REQUIRES_STACK JS_ALWAYS_INLINE bool
ScopeChainCheck(JSContext* cx, TreeFragment* f)
{
JS_ASSERT(f->globalObj == cx->fp->scopeChain->getGlobal());
JS_ASSERT(f->globalObj == cx->fp->getScopeChain()->getGlobal());
/*
* The JIT records and expects to execute with two scope-chain
@ -6681,7 +6673,7 @@ ScopeChainCheck(JSContext* cx, TreeFragment* f)
* class types; once a global is found, it's checked for #1. Failing
* either check causes an early return from execution.
*/
JSObject* child = cx->fp->scopeChain;
JSObject* child = cx->fp->getScopeChain();
while (JSObject* parent = child->getParent()) {
if (!js_IsCacheableNonGlobalScope(child)) {
debug_only_print0(LC_TMTracer,"Blacklist: non-cacheable object on scope chain.\n");
@ -7020,7 +7012,7 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr)
*/
JSStackFrame* const fp = cx->fp;
fp->blockChain = innermost->block;
fp->setBlockChain(innermost->block);
/*
* If we are not exiting from an inlined frame, the state->sp is spbase.
@ -7170,7 +7162,7 @@ MonitorLoopEdge(JSContext* cx, uintN& inlineCallCount, RecordReason reason)
* Make sure the shape of the global object still matches (this might flush
* the JIT cache).
*/
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
JSObject* globalObj = cx->fp->getScopeChain()->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
@ -8086,7 +8078,7 @@ JS_REQUIRES_STACK LIns*
TraceRecorder::scopeChain()
{
return cx->fp->callee()
? getFrameObjPtr(&cx->fp->scopeChain)
? getFrameObjPtr(cx->fp->addressScopeChain())
: entryScopeChain();
}
@ -8100,7 +8092,7 @@ TraceRecorder::entryScopeChain() const
{
return lir->insLoad(LIR_ldp,
lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp), ACCSET_OTHER),
offsetof(JSStackFrame, scopeChain), ACCSET_OTHER);
JSStackFrame::offsetScopeChain(), ACCSET_OTHER);
}
/*
@ -8142,7 +8134,7 @@ JS_DEFINE_CALLINFO_4(extern, UINT32, GetClosureArg, CONTEXT, OBJECT, CVIPTR, DOU
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::scopeChainProp(JSObject* chainHead, Value*& vp, LIns*& ins, NameResult& nr)
{
JS_ASSERT(chainHead == cx->fp->scopeChain);
JS_ASSERT(chainHead == cx->fp->getScopeChain());
JS_ASSERT(chainHead != globalObj);
TraceMonitor &localtm = *traceMonitor;
@ -10241,7 +10233,7 @@ TraceRecorder::clearFrameSlotsFromTracker(Tracker& which, JSStackFrame* fp, unsi
while (vp < vpstop)
which.set(vp++, (LIns*)0);
which.set(fp->addressArgsObj(), (LIns*)0);
which.set(&fp->scopeChain, (LIns*)0);
which.set(fp->addressScopeChain(), (LIns*)0);
}
vp = &fp->slots()[0];
vpstop = &fp->slots()[nslots];
@ -10320,7 +10312,7 @@ TraceRecorder::putActivationObjects()
slots_ins = INS_CONSTPTR(0);
}
LIns* scopeChain_ins = getFrameObjPtr(&cx->fp->scopeChain);
LIns* scopeChain_ins = getFrameObjPtr(cx->fp->addressScopeChain());
LIns* args[] = { slots_ins, INS_CONST(nslots), args_ins,
INS_CONST(cx->fp->fun->nargs), scopeChain_ins, cx_ins };
lir->insCall(&js_PutCallObjectOnTrace_ci, args);
@ -10344,7 +10336,7 @@ IsTraceableRecursion(JSContext *cx)
return false;
if ((fp->flags & JSFRAME_CONSTRUCTING) || (down->flags & JSFRAME_CONSTRUCTING))
return false;
if (fp->blockChain || down->blockChain)
if (fp->hasBlockChain() || down->hasBlockChain())
return false;
if (*fp->script->code != JSOP_TRACE)
return false;
@ -10392,7 +10384,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount)
nativeFrameTracker.set(fp->addressArgsObj(), NULL);
setFrameObjPtr(fp->addressArgsObj(), INS_NULL());
nativeFrameTracker.set(&fp->scopeChain, NULL);
nativeFrameTracker.set(fp->addressScopeChain(), NULL);
vp = fp->slots();
vpstop = vp + fp->script->nfixed;
@ -10412,7 +10404,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount)
if (cx->fp->fun && JSFUN_HEAVYWEIGHT_TEST(cx->fp->fun->flags)) {
// We need to make sure every part of the frame is known to the tracker
// before taking a snapshot.
setFrameObjPtr(&fp->scopeChain, INS_NULL());
setFrameObjPtr(fp->addressScopeChain(), INS_NULL());
if (js_IsNamedLambda(cx->fp->fun))
RETURN_STOP_A("can't call named lambda heavyweight on trace");
@ -10423,9 +10415,9 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount)
LIns* call_ins = lir->insCall(&js_CreateCallObjectOnTrace_ci, args);
guard(false, lir->insEqP_0(call_ins), snapshot(OOM_EXIT));
setFrameObjPtr(&fp->scopeChain, call_ins);
setFrameObjPtr(fp->addressScopeChain(), call_ins);
} else {
setFrameObjPtr(&fp->scopeChain, scopeChain_ins);
setFrameObjPtr(fp->addressScopeChain(), scopeChain_ins);
}
/*
@ -10481,7 +10473,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount)
* Make sure the shape of the global object still matches (this might
* flush the JIT cache).
*/
JSObject* globalObj = cx->fp->scopeChain->getGlobal();
JSObject* globalObj = cx->fp->getScopeChain()->getGlobal();
uint32 globalShape = -1;
SlotList* globalSlots = NULL;
if (!CheckGlobalObjectShape(cx, traceMonitor, globalObj, &globalShape, &globalSlots))
@ -13082,7 +13074,7 @@ TraceRecorder::record_JSOP_SETELEM()
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_CALLNAME()
{
JSObject* obj = cx->fp->scopeChain;
JSObject* obj = cx->fp->getScopeChain();
if (obj != globalObj) {
Value* vp;
LIns* ins;
@ -13378,9 +13370,9 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc,
JS_ASSERT(argc < FrameInfo::CONSTRUCTING_FLAG);
tree->gcthings.addUnique(fval);
fi->block = fp->blockChain;
if (fp->blockChain)
tree->gcthings.addUnique(ObjectValue(*fp->blockChain));
fi->block = fp->maybeBlockChain();
if (fp->hasBlockChain())
tree->gcthings.addUnique(ObjectValue(*fp->getBlockChain()));
fi->pc = cx->regs->pc;
fi->imacpc = fp->imacpc;
fi->spdist = cx->regs->sp - fp->slots();
@ -13624,7 +13616,7 @@ TraceRecorder::record_NativeCallComplete()
JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr)
{
JSObject* obj = cx->fp->scopeChain;
JSObject* obj = cx->fp->getScopeChain();
if (obj != globalObj)
return scopeChainProp(obj, vp, ins, nr);
@ -14726,7 +14718,7 @@ TraceRecorder::record_JSOP_BINDNAME()
JSObject *obj;
if (!fp->fun) {
obj = fp->scopeChain;
obj = fp->getScopeChain();
#ifdef DEBUG
JSStackFrame *fp2 = fp;
@ -14787,7 +14779,7 @@ TraceRecorder::record_JSOP_BINDNAME()
JSAtom *atom = atoms[GET_INDEX(cx->regs->pc)];
jsid id = ATOM_TO_JSID(atom);
JSContext *localCx = cx;
JSObject *obj2 = js_FindIdentifierBase(cx, fp->scopeChain, id);
JSObject *obj2 = js_FindIdentifierBase(cx, fp->getScopeChain(), id);
if (!obj2)
RETURN_ERROR_A("error in js_FindIdentifierBase");
if (!TRACE_RECORDER(localCx))
@ -15854,7 +15846,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_LEAVEBLOCK()
{
/* We mustn't exit the lexical block we began recording in. */
if (cx->fp->blockChain == lexicalBlock)
if (cx->fp->getBlockChain() == lexicalBlock)
return ARECORD_STOP;
return ARECORD_CONTINUE;
}

View File

@ -381,7 +381,7 @@ JSCompartment::wrap(JSContext *cx, Value *vp)
* we parent all wrappers to the global object in their home compartment.
* This loses us some transparency, and is generally very cheesy.
*/
JSObject *global = cx->fp ? cx->fp->scopeChain->getGlobal() : cx->globalObject;
JSObject *global = cx->fp ? cx->fp->getScopeChain()->getGlobal() : cx->globalObject;
wrapper->setParent(global);
return true;
}
@ -489,7 +489,7 @@ SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs &regs, JSObj
JSStackFrame *fp = frame.getFrame();
PodZero(fp); // fp->fun and fp->script are both NULL
fp->argv = vp + 2;
fp->scopeChain = obj->getGlobal();
fp->setScopeChain(obj->getGlobal());
fp->flags = JSFRAME_DUMMY;
regs.pc = NULL;

View File

@ -1735,7 +1735,7 @@ ParseXMLSource(JSContext *cx, JSString *src)
{
Parser parser(cx);
if (parser.init(chars, length, NULL, filename, lineno)) {
JSObject *scopeChain = js_GetTopStackFrame(cx)->scopeChain;
JSObject *scopeChain = js_GetTopStackFrame(cx)->getScopeChain();
JSParseNode *pn = parser.parseXMLText(scopeChain, false);
uintN flags;
if (pn && GetXMLSettingFlags(cx, &flags)) {
@ -7227,7 +7227,7 @@ js_GetDefaultXMLNamespace(JSContext *cx, jsval *vp)
fp = js_GetTopStackFrame(cx);
obj = NULL;
for (tmp = fp->scopeChain; tmp; tmp = tmp->getParent()) {
for (tmp = fp->getScopeChain(); tmp; tmp = tmp->getParent()) {
Class *clasp = tmp->getClass();
if (clasp == &js_BlockClass || clasp == &js_WithClass)
continue;
@ -7440,7 +7440,7 @@ js_FindXMLProperty(JSContext *cx, const Value &nameval, JSObject **objp, jsid *i
if (!IsFunctionQName(cx, qn, &funid))
return JS_FALSE;
obj = js_GetTopStackFrame(cx)->scopeChain;
obj = js_GetTopStackFrame(cx)->getScopeChain();
do {
/* Skip any With object that can wrap XML. */
target = obj;