From ea02e5caf2cf75d6b4192d8f3c20379b821422fc Mon Sep 17 00:00:00 2001 From: Robert Sayre Date: Thu, 12 Aug 2010 21:47:46 -0700 Subject: [PATCH] =?UTF-8?q?Backed=20out=20changeset=201406935fced4.=20Bria?= =?UTF-8?q?n=20Hackett=20=E2=80=93=20Put=20JSStackFrame.scopeChain/blockCh?= =?UTF-8?q?ain=20behind=20an=20interface,=20bug=20586533.=20r=3Dlw.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- js/src/jsapi.cpp | 2 +- js/src/jsbuiltins.cpp | 2 +- js/src/jsdbgapi.cpp | 6 +- js/src/jsfun.cpp | 18 +++--- js/src/jsgc.cpp | 4 +- js/src/jsinterp.cpp | 108 +++++++++++++++++------------------ js/src/jsinterp.h | 124 +++++++++++++---------------------------- js/src/jsiter.cpp | 6 +- js/src/jsobj.cpp | 18 +++--- js/src/jsobjinlines.h | 2 +- js/src/jsrecursion.cpp | 4 +- js/src/jstracer.cpp | 94 +++++++++++++++++-------------- js/src/jswrapper.cpp | 4 +- js/src/jsxml.cpp | 6 +- 14 files changed, 180 insertions(+), 218 deletions(-) diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index 73f767aab47..5aeb9c260ad 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -1823,7 +1823,7 @@ JS_GetGlobalForScopeChain(JSContext *cx) VOUCH_DOES_NOT_REQUIRE_STACK(); if (cx->fp) - return cx->fp->getScopeChain()->getGlobal(); + return cx->fp->scopeChain->getGlobal(); JSObject *scope = cx->globalObject; if (!scope) { diff --git a/js/src/jsbuiltins.cpp b/js/src/jsbuiltins.cpp index d4534be6703..4406b582856 100644 --- a/js/src/jsbuiltins.cpp +++ b/js/src/jsbuiltins.cpp @@ -351,7 +351,7 @@ js_PopInterpFrame(JSContext* cx, TracerState* state) return JS_FALSE; if (fp->imacpc) return JS_FALSE; - if (fp->hasBlockChain()) + if (fp->blockChain) return JS_FALSE; fp->putActivationObjects(cx); diff --git a/js/src/jsdbgapi.cpp b/js/src/jsdbgapi.cpp index 2e0b9e9230a..582022a20bc 100644 --- a/js/src/jsdbgapi.cpp +++ b/js/src/jsdbgapi.cpp @@ -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->setScopeChain(closure->getParent()); + fp->scopeChain = 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->maybeScopeChain(); + return fp->scopeChain; } JS_PUBLIC_API(JSObject *) @@ -1564,7 +1564,7 @@ SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs ®s, JSObj PodZero(fp); fp->fun = fun; fp->argv = vp + 2; - fp->setScopeChain(scopeobj->getGlobal()); + fp->scopeChain = scopeobj->getGlobal(); regs.pc = NULL; regs.sp = fp->slots(); diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index 16d3455cbb1..f22cf241bf3 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -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->getScopeChain()->getGlobal(); + JSObject *global = fp->scopeChain->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->maybeScopeChain(), PrivateValue(fp)); + envobj->init(&js_DeclEnvClass, NULL, fp->scopeChain, 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->getScopeChain()->getClass(); + Class *classp = fp->scopeChain->getClass(); if (classp == &js_WithClass || classp == &js_BlockClass) - JS_ASSERT(fp->getScopeChain()->getPrivate() != js_FloatingFrameIfGenerator(cx, fp)); + JS_ASSERT(fp->scopeChain->getPrivate() != js_FloatingFrameIfGenerator(cx, fp)); else if (classp == &js_CallClass) - JS_ASSERT(fp->getScopeChain()->getPrivate() != fp); + JS_ASSERT(fp->scopeChain->getPrivate() != fp); #endif /* @@ -798,9 +798,9 @@ js_GetCallObject(JSContext *cx, JSStackFrame *fp) return NULL; /* Root envobj before js_DefineNativeProperty (-> JSClass.addProperty). */ - fp->setScopeChain(envobj); + fp->scopeChain = envobj; JS_ASSERT(fp->argv); - if (!js_DefineNativeProperty(cx, fp->getScopeChain(), ATOM_TO_JSID(lambdaName), + if (!js_DefineNativeProperty(cx, fp->scopeChain, 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->getScopeChain()); + JSObject *callobj = NewCallObject(cx, fp->fun, fp->scopeChain); 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->setScopeChain(callobj); + fp->scopeChain = callobj; return callobj; } diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 8afa612ed4b..dfde3072b60 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -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->hasScopeChain()) - JS_CALL_OBJECT_TRACER(trc, fp->getScopeChain(), "scope chain"); + if (fp->scopeChain) + JS_CALL_OBJECT_TRACER(trc, fp->scopeChain, "scope chain"); } void diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 7f9d6f933ae..3ee7c3ce1bc 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -103,7 +103,7 @@ jsbytecode *const JSStackFrame::sInvalidPC = (jsbytecode *)0xbeef; JSObject * js_GetScopeChain(JSContext *cx, JSStackFrame *fp) { - JSObject *sharedBlock = fp->maybeBlockChain(); + JSObject *sharedBlock = fp->blockChain; 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->hasScopeChain()); - return fp->getScopeChain(); + JS_ASSERT(fp->scopeChain); + return fp->scopeChain; } /* 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->getScopeChain()->getClass() == &js_BlockClass, - fp->getScopeChain()->getPrivate() != js_FloatingFrameIfGenerator(cx, fp)); + JS_ASSERT_IF(fp->scopeChain->getClass() == &js_BlockClass, + fp->scopeChain->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->getScopeChain(); + limitClone = fp->scopeChain; 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->getScopeChain(); + return fp->scopeChain; } /* @@ -206,7 +206,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) newChild->setParent(clone); newChild = clone; } - newChild->setParent(fp->getScopeChain()); + newChild->setParent(fp->scopeChain); /* @@ -219,7 +219,7 @@ js_GetScopeChain(JSContext *cx, JSStackFrame *fp) sharedBlock); /* Place our newly cloned blocks at the head of the scope chain. */ - fp->setScopeChain(innermostNewChild); + fp->scopeChain = 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->setScopeChain(NULL); - fp->setBlockChain(NULL); + fp->scopeChain = NULL; + fp->blockChain = 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->setScopeChain(down->maybeScopeChain()); + fp->scopeChain = down->scopeChain; /* Ensure that we have a scope chain. */ - if (!fp->hasScopeChain()) - fp->setScopeChain(parent); + if (!fp->scopeChain) + fp->scopeChain = parent; } else { /* Use parent scope so js_GetCallObject can find the right "Call". */ - fp->setScopeChain(parent); + fp->scopeChain = 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->setScopeChain(chain); + fp->scopeChain = 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->setScopeChain(innerizedChain); + fp->scopeChain = 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->setBlockChain(NULL); + fp->blockChain = NULL; /* Initialize regs. */ regs.pc = script->code; @@ -1245,7 +1245,7 @@ js_EnterWith(JSContext *cx, jsint stackIndex) if (!withobj) return JS_FALSE; - fp->setScopeChain(withobj); + fp->scopeChain = withobj; return JS_TRUE; } @@ -1254,11 +1254,11 @@ js_LeaveWith(JSContext *cx) { JSObject *withobj; - withobj = cx->fp->getScopeChain(); + withobj = cx->fp->scopeChain; 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->setScopeChain(withobj->getParent()); + cx->fp->scopeChain = 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->maybeBlockChain(); obj; obj = obj->getParent()) { + for (obj = fp->blockChain; obj; obj = obj->getParent()) { JS_ASSERT(obj->getClass() == &js_BlockClass); if (OBJ_BLOCK_DEPTH(cx, obj) < stackDepth) break; } - fp->setBlockChain(obj); + fp->blockChain = obj; for (;;) { - obj = fp->getScopeChain(); + obj = fp->scopeChain; 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->maybeBlockChain(); + JSObject *obj = fp->blockChain; JS_ASSERT_IF(obj, OBJ_BLOCK_DEPTH(cx, obj) + OBJ_BLOCK_COUNT(cx, obj) <= (size_t) (regs.sp - fp->base())); - for (obj = fp->maybeScopeChain(); obj; obj = obj->getParent()) { + for (obj = fp->scopeChain; 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->getScopeChain()); + regs.sp[-1].setObject(*fp->scopeChain); END_CASE(JSOP_ENTERWITH) BEGIN_CASE(JSOP_LEAVEWITH) - JS_ASSERT(®s.sp[-1].toObject() == fp->getScopeChain()); + JS_ASSERT(®s.sp[-1].toObject() == fp->scopeChain); regs.sp--; js_LeaveWith(cx); END_CASE(JSOP_LEAVEWITH) @@ -2609,8 +2609,8 @@ BEGIN_CASE(JSOP_STOP) if (inlineCallCount) inline_return: { - JS_ASSERT(!fp->hasBlockChain()); - JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->getScopeChain(), 0)); + JS_ASSERT(!fp->blockChain); + JS_ASSERT(!js_IsActiveWithOrBlock(cx, fp->scopeChain, 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->getScopeChain(); + obj = fp->scopeChain; if (!obj->getParent()) break; @@ -3150,7 +3150,7 @@ BEGIN_CASE(JSOP_BINDNAME) } jsid id = ATOM_TO_JSID(atom); - obj = js_FindIdentifierBase(cx, fp->getScopeChain(), id); + obj = js_FindIdentifierBase(cx, fp->scopeChain, 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->getScopeChain(); + obj = fp->scopeChain; JSObject *obj2; PropertyCacheEntry *entry; @@ -4617,9 +4617,9 @@ BEGIN_CASE(JSOP_APPLY) newfp->argv = vp + 2; newfp->rval.setUndefined(); newfp->annotation = NULL; - newfp->setScopeChain(obj->getParent()); + newfp->scopeChain = obj->getParent(); newfp->flags = flags; - newfp->setBlockChain(NULL); + newfp->blockChain = 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->getScopeChain(); + JSObject *obj = fp->scopeChain; 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->getScopeChain(), JSProto_RegExp, &proto)) + if (!js_GetClassPrototype(cx, fp->scopeChain, 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->getScopeChain(); + obj2 = fp->scopeChain; } 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->hasBlockChain()) { - obj2 = fp->getScopeChain(); + if (!fp->blockChain) { + obj2 = fp->scopeChain; } 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->setScopeChain(obj); + fp->scopeChain = 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->setScopeChain(obj2); + fp->scopeChain = 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->getScopeChain()); + obj = CloneFunctionObject(cx, fun, fp->scopeChain); if (!obj) goto error; } else { @@ -5623,7 +5623,7 @@ BEGIN_CASE(JSOP_LAMBDA) do { JSObject *parent; if (FUN_NULL_CLOSURE(fun)) { - parent = fp->getScopeChain(); + parent = fp->scopeChain; 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->maybeBlockChain() == obj->getParent()); + JS_ASSERT(fp->blockChain == 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->getScopeChain(); + JSObject *obj2 = fp->scopeChain; Class *clasp; while ((clasp = obj2->getClass()) == &js_WithClass) obj2 = obj2->getParent(); @@ -6647,7 +6647,7 @@ BEGIN_CASE(JSOP_ENTERBLOCK) } #endif - fp->setBlockChain(obj); + fp->blockChain = obj; } END_CASE(JSOP_ENTERBLOCK) @@ -6655,8 +6655,8 @@ BEGIN_CASE(JSOP_LEAVEBLOCKEXPR) BEGIN_CASE(JSOP_LEAVEBLOCK) { #ifdef DEBUG - JS_ASSERT(fp->getBlockChain()->getClass() == &js_BlockClass); - uintN blockDepth = OBJ_BLOCK_DEPTH(cx, fp->getBlockChain()); + JS_ASSERT(fp->blockChain->getClass() == &js_BlockClass); + uintN blockDepth = OBJ_BLOCK_DEPTH(cx, fp->blockChain); 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->getScopeChain(); - if (obj->getProto() == fp->getBlockChain()) { + JSObject *obj = fp->scopeChain; + if (obj->getProto() == fp->blockChain) { JS_ASSERT(obj->getClass() == &js_BlockClass); if (!js_PutBlockObject(cx, JS_TRUE)) goto error; } /* Pop the block chain, too. */ - fp->setBlockChain(fp->getBlockChain()->getParent()); + fp->blockChain = fp->blockChain->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->hasBlockChain()); - JS_ASSERT_IF(!fp->isGenerator(), !js_IsActiveWithOrBlock(cx, fp->getScopeChain(), 0)); + JS_ASSERT_IF(!fp->isGenerator(), !fp->blockChain); + JS_ASSERT_IF(!fp->isGenerator(), !js_IsActiveWithOrBlock(cx, fp->scopeChain, 0)); /* Undo the remaining effects committed on entry to Interpret. */ if (cx->version == currentVersion && currentVersion != originalVersion) diff --git a/js/src/jsinterp.h b/js/src/jsinterp.h index f77995c5486..3f79ca30cb2 100644 --- a/js/src/jsinterp.h +++ b/js/src/jsinterp.h @@ -86,8 +86,6 @@ 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 */ @@ -107,6 +105,45 @@ 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. */ @@ -180,89 +217,6 @@ 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) { diff --git a/js/src/jsiter.cpp b/js/src/jsiter.cpp index 8d8df525daf..2f6ffecc6e4 100644 --- a/js/src/jsiter.cpp +++ b/js/src/jsiter.cpp @@ -1144,9 +1144,9 @@ js_NewGenerator(JSContext *cx) newfp->argv = vp + 2; newfp->rval = fp->rval; newfp->annotation = NULL; - newfp->setScopeChain(fp->maybeScopeChain()); - JS_ASSERT(!fp->hasBlockChain()); - newfp->setBlockChain(NULL); + newfp->scopeChain = fp->scopeChain; + JS_ASSERT(!fp->blockChain); + newfp->blockChain = NULL; newfp->flags = fp->flags | JSFRAME_GENERATOR | JSFRAME_FLOATING_GENERATOR; /* Copy in arguments and slots. */ diff --git a/js/src/jsobj.cpp b/js/src/jsobj.cpp index d5972267e2f..a014a2438b6 100644 --- a/js/src/jsobj.cpp +++ b/js/src/jsobj.cpp @@ -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->getScopeChain(); + JSObject *obj = fp->scopeChain; 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->setScopeChain(obj->getParent()); + fp->scopeChain = 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->maybeScopeChain(); + start = fp->scopeChain; 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)->getScopeChain(); + scopeChain = js_GetTopStackFrame(cx)->scopeChain; /* 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->maybeScopeChain(); + scope = cx->fp->scopeChain; 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->hasScopeChain()) - fprintf(stderr, " scopeChain: (JSObject *) %p\n", (void *) fp->getScopeChain()); - if (fp->hasBlockChain()) - fprintf(stderr, " blockChain: (JSObject *) %p\n", (void *) fp->getBlockChain()); + if (fp->scopeChain) + fprintf(stderr, " scopeChain: (JSObject *) %p\n", (void *) fp->scopeChain); + if (fp->blockChain) + fprintf(stderr, " blockChain: (JSObject *) %p\n", (void *) fp->blockChain); fputc('\n', stderr); } diff --git a/js/src/jsobjinlines.h b/js/src/jsobjinlines.h index 7b91853ae21..1ee9854e79b 100644 --- a/js/src/jsobjinlines.h +++ b/js/src/jsobjinlines.h @@ -611,7 +611,7 @@ NewBuiltinClassInstance(JSContext *cx, Class *clasp) if (!global) return NULL; } else { - global = cx->fp->getScopeChain()->getGlobal(); + global = cx->fp->scopeChain->getGlobal(); } JS_ASSERT(global->getClass()->flags & JSCLASS_IS_GLOBAL); diff --git a/js/src/jsrecursion.cpp b/js/src/jsrecursion.cpp index 09f9830921c..e7bd1415f46 100644 --- a/js/src/jsrecursion.cpp +++ b/js/src/jsrecursion.cpp @@ -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->maybeBlockChain(); + exit->block = cx->fp->down->blockChain; 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, JSStackFrame::offsetScopeChain(), fp->addressScopeChain(), &info); + slurpFrameObjPtrSlot(fp_ins, offsetof(JSStackFrame, scopeChain), &fp->scopeChain, &info); /* vars */ LIns* slots_ins = addName(lir->ins2(LIR_addp, fp_ins, INS_CONSTWORD(sizeof(JSStackFrame))), "slots"); diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index b4783c17152..b00d3a4c634 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -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->getScopeChain()->getGlobal()->shape()), ORACLE_MASK); + HashAccum(h, uintptr_t(fp->scopeChain->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->addressScopeChain(), fp)) + if (!visitor.visitFrameObjPtr(&fp->scopeChain, fp)) return false; visitor.setStackSlotKind("var"); if (!visitor.visitStackSlots(fp->slots(), fp->script->nfixed, fp)) @@ -1873,7 +1873,7 @@ template static JS_REQUIRES_STACK JS_ALWAYS_INLINE void VisitGlobalSlots(Visitor &visitor, JSContext *cx, SlotList &gslots) { - VisitGlobalSlots(visitor, cx, cx->fp->getScopeChain()->getGlobal(), + VisitGlobalSlots(visitor, cx, cx->fp->scopeChain->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->getScopeChain()->getGlobal(), + VisitSlots(visitor, cx, cx->fp->scopeChain->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->getScopeChain()->getGlobal(), + VisitSlots(visitor, cx, cx->fp->scopeChain->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->maybeBlockChain()), + lexicalBlock(cx->fp->blockChain), 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->getScopeChain()->getGlobal()); + JS_ASSERT(globalObj == cx->fp->scopeChain->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->getScopeChain()); + fp->setCallObj(fp->scopeChain); // 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->getScopeChain()->getPrivate()) - fp->getScopeChain()->setPrivate(fp); + if (!fp->scopeChain->getPrivate()) + fp->scopeChain->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->addressScopeChain() == p || fp->addressArgsObj() == p) + if (&fp->scopeChain == 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->maybeBlockChain(); - if (fp->hasBlockChain()) - tree->gcthings.addUnique(ObjectValue(*fp->getBlockChain())); + exit->block = fp->blockChain; + if (fp->blockChain) + tree->gcthings.addUnique(ObjectValue(*fp->blockChain)); exit->pc = pc; exit->imacpc = fp->imacpc; exit->sp_adj = (stackSlots * sizeof(double)) - tree->nativeStackBase; @@ -5671,7 +5671,14 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee) cx->regs->sp = sp; cx->regs->pc = fi.pc; fp->imacpc = fi.imacpc; - fp->setBlockChain(fi.block); + 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 /* * Get pointer to new frame/slots, without changing global state. @@ -5709,9 +5716,9 @@ SynthesizeFrame(JSContext* cx, const FrameInfo& fi, JSObject* callee) #endif newfp->rval = UndefinedValue(); newfp->annotation = NULL; - newfp->setScopeChain(NULL); // will be updated in FlushNativeStackFrame + newfp->scopeChain = NULL; // will be updated in FlushNativeStackFrame newfp->flags = fi.is_constructing() ? JSFRAME_CONSTRUCTING : 0; - newfp->setBlockChain(NULL); + newfp->blockChain = NULL; newfp->thisv.setNull(); // will be updated in FlushNativeStackFrame newfp->imacpc = NULL; @@ -5781,8 +5788,9 @@ SynthesizeSlowNativeFrame(TracerState& state, JSContext *cx, VMSideExit *exit) fp->fun = GET_FUNCTION_PRIVATE(cx, fp->callee()); fp->rval = UndefinedValue(); fp->annotation = NULL; - fp->setScopeChain(cx->fp->maybeScopeChain()); - fp->setBlockChain(NULL); + JS_ASSERT(cx->fp->scopeChain); + fp->scopeChain = cx->fp->scopeChain; + fp->blockChain = NULL; fp->flags = exit->constructing() ? JSFRAME_CONSTRUCTING : 0; state.bailedSlowNativeRegs = *cx->regs; @@ -6149,7 +6157,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->getScopeChain()->getGlobal(); + JSObject* globalObj = cx->fp->scopeChain->getGlobal(); uint32 globalShape = -1; SlotList* globalSlots = NULL; if (!CheckGlobalObjectShape(cx, tm, globalObj, &globalShape, &globalSlots)) { @@ -6655,7 +6663,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->getScopeChain()->getGlobal()); + JS_ASSERT(f->globalObj == cx->fp->scopeChain->getGlobal()); /* * The JIT records and expects to execute with two scope-chain @@ -6673,7 +6681,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->getScopeChain(); + JSObject* child = cx->fp->scopeChain; while (JSObject* parent = child->getParent()) { if (!js_IsCacheableNonGlobalScope(child)) { debug_only_print0(LC_TMTracer,"Blacklist: non-cacheable object on scope chain.\n"); @@ -7012,7 +7020,7 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr) */ JSStackFrame* const fp = cx->fp; - fp->setBlockChain(innermost->block); + fp->blockChain = innermost->block; /* * If we are not exiting from an inlined frame, the state->sp is spbase. @@ -7162,7 +7170,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->getScopeChain()->getGlobal(); + JSObject* globalObj = cx->fp->scopeChain->getGlobal(); uint32 globalShape = -1; SlotList* globalSlots = NULL; @@ -8078,7 +8086,7 @@ JS_REQUIRES_STACK LIns* TraceRecorder::scopeChain() { return cx->fp->callee() - ? getFrameObjPtr(cx->fp->addressScopeChain()) + ? getFrameObjPtr(&cx->fp->scopeChain) : entryScopeChain(); } @@ -8092,7 +8100,7 @@ TraceRecorder::entryScopeChain() const { return lir->insLoad(LIR_ldp, lir->insLoad(LIR_ldp, cx_ins, offsetof(JSContext, fp), ACCSET_OTHER), - JSStackFrame::offsetScopeChain(), ACCSET_OTHER); + offsetof(JSStackFrame, scopeChain), ACCSET_OTHER); } /* @@ -8134,7 +8142,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->getScopeChain()); + JS_ASSERT(chainHead == cx->fp->scopeChain); JS_ASSERT(chainHead != globalObj); TraceMonitor &localtm = *traceMonitor; @@ -10233,7 +10241,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->addressScopeChain(), (LIns*)0); + which.set(&fp->scopeChain, (LIns*)0); } vp = &fp->slots()[0]; vpstop = &fp->slots()[nslots]; @@ -10312,7 +10320,7 @@ TraceRecorder::putActivationObjects() slots_ins = INS_CONSTPTR(0); } - LIns* scopeChain_ins = getFrameObjPtr(cx->fp->addressScopeChain()); + LIns* scopeChain_ins = getFrameObjPtr(&cx->fp->scopeChain); 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); @@ -10336,7 +10344,7 @@ IsTraceableRecursion(JSContext *cx) return false; if ((fp->flags & JSFRAME_CONSTRUCTING) || (down->flags & JSFRAME_CONSTRUCTING)) return false; - if (fp->hasBlockChain() || down->hasBlockChain()) + if (fp->blockChain || down->blockChain) return false; if (*fp->script->code != JSOP_TRACE) return false; @@ -10384,7 +10392,7 @@ TraceRecorder::record_EnterFrame(uintN& inlineCallCount) nativeFrameTracker.set(fp->addressArgsObj(), NULL); setFrameObjPtr(fp->addressArgsObj(), INS_NULL()); - nativeFrameTracker.set(fp->addressScopeChain(), NULL); + nativeFrameTracker.set(&fp->scopeChain, NULL); vp = fp->slots(); vpstop = vp + fp->script->nfixed; @@ -10404,7 +10412,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->addressScopeChain(), INS_NULL()); + setFrameObjPtr(&fp->scopeChain, INS_NULL()); if (js_IsNamedLambda(cx->fp->fun)) RETURN_STOP_A("can't call named lambda heavyweight on trace"); @@ -10415,9 +10423,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->addressScopeChain(), call_ins); + setFrameObjPtr(&fp->scopeChain, call_ins); } else { - setFrameObjPtr(fp->addressScopeChain(), scopeChain_ins); + setFrameObjPtr(&fp->scopeChain, scopeChain_ins); } /* @@ -10473,7 +10481,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->getScopeChain()->getGlobal(); + JSObject* globalObj = cx->fp->scopeChain->getGlobal(); uint32 globalShape = -1; SlotList* globalSlots = NULL; if (!CheckGlobalObjectShape(cx, traceMonitor, globalObj, &globalShape, &globalSlots)) @@ -13074,7 +13082,7 @@ TraceRecorder::record_JSOP_SETELEM() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_CALLNAME() { - JSObject* obj = cx->fp->getScopeChain(); + JSObject* obj = cx->fp->scopeChain; if (obj != globalObj) { Value* vp; LIns* ins; @@ -13370,9 +13378,9 @@ TraceRecorder::interpretedFunctionCall(Value& fval, JSFunction* fun, uintN argc, JS_ASSERT(argc < FrameInfo::CONSTRUCTING_FLAG); tree->gcthings.addUnique(fval); - fi->block = fp->maybeBlockChain(); - if (fp->hasBlockChain()) - tree->gcthings.addUnique(ObjectValue(*fp->getBlockChain())); + fi->block = fp->blockChain; + if (fp->blockChain) + tree->gcthings.addUnique(ObjectValue(*fp->blockChain)); fi->pc = cx->regs->pc; fi->imacpc = fp->imacpc; fi->spdist = cx->regs->sp - fp->slots(); @@ -13616,7 +13624,7 @@ TraceRecorder::record_NativeCallComplete() JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::name(Value*& vp, LIns*& ins, NameResult& nr) { - JSObject* obj = cx->fp->getScopeChain(); + JSObject* obj = cx->fp->scopeChain; if (obj != globalObj) return scopeChainProp(obj, vp, ins, nr); @@ -14718,7 +14726,7 @@ TraceRecorder::record_JSOP_BINDNAME() JSObject *obj; if (!fp->fun) { - obj = fp->getScopeChain(); + obj = fp->scopeChain; #ifdef DEBUG JSStackFrame *fp2 = fp; @@ -14779,7 +14787,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->getScopeChain(), id); + JSObject *obj2 = js_FindIdentifierBase(cx, fp->scopeChain, id); if (!obj2) RETURN_ERROR_A("error in js_FindIdentifierBase"); if (!TRACE_RECORDER(localCx)) @@ -15846,7 +15854,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus TraceRecorder::record_JSOP_LEAVEBLOCK() { /* We mustn't exit the lexical block we began recording in. */ - if (cx->fp->getBlockChain() == lexicalBlock) + if (cx->fp->blockChain == lexicalBlock) return ARECORD_STOP; return ARECORD_CONTINUE; } diff --git a/js/src/jswrapper.cpp b/js/src/jswrapper.cpp index 1c54921ce22..be75e6a93a0 100644 --- a/js/src/jswrapper.cpp +++ b/js/src/jswrapper.cpp @@ -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->getScopeChain()->getGlobal() : cx->globalObject; + JSObject *global = cx->fp ? cx->fp->scopeChain->getGlobal() : cx->globalObject; wrapper->setParent(global); return true; } @@ -489,7 +489,7 @@ SetupFakeFrame(JSContext *cx, ExecuteFrameGuard &frame, JSFrameRegs ®s, JSObj JSStackFrame *fp = frame.getFrame(); PodZero(fp); // fp->fun and fp->script are both NULL fp->argv = vp + 2; - fp->setScopeChain(obj->getGlobal()); + fp->scopeChain = obj->getGlobal(); fp->flags = JSFRAME_DUMMY; regs.pc = NULL; diff --git a/js/src/jsxml.cpp b/js/src/jsxml.cpp index c96b9c2220e..8e47ff09b9f 100644 --- a/js/src/jsxml.cpp +++ b/js/src/jsxml.cpp @@ -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)->getScopeChain(); + JSObject *scopeChain = js_GetTopStackFrame(cx)->scopeChain; 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->getScopeChain(); tmp; tmp = tmp->getParent()) { + for (tmp = fp->scopeChain; 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)->getScopeChain(); + obj = js_GetTopStackFrame(cx)->scopeChain; do { /* Skip any With object that can wrap XML. */ target = obj;