Bug 624110 - Properly traverse the scope chain over strict eval frames in the tracer. r=brendan
authorJeff Walden <jwalden@mit.edu>
Mon, 10 Jan 2011 13:09:07 -0600
changeset 61219 bc2ae2ec69c40cf50144257ee35578f3c5b36470
parent 61218 e0ce1fb5e566b17b62d845c842d7208bec4551cd
child 61220 26bcf65a0229eb417a7d6069d7752085432e095e
push id18277
push usercleary@mozilla.com
push dateTue, 25 Jan 2011 03:52:51 +0000
treeherdermozilla-central@7ee91bd90e7a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbrendan
bugs624110
milestone2.0b10pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 624110 - Properly traverse the scope chain over strict eval frames in the tracer. r=brendan
js/src/jit-test/tests/basic/strict-eval-loop-error.js
js/src/jstracer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/strict-eval-loop-error.js
@@ -0,0 +1,3 @@
+var COUNT = RUNLOOP;
+eval("'use strict'; for (let j = 0; j < COUNT; j++); try { x; throw new Error(); } catch (e) { if (!(e instanceof ReferenceError)) throw e; }");
+assertEq(typeof j, "undefined");
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -14973,16 +14973,23 @@ TraceRecorder::record_JSOP_FORLOCAL()
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_POPN()
 {
     return ARECORD_CONTINUE;
 }
 
+static inline bool
+IsFindableCallObj(JSObject *obj)
+{
+    return obj->isCall() &&
+           (obj->callIsForEval() || obj->getCallObjCalleeFunction()->isHeavyweight());
+}
+
 /*
  * Generate LIR to reach |obj2| from |obj| by traversing the scope chain. The
  * generated code also ensures that any call objects found have not changed shape.
  *
  *      obj               starting object
  *      obj_ins           LIR instruction representing obj
  *      targetObj         end object for traversal
  *      targetIns [out]   LIR instruction representing obj2
@@ -15014,23 +15021,20 @@ TraceRecorder::traverseScopeChain(JSObje
      * and can bypass the scope chain traversal completely.
      */
     bool foundCallObj = false;
     bool foundBlockObj = false;
     JSObject* searchObj = obj;
 
     for (;;) {
         if (searchObj != globalObj) {
-            Class* clasp = searchObj->getClass();
-            if (clasp == &js_BlockClass) {
+            if (searchObj->isBlock())
                 foundBlockObj = true;
-            } else if (clasp == &js_CallClass &&
-                       searchObj->getCallObjCalleeFunction()->isHeavyweight()) {
+            else if (IsFindableCallObj(searchObj))
                 foundCallObj = true;
-            }
         }
 
         if (searchObj == targetObj)
             break;
 
         searchObj = searchObj->getParent();
         if (!searchObj)
             RETURN_STOP("cannot traverse this scope chain on trace");
@@ -15049,18 +15053,17 @@ TraceRecorder::traverseScopeChain(JSObje
     for (;;) {
         if (obj != globalObj) {
             if (!js_IsCacheableNonGlobalScope(obj))
                 RETURN_STOP("scope chain lookup crosses non-cacheable object");
 
             // We must guard on the shape of all call objects for heavyweight functions
             // that we traverse on the scope chain: if the shape changes, a variable with
             // the same name may have been inserted in the scope chain.
-            if (obj->isCall() &&
-                obj->getCallObjCalleeFunction()->isHeavyweight()) {
+            if (IsFindableCallObj(obj)) {
                 if (!exit)
                     exit = snapshot(BRANCH_EXIT);
                 guard(true,
                       w.name(w.eqiN(w.ldiObjShape(obj_ins), obj->shape()), "guard_shape"),
                       exit);
             }
         }