Bug 522123: Don't reify lazy scope chain blocks twice in 'eval'. r=mrbkap
authorJim Blandy <jimb@mozilla.org>
Wed, 21 Oct 2009 14:34:55 -0700
changeset 34317 64094cb2f8b22cfffc38cd5a8795214d1e2e5a42
parent 34316 8499ce94e7a1369d3c500ea033585aff2f5731af
child 34318 240dc0b2b41f72f033d968b140f6a78106165b2e
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmrbkap
bugs522123
milestone1.9.3a1pre
Bug 522123: Don't reify lazy scope chain blocks twice in 'eval'. r=mrbkap
js/src/jsobj.cpp
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1316,32 +1316,37 @@ obj_eval(JSContext *cx, JSObject *obj, u
             return JS_FALSE;
         argv[1] = OBJECT_TO_JSVAL(scopeobj);
     }
 
     /* From here on, control must exit through label out with ok set. */
     MUST_FLOW_THROUGH("out");
     uintN staticLevel = caller->script->staticLevel + 1;
     if (!scopeobj) {
+
+        /*
+         * Bring fp->scopeChain up to date. We're either going to use
+         * it (direct call) or save it and restore it (indirect call).
+         */
+        callerScopeChain = js_GetScopeChain(cx, caller);
+        if (!callerScopeChain) {
+            ok = JS_FALSE;
+            goto out;
+        }
+
 #if JS_HAS_EVAL_THIS_SCOPE
         /*
          * If we see an indirect call, then run eval in the global scope. We do
          * this so the compiler can make assumptions about what bindings may or
          * may not exist in the current frame if it doesn't see 'eval'.
          */
         if (indirectCall) {
             /* Pretend that we're top level. */
             staticLevel = 0;
 
-            callerScopeChain = js_GetScopeChain(cx, caller);
-            if (!callerScopeChain) {
-                ok = JS_FALSE;
-                goto out;
-            }
-
             OBJ_TO_INNER_OBJECT(cx, obj);
             if (!obj) {
                 ok = JS_FALSE;
                 goto out;
             }
 
             ok = js_CheckPrincipalsAccess(cx, obj,
                                           JS_StackFramePrincipals(cx, caller),
@@ -1362,30 +1367,26 @@ obj_eval(JSContext *cx, JSObject *obj, u
 
             callerVarObj = caller->varobj;
             if (obj != callerVarObj) {
                 /* Set fp->varobj too, for the compiler. */
                 caller->varobj = fp->varobj = obj;
                 setCallerVarObj = JS_TRUE;
                 JS_PUSH_TEMP_ROOT_OBJECT(cx, callerVarObj, &varobjtvr);
             }
+        } else {
+            /*
+             * Compile using the caller's current scope object.
+             *
+             * NB: This means that native callers (who reach this point through
+             * the C API) must use the two parameter form.
+             */
+            scopeobj = callerScopeChain;
         }
 #endif
-
-        /*
-         * Compile using caller's current scope object.
-         *
-         * NB: This means that native callers (who reach this point through
-         * the C API) must use the two parameter form.
-         */
-        scopeobj = js_GetScopeChain(cx, caller);
-        if (!scopeobj) {
-            ok = JS_FALSE;
-            goto out;
-        }
     } else {
         scopeobj = js_GetWrappedObject(cx, scopeobj);
         OBJ_TO_INNER_OBJECT(cx, scopeobj);
         if (!scopeobj) {
             ok = JS_FALSE;
             goto out;
         }