Don't trace upvar accesses through call objects for non-heavyweight functions, r=dvander, a=beltzner
authorDavid Mandelin <dmandelin@mozilla.com>
Fri, 19 Feb 2010 13:40:08 -0800
changeset 33640 71de40148a4073d25a18a9120b9dbc4745b184da
parent 33639 4c4d52bf65632ad40c5c5c6f53a1381bb520e7f8
child 33641 263ee4ee7da28f551bec0172dffcc492edfbb83c
push id1097
push userdmandelin@mozilla.com
push dateMon, 01 Mar 2010 22:26:47 +0000
reviewersdvander, beltzner
milestone1.9.2.2pre
Don't trace upvar accesses through call objects for non-heavyweight functions, r=dvander, a=beltzner
js/src/jstracer.cpp
js/src/trace-test/tests/basic/indirectEvalScope.js
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -12677,19 +12677,24 @@ TraceRecorder::traverseScopeChain(JSObje
     bool foundBlockObj = false;
     JSObject* searchObj = obj;
 
     for (;;) {
         if (searchObj != globalObj) {
             JSClass* cls = STOBJ_GET_CLASS(searchObj);
             if (cls == &js_BlockClass) {
                 foundBlockObj = true;
-            } else if (cls == &js_CallClass &&
-                       JSFUN_HEAVYWEIGHT_TEST(js_GetCallObjectFunction(searchObj)->flags)) {
-                foundCallObj = true;
+            } else if (cls == &js_CallClass) {
+                // If the function that owns this call object is not heavyweight, then
+                // we can't be sure it will always be there, which means the scope chain
+                // does not have a definite length, so abort.
+                if (JSFUN_HEAVYWEIGHT_TEST(js_GetCallObjectFunction(searchObj)->flags))
+                    foundCallObj = true;
+                else
+                    ABORT_TRACE("found call object for non-heavyweight function on scope chain");
             }
         }
 
         if (searchObj == targetObj)
             break;
 
         searchObj = STOBJ_GET_PARENT(searchObj);
         if (!searchObj)
new file mode 100644
--- /dev/null
+++ b/js/src/trace-test/tests/basic/indirectEvalScope.js
@@ -0,0 +1,11 @@
+var ev = eval;
+var z;
+
+function f() {
+  var m = 22;
+
+  return ev("(function g() { for (var i = 0; i < 5; ++i) m; })");
+}
+
+var g = f();
+g();