Introduce a RandonNumberGenerator class. Refactor the random/private_random uses...
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Sep 2013 11:13:55 +0000 (11:13 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 10 Sep 2013 11:13:55 +0000 (11:13 +0000)
The RandomNumberGenerator is a pseudorandom number generator
with 48-bit state. It is properly seeded using either

(1) the --random-seed if specified, or
(2) the entropy_source function if configured, or
(3) /dev/urandom if available, or
(4) falls back to Time and TimeTicks based seeding.

Each Isolate now contains a RandomNumberGenerator, which replaces
the previous private_random_seed.

Every native context still has its own random_seed. But this random
seed is now properly initialized during bootstrapping,
instead of on-demand initialization. This will allow us to cleanup
and speedup the HRandom implementation quite a lot (this is delayed
for a followup CL)!

Also stop messing with the system rand()/random(), which should
not be done from a library anyway! We probably re-seeded the
libc rand()/random() after the application (i.e. Chrome) already
seeded it (with better entropy than what we used).

Another followup CL will replace the use of the per-isolate
random number generator for the address randomization and
thereby get rid of the Isolate::UncheckedCurrent() usage in
the platform code.

TEST=cctest/test-random-number-generator,cctest/test-random
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/23548024

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16612 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

34 files changed:
src/api.cc
src/assembler.cc
src/bootstrapper.cc
src/flags.h
src/heap.cc
src/isolate-inl.h
src/isolate.cc
src/isolate.h
src/objects.cc
src/platform-cygwin.cc
src/platform-freebsd.cc
src/platform-linux.cc
src/platform-macos.cc
src/platform-openbsd.cc
src/platform-posix.cc
src/platform-solaris.cc
src/platform-win32.cc
src/platform.h
src/platform/time.h
src/utils/random-number-generator.cc [new file with mode: 0644]
src/utils/random-number-generator.h [new file with mode: 0644]
src/v8.cc
src/v8.h
test/cctest/cctest.gyp
test/cctest/test-assembler-x64.cc
test/cctest/test-platform-linux.cc
test/cctest/test-platform-win32.cc
test/cctest/test-random-number-generator.cc [new file with mode: 0644]
test/cctest/test-random.cc
test/cctest/test-spaces.cc
test/cctest/test-strings.cc
test/cctest/test-strtod.cc
test/cctest/test-utils.cc
tools/gyp/v8.gyp

index bf27217..d1f6b78 100644 (file)
@@ -62,6 +62,7 @@
 #include "scanner-character-streams.h"
 #include "snapshot.h"
 #include "unicode-inl.h"
+#include "utils/random-number-generator.h"
 #include "v8threads.h"
 #include "version.h"
 #include "vm-state-inl.h"
@@ -5208,8 +5209,8 @@ bool v8::V8::Initialize() {
 }
 
 
-void v8::V8::SetEntropySource(EntropySource source) {
-  i::V8::SetEntropySource(source);
+void v8::V8::SetEntropySource(EntropySource entropy_source) {
+  i::RandomNumberGenerator::SetEntropySource(entropy_source);
 }
 
 
index 44d5f22..fbff62d 100644 (file)
@@ -43,7 +43,7 @@
 #include "deoptimizer.h"
 #include "execution.h"
 #include "ic.h"
-#include "isolate.h"
+#include "isolate-inl.h"
 #include "jsregexp.h"
 #include "lazy-instance.h"
 #include "platform.h"
@@ -119,7 +119,7 @@ AssemblerBase::AssemblerBase(Isolate* isolate, void* buffer, int buffer_size)
       emit_debug_code_(FLAG_debug_code),
       predictable_code_size_(false) {
   if (FLAG_mask_constants_with_cookie && isolate != NULL)  {
-    jit_cookie_ = V8::RandomPrivate(isolate);
+    jit_cookie_ = isolate->random_number_generator()->NextInt();
   }
 
   if (buffer == NULL) {
index 92ff269..764c846 100644 (file)
@@ -1316,13 +1316,9 @@ void Genesis::InitializeGlobal(Handle<GlobalObject> inner_global,
   Handle<FixedArray> embedder_data = factory->NewFixedArray(2);
   native_context()->set_embedder_data(*embedder_data);
 
-  {
-    // Initialize the random seed slot.
-    Handle<ByteArray> zeroed_byte_array(
-        factory->NewByteArray(kRandomStateSize));
-    native_context()->set_random_seed(*zeroed_byte_array);
-    memset(zeroed_byte_array->GetDataStartAddress(), 0, kRandomStateSize);
-  }
+  // Allocate the random seed slot.
+  Handle<ByteArray> random_seed = factory->NewByteArray(kRandomStateSize);
+  native_context()->set_random_seed(*random_seed);
 }
 
 
@@ -2647,6 +2643,14 @@ Genesis::Genesis(Isolate* isolate,
   InitializeExperimentalGlobal();
   if (!InstallExperimentalNatives()) return;
 
+  // Initially seed the per-context random number generator
+  // using the per-isolate random number generator.
+  uint32_t* state = reinterpret_cast<uint32_t*>(
+      native_context()->random_seed()->GetDataStartAddress());
+  do {
+    isolate->random_number_generator()->NextBytes(state, kRandomStateSize);
+  } while (state[0] == 0 || state[1] == 0);
+
   result_ = native_context();
 }
 
index f0b239b..fe182e5 100644 (file)
 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
 #ifndef V8_FLAGS_H_
 #define V8_FLAGS_H_
 
+#include "atomicops.h"
+
 namespace v8 {
 namespace internal {
 
index aaa3d8b..c06a592 100644 (file)
@@ -38,6 +38,7 @@
 #include "global-handles.h"
 #include "heap-profiler.h"
 #include "incremental-marking.h"
+#include "isolate-inl.h"
 #include "mark-compact.h"
 #include "natives.h"
 #include "objects-visiting.h"
@@ -47,6 +48,7 @@
 #include "scopeinfo.h"
 #include "snapshot.h"
 #include "store-buffer.h"
+#include "utils/random-number-generator.h"
 #include "v8threads.h"
 #include "v8utils.h"
 #include "vm-state-inl.h"
@@ -5762,7 +5764,7 @@ MaybeObject* Heap::AllocateSymbol() {
   int hash;
   int attempts = 0;
   do {
-    hash = V8::RandomPrivate(isolate()) & Name::kHashBitMask;
+    hash = isolate()->random_number_generator()->NextInt() & Name::kHashBitMask;
     attempts++;
   } while (hash == 0 && attempts < 30);
   if (hash == 0) hash = 1;  // never return 0
@@ -6927,8 +6929,8 @@ bool Heap::SetUp() {
   ASSERT(hash_seed() == 0);
   if (FLAG_randomize_hashes) {
     if (FLAG_hash_seed == 0) {
-      set_hash_seed(
-          Smi::FromInt(V8::RandomPrivate(isolate()) & 0x3fffffff));
+      int rnd = isolate()->random_number_generator()->NextInt();
+      set_hash_seed(Smi::FromInt(rnd & Name::kHashBitMask));
     } else {
       set_hash_seed(Smi::FromInt(FLAG_hash_seed));
     }
index 5e2c8c2..45076f5 100644 (file)
@@ -28,9 +28,9 @@
 #ifndef V8_ISOLATE_INL_H_
 #define V8_ISOLATE_INL_H_
 
-#include "isolate.h"
-
 #include "debug.h"
+#include "isolate.h"
+#include "utils/random-number-generator.h"
 
 namespace v8 {
 namespace internal {
@@ -67,6 +67,13 @@ bool Isolate::DebuggerHasBreakPoints() {
 }
 
 
+RandomNumberGenerator* Isolate::random_number_generator() {
+  if (random_number_generator_ == NULL) {
+    random_number_generator_ = new RandomNumberGenerator;
+  }
+  return random_number_generator_;
+}
+
 } }  // namespace v8::internal
 
 #endif  // V8_ISOLATE_INL_H_
index 74a77c6..3a2084a 100644 (file)
@@ -39,7 +39,7 @@
 #include "deoptimizer.h"
 #include "heap-profiler.h"
 #include "hydrogen.h"
-#include "isolate.h"
+#include "isolate-inl.h"
 #include "lithium-allocator.h"
 #include "log.h"
 #include "marking-thread.h"
@@ -54,6 +54,7 @@
 #include "spaces.h"
 #include "stub-cache.h"
 #include "sweeper-thread.h"
+#include "utils/random-number-generator.h"
 #include "version.h"
 #include "vm-state-inl.h"
 
@@ -1772,6 +1773,9 @@ Isolate::Isolate()
       regexp_stack_(NULL),
       date_cache_(NULL),
       code_stub_interface_descriptors_(NULL),
+      // TODO(bmeurer) Initialized lazily because it depends on flags; can
+      // be fixed once the default isolate cleanup is done.
+      random_number_generator_(NULL),
       has_fatal_error_(false),
       use_crankshaft_(true),
       initialized_from_snapshot_(false),
@@ -2047,6 +2051,9 @@ Isolate::~Isolate() {
   delete external_reference_table_;
   external_reference_table_ = NULL;
 
+  delete random_number_generator_;
+  random_number_generator_ = NULL;
+
 #ifdef ENABLE_DEBUGGER_SUPPORT
   delete debugger_;
   debugger_ = NULL;
index 1debf4b..8db6f4b 100644 (file)
@@ -77,6 +77,7 @@ class NoAllocationStringAllocator;
 class InnerPointerToCodeCache;
 class MarkingThread;
 class PreallocatedMemoryThread;
+class RandomNumberGenerator;
 class RegExpStack;
 class SaveContext;
 class UnicodeCache;
@@ -1125,6 +1126,8 @@ class Isolate {
 
   void* stress_deopt_count_address() { return &stress_deopt_count_; }
 
+  inline RandomNumberGenerator* random_number_generator();
+
   // Given an address occupied by a live code object, return that object.
   Object* FindCodeObject(Address a);
 
@@ -1306,6 +1309,7 @@ class Isolate {
   DateCache* date_cache_;
   unibrow::Mapping<unibrow::Ecma262Canonicalize> interp_canonicalize_mapping_;
   CodeStubInterfaceDescriptor* code_stub_interface_descriptors_;
+  RandomNumberGenerator* random_number_generator_;
   bool is_memory_constrained_;
 
   // True if fatal error has been signaled for this isolate.
index 507fbfc..6476871 100644 (file)
@@ -4719,7 +4719,7 @@ Smi* JSReceiver::GenerateIdentityHash() {
   do {
     // Generate a random 32-bit hash value but limit range to fit
     // within a smi.
-    hash_value = V8::RandomPrivate(isolate) & Smi::kMaxValue;
+    hash_value = isolate->random_number_generator()->NextInt() & Smi::kMaxValue;
     attempts++;
   } while (hash_value == 0 && attempts < 30);
   hash_value = hash_value != 0 ? hash_value : 1;  // never return 0
index 6b41417..d7dcaf0 100644 (file)
@@ -236,8 +236,9 @@ static void* GetRandomAddr() {
     static const intptr_t kAllocationRandomAddressMin = 0x04000000;
     static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
 #endif
-    uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits)
-        | kAllocationRandomAddressMin;
+    uintptr_t address =
+        (isolate->random_number_generator()->NextInt() << kPageSizeBits) |
+        kAllocationRandomAddressMin;
     address &= kAllocationRandomAddressMax;
     return reinterpret_cast<void *>(address);
   }
@@ -366,16 +367,4 @@ bool VirtualMemory::HasLazyCommits() {
   return false;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator.
-  // Convert the current time to a 64-bit integer first, before converting it
-  // to an unsigned. Going directly can cause an overflow and the seed to be
-  // set to all ones. The seed will be identical for different instances that
-  // call this setup code within the same millisecond.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index b21ebf7..007bc0d 100644 (file)
@@ -340,16 +340,4 @@ bool VirtualMemory::HasLazyCommits() {
   return false;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator.
-  // Convert the current time to a 64-bit integer first, before converting it
-  // to an unsigned. Going directly can cause an overflow and the seed to be
-  // set to all ones. The seed will be identical for different instances that
-  // call this setup code within the same millisecond.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index 30825d7..d0fd77a 100644 (file)
@@ -466,12 +466,4 @@ bool VirtualMemory::HasLazyCommits() {
   return true;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator. We preserve microsecond resolution.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()) ^ (getpid() << 16);
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index 5dd38b2..f618737 100644 (file)
@@ -360,12 +360,4 @@ bool VirtualMemory::HasLazyCommits() {
   return false;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator. We preserve microsecond resolution.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()) ^ (getpid() << 16);
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index eb48373..faf9ba3 100644 (file)
@@ -397,12 +397,4 @@ bool VirtualMemory::HasLazyCommits() {
   return false;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator. We preserve microsecond resolution.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis()) ^ (getpid() << 16);
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index b111213..fe27eaf 100644 (file)
@@ -69,6 +69,7 @@
 #include "v8.h"
 
 #include "codegen.h"
+#include "isolate-inl.h"
 #include "platform.h"
 
 namespace v8 {
@@ -171,17 +172,14 @@ void* OS::GetRandomMmapAddr() {
   // CpuFeatures::Probe. We don't care about randomization in this case because
   // the code page is immediately freed.
   if (isolate != NULL) {
+    uintptr_t raw_addr;
+    isolate->random_number_generator()->NextBytes(&raw_addr, sizeof(raw_addr));
 #if V8_TARGET_ARCH_X64
-    uint64_t rnd1 = V8::RandomPrivate(isolate);
-    uint64_t rnd2 = V8::RandomPrivate(isolate);
-    uint64_t raw_addr = (rnd1 << 32) ^ rnd2;
     // Currently available CPUs have 48 bits of virtual addressing.  Truncate
     // the hint address to 46 bits to give the kernel a fighting chance of
     // fulfilling our placement request.
     raw_addr &= V8_UINT64_C(0x3ffffffff000);
 #else
-    uint32_t raw_addr = V8::RandomPrivate(isolate);
-
     raw_addr &= 0x3ffff000;
 
 # ifdef __sun
index d8b60c3..66f23ae 100644 (file)
@@ -361,16 +361,4 @@ bool VirtualMemory::HasLazyCommits() {
   return false;
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator.
-  // Convert the current time to a 64-bit integer first, before converting it
-  // to an unsigned. Going directly will cause an overflow and the seed to be
-  // set to all ones. The seed will be identical for different instances that
-  // call this setup code within the same millisecond.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
-  srandom(static_cast<unsigned int>(seed));
-}
-
-
 } }  // namespace v8::internal
index 8247d2e..83bfc89 100644 (file)
@@ -43,6 +43,7 @@
 #include "v8.h"
 
 #include "codegen.h"
+#include "isolate-inl.h"
 #include "platform.h"
 #include "simulator.h"
 #include "vm-state-inl.h"
@@ -124,13 +125,6 @@ int strncpy_s(char* dest, size_t dest_size, const char* source, size_t count) {
 
 #endif  // __MINGW32__
 
-// Generate a pseudo-random number in the range 0-2^31-1. Usually
-// defined in stdlib.h. Missing in both Microsoft Visual Studio C++ and MinGW.
-int random() {
-  return rand();
-}
-
-
 namespace v8 {
 namespace internal {
 
@@ -794,8 +788,9 @@ void* OS::GetRandomMmapAddr() {
     static const intptr_t kAllocationRandomAddressMin = 0x04000000;
     static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
 #endif
-    uintptr_t address = (V8::RandomPrivate(isolate) << kPageSizeBits)
-        | kAllocationRandomAddressMin;
+    uintptr_t address =
+        (isolate->random_number_generator()->NextInt() << kPageSizeBits) |
+        kAllocationRandomAddressMin;
     address &= kAllocationRandomAddressMax;
     return reinterpret_cast<void *>(address);
   }
@@ -1580,15 +1575,4 @@ void Thread::YieldCPU() {
   Sleep(0);
 }
 
-
-void OS::SetUp() {
-  // Seed the random number generator.
-  // Convert the current time to a 64-bit integer first, before converting it
-  // to an unsigned. Going directly can cause an overflow and the seed to be
-  // set to all ones. The seed will be identical for different instances that
-  // call this setup code within the same millisecond.
-  uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
-  srand(static_cast<unsigned int>(seed));
-}
-
 } }  // namespace v8::internal
index 6ae3fa0..428ba55 100644 (file)
@@ -86,11 +86,6 @@ inline int lrint(double flt) {
 
 #endif  // V8_CC_MSVC
 
-// Random is missing on both Visual Studio and MinGW.
-#if V8_CC_MSVC || V8_CC_MINGW
-int random();
-#endif  // V8_CC_MSVC || V8_CC_MINGW
-
 namespace v8 {
 namespace internal {
 
@@ -171,9 +166,6 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
 
 class OS {
  public:
-  // Initializes the platform OS support. Called once at VM startup.
-  static void SetUp();
-
   // Initializes the platform OS support that depend on CPU features. This is
   // called after CPU initialization.
   static void PostSetUp();
index 3fed628..2ce6cdd 100644 (file)
@@ -222,6 +222,15 @@ class Time V8_FINAL BASE_EMBEDDED {
   // with which we might compare it.
   static Time Max() { return Time(std::numeric_limits<int64_t>::max()); }
 
+  // Converts to/from internal values. The meaning of the "internal value" is
+  // completely up to the implementation, so it should be treated as opaque.
+  static Time FromInternalValue(int64_t value) {
+    return Time(value);
+  }
+  int64_t ToInternalValue() const {
+    return us_;
+  }
+
   // Converts to/from POSIX time specs.
   static Time FromTimespec(struct timespec ts);
   struct timespec ToTimespec() const;
@@ -329,6 +338,15 @@ class TimeTicks V8_FINAL BASE_EMBEDDED {
   // Returns true if this object has not been initialized.
   bool IsNull() const { return ticks_ == 0; }
 
+  // Converts to/from internal values. The meaning of the "internal value" is
+  // completely up to the implementation, so it should be treated as opaque.
+  static TimeTicks FromInternalValue(int64_t value) {
+    return TimeTicks(value);
+  }
+  int64_t ToInternalValue() const {
+    return ticks_;
+  }
+
   TimeTicks& operator=(const TimeTicks other) {
     ticks_ = other.ticks_;
     return *this;
diff --git a/src/utils/random-number-generator.cc b/src/utils/random-number-generator.cc
new file mode 100644 (file)
index 0000000..1e03ee2
--- /dev/null
@@ -0,0 +1,136 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "utils/random-number-generator.h"
+
+#include <cstdio>
+
+#include "flags.h"
+#include "platform/mutex.h"
+#include "platform/time.h"
+#include "utils.h"
+
+namespace v8 {
+namespace internal {
+
+static LazyMutex entropy_mutex = LAZY_MUTEX_INITIALIZER;
+static RandomNumberGenerator::EntropySource entropy_source = NULL;
+
+
+// static
+void RandomNumberGenerator::SetEntropySource(EntropySource source) {
+  LockGuard<Mutex> lock_guard(entropy_mutex.Pointer());
+  entropy_source = source;
+}
+
+
+RandomNumberGenerator::RandomNumberGenerator() {
+  // Check --random-seed flag first.
+  if (FLAG_random_seed != 0) {
+    SetSeed(FLAG_random_seed);
+    return;
+  }
+
+  // Check if embedder supplied an entropy source.
+  { LockGuard<Mutex> lock_guard(entropy_mutex.Pointer());
+    if (entropy_source != NULL) {
+      int64_t seed;
+      if (entropy_source(reinterpret_cast<unsigned char*>(&seed),
+                         sizeof(seed))) {
+        SetSeed(seed);
+        return;
+      }
+    }
+  }
+
+  // Gather entropy from /dev/urandom if available.
+  FILE* fp = fopen("/dev/urandom", "rb");
+  if (fp != NULL) {
+    int64_t seed;
+    size_t n = fread(&seed, sizeof(seed), 1, fp);
+    fclose(fp);
+    if (n == 1) {
+      SetSeed(seed);
+      return;
+    }
+  }
+
+  // We cannot assume that random() or rand() were seeded
+  // properly, so instead of relying on random() or rand(),
+  // we just seed our PRNG using timing data as fallback.
+  int64_t seed = Time::NowFromSystemTime().ToInternalValue() << 24;
+  seed ^= TimeTicks::HighResNow().ToInternalValue() << 16;
+  seed ^= TimeTicks::Now().ToInternalValue() << 8;
+  SetSeed(seed);
+}
+
+
+int RandomNumberGenerator::NextInt(int max) {
+  ASSERT_LE(0, max);
+
+  // Fast path if max is a power of 2.
+  if (IsPowerOf2(max)) {
+    return static_cast<int>((max * static_cast<int64_t>(Next(31))) >> 31);
+  }
+
+  while (true) {
+    int rnd = Next(31);
+    int val = rnd % max;
+    if (rnd - val + (max - 1) >= 0) {
+      return val;
+    }
+  }
+}
+
+
+double RandomNumberGenerator::NextDouble() {
+  return ((static_cast<int64_t>(Next(26)) << 27) + Next(27)) /
+      static_cast<double>(static_cast<int64_t>(1) << 53);
+}
+
+
+void RandomNumberGenerator::NextBytes(void* buffer, size_t buflen) {
+  for (size_t n = 0; n < buflen; ++n) {
+    static_cast<uint8_t*>(buffer)[n] = static_cast<uint8_t>(Next(8));
+  }
+}
+
+
+int RandomNumberGenerator::Next(int bits) {
+  ASSERT_LT(0, bits);
+  ASSERT_GE(32, bits);
+  int64_t seed = (seed_ * kMultiplier + kAddend) & kMask;
+  seed_ = seed;
+  return static_cast<int>(seed >> (48 - bits));
+}
+
+
+void RandomNumberGenerator::SetSeed(int64_t seed) {
+  seed_ = (seed ^ kMultiplier) & kMask;
+}
+
+} }  // namespace v8::internal
diff --git a/src/utils/random-number-generator.h b/src/utils/random-number-generator.h
new file mode 100644 (file)
index 0000000..fc14ef4
--- /dev/null
@@ -0,0 +1,106 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef V8_UTILS_RANDOM_NUMBER_GENERATOR_H_
+#define V8_UTILS_RANDOM_NUMBER_GENERATOR_H_
+
+#include "globals.h"
+
+namespace v8 {
+namespace internal {
+
+// -----------------------------------------------------------------------------
+// RandomNumberGenerator
+//
+// This class is used to generate a stream of pseudorandom numbers. The class
+// uses a 48-bit seed, which is modified using a linear congruential formula.
+// (See Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.)
+// If two instances of RandomNumberGenerator are created with the same seed, and
+// the same sequence of method calls is made for each, they will generate and
+// return identical sequences of numbers.
+// This class is neither reentrant nor threadsafe.
+
+class RandomNumberGenerator V8_FINAL {
+ public:
+  // EntropySource is used as a callback function when V8 needs a source of
+  // entropy.
+  typedef bool (*EntropySource)(unsigned char* buffer, size_t buflen);
+  static void SetEntropySource(EntropySource entropy_source);
+
+  RandomNumberGenerator();
+  explicit RandomNumberGenerator(int64_t seed) { SetSeed(seed); }
+
+  // Returns the next pseudorandom, uniformly distributed int value from this
+  // random number generator's sequence. The general contract of |NextInt()| is
+  // that one int value is pseudorandomly generated and returned.
+  // All 2^32 possible integer values are produced with (approximately) equal
+  // probability.
+  V8_INLINE(int NextInt()) V8_WARN_UNUSED_RESULT {
+    return Next(32);
+  }
+
+  // Returns a pseudorandom, uniformly distributed int value between 0
+  // (inclusive) and the specified max value (exclusive), drawn from this random
+  // number generator's sequence. The general contract of |NextInt(int)| is that
+  // one int value in the specified range is pseudorandomly generated and
+  // returned. All max possible int values are produced with (approximately)
+  // equal probability.
+  int NextInt(int max) V8_WARN_UNUSED_RESULT;
+
+  // Returns the next pseudorandom, uniformly distributed boolean value from
+  // this random number generator's sequence. The general contract of
+  // |NextBoolean()| is that one boolean value is pseudorandomly generated and
+  // returned. The values true and false are produced with (approximately) equal
+  // probability.
+  V8_INLINE(bool NextBool()) V8_WARN_UNUSED_RESULT {
+    return Next(1) != 0;
+  }
+
+  // Returns the next pseudorandom, uniformly distributed double value between
+  // 0.0 and 1.0 from this random number generator's sequence.
+  // The general contract of |NextDouble()| is that one double value, chosen
+  // (approximately) uniformly from the range 0.0 (inclusive) to 1.0
+  // (exclusive), is pseudorandomly generated and returned.
+  double NextDouble() V8_WARN_UNUSED_RESULT;
+
+  // Fills the elements of a specified array of bytes with random numbers.
+  void NextBytes(void* buffer, size_t buflen);
+
+ private:
+  static const int64_t kMultiplier = V8_2PART_UINT64_C(0x5, deece66d);
+  static const int64_t kAddend = 0xb;
+  static const int64_t kMask = V8_2PART_UINT64_C(0xffff, ffffffff);
+
+  int Next(int bits) V8_WARN_UNUSED_RESULT;
+  void SetSeed(int64_t seed);
+
+  int64_t seed_;
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_UTILS_RANDOM_NUMBER_GENERATOR_H_
index d9ce840..e894164 100644 (file)
--- a/src/v8.cc
+++ b/src/v8.cc
@@ -53,10 +53,6 @@ V8_DECLARE_ONCE(init_once);
 List<CallCompletedCallback>* V8::call_completed_callbacks_ = NULL;
 v8::ArrayBuffer::Allocator* V8::array_buffer_allocator_ = NULL;
 
-static LazyMutex entropy_mutex = LAZY_MUTEX_INITIALIZER;
-
-static EntropySource entropy_source;
-
 
 bool V8::Initialize(Deserializer* des) {
   InitializeOncePerProcess();
@@ -107,41 +103,6 @@ void V8::TearDown() {
 }
 
 
-static void seed_random(uint32_t* state) {
-  for (int i = 0; i < 2; ++i) {
-    if (FLAG_random_seed != 0) {
-      state[i] = FLAG_random_seed;
-    } else if (entropy_source != NULL) {
-      uint32_t val;
-      LockGuard<Mutex> lock_guard(entropy_mutex.Pointer());
-      entropy_source(reinterpret_cast<unsigned char*>(&val), sizeof(uint32_t));
-      state[i] = val;
-    } else {
-      state[i] = random();
-    }
-  }
-}
-
-
-// Random number generator using George Marsaglia's MWC algorithm.
-static uint32_t random_base(uint32_t* state) {
-  // Initialize seed using the system random().
-  // No non-zero seed will ever become zero again.
-  if (state[0] == 0) seed_random(state);
-
-  // Mix the bits.  Never replaces state[i] with 0 if it is nonzero.
-  state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16);
-  state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
-
-  return (state[0] << 14) + (state[1] & 0x3FFFF);
-}
-
-
-void V8::SetEntropySource(EntropySource source) {
-  entropy_source = source;
-}
-
-
 void V8::SetReturnAddressLocationResolver(
       ReturnAddressLocationResolver resolver) {
   StackFrame::SetReturnAddressLocationResolver(resolver);
@@ -152,15 +113,18 @@ void V8::SetReturnAddressLocationResolver(
 uint32_t V8::Random(Context* context) {
   ASSERT(context->IsNativeContext());
   ByteArray* seed = context->random_seed();
-  return random_base(reinterpret_cast<uint32_t*>(seed->GetDataStartAddress()));
-}
+  uint32_t* state = reinterpret_cast<uint32_t*>(seed->GetDataStartAddress());
+
+  // When we get here, the RNG must have been initialized,
+  // see the Genesis constructor in file bootstrapper.cc.
+  ASSERT_NE(0, state[0]);
+  ASSERT_NE(0, state[1]);
 
+  // Mix the bits.  Never replaces state[i] with 0 if it is nonzero.
+  state[0] = 18273 * (state[0] & 0xFFFF) + (state[0] >> 16);
+  state[1] = 36969 * (state[1] & 0xFFFF) + (state[1] >> 16);
 
-// Used internally by the JIT and memory allocator for security
-// purposes. So, we keep a different state to prevent informations
-// leaks that could be used in an exploit.
-uint32_t V8::RandomPrivate(Isolate* isolate) {
-  return random_base(isolate->private_random_seed());
+  return (state[0] << 14) + (state[1] & 0x3FFFF);
 }
 
 
@@ -282,7 +246,6 @@ void V8::InitializeOncePerProcessImpl() {
     FLAG_concurrent_recompilation = false;
   }
 
-  OS::SetUp();
   Sampler::SetUp();
   CPU::SetUp();
   OS::PostSetUp();
index 23277b3..5848f74 100644 (file)
--- a/src/v8.h
+++ b/src/v8.h
@@ -97,11 +97,6 @@ class V8 : public AllStatic {
   static void SetFunctionEntryHook(FunctionEntryHook entry_hook);
   // Random number generation support. Not cryptographically safe.
   static uint32_t Random(Context* context);
-  // We use random numbers internally in memory allocation and in the
-  // compilers for security. In order to prevent information leaks we
-  // use a separate random state for internal random number
-  // generation.
-  static uint32_t RandomPrivate(Isolate* isolate);
   static Object* FillHeapNumberWithRandom(Object* heap_number,
                                           Context* context);
 
index 75d26b6..0775cc5 100644 (file)
@@ -91,6 +91,7 @@
         'test-platform-tls.cc',
         'test-profile-generator.cc',
         'test-random.cc',
+        'test-random-number-generator.cc',
         'test-regexp.cc',
         'test-reloc-info.cc',
         'test-semaphore.cc',
index d5aaf4f..f7d2311 100644 (file)
@@ -90,7 +90,6 @@ static const v8::internal::Register arg2 = rsi;
 
 
 TEST(AssemblerX64ReturnOperation) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -113,7 +112,6 @@ TEST(AssemblerX64ReturnOperation) {
 
 
 TEST(AssemblerX64StackOperations) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -146,7 +144,6 @@ TEST(AssemblerX64StackOperations) {
 
 
 TEST(AssemblerX64ArithmeticOperations) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -169,7 +166,6 @@ TEST(AssemblerX64ArithmeticOperations) {
 
 
 TEST(AssemblerX64ImulOperation) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -198,7 +194,6 @@ TEST(AssemblerX64ImulOperation) {
 
 
 TEST(AssemblerX64MemoryOperands) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -233,7 +228,6 @@ TEST(AssemblerX64MemoryOperands) {
 
 
 TEST(AssemblerX64ControlFlow) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
@@ -263,7 +257,6 @@ TEST(AssemblerX64ControlFlow) {
 
 
 TEST(AssemblerX64LoopImmediates) {
-  OS::SetUp();
   // Allocate an executable page of memory.
   size_t actual_size;
   byte* buffer = static_cast<byte*>(OS::Allocate(Assembler::kMinimalBufferSize,
index 34ae43c..f289e94 100644 (file)
@@ -40,7 +40,6 @@ using namespace ::v8::internal;
 
 
 TEST(VirtualMemory) {
-  OS::SetUp();
   VirtualMemory* vm = new VirtualMemory(1 * MB);
   CHECK(vm->IsReserved());
   void* block_addr = vm->address();
@@ -55,6 +54,5 @@ TEST(VirtualMemory) {
 
 
 TEST(GetCurrentProcessId) {
-  OS::SetUp();
   CHECK_EQ(static_cast<int>(getpid()), OS::GetCurrentProcessId());
 }
index a5089d3..d7fdab1 100644 (file)
@@ -39,7 +39,6 @@ using namespace ::v8::internal;
 
 
 TEST(VirtualMemory) {
-  OS::SetUp();
   VirtualMemory* vm = new VirtualMemory(1 * MB);
   CHECK(vm->IsReserved());
   void* block_addr = vm->address();
@@ -54,7 +53,6 @@ TEST(VirtualMemory) {
 
 
 TEST(GetCurrentProcessId) {
-  OS::SetUp();
   CHECK_EQ(static_cast<int>(::GetCurrentProcessId()),
            OS::GetCurrentProcessId());
 }
diff --git a/test/cctest/test-random-number-generator.cc b/test/cctest/test-random-number-generator.cc
new file mode 100644 (file)
index 0000000..d9fadfa
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright 2013 the V8 project authors. All rights reserved.
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+//       notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+//       copyright notice, this list of conditions and the following
+//       disclaimer in the documentation and/or other materials provided
+//       with the distribution.
+//     * Neither the name of Google Inc. nor the names of its
+//       contributors may be used to endorse or promote products derived
+//       from this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "v8.h"
+
+#include "cctest.h"
+#include "utils/random-number-generator.h"
+
+using namespace v8::internal;
+
+
+static const int kMaxRuns = 12345;
+static const int kRandomSeeds[] = {
+  -1, 1, 42, 100, 1234567890, 987654321, 0xdeadbeef
+};
+
+
+TEST(NextIntWithMaxValue) {
+  for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) {
+    RandomNumberGenerator rng(kRandomSeeds[n]);
+    for (int max = 1; max <= kMaxRuns; ++max) {
+      int n = rng.NextInt(max);
+      CHECK_LE(0, n);
+      CHECK_LT(n, max);
+    }
+  }
+}
+
+
+TEST(NextBoolReturnsBooleanValue) {
+  for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) {
+    RandomNumberGenerator rng(kRandomSeeds[n]);
+    for (int k = 0; k < kMaxRuns; ++k) {
+      bool b = rng.NextBool();
+      CHECK(b == false || b == true);
+    }
+  }
+}
+
+
+TEST(NextDoubleRange) {
+  for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) {
+    RandomNumberGenerator rng(kRandomSeeds[n]);
+    for (int k = 0; k < kMaxRuns; ++k) {
+      double d = rng.NextDouble();
+      CHECK_LE(0.0, d);
+      CHECK_LT(d, 1.0);
+    }
+  }
+}
+
+
+TEST(RandomSeedFlagIsUsed) {
+  for (unsigned n = 0; n < ARRAY_SIZE(kRandomSeeds); ++n) {
+    FLAG_random_seed = kRandomSeeds[n];
+    RandomNumberGenerator rng1;
+    RandomNumberGenerator rng2(kRandomSeeds[n]);
+    for (int k = 1; k <= kMaxRuns; ++k) {
+      int64_t i1, i2;
+      rng1.NextBytes(&i1, sizeof(i1));
+      rng2.NextBytes(&i2, sizeof(i2));
+      CHECK_EQ(i2, i1);
+      CHECK_EQ(rng2.NextInt(), rng1.NextInt());
+      CHECK_EQ(rng2.NextInt(k), rng1.NextInt(k));
+      CHECK_EQ(rng2.NextDouble(), rng1.NextDouble());
+    }
+  }
+}
index 804546a..4227326 100644 (file)
@@ -96,14 +96,5 @@ TEST(CrankshaftRandom) {
   // Test with some random values.
   TestSeeds(fun, context, 0xC0C0AFFE, 0x31415926);
   TestSeeds(fun, context, 0x01020304, 0xFFFFFFFF);
-  TestSeeds(fun, context, 0x00000001, 0x00000000);
-
-  // Test that we bail out to runtime when seeds are uninitialized (zeros).
-  SetSeeds(seeds, 0, 0);
-  Handle<Object> value =
-      Execution::Call(isolate, fun, global, 0, NULL, &has_pending_exception);
-  CHECK(value->IsHeapNumber());
-  CHECK(fun->IsOptimized());
-  double crankshaft_value = HeapNumber::cast(*value)->value();
-  CHECK_NE(0.0, crankshaft_value);
+  TestSeeds(fun, context, 0x00000001, 0x00000001);
 }
index 1f362d7..3326a01 100644 (file)
@@ -207,7 +207,6 @@ static unsigned int Pseudorandom() {
 
 
 TEST(MemoryChunk) {
-  OS::SetUp();
   Isolate* isolate = Isolate::Current();
   isolate->InitializeLoggingAndCounters();
   Heap* heap = isolate->heap();
@@ -264,7 +263,6 @@ TEST(MemoryChunk) {
 
 
 TEST(MemoryAllocator) {
-  OS::SetUp();
   Isolate* isolate = Isolate::Current();
   isolate->InitializeLoggingAndCounters();
   Heap* heap = isolate->heap();
@@ -314,7 +312,6 @@ TEST(MemoryAllocator) {
 
 
 TEST(NewSpace) {
-  OS::SetUp();
   Isolate* isolate = Isolate::Current();
   isolate->InitializeLoggingAndCounters();
   Heap* heap = isolate->heap();
@@ -344,7 +341,6 @@ TEST(NewSpace) {
 
 
 TEST(OldSpace) {
-  OS::SetUp();
   Isolate* isolate = Isolate::Current();
   isolate->InitializeLoggingAndCounters();
   Heap* heap = isolate->heap();
index 726188d..9049df1 100644 (file)
@@ -41,9 +41,9 @@
 #include "zone-inl.h"
 
 // Adapted from http://en.wikipedia.org/wiki/Multiply-with-carry
-class RandomNumberGenerator {
+class MyRandomNumberGenerator {
  public:
-  RandomNumberGenerator() {
+  MyRandomNumberGenerator() {
     init();
   }
 
@@ -133,7 +133,7 @@ class AsciiResource: public v8::String::ExternalAsciiStringResource,
 static void InitializeBuildingBlocks(Handle<String>* building_blocks,
                                      int bb_length,
                                      bool long_blocks,
-                                     RandomNumberGenerator* rng,
+                                     MyRandomNumberGenerator* rng,
                                      Zone* zone) {
   // A list of pointers that we don't have any interest in cleaning up.
   // If they are reachable from a root then leak detection won't complain.
@@ -276,7 +276,7 @@ class ConsStringGenerationData {
   // Cached data.
   Handle<String> building_blocks_[kNumberOfBuildingBlocks];
   String* empty_string_;
-  RandomNumberGenerator rng_;
+  MyRandomNumberGenerator rng_;
   // Stats.
   ConsStringStats stats_;
   unsigned early_terminations_;
index 952f57c..e7d8576 100644 (file)
@@ -432,7 +432,7 @@ static uint32_t DeterministicRandom() {
   static uint32_t lo = 0;
 
   // Initialization values don't have any special meaning. (They are the result
-  // of two calls to random().)
+  // of two calls to rand().)
   if (hi == 0) hi = 0xbfe166e7;
   if (lo == 0) lo = 0x64d1c3c9;
 
@@ -448,12 +448,13 @@ static const int kShortStrtodRandomCount = 2;
 static const int kLargeStrtodRandomCount = 2;
 
 TEST(RandomStrtod) {
+  srand(time(NULL));
   char buffer[kBufferSize];
   for (int length = 1; length < 15; length++) {
     for (int i = 0; i < kShortStrtodRandomCount; ++i) {
       int pos = 0;
       for (int j = 0; j < length; ++j) {
-        buffer[pos++] = random() % 10 + '0';
+        buffer[pos++] = rand() % 10 + '0';
       }
       int exponent = DeterministicRandom() % (25*2 + 1) - 25 - length;
       buffer[pos] = '\0';
@@ -466,7 +467,7 @@ TEST(RandomStrtod) {
     for (int i = 0; i < kLargeStrtodRandomCount; ++i) {
       int pos = 0;
       for (int j = 0; j < length; ++j) {
-        buffer[pos++] = random() % 10 + '0';
+        buffer[pos++] = rand() % 10 + '0';
       }
       int exponent = DeterministicRandom() % (308*2 + 1) - 308 - length;
       buffer[pos] = '\0';
index 541c423..feff477 100644 (file)
@@ -140,7 +140,6 @@ void TestMemMove(byte* area1,
 
 TEST(MemMove) {
   v8::V8::Initialize();
-  OS::SetUp();
   byte* area1 = new byte[kAreaSize];
   byte* area2 = new byte[kAreaSize];
   byte* area3 = new byte[kAreaSize];
index 5a5a2ae..5d4933a 100644 (file)
         '../../src/utils-inl.h',
         '../../src/utils.cc',
         '../../src/utils.h',
+        '../../src/utils/random-number-generator.cc',
+        '../../src/utils/random-number-generator.h',
         '../../src/v8-counters.cc',
         '../../src/v8-counters.h',
         '../../src/v8.cc',