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 61226 46b9f2a8343b45dc4b59a5bad97ce6db280ddab6
parent 61225 a7d178f043dbc420c38e1bdd8f62453745c94572
child 61227 b21d0f75e50a22a9919a5fa89d6531db5d0986bd
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);
             }
         }