Bug 774364 - Part 4: Add setRNGState testing function. r=sstangl
authorTooru Fujisawa <arai_a@mac.com>
Fri, 07 Aug 2015 07:42:17 +0900
changeset 294317 4ed0c752ce47dab0affd2b3da58d008a9283e7b9
parent 294316 174b80f07d0cc911824b2a8c4dca744130423ab2
child 294318 1739b4d8202c6a1f17338112a413a999f9b82eff
push id5245
push userraliiev@mozilla.com
push dateThu, 29 Oct 2015 11:30:51 +0000
treeherdermozilla-beta@dac831dc1bd0 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssstangl
bugs774364
milestone43.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 774364 - Part 4: Add setRNGState testing function. r=sstangl
js/src/builtin/TestingFunctions.cpp
js/src/jit-test/tests/basic/math-random.js
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -2756,16 +2756,33 @@ GetLcovInfo(JSContext* cx, unsigned argc
 
     if (!str)
         return false;
 
     args.rval().setString(str);
     return true;
 }
 
+#ifdef DEBUG
+static bool
+SetRNGState(JSContext* cx, unsigned argc, Value* vp)
+{
+    CallArgs args = CallArgsFromVp(argc, vp);
+    if (!args.requireAtLeast(cx, "SetRNGState", 1))
+        return false;
+
+    double seed;
+    if (!ToNumber(cx, args[0], &seed))
+        return false;
+
+    cx->compartment()->rngState = static_cast<uint64_t>(seed) & RNG_MASK;
+    return true;
+}
+#endif
+
 static const JSFunctionSpecWithHelp TestingFunctions[] = {
     JS_FN_HELP("gc", ::GC, 0, 0,
 "gc([obj] | 'compartment' [, 'shrinking'])",
 "  Run the garbage collector. When obj is given, GC only its compartment.\n"
 "  If 'compartment' is given, GC any compartments that were scheduled for\n"
 "  GC via schedulegc.\n"
 "  If 'shrinking' is passed as the optional second argument, perform a\n"
 "  shrinking GC rather than a normal GC."),
@@ -3203,16 +3220,22 @@ gc::ZealModeHelpText),
 "  On non-ARM, no-op. On ARM, set the hardware capabilities. The list of \n"
 "  flags is available by calling this function with \"help\" as the flag's name"),
 
     JS_FN_HELP("getLcovInfo", GetLcovInfo, 1, 0,
 "getLcovInfo(global)",
 "  Generate LCOV tracefile for the given compartment.  If no global are provided then\n"
 "  the current global is used as the default one.\n"),
 
+#ifdef DEBUG
+    JS_FN_HELP("setRNGState", SetRNGState, 1, 0,
+"setRNGState(seed)",
+"  Set this compartment's RNG state.\n"),
+#endif
+
     JS_FS_HELP_END
 };
 
 static const JSPropertySpec TestingProperties[] = {
     JS_PSG("timesAccessed", TimesAccessed, 0),
     JS_PS_END
 };
 
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/basic/math-random.js
@@ -0,0 +1,44 @@
+function test() {
+  // With this seed, state won't be reset in 10000 iteration.  The result is
+  // deterministic and it can be used to check the correctness of
+  // implementation.
+  setRNGState(0x12341234);
+
+  function f() {
+    let x = [];
+    for (let i = 0; i < 10000; i++)  {
+      x.push(Math.random());
+    }
+    return x;
+  }
+  let x = f();
+  assertEq(x[0], 0.3562073961260165);
+  assertEq(x[10], 0.9777930699941514);
+  assertEq(x[100], 0.9146259915430884);
+  assertEq(x[1000], 0.315983055288946);
+  assertEq(x[2000], 0.7132284805929497);
+  assertEq(x[3000], 0.9621073641614717);
+  assertEq(x[4000], 0.3928228025111996);
+  assertEq(x[5000], 0.555710685962832);
+  assertEq(x[6000], 0.5207553912782503);
+  assertEq(x[7000], 0.08268413491723015);
+  assertEq(x[8000], 0.031796243723989925);
+  assertEq(x[9000], 0.900683320457098);
+  assertEq(x[9999], 0.7750389203054577);
+
+  // With this seed, state will be reset before calculating high bits.
+  // The result is nondeterministic, but it should be in [0, 1) range.
+  setRNGState(0);
+  x = f();
+  assertEq(x[0] >= 0 && x[0] < 1, true);
+
+  // With this seed, high bits will be 0 and state will be reset before
+  // calculating low bits.  The result is also nondeterministic, but it should
+  // be in [0, 1 / (1 << 26)) range.
+  setRNGState(0x615c0e462aa9);
+  x = f();
+  assertEq(x[0] >= 0 && x[0] < 1 / (1 << 26), true);
+}
+
+if (typeof setRNGState == "function")
+  test();