Bug 858582 - Prevent callsite cloning of callsite clones. (r=bhackett)
authorShu-yu Guo <shu@rfrn.org>
Wed, 24 Apr 2013 18:41:01 -0700
changeset 129818 e1255e1e6ad3e0656ba13bd60d3ef518b3794ece
parent 129817 00c0b12c29e1e673aaf3e1e5f002c75f2a2e617a
child 129819 c1f983b78f1625fee2d390906ea263bb94ea2f9e
push id24590
push userryanvm@gmail.com
push dateFri, 26 Apr 2013 01:39:07 +0000
treeherdermozilla-central@7f68735fc8da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett
bugs858582
milestone23.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 858582 - Prevent callsite cloning of callsite clones. (r=bhackett)
js/src/jit-test/tests/parallelarray/bug858582.js
js/src/jscntxt.cpp
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/parallelarray/bug858582.js
@@ -0,0 +1,64 @@
+// |jit-test| error: TypeError
+// Don't crash.
+gczeal(2);
+evaluate("\
+function assertAlmostEq(v1, v2) {\
+  print(\"v2 = \" + v2);\
+  print(\"% diff = \" + percent);\
+function assertStructuralEq(e1, e2) {}\
+function assertEqParallelArrayArray(a, b) {\
+    try {} catch (e) {\
+      print(\"...in index \", i, \" of \", l);\
+  }\
+}\
+    function assertEqArray(a, b) {\
+      try {} catch (e) {}\
+}\
+function assertEqParallelArray(a, b) {\
+  var shape = a.shape;\
+  function bump(indices) {\
+  var iv = shape.map(function () { return 0; });\
+      print(\"...in indices \", iv, \" of \", shape);\
+    }\
+  } while (bump(iv));\
+}\
+function assertParallelArrayModesEq(modes, acc, opFunction, cmpFunction) {\
+  modes.forEach(function (mode) {\
+    var result = opFunction({ mode: mode, expect: \"success\" });\
+    cmpFunction(acc, result);\
+  });\
+function assertParallelArrayModesCommute(modes, opFunction) {\
+    var acc = opFunction({ mode: modes[0], expect: \"success\" });\
+}\
+function comparePerformance(opts) {\
+        print(\"Option \" + opts[i].name + \" took \" + diff + \"ms\");\
+        print(\"Option \" + opts[i].name + \" relative to option \" +\
+              opts[0].name + \": \" + (rel|0) + \"%\");\
+    }\
+}\
+function compareAgainstArray(jsarray, opname, func, cmpFunction) {\
+  var expected = jsarray[opname].apply(jsarray, [func]);\
+  var parray = new ParallelArray(jsarray);\
+  assertParallelArrayModesEq([\"seq\", \"par\", \"par\"], expected, function(m) {\
+    var result = parray[opname].apply(parray, [func, m]);\
+  }, cmpFunction);\
+}\
+function testFilter(jsarray, func, cmpFunction) {}\
+", { noScriptRval : true });
+  compareAgainstArray([
+	"a", 
+	"b", 
+	('captures: 1,1; RegExp.leftContext: ""; RegExp.rightContext: "123456"'), 
+	"d", "e", 
+	"f", "g", "h",
+        "i", "j", "k", "l", 
+	"m", "n", "o", "p",
+        "q", "r", "s", "t", 
+	(.6  ), "v", "w", "x", "y", "z"
+	], "map", function(e) { 
+		return e != "u" 
+			&& 
+			(function b   (   )  { 
+			} )      
+			!= "x"; 
+	});
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -269,26 +269,29 @@ js::CloneFunctionAtCallsite(JSContext *c
     key.original = fun;
 
     Table::AddPtr p = table.lookupForAdd(key);
     SkipRoot skipHash(cx, &p); /* Prevent the hash from being poisoned. */
     if (p)
         return p->value;
 
     RootedObject parent(cx, fun->environment());
-    RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent,
-                                                 JSFunction::ExtendedFinalizeKind));
+    RootedFunction clone(cx, CloneFunctionObject(cx, fun, parent));
     if (!clone)
         return NULL;
 
-    // Store a link back to the original for function.caller.
+    /*
+     * Store a link back to the original for function.caller and avoid cloning
+     * clones.
+     */
+    clone->nonLazyScript()->shouldCloneAtCallsite = false;
     clone->nonLazyScript()->isCallsiteClone = true;
     clone->nonLazyScript()->setOriginalFunctionObject(fun);
 
-    // Recalculate the hash if script or fun have been moved.
+    /* Recalculate the hash if script or fun have been moved. */
     if (key.script != script && key.original != fun) {
         key.script = script;
         key.original = fun;
         Table::AddPtr p = table.lookupForAdd(key);
         JS_ASSERT(!p);
     }
 
     if (!table.relookupOrAdd(p, key, clone.get()))