Bug 858582 - Prevent callsite cloning of callsite clones. r=bhackett, a=akeybl
authorShu-yu Guo <shu@rfrn.org>
Wed, 24 Apr 2013 18:41:01 -0700
changeset 133602 406f5f8fb4d33ea20cb011052fefe13310e9a363
parent 133601 7057622584a0152ba7fd8c4d66f907faa91c1f27
child 133603 7fe1490b077893a1912f50c1c5c753b67233e3c1
push id3732
push userryanvm@gmail.com
push dateMon, 06 May 2013 15:37:23 +0000
treeherdermozilla-aurora@ef2db5f5aa7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbhackett, akeybl
bugs858582
milestone22.0a2
Bug 858582 - Prevent callsite cloning of callsite clones. r=bhackett, a=akeybl
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
@@ -286,26 +286,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()))