Clone lambdas in heavyweight scopes (bug 625157, r=brendan).
authorDavid Anderson <danderson@mozilla.com>
Wed, 26 Jan 2011 12:41:15 -0800
changeset 61442 6962ba9824d70e91245fef9b1d2edc17c9cefaca
parent 61441 df6e9f32a9463a95b036aa546c4b2dea2f755145
child 61443 b57667518fd004ed97123326b16595aabc166c29
push idunknown
push userunknown
push dateunknown
reviewersbrendan
bugs625157
milestone2.0b10pre
Clone lambdas in heavyweight scopes (bug 625157, r=brendan).
js/src/jit-test/tests/jaeger/bug625157.js
js/src/jstracer.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/jaeger/bug625157.js
@@ -0,0 +1,16 @@
+function f() {
+    {
+        function g() {
+            var a = [];
+            for (var i = 0; i < 10; i++)
+                a.push({});
+            for (var i = 0; i < 10; i++)
+                a[i].m = function() { return 0; }
+            assertEq(a[8].m !== a[9].m, true);
+        }
+        g();
+    }
+}
+f()
+
+
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -15429,31 +15429,31 @@ TraceRecorder::getFullIndex(ptrdiff_t pc
 }
 
 JS_REQUIRES_STACK AbortableRecordingStatus
 TraceRecorder::record_JSOP_LAMBDA()
 {
     JSFunction* fun;
     fun = cx->fp()->script()->getFunction(getFullIndex());
 
+    if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() != globalObj)
+        RETURN_STOP_A("Null closure function object parent must be global object");
+
     /*
      * Emit code to clone a null closure parented by this recorder's global
      * object, in order to preserve function object evaluation rules observable
      * via identity and mutation. But don't clone if our result is consumed by
      * JSOP_SETMETHOD or JSOP_INITMETHOD, since we optimize away the clone for
      * these combinations and clone only if the "method value" escapes.
      *
      * See jsinterp.cpp, the JSOP_LAMBDA null closure case. The JSOP_SETMETHOD and
      * JSOP_INITMETHOD logic governing the early ARECORD_CONTINUE returns below
      * must agree with the corresponding break-from-do-while(0) logic there.
      */
-    if (FUN_NULL_CLOSURE(fun)) {
-        if (FUN_OBJECT(fun)->getParent() != globalObj)
-            RETURN_STOP_A("Null closure function object parent must be global object");
-
+    if (FUN_NULL_CLOSURE(fun) && FUN_OBJECT(fun)->getParent() == &cx->fp()->scopeChain()) {
         jsbytecode *pc2 = AdvanceOverBlockchainOp(cx->regs->pc + JSOP_LAMBDA_LENGTH);
         JSOp op2 = JSOp(*pc2);
 
         if (op2 == JSOP_INITMETHOD) {
             stack(0, w.immpObjGC(FUN_OBJECT(fun)));
             return ARECORD_CONTINUE;
         }