Bug 702572: always clone function in DEFLOCALFUN, r=jorendorff
authorDavid Mandelin <dmandelin@mozilla.com>
Tue, 06 Dec 2011 16:27:41 -0800
changeset 83772 bab6fef4017c60de65f5f7213d17642b8298788e
parent 83771 61d41436beb3764b450cd930b20805738cddf2d0
child 83773 fcdee6d5f3e50b1191e899f14e473a979197b41e
push id519
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 00:38:35 +0000
treeherdermozilla-beta@788ea1ef610b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs702572
milestone11.0a1
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 702572: always clone function in DEFLOCALFUN, r=jorendorff
js/src/jit-test/tests/basic/bug702572.js
js/src/jsinterp.cpp
js/src/methodjit/StubCalls.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/bug702572.js
@@ -0,0 +1,10 @@
+eval("function f() { function g() {} return g; }");
+assertEq(f().prototype !== f().prototype, true);
+
+function f1() {
+    function g1() {
+        function h1() { return h1; }
+    }
+    return g1;
+}
+assertEq(f1().prototype !== f1().prototype, true);
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -4202,34 +4202,29 @@ BEGIN_CASE(JSOP_DEFLOCALFUN)
      * variable slot that the compiler allocated.  This is an optimization over
      * JSOP_DEFFUN that avoids requiring a call object for the outer function's
      * activation.
      */
     JSFunction *fun;
     LOAD_FUNCTION(SLOTNO_LEN);
     JS_ASSERT(fun->isInterpreted());
     JS_ASSERT(!fun->isFlatClosure());
-    JSObject *obj = fun;
-
+
+    JSObject *parent;
     if (fun->isNullClosure()) {
-        obj = CloneFunctionObjectIfNotSingleton(cx, fun, &regs.fp()->scopeChain());
-        if (!obj)
-            goto error;
+        parent = &regs.fp()->scopeChain();
     } else {
-        JSObject *parent = GetScopeChainFast(cx, regs.fp(), JSOP_DEFLOCALFUN,
-                                             JSOP_DEFLOCALFUN_LENGTH);
+        parent = GetScopeChainFast(cx, regs.fp(), JSOP_DEFLOCALFUN,
+                                   JSOP_DEFLOCALFUN_LENGTH);
         if (!parent)
             goto error;
-
-        if (obj->toFunction()->environment() != parent) {
-            obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
-            if (!obj)
-                goto error;
-        }
     }
+    JSObject *obj = CloneFunctionObjectIfNotSingleton(cx, fun, parent);
+    if (!obj)
+        goto error;
 
     JS_ASSERT_IF(script->hasGlobal(), obj->getProto() == fun->getProto());
 
     uint32 slot = GET_SLOTNO(regs.pc);
     regs.fp()->slots()[slot].setObject(*obj);
 }
 END_CASE(JSOP_DEFLOCALFUN)
 
--- a/js/src/methodjit/StubCalls.cpp
+++ b/js/src/methodjit/StubCalls.cpp
@@ -1327,34 +1327,29 @@ stubs::DefLocalFun(VMFrame &f, JSFunctio
      * Define a local function (i.e., one nested at the top level of another
      * function), parented by the current scope chain, stored in a local
      * variable slot that the compiler allocated.  This is an optimization over
      * JSOP_DEFFUN that avoids requiring a call object for the outer function's
      * activation.
      */
     JS_ASSERT(fun->isInterpreted());
     JS_ASSERT(!fun->isFlatClosure());
-    JSObject *obj = fun;
 
+    JSObject *parent;
     if (fun->isNullClosure()) {
-        obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, &f.fp()->scopeChain());
-        if (!obj)
-            THROWV(NULL);
+        parent = &f.fp()->scopeChain();
     } else {
-        JSObject *parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
-                                             JSOP_DEFLOCALFUN_LENGTH);
+        parent = GetScopeChainFast(f.cx, f.fp(), JSOP_DEFLOCALFUN,
+                                   JSOP_DEFLOCALFUN_LENGTH);
         if (!parent)
             THROWV(NULL);
-
-        if (obj->toFunction()->environment() != parent) {
-            obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent);
-            if (!obj)
-                THROWV(NULL);
-        }
     }
+    JSObject *obj = CloneFunctionObjectIfNotSingleton(f.cx, fun, parent);
+    if (!obj)
+        THROWV(NULL);
 
     JS_ASSERT_IF(f.script()->compileAndGo, obj->getGlobal() == fun->getGlobal());
 
     return obj;
 }
 
 JSObject * JS_FASTCALL
 stubs::DefLocalFun_FC(VMFrame &f, JSFunction *fun)