diff options
author | Refael Ackermann <refack@gmail.com> | 2014-09-29 13:20:04 +0400 |
---|---|---|
committer | Fedor Indutny <fedor@indutny.com> | 2014-10-08 15:35:57 +0400 |
commit | 939278ac059b44439d41aab12bf552c8ae3c52d0 (patch) | |
tree | 86c586915a96d308b1b04de679a8ae293caf3e41 /deps/v8/src/base/utils | |
parent | 4412a71d76a0fa002f627ec21d2337e089da6764 (diff) | |
download | android-node-v8-939278ac059b44439d41aab12bf552c8ae3c52d0.tar.gz android-node-v8-939278ac059b44439d41aab12bf552c8ae3c52d0.tar.bz2 android-node-v8-939278ac059b44439d41aab12bf552c8ae3c52d0.zip |
deps: update v8 to 3.28.73
Reviewed-By: Fedor Indutny <fedor@indutny.com>
PR-URL: https://github.com/joyent/node/pull/8476
Diffstat (limited to 'deps/v8/src/base/utils')
-rw-r--r-- | deps/v8/src/base/utils/random-number-generator.cc | 131 | ||||
-rw-r--r-- | deps/v8/src/base/utils/random-number-generator.h | 89 |
2 files changed, 220 insertions, 0 deletions
diff --git a/deps/v8/src/base/utils/random-number-generator.cc b/deps/v8/src/base/utils/random-number-generator.cc new file mode 100644 index 0000000000..be79811171 --- /dev/null +++ b/deps/v8/src/base/utils/random-number-generator.cc @@ -0,0 +1,131 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "src/base/utils/random-number-generator.h" + +#include <stdio.h> +#include <stdlib.h> + +#include <new> + +#include "src/base/macros.h" +#include "src/base/platform/mutex.h" +#include "src/base/platform/time.h" + +namespace v8 { +namespace base { + +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 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; + } + } + } + +#if V8_OS_CYGWIN || V8_OS_WIN + // Use rand_s() to gather entropy on Windows. See: + // https://code.google.com/p/v8/issues/detail?id=2905 + unsigned first_half, second_half; + errno_t result = rand_s(&first_half); + DCHECK_EQ(0, result); + result = rand_s(&second_half); + DCHECK_EQ(0, result); + SetSeed((static_cast<int64_t>(first_half) << 32) + second_half); +#else + // 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. + // This is weak entropy, but it's sufficient, because + // it is the responsibility of the embedder to install + // an entropy source using v8::V8::SetEntropySource(), + // which provides reasonable entropy, see: + // https://code.google.com/p/v8/issues/detail?id=2905 + int64_t seed = Time::NowFromSystemTime().ToInternalValue() << 24; + seed ^= TimeTicks::HighResolutionNow().ToInternalValue() << 16; + seed ^= TimeTicks::Now().ToInternalValue() << 8; + SetSeed(seed); +#endif // V8_OS_CYGWIN || V8_OS_WIN +} + + +int RandomNumberGenerator::NextInt(int max) { + DCHECK_LE(0, max); + + // Fast path if max is a power of 2. + if (IS_POWER_OF_TWO(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) { + DCHECK_LT(0, bits); + DCHECK_GE(32, bits); + // Do unsigned multiplication, which has the intended modulo semantics, while + // signed multiplication would expose undefined behavior. + uint64_t product = static_cast<uint64_t>(seed_) * kMultiplier; + // Assigning a uint64_t to an int64_t is implementation defined, but this + // should be OK. Use a static_cast to explicitly state that we know what we're + // doing. (Famous last words...) + int64_t seed = static_cast<int64_t>((product + kAddend) & kMask); + seed_ = seed; + return static_cast<int>(seed >> (48 - bits)); +} + + +void RandomNumberGenerator::SetSeed(int64_t seed) { + seed_ = (seed ^ kMultiplier) & kMask; +} + +} } // namespace v8::base diff --git a/deps/v8/src/base/utils/random-number-generator.h b/deps/v8/src/base/utils/random-number-generator.h new file mode 100644 index 0000000000..5955d66597 --- /dev/null +++ b/deps/v8/src/base/utils/random-number-generator.h @@ -0,0 +1,89 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8_BASE_UTILS_RANDOM_NUMBER_GENERATOR_H_ +#define V8_BASE_UTILS_RANDOM_NUMBER_GENERATOR_H_ + +#include "src/base/macros.h" + +namespace v8 { +namespace base { + +// ----------------------------------------------------------------------------- +// 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 uses (probably) weak entropy by default, but it's sufficient, +// because it is the responsibility of the embedder to install an entropy source +// using v8::V8::SetEntropySource(), which provides reasonable entropy, see: +// https://code.google.com/p/v8/issues/detail?id=2905 +// 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); + + // Override the current ssed. + void SetSeed(int64_t seed); + + 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; + + int64_t seed_; +}; + +} } // namespace v8::base + +#endif // V8_BASE_UTILS_RANDOM_NUMBER_GENERATOR_H_ |