Title: [192855] trunk/Source
Revision
192855
Author
[email protected]
Date
2015-11-30 19:39:59 -0800 (Mon, 30 Nov 2015)

Log Message

Use a better RNG for Math.random()
https://bugs.webkit.org/show_bug.cgi?id=151641

Reviewed by Anders Carlsson.

Source/_javascript_Core:

Updated for interface change.

* runtime/JSGlobalObject.cpp:
(JSC::JSGlobalObject::setInputCursor):

Source/WTF:

Use 64 bits in the random number generator instead of 32 bit. (In
the end, _javascript_, which uses doubles, will only see 52 bits.) This
prevents programs that mulitply a random number by a large constant from
seeing non-random "banding" caused by zeroes in the low 20 bits.

I also took the opportunity to upgrade from GameRandom to Xorshift+,
since Xorshift+ passes more benchmarks for randomness, and is not any
slower or more complicated.

Now let us all remember the fateful words of Steve Weibe, who would be
King of Kong: "The randomness went the opposite way that it usually goes."

* wtf/WeakRandom.h:
(WTF::WeakRandom::WeakRandom):
(WTF::WeakRandom::setSeed): Use standard naming.

(WTF::WeakRandom::seed): This function is safe now. "Unsafe" in function
names makes me itch.

(WTF::WeakRandom::get):
(WTF::WeakRandom::getUint32): Update to 64bit.

(WTF::WeakRandom::advance): The Xorshift+ algorithm.

(WTF::WeakRandom::initializeSeed): Deleted.
(WTF::WeakRandom::seedUnsafe): Deleted.

Modified Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (192854 => 192855)


--- trunk/Source/_javascript_Core/ChangeLog	2015-12-01 02:53:25 UTC (rev 192854)
+++ trunk/Source/_javascript_Core/ChangeLog	2015-12-01 03:39:59 UTC (rev 192855)
@@ -1,3 +1,15 @@
+2015-11-30  Geoffrey Garen  <[email protected]>
+
+        Use a better RNG for Math.random()
+        https://bugs.webkit.org/show_bug.cgi?id=151641
+
+        Reviewed by Anders Carlsson.
+
+        Updated for interface change.
+
+        * runtime/JSGlobalObject.cpp:
+        (JSC::JSGlobalObject::setInputCursor):
+
 2015-11-30  Benjamin Poulain  <[email protected]>
 
         [JSC] Speed up Air Liveness Analysis on Tmps

Modified: trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp (192854 => 192855)


--- trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-12-01 02:53:25 UTC (rev 192854)
+++ trunk/Source/_javascript_Core/runtime/JSGlobalObject.cpp	2015-12-01 03:39:59 UTC (rev 192855)
@@ -1014,10 +1014,10 @@
     // Save or set the random seed. This performed here rather than the constructor
     // to avoid threading the input cursor through all the abstraction layers.
     if (cursor.isCapturing())
-        cursor.appendInput<SetRandomSeed>(m_weakRandom.seedUnsafe());
+        cursor.appendInput<SetRandomSeed>(m_weakRandom.seed());
     else if (cursor.isReplaying()) {
         if (SetRandomSeed* input = cursor.fetchInput<SetRandomSeed>())
-            m_weakRandom.initializeSeed(static_cast<unsigned>(input->randomSeed()));
+            m_weakRandom.setSeed(static_cast<unsigned>(input->randomSeed()));
     }
 }
 #endif

Modified: trunk/Source/WTF/ChangeLog (192854 => 192855)


--- trunk/Source/WTF/ChangeLog	2015-12-01 02:53:25 UTC (rev 192854)
+++ trunk/Source/WTF/ChangeLog	2015-12-01 03:39:59 UTC (rev 192855)
@@ -1,3 +1,37 @@
+2015-11-30  Geoffrey Garen  <[email protected]>
+
+        Use a better RNG for Math.random()
+        https://bugs.webkit.org/show_bug.cgi?id=151641
+
+        Reviewed by Anders Carlsson.
+
+        Use 64 bits in the random number generator instead of 32 bit. (In
+        the end, _javascript_, which uses doubles, will only see 52 bits.) This
+        prevents programs that mulitply a random number by a large constant from
+        seeing non-random "banding" caused by zeroes in the low 20 bits.
+
+        I also took the opportunity to upgrade from GameRandom to Xorshift+,
+        since Xorshift+ passes more benchmarks for randomness, and is not any
+        slower or more complicated.
+
+        Now let us all remember the fateful words of Steve Weibe, who would be
+        King of Kong: "The randomness went the opposite way that it usually goes."
+
+        * wtf/WeakRandom.h:
+        (WTF::WeakRandom::WeakRandom):
+        (WTF::WeakRandom::setSeed): Use standard naming.
+
+        (WTF::WeakRandom::seed): This function is safe now. "Unsafe" in function
+        names makes me itch.
+
+        (WTF::WeakRandom::get):
+        (WTF::WeakRandom::getUint32): Update to 64bit.
+
+        (WTF::WeakRandom::advance): The Xorshift+ algorithm.
+
+        (WTF::WeakRandom::initializeSeed): Deleted.
+        (WTF::WeakRandom::seedUnsafe): Deleted.
+
 2015-11-30  Benjamin Poulain  <[email protected]>
 
         [JSC] Speed up Air Liveness Analysis on Tmps

Modified: trunk/Source/WTF/wtf/WeakRandom.h (192854 => 192855)


--- trunk/Source/WTF/wtf/WeakRandom.h	2015-12-01 02:53:25 UTC (rev 192854)
+++ trunk/Source/WTF/wtf/WeakRandom.h	2015-12-01 03:39:59 UTC (rev 192855)
@@ -22,76 +22,57 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  *
+ * Vigna, Sebastiano (2014). "Further scramblings of Marsaglia's xorshift
+ * generators". arXiv:1404.0390 (http://arxiv.org/abs/1404.0390)
  *
- * Copyright (c) 2009 Ian C. Bullard
- * 
- * Permission is hereby granted, free of charge, to any person
- * obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without
- * restriction, including without limitation the rights to use,
- * copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following
- * conditions:
- * 
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
- * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
- * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
+ * See also https://en.wikipedia.org/wiki/Xorshift.
  */
 
 #ifndef WeakRandom_h
 #define WeakRandom_h
 
 #include <limits.h>
-#include <wtf/RandomNumber.h>
+#include <wtf/CryptographicallyRandomNumber.h>
 #include <wtf/StdLibExtras.h>
 
 namespace WTF {
 
 class WeakRandom {
 public:
-    WeakRandom()
+    WeakRandom(unsigned seed = cryptographicallyRandomNumber())
     {
-        initializeSeed(randomNumber() * (std::numeric_limits<unsigned>::max() + 1.0));
+        setSeed(seed);
     }
-    
-    WeakRandom(unsigned seed)
+
+    void setSeed(unsigned seed)
     {
-        initializeSeed(seed);
-    }
-    
-    void initializeSeed(unsigned seed)
-    {
-        m_low = seed ^ 0x49616E42;
+        m_seed = seed;
+
+        // A zero seed would cause an infinite series of zeroes.
+        if (!seed)
+            seed = 1;
+
+        m_low = seed;
         m_high = seed;
     }
 
-    // Returns the seed provided that you've never called get() or getUint32().
-    unsigned seedUnsafe() const { return m_high; }
+    unsigned seed() const { return m_seed; }
 
     double get()
     {
-        return advance() / (UINT_MAX + 1.0);
+        return advance() / (std::numeric_limits<uint64_t>::max() + 1.0);
     }
 
     unsigned getUint32()
     {
-        return advance();
+        return static_cast<unsigned>(advance());
     }
 
     unsigned getUint32(unsigned limit)
     {
         if (limit <= 1)
             return 0;
-        uint64_t cutoff = (static_cast<uint64_t>(UINT_MAX) + 1) / limit * limit;
+        uint64_t cutoff = (static_cast<uint64_t>(std::numeric_limits<unsigned>::max()) + 1) / limit * limit;
         for (;;) {
             uint64_t value = getUint32();
             if (value >= cutoff)
@@ -101,16 +82,21 @@
     }
 
 private:
-    unsigned advance()
+    uint64_t advance()
     {
-        m_high = (m_high << 16) + (m_high >> 16);
-        m_high += m_low;
-        m_low += m_high;
-        return m_high;
+        uint64_t x = m_low;
+        uint64_t y = m_high;
+        m_low = y;
+        x ^= x << 23;
+        x ^= x >> 17;
+        x ^= y ^ (y >> 26);
+        m_high = x;
+        return x + y;
     }
 
-    unsigned m_low;
-    unsigned m_high;
+    unsigned m_seed;
+    uint64_t m_low;
+    uint64_t m_high;
 };
 
 } // namespace WTF
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to