Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git "a/src/base/\043functional.h\043" "b/src/base/\043functional.h\043"
new file mode 100644
index 0000000..ff0d807
--- /dev/null
+++ "b/src/base/\043functional.h\043"
@@ -0,0 +1,227 @@
+// Copyright 2014 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_FUNCTIONAL_H_
+#define V8_BASE_FUNCTIONAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstddef>
+#include <cstring>
+#include <functional>
+#include <utility>
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+// base::hash is an implementation of the hash function object specified by
+// C++11. It was designed to be compatible with std::hash (in C++11) and
+// boost:hash (which in turn is based on the hash function object specified by
+// the Draft Technical Report on C++ Library Extensions (TR1)).
+//
+// base::hash is implemented by calling the hash_value function. The namespace
+// isn't specified so that it can detect overloads via argument dependant
+// lookup. So if there is a free function hash_value in the same namespace as a
+// custom type, it will get called.
+//
+// If users are asked to implement a hash function for their own types with no
+// guidance, they generally write bad hash functions. Instead, we provide a
+// simple function base::hash_combine to pass hash-relevant member variables
+// into, in order to define a decent hash function. base::hash_combine is
+// declared as:
+//
+// template<typename T, typename... Ts>
+// size_t hash_combine(const T& v, const Ts& ...vs);
+//
+// Consider the following example:
+//
+// namespace v8 {
+// namespace bar {
+// struct Point { int x; int y; };
+// size_t hash_value(Point const& p) {
+// return base::hash_combine(p.x, p.y);
+// }
+// }
+//
+// namespace foo {
+// void DoSomeWork(bar::Point const& p) {
+// base::hash<bar::Point> h;
+// ...
+// size_t hash_code = h(p); // calls bar::hash_value(Point const&)
+// ...
+// }
+// }
+// }
+//
+// Based on the "Hashing User-Defined Types in C++1y" proposal from Jeffrey
+// Yasskin and Chandler Carruth, see
+// http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2012/n3333.html.
+
+template <typename>
+struct hash;
+
+
+V8_INLINE size_t hash_combine() { return 0u; }
+V8_INLINE size_t hash_combine(size_t seed) { return seed; }
+size_t hash_combine(size_t seed, size_t value);
+template <typename T, typename... Ts>
+V8_INLINE size_t hash_combine(T const& v, Ts const&... vs) {
+ return hash_combine(hash_combine(vs...), hash<T>()(v));
+}
+
+
+template <typename Iterator>
+V8_INLINE size_t hash_range(Iterator first, Iterator last) {
+ size_t seed = 0;
+ for (; first != last; ++first) {
+ seed = hash_combine(seed, *first);
+ }
+ return seed;
+}
+
+
+#define V8_BASE_HASH_VALUE_TRIVIAL(type) \
+ V8_INLINE size_t hash_value(type v) { return static_cast<size_t>(v); }
+V8_BASE_HASH_VALUE_TRIVIAL(bool)
+V8_BASE_HASH_VALUE_TRIVIAL(unsigned char)
+V8_BASE_HASH_VALUE_TRIVIAL(unsigned short) // NOLINT(runtime/int)
+#undef V8_BASE_HASH_VALUE_TRIVIAL
+
+size_t hash_value(unsigned int);
+size_t hash_value(unsigned long); // NOLINT(runtime/int)
+size_t hash_value(unsigned long long); // NOLINT(runtime/int)
+
+#define V8_BASE_HASH_VALUE_SIGNED(type) \
+ V8_INLINE size_t hash_value(signed type v) { \
+ return hash_value(bit_cast<unsigned type>(v)); \
+ }
+V8_BASE_HASH_VALUE_SIGNED(char)
+V8_BASE_HASH_VALUE_SIGNED(short) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(int) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(long) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(long long) // NOLINT(runtime/int)
+#undef V8_BASE_HASH_VALUE_SIGNED
+
+V8_INLINE size_t hash_value(float v) {
+ // 0 and -0 both hash to zero.
+ return v != 0.0f ? hash_value(bit_cast<uint32_t>(v)) : 0;
+}
+
+V8_INLINE size_t hash_value(double v) {
+ // 0 and -0 both hash to zero.
+ return v != 0.0 ? hash_value(bit_cast<uint64_t>(v)) : 0;
+}
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(const T (&v)[N]) {
+ return hash_range(v, v + N);
+}
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(T (&v)[N]) {
+ return hash_range(v, v + N);
+}
+
+template <typename T>
+V8_INLINE size_t hash_value(T* const& v) {
+ return hash_value(bit_cast<uintptr_t>(v));
+}
+
+template <typename T1, typename T2>
+V8_INLINE size_t hash_value(std::pair<T1, T2> const& v) {
+ return hash_combine(v.first, v.second);
+}
+
+
+template <typename T>
+struct hash : public std::unary_function<T, size_t> {
+ V8_INLINE size_t operator()(T const& v) const { return hash_value(v); }
+};
+
+#define V8_BASE_HASH_SPECIALIZE(type) \
+ template <> \
+ struct hash<type> : public std::unary_function<type, size_t> { \
+ V8_INLINE size_t operator()(type const v) const { \
+ return ::v8::base::hash_value(v); \
+ } \
+ };
+V8_BASE_HASH_SPECIALIZE(bool)
+V8_BASE_HASH_SPECIALIZE(signed char)
+V8_BASE_HASH_SPECIALIZE(unsigned char)
+V8_BASE_HASH_SPECIALIZE(short) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned short) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(int)
+V8_BASE_HASH_SPECIALIZE(unsigned int)
+V8_BASE_HASH_SPECIALIZE(long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(long long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned long long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(float)
+V8_BASE_HASH_SPECIALIZE(double)
+#undef V8_BASE_HASH_SPECIALIZE
+
+template <typename T>
+struct hash<T*> : public std::unary_function<T*, size_t> {
+ V8_INLINE size_t operator()(T* const v) const {
+ return ::v8::base::hash_value(v);
+ }
+};
+
+
+// base::bit_equal_to is a function object class for bitwise equality
+// comparison, similar to std::equal_to, except that the comparison is performed
+// on the bit representation of the operands.
+//
+// base::bit_hash is a function object class for bitwise hashing, similar to
+// base::hash. It can be used together with base::bit_equal_to to implement a
+// hash data structure based on the bitwise representation of types.
+
+template <typename T>
+struct bit_equal_to : public std::binary_function<T, T, bool> {};
+
+template <typename T>
+struct bit_hash : public std::unary_function<T, size_t> {};
+
+#define V8_BASE_BIT_SPECIALIZE_TRIVIAL(type) \
+ template <> \
+ struct bit_equal_to<type> : public std::equal_to<type> {}; \
+ template <> \
+ struct bit_hash<type> : public hash<type> {};
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(signed char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(short) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned short) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long long) // NOLINT(runtime/int)
+#undef V8_BASE_BIT_SPECIALIZE_TRIVIAL
+
+#define V8_BASE_BIT_SPECIALIZE_BIT_CAST(type, btype) \
+ template <> \
+ struct bit_equal_to<type> : public std::binary_function<type, type, bool> { \
+ V8_INLINE bool operator()(type lhs, type rhs) const { \
+ return bit_cast<btype>(lhs) == bit_cast<btype>(rhs); \
+ } \
+ }; \
+ template <> \
+ struct bit_hash<type> : public std::unary_function<type, size_t> { \
+ V8_INLINE size_t operator()(type v) const { \
+ hash<btype> h; \
+ return h(bit_cast<btype>(v)); \
+ } \
+ };
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(float, uint32_t)
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(double, uint64_t)
+#undef V8_BASE_BIT_SPECIALIZE_BIT_CAST
+
+} // namespace base
+} // namespace v8
+
+#endif // V8_BASE_FUNCTIONAL_H_
diff --git a/src/base/atomicops.h b/src/base/atomicops.h
index eba172f..675e43f 100644
--- a/src/base/atomicops.h
+++ b/src/base/atomicops.h
@@ -25,7 +25,7 @@
#ifndef V8_BASE_ATOMICOPS_H_
#define V8_BASE_ATOMICOPS_H_
-#include "include/v8stdint.h"
+#include <stdint.h>
#include "src/base/build_config.h"
#if defined(_WIN32) && defined(V8_HOST_ARCH_64_BIT)
@@ -42,15 +42,17 @@
typedef char Atomic8;
typedef int32_t Atomic32;
-#ifdef V8_HOST_ARCH_64_BIT
+#if defined(__native_client__)
+typedef int64_t Atomic64;
+#elif defined(V8_HOST_ARCH_64_BIT)
// We need to be able to go between Atomic64 and AtomicWord implicitly. This
// means Atomic64 and AtomicWord should be the same type on 64-bit.
#if defined(__ILP32__)
typedef int64_t Atomic64;
#else
typedef intptr_t Atomic64;
-#endif
-#endif
+#endif // defined(V8_HOST_ARCH_64_BIT)
+#endif // defined(__native_client__)
// Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or
// Atomic64 routines below, depending on your architecture.
@@ -140,6 +142,8 @@
#include "src/base/atomicops_internals_x86_msvc.h"
#elif defined(__APPLE__)
#include "src/base/atomicops_internals_mac.h"
+#elif defined(__native_client__)
+#include "src/base/atomicops_internals_portable.h"
#elif defined(__GNUC__) && V8_HOST_ARCH_ARM64
#include "src/base/atomicops_internals_arm64_gcc.h"
#elif defined(__GNUC__) && V8_HOST_ARCH_ARM
diff --git a/src/base/atomicops_internals_mac.h b/src/base/atomicops_internals_mac.h
index a046872..84f9dbc 100644
--- a/src/base/atomicops_internals_mac.h
+++ b/src/base/atomicops_internals_mac.h
@@ -12,6 +12,20 @@
namespace v8 {
namespace base {
+#define ATOMICOPS_COMPILER_BARRIER() __asm__ __volatile__("" : : : "memory")
+
+inline void MemoryBarrier() { OSMemoryBarrier(); }
+
+inline void AcquireMemoryBarrier() {
+// On x86 processors, loads already have acquire semantics, so
+// there is no need to put a full barrier here.
+#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+ ATOMICOPS_COMPILER_BARRIER();
+#else
+ MemoryBarrier();
+#endif
+}
+
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@@ -46,10 +60,6 @@
return OSAtomicAdd32Barrier(increment, const_cast<Atomic32*>(ptr));
}
-inline void MemoryBarrier() {
- OSMemoryBarrier();
-}
-
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
@@ -98,7 +108,7 @@
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
Atomic32 value = *ptr;
- MemoryBarrier();
+ AcquireMemoryBarrier();
return value;
}
@@ -188,7 +198,7 @@
inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
Atomic64 value = *ptr;
- MemoryBarrier();
+ AcquireMemoryBarrier();
return value;
}
@@ -199,6 +209,7 @@
#endif // defined(__LP64__)
+#undef ATOMICOPS_COMPILER_BARRIER
} } // namespace v8::base
#endif // V8_BASE_ATOMICOPS_INTERNALS_MAC_H_
diff --git a/src/base/atomicops_internals_portable.h b/src/base/atomicops_internals_portable.h
new file mode 100644
index 0000000..a3a6e74
--- /dev/null
+++ b/src/base/atomicops_internals_portable.h
@@ -0,0 +1,138 @@
+// Copyright 2012 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.
+
+// This file is an internal atomic implementation, use atomicops.h instead.
+
+#ifndef V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
+#define V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
+
+namespace v8 {
+namespace base {
+
+inline void MemoryBarrier() { __sync_synchronize(); }
+
+inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ return __sync_lock_test_and_set(ptr, new_value);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return __sync_add_and_fetch(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return __sync_add_and_fetch(ptr, increment);
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+// 64-bit versions of the operations.
+// See the 32-bit versions for comments.
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ return __sync_lock_test_and_set(ptr, new_value);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return __sync_add_and_fetch(ptr, increment);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return __sync_add_and_fetch(ptr, increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value, Atomic64 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value, Atomic64 new_value) {
+ return __sync_val_compare_and_swap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ __sync_lock_test_and_set(ptr, value);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ return __sync_add_and_fetch(ptr, 0);
+}
+}
+} // namespace v8::base
+
+#endif // V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
diff --git a/src/base/base.gyp b/src/base/base.gyp
deleted file mode 100644
index e391e2e..0000000
--- a/src/base/base.gyp
+++ /dev/null
@@ -1,46 +0,0 @@
-# Copyright 2014 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.
-
-{
- 'variables': {
- 'v8_code': 1,
- },
- 'includes': ['../../build/toolchain.gypi', '../../build/features.gypi'],
- 'targets': [
- {
- 'target_name': 'base-unittests',
- 'type': 'executable',
- 'dependencies': [
- '../../testing/gtest.gyp:gtest',
- '../../testing/gtest.gyp:gtest_main',
- '../../tools/gyp/v8.gyp:v8_libbase',
- ],
- 'include_dirs': [
- '../..',
- ],
- 'sources': [ ### gcmole(all) ###
- 'bits-unittest.cc',
- 'cpu-unittest.cc',
- 'division-by-constant-unittest.cc',
- 'flags-unittest.cc',
- 'platform/condition-variable-unittest.cc',
- 'platform/mutex-unittest.cc',
- 'platform/platform-unittest.cc',
- 'platform/semaphore-unittest.cc',
- 'platform/time-unittest.cc',
- 'sys-info-unittest.cc',
- 'utils/random-number-generator-unittest.cc',
- ],
- 'conditions': [
- ['os_posix == 1', {
- # TODO(svenpanne): This is a temporary work-around to fix the warnings
- # that show up because we use -std=gnu++0x instead of -std=c++11.
- 'cflags!': [
- '-pedantic',
- ],
- }],
- ],
- },
- ],
-}
diff --git a/src/base/bits-unittest.cc b/src/base/bits-unittest.cc
deleted file mode 100644
index 06c1183..0000000
--- a/src/base/bits-unittest.cc
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2014 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 <limits>
-
-#include "src/base/bits.h"
-#include "src/base/macros.h"
-#include "testing/gtest-support.h"
-
-#ifdef DEBUG
-#define DISABLE_IN_RELEASE(Name) Name
-#else
-#define DISABLE_IN_RELEASE(Name) DISABLED_##Name
-#endif
-
-namespace v8 {
-namespace base {
-namespace bits {
-
-TEST(Bits, CountPopulation32) {
- EXPECT_EQ(0u, CountPopulation32(0));
- EXPECT_EQ(1u, CountPopulation32(1));
- EXPECT_EQ(8u, CountPopulation32(0x11111111));
- EXPECT_EQ(16u, CountPopulation32(0xf0f0f0f0));
- EXPECT_EQ(24u, CountPopulation32(0xfff0f0ff));
- EXPECT_EQ(32u, CountPopulation32(0xffffffff));
-}
-
-
-TEST(Bits, CountLeadingZeros32) {
- EXPECT_EQ(32u, CountLeadingZeros32(0));
- EXPECT_EQ(31u, CountLeadingZeros32(1));
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_EQ(31u - shift, CountLeadingZeros32(1u << shift));
- }
- EXPECT_EQ(4u, CountLeadingZeros32(0x0f0f0f0f));
-}
-
-
-TEST(Bits, CountTrailingZeros32) {
- EXPECT_EQ(32u, CountTrailingZeros32(0));
- EXPECT_EQ(31u, CountTrailingZeros32(0x80000000));
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_EQ(shift, CountTrailingZeros32(1u << shift));
- }
- EXPECT_EQ(4u, CountTrailingZeros32(0xf0f0f0f0));
-}
-
-
-TEST(Bits, IsPowerOfTwo32) {
- EXPECT_FALSE(IsPowerOfTwo32(0U));
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_TRUE(IsPowerOfTwo32(1U << shift));
- EXPECT_FALSE(IsPowerOfTwo32((1U << shift) + 5U));
- EXPECT_FALSE(IsPowerOfTwo32(~(1U << shift)));
- }
- TRACED_FORRANGE(uint32_t, shift, 2, 31) {
- EXPECT_FALSE(IsPowerOfTwo32((1U << shift) - 1U));
- }
- EXPECT_FALSE(IsPowerOfTwo32(0xffffffff));
-}
-
-
-TEST(Bits, IsPowerOfTwo64) {
- EXPECT_FALSE(IsPowerOfTwo64(0U));
- TRACED_FORRANGE(uint32_t, shift, 0, 63) {
- EXPECT_TRUE(IsPowerOfTwo64(V8_UINT64_C(1) << shift));
- EXPECT_FALSE(IsPowerOfTwo64((V8_UINT64_C(1) << shift) + 5U));
- EXPECT_FALSE(IsPowerOfTwo64(~(V8_UINT64_C(1) << shift)));
- }
- TRACED_FORRANGE(uint32_t, shift, 2, 63) {
- EXPECT_FALSE(IsPowerOfTwo64((V8_UINT64_C(1) << shift) - 1U));
- }
- EXPECT_FALSE(IsPowerOfTwo64(V8_UINT64_C(0xffffffffffffffff)));
-}
-
-
-TEST(Bits, RoundUpToPowerOfTwo32) {
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_EQ(1u << shift, RoundUpToPowerOfTwo32(1u << shift));
- }
- EXPECT_EQ(0u, RoundUpToPowerOfTwo32(0));
- EXPECT_EQ(4u, RoundUpToPowerOfTwo32(3));
- EXPECT_EQ(0x80000000u, RoundUpToPowerOfTwo32(0x7fffffffu));
-}
-
-
-TEST(BitsDeathTest, DISABLE_IN_RELEASE(RoundUpToPowerOfTwo32)) {
- ASSERT_DEATH_IF_SUPPORTED({ RoundUpToPowerOfTwo32(0x80000001u); },
- "0x80000000");
-}
-
-
-TEST(Bits, RoundDownToPowerOfTwo32) {
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_EQ(1u << shift, RoundDownToPowerOfTwo32(1u << shift));
- }
- EXPECT_EQ(0u, RoundDownToPowerOfTwo32(0));
- EXPECT_EQ(4u, RoundDownToPowerOfTwo32(5));
- EXPECT_EQ(0x80000000u, RoundDownToPowerOfTwo32(0x80000001u));
-}
-
-
-TEST(Bits, RotateRight32) {
- TRACED_FORRANGE(uint32_t, shift, 0, 31) {
- EXPECT_EQ(0u, RotateRight32(0u, shift));
- }
- EXPECT_EQ(1u, RotateRight32(1, 0));
- EXPECT_EQ(1u, RotateRight32(2, 1));
- EXPECT_EQ(0x80000000u, RotateRight32(1, 1));
-}
-
-
-TEST(Bits, RotateRight64) {
- TRACED_FORRANGE(uint64_t, shift, 0, 63) {
- EXPECT_EQ(0u, RotateRight64(0u, shift));
- }
- EXPECT_EQ(1u, RotateRight64(1, 0));
- EXPECT_EQ(1u, RotateRight64(2, 1));
- EXPECT_EQ(V8_UINT64_C(0x8000000000000000), RotateRight64(1, 1));
-}
-
-
-TEST(Bits, SignedAddOverflow32) {
- int32_t val = 0;
- EXPECT_FALSE(SignedAddOverflow32(0, 0, &val));
- EXPECT_EQ(0, val);
- EXPECT_TRUE(
- SignedAddOverflow32(std::numeric_limits<int32_t>::max(), 1, &val));
- EXPECT_EQ(std::numeric_limits<int32_t>::min(), val);
- EXPECT_TRUE(
- SignedAddOverflow32(std::numeric_limits<int32_t>::min(), -1, &val));
- EXPECT_EQ(std::numeric_limits<int32_t>::max(), val);
- EXPECT_TRUE(SignedAddOverflow32(std::numeric_limits<int32_t>::max(),
- std::numeric_limits<int32_t>::max(), &val));
- EXPECT_EQ(-2, val);
- TRACED_FORRANGE(int32_t, i, 1, 50) {
- TRACED_FORRANGE(int32_t, j, 1, i) {
- EXPECT_FALSE(SignedAddOverflow32(i, j, &val));
- EXPECT_EQ(i + j, val);
- }
- }
-}
-
-
-TEST(Bits, SignedSubOverflow32) {
- int32_t val = 0;
- EXPECT_FALSE(SignedSubOverflow32(0, 0, &val));
- EXPECT_EQ(0, val);
- EXPECT_TRUE(
- SignedSubOverflow32(std::numeric_limits<int32_t>::min(), 1, &val));
- EXPECT_EQ(std::numeric_limits<int32_t>::max(), val);
- EXPECT_TRUE(
- SignedSubOverflow32(std::numeric_limits<int32_t>::max(), -1, &val));
- EXPECT_EQ(std::numeric_limits<int32_t>::min(), val);
- TRACED_FORRANGE(int32_t, i, 1, 50) {
- TRACED_FORRANGE(int32_t, j, 1, i) {
- EXPECT_FALSE(SignedSubOverflow32(i, j, &val));
- EXPECT_EQ(i - j, val);
- }
- }
-}
-
-} // namespace bits
-} // namespace base
-} // namespace v8
diff --git a/src/base/bits.cc b/src/base/bits.cc
index 6daee53..74d747f 100644
--- a/src/base/bits.cc
+++ b/src/base/bits.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "src/base/bits.h"
+
+#include <limits>
+
#include "src/base/logging.h"
namespace v8 {
@@ -20,6 +23,31 @@
return value + 1;
}
+
+int32_t SignedMulHigh32(int32_t lhs, int32_t rhs) {
+ int64_t const value = static_cast<int64_t>(lhs) * static_cast<int64_t>(rhs);
+ return bit_cast<int32_t, uint32_t>(bit_cast<uint64_t>(value) >> 32u);
+}
+
+
+int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc) {
+ return bit_cast<int32_t>(bit_cast<uint32_t>(acc) +
+ bit_cast<uint32_t>(SignedMulHigh32(lhs, rhs)));
+}
+
+
+int32_t SignedDiv32(int32_t lhs, int32_t rhs) {
+ if (rhs == 0) return 0;
+ if (rhs == -1) return -lhs;
+ return lhs / rhs;
+}
+
+
+int32_t SignedMod32(int32_t lhs, int32_t rhs) {
+ if (rhs == 0 || rhs == -1) return 0;
+ return lhs % rhs;
+}
+
} // namespace bits
} // namespace base
} // namespace v8
diff --git a/src/base/bits.h b/src/base/bits.h
index e6a733a..0f4d4c7 100644
--- a/src/base/bits.h
+++ b/src/base/bits.h
@@ -5,7 +5,7 @@
#ifndef V8_BASE_BITS_H_
#define V8_BASE_BITS_H_
-#include "include/v8stdint.h"
+#include <stdint.h>
#include "src/base/macros.h"
#if V8_CC_MSVC
#include <intrin.h>
@@ -19,7 +19,7 @@
namespace bits {
// CountPopulation32(value) returns the number of bits set in |value|.
-inline uint32_t CountPopulation32(uint32_t value) {
+inline unsigned CountPopulation32(uint32_t value) {
#if V8_HAS_BUILTIN_POPCOUNT
return __builtin_popcount(value);
#else
@@ -28,20 +28,31 @@
value = ((value >> 4) & 0x0f0f0f0f) + (value & 0x0f0f0f0f);
value = ((value >> 8) & 0x00ff00ff) + (value & 0x00ff00ff);
value = ((value >> 16) & 0x0000ffff) + (value & 0x0000ffff);
- return value;
+ return static_cast<unsigned>(value);
+#endif
+}
+
+
+// CountPopulation64(value) returns the number of bits set in |value|.
+inline unsigned CountPopulation64(uint64_t value) {
+#if V8_HAS_BUILTIN_POPCOUNT
+ return __builtin_popcountll(value);
+#else
+ return CountPopulation32(static_cast<uint32_t>(value)) +
+ CountPopulation32(static_cast<uint32_t>(value >> 32));
#endif
}
// CountLeadingZeros32(value) returns the number of zero bits following the most
// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 32.
-inline uint32_t CountLeadingZeros32(uint32_t value) {
+inline unsigned CountLeadingZeros32(uint32_t value) {
#if V8_HAS_BUILTIN_CLZ
return value ? __builtin_clz(value) : 32;
#elif V8_CC_MSVC
unsigned long result; // NOLINT(runtime/int)
if (!_BitScanReverse(&result, value)) return 32;
- return static_cast<uint32_t>(31 - result);
+ return static_cast<unsigned>(31 - result);
#else
value = value | (value >> 1);
value = value | (value >> 2);
@@ -53,16 +64,33 @@
}
+// CountLeadingZeros64(value) returns the number of zero bits following the most
+// significant 1 bit in |value| if |value| is non-zero, otherwise it returns 64.
+inline unsigned CountLeadingZeros64(uint64_t value) {
+#if V8_HAS_BUILTIN_CLZ
+ return value ? __builtin_clzll(value) : 64;
+#else
+ value = value | (value >> 1);
+ value = value | (value >> 2);
+ value = value | (value >> 4);
+ value = value | (value >> 8);
+ value = value | (value >> 16);
+ value = value | (value >> 32);
+ return CountPopulation64(~value);
+#endif
+}
+
+
// CountTrailingZeros32(value) returns the number of zero bits preceding the
// least significant 1 bit in |value| if |value| is non-zero, otherwise it
// returns 32.
-inline uint32_t CountTrailingZeros32(uint32_t value) {
+inline unsigned CountTrailingZeros32(uint32_t value) {
#if V8_HAS_BUILTIN_CTZ
return value ? __builtin_ctz(value) : 32;
#elif V8_CC_MSVC
unsigned long result; // NOLINT(runtime/int)
if (!_BitScanForward(&result, value)) return 32;
- return static_cast<uint32_t>(result);
+ return static_cast<unsigned>(result);
#else
if (value == 0) return 32;
unsigned count = 0;
@@ -73,6 +101,22 @@
}
+// CountTrailingZeros64(value) returns the number of zero bits preceding the
+// least significant 1 bit in |value| if |value| is non-zero, otherwise it
+// returns 64.
+inline unsigned CountTrailingZeros64(uint64_t value) {
+#if V8_HAS_BUILTIN_CTZ
+ return value ? __builtin_ctzll(value) : 64;
+#else
+ if (value == 0) return 64;
+ unsigned count = 0;
+ for (value ^= value - 1; value >>= 1; ++count)
+ ;
+ return count;
+#endif
+}
+
+
// Returns true iff |value| is a power of 2.
inline bool IsPowerOfTwo32(uint32_t value) {
return value && !(value & (value - 1));
@@ -143,6 +187,44 @@
#endif
}
+
+// SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and
+// |rhs|, extracts the most significant 32 bits of the result, and returns
+// those.
+int32_t SignedMulHigh32(int32_t lhs, int32_t rhs);
+
+
+// SignedMulHighAndAdd32(lhs, rhs, acc) multiplies two signed 32-bit values
+// |lhs| and |rhs|, extracts the most significant 32 bits of the result, and
+// adds the accumulate value |acc|.
+int32_t SignedMulHighAndAdd32(int32_t lhs, int32_t rhs, int32_t acc);
+
+
+// SignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient
+// truncated to int32. If |rhs| is zero, then zero is returned. If |lhs|
+// is minint and |rhs| is -1, it returns minint.
+int32_t SignedDiv32(int32_t lhs, int32_t rhs);
+
+
+// SignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder
+// truncated to int32. If either |rhs| is zero or |lhs| is minint and |rhs|
+// is -1, it returns zero.
+int32_t SignedMod32(int32_t lhs, int32_t rhs);
+
+
+// UnsignedDiv32(lhs, rhs) divides |lhs| by |rhs| and returns the quotient
+// truncated to uint32. If |rhs| is zero, then zero is returned.
+inline uint32_t UnsignedDiv32(uint32_t lhs, uint32_t rhs) {
+ return rhs ? lhs / rhs : 0u;
+}
+
+
+// UnsignedMod32(lhs, rhs) divides |lhs| by |rhs| and returns the remainder
+// truncated to uint32. If |rhs| is zero, then zero is returned.
+inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) {
+ return rhs ? lhs % rhs : 0u;
+}
+
} // namespace bits
} // namespace base
} // namespace v8
diff --git a/src/base/build_config.h b/src/base/build_config.h
index 2bf57c9..f528776 100644
--- a/src/base/build_config.h
+++ b/src/base/build_config.h
@@ -29,6 +29,10 @@
#define V8_HOST_ARCH_64_BIT 1
#endif
#endif // __native_client__
+#elif defined(__pnacl__)
+// PNaCl is also ILP-32.
+#define V8_HOST_ARCH_IA32 1
+#define V8_HOST_ARCH_32_BIT 1
#elif defined(_M_IX86) || defined(__i386__)
#define V8_HOST_ARCH_IA32 1
#define V8_HOST_ARCH_32_BIT 1
diff --git a/src/base/compiler-specific.h b/src/base/compiler-specific.h
index 475a32c..9755fc1 100644
--- a/src/base/compiler-specific.h
+++ b/src/base/compiler-specific.h
@@ -7,15 +7,13 @@
#include "include/v8config.h"
-// Annotate a variable indicating it's ok if the variable is not used.
-// (Typically used to silence a compiler warning when the assignment
-// is important for some other reason.)
+// Annotate a typedef or function indicating it's ok if it's not used.
// Use like:
-// int x ALLOW_UNUSED = ...;
+// typedef Foo Bar ALLOW_UNUSED_TYPE;
#if V8_HAS_ATTRIBUTE_UNUSED
-#define ALLOW_UNUSED __attribute__((unused))
+#define ALLOW_UNUSED_TYPE __attribute__((unused))
#else
-#define ALLOW_UNUSED
+#define ALLOW_UNUSED_TYPE
#endif
@@ -39,8 +37,6 @@
#define FINAL final
#elif V8_HAS___FINAL
#define FINAL __final
-#elif V8_HAS_SEALED
-#define FINAL sealed
#else
#define FINAL /* NOT SUPPORTED */
#endif
diff --git a/src/base/cpu-unittest.cc b/src/base/cpu-unittest.cc
deleted file mode 100644
index 5c58f86..0000000
--- a/src/base/cpu-unittest.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2014 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/cpu.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-TEST(CPUTest, FeatureImplications) {
- CPU cpu;
-
- // ia32 and x64 features
- EXPECT_TRUE(!cpu.has_sse() || cpu.has_mmx());
- EXPECT_TRUE(!cpu.has_sse2() || cpu.has_sse());
- EXPECT_TRUE(!cpu.has_sse3() || cpu.has_sse2());
- EXPECT_TRUE(!cpu.has_ssse3() || cpu.has_sse3());
- EXPECT_TRUE(!cpu.has_sse41() || cpu.has_sse3());
- EXPECT_TRUE(!cpu.has_sse42() || cpu.has_sse41());
-
- // arm features
- EXPECT_TRUE(!cpu.has_vfp3_d32() || cpu.has_vfp3());
-}
-
-
-TEST(CPUTest, RequiredFeatures) {
- CPU cpu;
-
-#if V8_HOST_ARCH_ARM
- EXPECT_TRUE(cpu.has_fpu());
-#endif
-
-#if V8_HOST_ARCH_IA32
- EXPECT_TRUE(cpu.has_fpu());
- EXPECT_TRUE(cpu.has_sahf());
-#endif
-
-#if V8_HOST_ARCH_X64
- EXPECT_TRUE(cpu.has_fpu());
- EXPECT_TRUE(cpu.has_cmov());
- EXPECT_TRUE(cpu.has_mmx());
- EXPECT_TRUE(cpu.has_sse());
- EXPECT_TRUE(cpu.has_sse2());
-#endif
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/cpu.cc b/src/base/cpu.cc
index cd40d4f..daf3302 100644
--- a/src/base/cpu.cc
+++ b/src/base/cpu.cc
@@ -7,12 +7,18 @@
#if V8_LIBC_MSVCRT
#include <intrin.h> // __cpuid()
#endif
-#if V8_OS_POSIX
-#include <unistd.h> // sysconf()
+#if V8_OS_LINUX
+#include <linux/auxvec.h> // AT_HWCAP
+#endif
+#if V8_GLIBC_PREREQ(2, 16)
+#include <sys/auxv.h> // getauxval()
#endif
#if V8_OS_QNX
#include <sys/syspage.h> // cpuinfo
#endif
+#if V8_OS_POSIX
+#include <unistd.h> // sysconf()
+#endif
#include <ctype.h>
#include <limits.h>
@@ -29,7 +35,9 @@
namespace v8 {
namespace base {
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+#if defined(__pnacl__)
+// Portable host shouldn't do feature detection.
+#elif V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
// Define __cpuid() for non-MSVC libraries.
#if !V8_LIBC_MSVCRT
@@ -90,11 +98,12 @@
#define HWCAP_IDIV (HWCAP_IDIVA | HWCAP_IDIVT)
#define HWCAP_LPAE (1 << 20)
-#define AT_HWCAP 16
-
-// Read the ELF HWCAP flags by parsing /proc/self/auxv.
static uint32_t ReadELFHWCaps() {
uint32_t result = 0;
+#if V8_GLIBC_PREREQ(2, 16)
+ result = static_cast<uint32_t>(getauxval(AT_HWCAP));
+#else
+ // Read the ELF HWCAP flags by parsing /proc/self/auxv.
FILE* fp = fopen("/proc/self/auxv", "r");
if (fp != NULL) {
struct { uint32_t tag; uint32_t value; } entry;
@@ -110,6 +119,7 @@
}
fclose(fp);
}
+#endif
return result;
}
@@ -281,34 +291,42 @@
#endif // V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
-CPU::CPU() : stepping_(0),
- model_(0),
- ext_model_(0),
- family_(0),
- ext_family_(0),
- type_(0),
- implementer_(0),
- architecture_(0),
- part_(0),
- has_fpu_(false),
- has_cmov_(false),
- has_sahf_(false),
- has_mmx_(false),
- has_sse_(false),
- has_sse2_(false),
- has_sse3_(false),
- has_ssse3_(false),
- has_sse41_(false),
- has_sse42_(false),
- has_idiva_(false),
- has_neon_(false),
- has_thumb2_(false),
- has_vfp_(false),
- has_vfp3_(false),
- has_vfp3_d32_(false),
- is_fp64_mode_(false) {
+CPU::CPU()
+ : stepping_(0),
+ model_(0),
+ ext_model_(0),
+ family_(0),
+ ext_family_(0),
+ type_(0),
+ implementer_(0),
+ architecture_(0),
+ variant_(-1),
+ part_(0),
+ has_fpu_(false),
+ has_cmov_(false),
+ has_sahf_(false),
+ has_mmx_(false),
+ has_sse_(false),
+ has_sse2_(false),
+ has_sse3_(false),
+ has_ssse3_(false),
+ has_sse41_(false),
+ has_sse42_(false),
+ has_avx_(false),
+ has_fma3_(false),
+ has_idiva_(false),
+ has_neon_(false),
+ has_thumb2_(false),
+ has_vfp_(false),
+ has_vfp3_(false),
+ has_vfp3_d32_(false),
+ is_fp64_mode_(false) {
memcpy(vendor_, "Unknown", 8);
-#if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
+#if V8_OS_NACL
+// Portable host shouldn't do feature detection.
+// TODO(jfb): Remove the hardcoded ARM simulator flags in the build, and
+// hardcode them here instead.
+#elif V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64
int cpu_info[4];
// __cpuid with an InfoType argument of 0 returns the number of
@@ -342,6 +360,8 @@
has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
+ has_avx_ = (cpu_info[2] & 0x10000000) != 0;
+ if (has_avx_) has_fma3_ = (cpu_info[2] & 0x00001000) != 0;
}
#if V8_HOST_ARCH_IA32
@@ -369,7 +389,7 @@
// Extract implementor from the "CPU implementer" field.
char* implementer = cpu_info.ExtractField("CPU implementer");
if (implementer != NULL) {
- char* end ;
+ char* end;
implementer_ = strtol(implementer, &end, 0);
if (end == implementer) {
implementer_ = 0;
@@ -377,10 +397,20 @@
delete[] implementer;
}
+ char* variant = cpu_info.ExtractField("CPU variant");
+ if (variant != NULL) {
+ char* end;
+ variant_ = strtol(variant, &end, 0);
+ if (end == variant) {
+ variant_ = -1;
+ }
+ delete[] variant;
+ }
+
// Extract part number from the "CPU part" field.
char* part = cpu_info.ExtractField("CPU part");
if (part != NULL) {
- char* end ;
+ char* end;
part_ = strtol(part, &end, 0);
if (end == part) {
part_ = 0;
@@ -408,7 +438,7 @@
//
// See http://code.google.com/p/android/issues/detail?id=10812
//
- // We try to correct this by looking at the 'elf_format'
+ // We try to correct this by looking at the 'elf_platform'
// field reported by the 'Processor' field, which is of the
// form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for
// an ARMv6-one. For example, the Raspberry Pi is one popular
@@ -420,6 +450,15 @@
}
delete[] processor;
}
+
+ // elf_platform moved to the model name field in Linux v3.8.
+ if (architecture_ == 7) {
+ char* processor = cpu_info.ExtractField("model name");
+ if (HasListItem(processor, "(v6l)")) {
+ architecture_ = 6;
+ }
+ delete[] processor;
+ }
}
// Try to extract the list of CPU features from ELF hwcaps.
@@ -521,7 +560,7 @@
// Extract implementor from the "CPU implementer" field.
char* implementer = cpu_info.ExtractField("CPU implementer");
if (implementer != NULL) {
- char* end ;
+ char* end;
implementer_ = strtol(implementer, &end, 0);
if (end == implementer) {
implementer_ = 0;
@@ -529,10 +568,20 @@
delete[] implementer;
}
+ char* variant = cpu_info.ExtractField("CPU variant");
+ if (variant != NULL) {
+ char* end;
+ variant_ = strtol(variant, &end, 0);
+ if (end == variant) {
+ variant_ = -1;
+ }
+ delete[] variant;
+ }
+
// Extract part number from the "CPU part" field.
char* part = cpu_info.ExtractField("CPU part");
if (part != NULL) {
- char* end ;
+ char* end;
part_ = strtol(part, &end, 0);
if (end == part) {
part_ = 0;
diff --git a/src/base/cpu.h b/src/base/cpu.h
index dc0eaf4..8c41f9d 100644
--- a/src/base/cpu.h
+++ b/src/base/cpu.h
@@ -47,6 +47,8 @@
static const int NVIDIA = 0x4e;
static const int QUALCOMM = 0x51;
int architecture() const { return architecture_; }
+ int variant() const { return variant_; }
+ static const int NVIDIA_DENVER = 0x0;
int part() const { return part_; }
static const int ARM_CORTEX_A5 = 0xc05;
static const int ARM_CORTEX_A7 = 0xc07;
@@ -68,6 +70,8 @@
bool has_ssse3() const { return has_ssse3_; }
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
+ bool has_avx() const { return has_avx_; }
+ bool has_fma3() const { return has_fma3_; }
// arm features
bool has_idiva() const { return has_idiva_; }
@@ -90,6 +94,7 @@
int type_;
int implementer_;
int architecture_;
+ int variant_;
int part_;
bool has_fpu_;
bool has_cmov_;
@@ -101,6 +106,8 @@
bool has_ssse3_;
bool has_sse41_;
bool has_sse42_;
+ bool has_avx_;
+ bool has_fma3_;
bool has_idiva_;
bool has_neon_;
bool has_thumb2_;
diff --git a/src/base/division-by-constant-unittest.cc b/src/base/division-by-constant-unittest.cc
deleted file mode 100644
index 47c2483..0000000
--- a/src/base/division-by-constant-unittest.cc
+++ /dev/null
@@ -1,132 +0,0 @@
-// Copyright 2014 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.
-
-// Check all examples from table 10-1 of "Hacker's Delight".
-
-#include "src/base/division-by-constant.h"
-
-#include <ostream> // NOLINT
-
-#include "testing/gtest-support.h"
-
-namespace v8 {
-namespace base {
-
-template <class T>
-std::ostream& operator<<(std::ostream& os,
- const MagicNumbersForDivision<T>& mag) {
- return os << "{ multiplier: " << mag.multiplier << ", shift: " << mag.shift
- << ", add: " << mag.add << " }";
-}
-
-
-// Some abbreviations...
-
-typedef MagicNumbersForDivision<uint32_t> M32;
-typedef MagicNumbersForDivision<uint64_t> M64;
-
-
-static M32 s32(int32_t d) {
- return SignedDivisionByConstant<uint32_t>(static_cast<uint32_t>(d));
-}
-
-
-static M64 s64(int64_t d) {
- return SignedDivisionByConstant<uint64_t>(static_cast<uint64_t>(d));
-}
-
-
-static M32 u32(uint32_t d) { return UnsignedDivisionByConstant<uint32_t>(d); }
-static M64 u64(uint64_t d) { return UnsignedDivisionByConstant<uint64_t>(d); }
-
-
-TEST(DivisionByConstant, Signed32) {
- EXPECT_EQ(M32(0x99999999U, 1, false), s32(-5));
- EXPECT_EQ(M32(0x55555555U, 1, false), s32(-3));
- int32_t d = -1;
- for (unsigned k = 1; k <= 32 - 1; ++k) {
- d *= 2;
- EXPECT_EQ(M32(0x7FFFFFFFU, k - 1, false), s32(d));
- }
- for (unsigned k = 1; k <= 32 - 2; ++k) {
- EXPECT_EQ(M32(0x80000001U, k - 1, false), s32(1 << k));
- }
- EXPECT_EQ(M32(0x55555556U, 0, false), s32(3));
- EXPECT_EQ(M32(0x66666667U, 1, false), s32(5));
- EXPECT_EQ(M32(0x2AAAAAABU, 0, false), s32(6));
- EXPECT_EQ(M32(0x92492493U, 2, false), s32(7));
- EXPECT_EQ(M32(0x38E38E39U, 1, false), s32(9));
- EXPECT_EQ(M32(0x66666667U, 2, false), s32(10));
- EXPECT_EQ(M32(0x2E8BA2E9U, 1, false), s32(11));
- EXPECT_EQ(M32(0x2AAAAAABU, 1, false), s32(12));
- EXPECT_EQ(M32(0x51EB851FU, 3, false), s32(25));
- EXPECT_EQ(M32(0x10624DD3U, 3, false), s32(125));
- EXPECT_EQ(M32(0x68DB8BADU, 8, false), s32(625));
-}
-
-
-TEST(DivisionByConstant, Unsigned32) {
- EXPECT_EQ(M32(0x00000000U, 0, true), u32(1));
- for (unsigned k = 1; k <= 30; ++k) {
- EXPECT_EQ(M32(1U << (32 - k), 0, false), u32(1U << k));
- }
- EXPECT_EQ(M32(0xAAAAAAABU, 1, false), u32(3));
- EXPECT_EQ(M32(0xCCCCCCCDU, 2, false), u32(5));
- EXPECT_EQ(M32(0xAAAAAAABU, 2, false), u32(6));
- EXPECT_EQ(M32(0x24924925U, 3, true), u32(7));
- EXPECT_EQ(M32(0x38E38E39U, 1, false), u32(9));
- EXPECT_EQ(M32(0xCCCCCCCDU, 3, false), u32(10));
- EXPECT_EQ(M32(0xBA2E8BA3U, 3, false), u32(11));
- EXPECT_EQ(M32(0xAAAAAAABU, 3, false), u32(12));
- EXPECT_EQ(M32(0x51EB851FU, 3, false), u32(25));
- EXPECT_EQ(M32(0x10624DD3U, 3, false), u32(125));
- EXPECT_EQ(M32(0xD1B71759U, 9, false), u32(625));
-}
-
-
-TEST(DivisionByConstant, Signed64) {
- EXPECT_EQ(M64(0x9999999999999999ULL, 1, false), s64(-5));
- EXPECT_EQ(M64(0x5555555555555555ULL, 1, false), s64(-3));
- int64_t d = -1;
- for (unsigned k = 1; k <= 64 - 1; ++k) {
- d *= 2;
- EXPECT_EQ(M64(0x7FFFFFFFFFFFFFFFULL, k - 1, false), s64(d));
- }
- for (unsigned k = 1; k <= 64 - 2; ++k) {
- EXPECT_EQ(M64(0x8000000000000001ULL, k - 1, false), s64(1LL << k));
- }
- EXPECT_EQ(M64(0x5555555555555556ULL, 0, false), s64(3));
- EXPECT_EQ(M64(0x6666666666666667ULL, 1, false), s64(5));
- EXPECT_EQ(M64(0x2AAAAAAAAAAAAAABULL, 0, false), s64(6));
- EXPECT_EQ(M64(0x4924924924924925ULL, 1, false), s64(7));
- EXPECT_EQ(M64(0x1C71C71C71C71C72ULL, 0, false), s64(9));
- EXPECT_EQ(M64(0x6666666666666667ULL, 2, false), s64(10));
- EXPECT_EQ(M64(0x2E8BA2E8BA2E8BA3ULL, 1, false), s64(11));
- EXPECT_EQ(M64(0x2AAAAAAAAAAAAAABULL, 1, false), s64(12));
- EXPECT_EQ(M64(0xA3D70A3D70A3D70BULL, 4, false), s64(25));
- EXPECT_EQ(M64(0x20C49BA5E353F7CFULL, 4, false), s64(125));
- EXPECT_EQ(M64(0x346DC5D63886594BULL, 7, false), s64(625));
-}
-
-
-TEST(DivisionByConstant, Unsigned64) {
- EXPECT_EQ(M64(0x0000000000000000ULL, 0, true), u64(1));
- for (unsigned k = 1; k <= 64 - 2; ++k) {
- EXPECT_EQ(M64(1ULL << (64 - k), 0, false), u64(1ULL << k));
- }
- EXPECT_EQ(M64(0xAAAAAAAAAAAAAAABULL, 1, false), u64(3));
- EXPECT_EQ(M64(0xCCCCCCCCCCCCCCCDULL, 2, false), u64(5));
- EXPECT_EQ(M64(0xAAAAAAAAAAAAAAABULL, 2, false), u64(6));
- EXPECT_EQ(M64(0x2492492492492493ULL, 3, true), u64(7));
- EXPECT_EQ(M64(0xE38E38E38E38E38FULL, 3, false), u64(9));
- EXPECT_EQ(M64(0xCCCCCCCCCCCCCCCDULL, 3, false), u64(10));
- EXPECT_EQ(M64(0x2E8BA2E8BA2E8BA3ULL, 1, false), u64(11));
- EXPECT_EQ(M64(0xAAAAAAAAAAAAAAABULL, 3, false), u64(12));
- EXPECT_EQ(M64(0x47AE147AE147AE15ULL, 5, true), u64(25));
- EXPECT_EQ(M64(0x0624DD2F1A9FBE77ULL, 7, true), u64(125));
- EXPECT_EQ(M64(0x346DC5D63886594BULL, 7, false), u64(625));
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/division-by-constant.cc b/src/base/division-by-constant.cc
index 235d39f..5167b7a 100644
--- a/src/base/division-by-constant.cc
+++ b/src/base/division-by-constant.cc
@@ -52,7 +52,7 @@
delta = ad - r2;
} while (q1 < delta || (q1 == delta && r1 == 0));
T mul = q2 + 1;
- return {neg ? (0 - mul) : mul, p - bits, false};
+ return MagicNumbersForDivision<T>(neg ? (0 - mul) : mul, p - bits, false);
}
@@ -93,7 +93,7 @@
}
delta = d - 1 - r2;
} while (p < bits * 2 && (q1 < delta || (q1 == delta && r1 == 0)));
- return {q2 + 1, p - bits, a};
+ return MagicNumbersForDivision<T>(q2 + 1, p - bits, a);
}
diff --git a/src/base/flags-unittest.cc b/src/base/flags-unittest.cc
deleted file mode 100644
index a1d6f37..0000000
--- a/src/base/flags-unittest.cc
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright 2014 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 "include/v8stdint.h"
-#include "src/base/flags.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-namespace {
-
-enum Flag1 {
- kFlag1None = 0,
- kFlag1First = 1u << 1,
- kFlag1Second = 1u << 2,
- kFlag1All = kFlag1None | kFlag1First | kFlag1Second
-};
-typedef Flags<Flag1> Flags1;
-
-
-DEFINE_OPERATORS_FOR_FLAGS(Flags1)
-
-
-Flags1 bar(Flags1 flags1) { return flags1; }
-
-} // namespace
-
-
-TEST(FlagsTest, BasicOperations) {
- Flags1 a;
- EXPECT_EQ(kFlag1None, static_cast<int>(a));
- a |= kFlag1First;
- EXPECT_EQ(kFlag1First, static_cast<int>(a));
- a = a | kFlag1Second;
- EXPECT_EQ(kFlag1All, static_cast<int>(a));
- a &= kFlag1Second;
- EXPECT_EQ(kFlag1Second, static_cast<int>(a));
- a = kFlag1None & a;
- EXPECT_EQ(kFlag1None, static_cast<int>(a));
- a ^= (kFlag1All | kFlag1None);
- EXPECT_EQ(kFlag1All, static_cast<int>(a));
- Flags1 b = ~a;
- EXPECT_EQ(kFlag1All, static_cast<int>(a));
- EXPECT_EQ(~static_cast<int>(a), static_cast<int>(b));
- Flags1 c = a;
- EXPECT_EQ(a, c);
- EXPECT_NE(a, b);
- EXPECT_EQ(a, bar(a));
- EXPECT_EQ(a, bar(kFlag1All));
-}
-
-
-namespace {
-namespace foo {
-
-enum Option {
- kNoOptions = 0,
- kOption1 = 1,
- kOption2 = 2,
- kAllOptions = kNoOptions | kOption1 | kOption2
-};
-typedef Flags<Option> Options;
-
-} // namespace foo
-
-
-DEFINE_OPERATORS_FOR_FLAGS(foo::Options)
-
-} // namespace
-
-
-TEST(FlagsTest, NamespaceScope) {
- foo::Options options;
- options ^= foo::kNoOptions;
- options |= foo::kOption1 | foo::kOption2;
- EXPECT_EQ(foo::kAllOptions, static_cast<int>(options));
-}
-
-
-namespace {
-
-struct Foo {
- enum Enum { kEnum1 = 1, kEnum2 = 2 };
- typedef Flags<Enum, uint32_t> Enums;
-};
-
-
-DEFINE_OPERATORS_FOR_FLAGS(Foo::Enums)
-
-} // namespace
-
-
-TEST(FlagsTest, ClassScope) {
- Foo::Enums enums;
- enums |= Foo::kEnum1;
- enums |= Foo::kEnum2;
- EXPECT_TRUE(enums & Foo::kEnum1);
- EXPECT_TRUE(enums & Foo::kEnum2);
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/flags.h b/src/base/flags.h
index f3420ee..060dba8 100644
--- a/src/base/flags.h
+++ b/src/base/flags.h
@@ -26,8 +26,9 @@
typedef S mask_type;
Flags() : mask_(0) {}
- Flags(flag_type flag) : mask_(flag) {} // NOLINT(runtime/explicit)
- explicit Flags(mask_type mask) : mask_(mask) {}
+ Flags(flag_type flag) // NOLINT(runtime/explicit)
+ : mask_(static_cast<S>(flag)) {}
+ explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
Flags& operator&=(const Flags& flags) {
mask_ &= flags.mask_;
@@ -64,42 +65,44 @@
};
-#define DEFINE_OPERATORS_FOR_FLAGS(Type) \
- inline Type operator&(Type::flag_type lhs, \
- Type::flag_type rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \
- return Type(lhs) & rhs; \
- } \
- inline Type operator&(Type::flag_type lhs, \
- const Type& rhs)ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator&(Type::flag_type lhs, const Type& rhs) { \
- return rhs & lhs; \
- } \
- inline void operator&(Type::flag_type lhs, Type::mask_type rhs)ALLOW_UNUSED; \
- inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \
- inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \
- ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \
- return Type(lhs) | rhs; \
- } \
- inline Type operator|(Type::flag_type lhs, const Type& rhs) \
- ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator|(Type::flag_type lhs, const Type& rhs) { \
- return rhs | lhs; \
- } \
- inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \
- ALLOW_UNUSED; \
- inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \
- inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \
- ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \
- return Type(lhs) ^ rhs; \
- } inline Type operator^(Type::flag_type lhs, const Type& rhs) \
- ALLOW_UNUSED WARN_UNUSED_RESULT; \
- inline Type operator^(Type::flag_type lhs, const Type& rhs) { \
- return rhs ^ lhs; \
- } inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \
- ALLOW_UNUSED; \
+#define DEFINE_OPERATORS_FOR_FLAGS(Type) \
+ inline Type operator&( \
+ Type::flag_type lhs, \
+ Type::flag_type rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator&(Type::flag_type lhs, Type::flag_type rhs) { \
+ return Type(lhs) & rhs; \
+ } \
+ inline Type operator&(Type::flag_type lhs, \
+ const Type& rhs)ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator&(Type::flag_type lhs, const Type& rhs) { \
+ return rhs & lhs; \
+ } \
+ inline void operator&(Type::flag_type lhs, \
+ Type::mask_type rhs)ALLOW_UNUSED_TYPE; \
+ inline void operator&(Type::flag_type lhs, Type::mask_type rhs) {} \
+ inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) \
+ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator|(Type::flag_type lhs, Type::flag_type rhs) { \
+ return Type(lhs) | rhs; \
+ } \
+ inline Type operator|(Type::flag_type lhs, const Type& rhs) \
+ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator|(Type::flag_type lhs, const Type& rhs) { \
+ return rhs | lhs; \
+ } \
+ inline void operator|(Type::flag_type lhs, Type::mask_type rhs) \
+ ALLOW_UNUSED_TYPE; \
+ inline void operator|(Type::flag_type lhs, Type::mask_type rhs) {} \
+ inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) \
+ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator^(Type::flag_type lhs, Type::flag_type rhs) { \
+ return Type(lhs) ^ rhs; \
+ } inline Type operator^(Type::flag_type lhs, const Type& rhs) \
+ ALLOW_UNUSED_TYPE WARN_UNUSED_RESULT; \
+ inline Type operator^(Type::flag_type lhs, const Type& rhs) { \
+ return rhs ^ lhs; \
+ } inline void operator^(Type::flag_type lhs, Type::mask_type rhs) \
+ ALLOW_UNUSED_TYPE; \
inline void operator^(Type::flag_type lhs, Type::mask_type rhs) {}
} // namespace base
diff --git a/src/base/functional.cc b/src/base/functional.cc
new file mode 100644
index 0000000..d212912
--- /dev/null
+++ b/src/base/functional.cc
@@ -0,0 +1,111 @@
+// Copyright 2014 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.
+//
+// This also contains public domain code from MurmurHash. From the
+// MurmurHash header:
+//
+// MurmurHash3 was written by Austin Appleby, and is placed in the public
+// domain. The author hereby disclaims copyright to this source code.
+
+#include "src/base/functional.h"
+
+#include <limits>
+
+#include "src/base/bits.h"
+
+namespace v8 {
+namespace base {
+
+namespace {
+
+// Thomas Wang, Integer Hash Functions.
+// https://gist.github.com/badboy/6267743
+template <typename T>
+V8_INLINE size_t hash_value_unsigned(T v) {
+ switch (sizeof(T)) {
+ case 4: {
+ // "32 bit Mix Functions"
+ v = ~v + (v << 15); // v = (v << 15) - v - 1;
+ v = v ^ (v >> 12);
+ v = v + (v << 2);
+ v = v ^ (v >> 4);
+ v = v * 2057; // v = (v + (v << 3)) + (v << 11);
+ v = v ^ (v >> 16);
+ return static_cast<size_t>(v);
+ }
+ case 8: {
+ switch (sizeof(size_t)) {
+ case 4: {
+ // "64 bit to 32 bit Hash Functions"
+ v = ~v + (v << 18); // v = (v << 18) - v - 1;
+ v = v ^ (v >> 31);
+ v = v * 21; // v = (v + (v << 2)) + (v << 4);
+ v = v ^ (v >> 11);
+ v = v + (v << 6);
+ v = v ^ (v >> 22);
+ return static_cast<size_t>(v);
+ }
+ case 8: {
+ // "64 bit Mix Functions"
+ v = ~v + (v << 21); // v = (v << 21) - v - 1;
+ v = v ^ (v >> 24);
+ v = (v + (v << 3)) + (v << 8); // v * 265
+ v = v ^ (v >> 14);
+ v = (v + (v << 2)) + (v << 4); // v * 21
+ v = v ^ (v >> 28);
+ v = v + (v << 31);
+ return static_cast<size_t>(v);
+ }
+ }
+ }
+ }
+ UNREACHABLE();
+ return static_cast<size_t>(v);
+}
+
+} // namespace
+
+
+// This code was taken from MurmurHash.
+size_t hash_combine(size_t seed, size_t value) {
+#if V8_HOST_ARCH_32_BIT
+ const uint32_t c1 = 0xcc9e2d51;
+ const uint32_t c2 = 0x1b873593;
+
+ value *= c1;
+ value = bits::RotateRight32(value, 15);
+ value *= c2;
+
+ seed ^= value;
+ seed = bits::RotateRight32(seed, 13);
+ seed = seed * 5 + 0xe6546b64;
+#else
+ const uint64_t m = V8_UINT64_C(0xc6a4a7935bd1e995);
+ const uint32_t r = 47;
+
+ value *= m;
+ value ^= value >> r;
+ value *= m;
+
+ seed ^= value;
+ seed *= m;
+#endif // V8_HOST_ARCH_32_BIT
+ return seed;
+}
+
+
+size_t hash_value(unsigned int v) { return hash_value_unsigned(v); }
+
+
+size_t hash_value(unsigned long v) { // NOLINT(runtime/int)
+ return hash_value_unsigned(v);
+}
+
+
+size_t hash_value(unsigned long long v) { // NOLINT(runtime/int)
+ return hash_value_unsigned(v);
+}
+
+} // namespace base
+} // namespace v8
diff --git a/src/base/functional.h b/src/base/functional.h
new file mode 100644
index 0000000..ff0d807
--- /dev/null
+++ b/src/base/functional.h
@@ -0,0 +1,227 @@
+// Copyright 2014 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_FUNCTIONAL_H_
+#define V8_BASE_FUNCTIONAL_H_
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <cstddef>
+#include <cstring>
+#include <functional>
+#include <utility>
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+// base::hash is an implementation of the hash function object specified by
+// C++11. It was designed to be compatible with std::hash (in C++11) and
+// boost:hash (which in turn is based on the hash function object specified by
+// the Draft Technical Report on C++ Library Extensions (TR1)).
+//
+// base::hash is implemented by calling the hash_value function. The namespace
+// isn't specified so that it can detect overloads via argument dependant
+// lookup. So if there is a free function hash_value in the same namespace as a
+// custom type, it will get called.
+//
+// If users are asked to implement a hash function for their own types with no
+// guidance, they generally write bad hash functions. Instead, we provide a
+// simple function base::hash_combine to pass hash-relevant member variables
+// into, in order to define a decent hash function. base::hash_combine is
+// declared as:
+//
+// template<typename T, typename... Ts>
+// size_t hash_combine(const T& v, const Ts& ...vs);
+//
+// Consider the following example:
+//
+// namespace v8 {
+// namespace bar {
+// struct Point { int x; int y; };
+// size_t hash_value(Point const& p) {
+// return base::hash_combine(p.x, p.y);
+// }
+// }
+//
+// namespace foo {
+// void DoSomeWork(bar::Point const& p) {
+// base::hash<bar::Point> h;
+// ...
+// size_t hash_code = h(p); // calls bar::hash_value(Point const&)
+// ...
+// }
+// }
+// }
+//
+// Based on the "Hashing User-Defined Types in C++1y" proposal from Jeffrey
+// Yasskin and Chandler Carruth, see
+// http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2012/n3333.html.
+
+template <typename>
+struct hash;
+
+
+V8_INLINE size_t hash_combine() { return 0u; }
+V8_INLINE size_t hash_combine(size_t seed) { return seed; }
+size_t hash_combine(size_t seed, size_t value);
+template <typename T, typename... Ts>
+V8_INLINE size_t hash_combine(T const& v, Ts const&... vs) {
+ return hash_combine(hash_combine(vs...), hash<T>()(v));
+}
+
+
+template <typename Iterator>
+V8_INLINE size_t hash_range(Iterator first, Iterator last) {
+ size_t seed = 0;
+ for (; first != last; ++first) {
+ seed = hash_combine(seed, *first);
+ }
+ return seed;
+}
+
+
+#define V8_BASE_HASH_VALUE_TRIVIAL(type) \
+ V8_INLINE size_t hash_value(type v) { return static_cast<size_t>(v); }
+V8_BASE_HASH_VALUE_TRIVIAL(bool)
+V8_BASE_HASH_VALUE_TRIVIAL(unsigned char)
+V8_BASE_HASH_VALUE_TRIVIAL(unsigned short) // NOLINT(runtime/int)
+#undef V8_BASE_HASH_VALUE_TRIVIAL
+
+size_t hash_value(unsigned int);
+size_t hash_value(unsigned long); // NOLINT(runtime/int)
+size_t hash_value(unsigned long long); // NOLINT(runtime/int)
+
+#define V8_BASE_HASH_VALUE_SIGNED(type) \
+ V8_INLINE size_t hash_value(signed type v) { \
+ return hash_value(bit_cast<unsigned type>(v)); \
+ }
+V8_BASE_HASH_VALUE_SIGNED(char)
+V8_BASE_HASH_VALUE_SIGNED(short) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(int) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(long) // NOLINT(runtime/int)
+V8_BASE_HASH_VALUE_SIGNED(long long) // NOLINT(runtime/int)
+#undef V8_BASE_HASH_VALUE_SIGNED
+
+V8_INLINE size_t hash_value(float v) {
+ // 0 and -0 both hash to zero.
+ return v != 0.0f ? hash_value(bit_cast<uint32_t>(v)) : 0;
+}
+
+V8_INLINE size_t hash_value(double v) {
+ // 0 and -0 both hash to zero.
+ return v != 0.0 ? hash_value(bit_cast<uint64_t>(v)) : 0;
+}
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(const T (&v)[N]) {
+ return hash_range(v, v + N);
+}
+
+template <typename T, size_t N>
+V8_INLINE size_t hash_value(T (&v)[N]) {
+ return hash_range(v, v + N);
+}
+
+template <typename T>
+V8_INLINE size_t hash_value(T* const& v) {
+ return hash_value(bit_cast<uintptr_t>(v));
+}
+
+template <typename T1, typename T2>
+V8_INLINE size_t hash_value(std::pair<T1, T2> const& v) {
+ return hash_combine(v.first, v.second);
+}
+
+
+template <typename T>
+struct hash : public std::unary_function<T, size_t> {
+ V8_INLINE size_t operator()(T const& v) const { return hash_value(v); }
+};
+
+#define V8_BASE_HASH_SPECIALIZE(type) \
+ template <> \
+ struct hash<type> : public std::unary_function<type, size_t> { \
+ V8_INLINE size_t operator()(type const v) const { \
+ return ::v8::base::hash_value(v); \
+ } \
+ };
+V8_BASE_HASH_SPECIALIZE(bool)
+V8_BASE_HASH_SPECIALIZE(signed char)
+V8_BASE_HASH_SPECIALIZE(unsigned char)
+V8_BASE_HASH_SPECIALIZE(short) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned short) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(int)
+V8_BASE_HASH_SPECIALIZE(unsigned int)
+V8_BASE_HASH_SPECIALIZE(long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(long long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(unsigned long long) // NOLINT(runtime/int)
+V8_BASE_HASH_SPECIALIZE(float)
+V8_BASE_HASH_SPECIALIZE(double)
+#undef V8_BASE_HASH_SPECIALIZE
+
+template <typename T>
+struct hash<T*> : public std::unary_function<T*, size_t> {
+ V8_INLINE size_t operator()(T* const v) const {
+ return ::v8::base::hash_value(v);
+ }
+};
+
+
+// base::bit_equal_to is a function object class for bitwise equality
+// comparison, similar to std::equal_to, except that the comparison is performed
+// on the bit representation of the operands.
+//
+// base::bit_hash is a function object class for bitwise hashing, similar to
+// base::hash. It can be used together with base::bit_equal_to to implement a
+// hash data structure based on the bitwise representation of types.
+
+template <typename T>
+struct bit_equal_to : public std::binary_function<T, T, bool> {};
+
+template <typename T>
+struct bit_hash : public std::unary_function<T, size_t> {};
+
+#define V8_BASE_BIT_SPECIALIZE_TRIVIAL(type) \
+ template <> \
+ struct bit_equal_to<type> : public std::equal_to<type> {}; \
+ template <> \
+ struct bit_hash<type> : public hash<type> {};
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(signed char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned char)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(short) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned short) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(long long) // NOLINT(runtime/int)
+V8_BASE_BIT_SPECIALIZE_TRIVIAL(unsigned long long) // NOLINT(runtime/int)
+#undef V8_BASE_BIT_SPECIALIZE_TRIVIAL
+
+#define V8_BASE_BIT_SPECIALIZE_BIT_CAST(type, btype) \
+ template <> \
+ struct bit_equal_to<type> : public std::binary_function<type, type, bool> { \
+ V8_INLINE bool operator()(type lhs, type rhs) const { \
+ return bit_cast<btype>(lhs) == bit_cast<btype>(rhs); \
+ } \
+ }; \
+ template <> \
+ struct bit_hash<type> : public std::unary_function<type, size_t> { \
+ V8_INLINE size_t operator()(type v) const { \
+ hash<btype> h; \
+ return h(bit_cast<btype>(v)); \
+ } \
+ };
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(float, uint32_t)
+V8_BASE_BIT_SPECIALIZE_BIT_CAST(double, uint64_t)
+#undef V8_BASE_BIT_SPECIALIZE_BIT_CAST
+
+} // namespace base
+} // namespace v8
+
+#endif // V8_BASE_FUNCTIONAL_H_
diff --git a/src/base/iterator.h b/src/base/iterator.h
new file mode 100644
index 0000000..e380dc3
--- /dev/null
+++ b/src/base/iterator.h
@@ -0,0 +1,56 @@
+// Copyright 2014 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_ITERATOR_H_
+#define V8_BASE_ITERATOR_H_
+
+#include <iterator>
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+// The intention of the base::iterator_range class is to encapsulate two
+// iterators so that the range defined by the iterators can be used like
+// a regular STL container (actually only a subset of the full container
+// functionality is available usually).
+template <typename ForwardIterator>
+class iterator_range {
+ public:
+ typedef ForwardIterator iterator;
+ typedef ForwardIterator const_iterator;
+ typedef typename std::iterator_traits<iterator>::pointer pointer;
+ typedef typename std::iterator_traits<iterator>::reference reference;
+ typedef typename std::iterator_traits<iterator>::value_type value_type;
+ typedef
+ typename std::iterator_traits<iterator>::difference_type difference_type;
+
+ iterator_range() : begin_(), end_() {}
+ template <typename ForwardIterator2>
+ iterator_range(ForwardIterator2 const& begin, ForwardIterator2 const& end)
+ : begin_(begin), end_(end) {}
+
+ iterator begin() { return begin_; }
+ iterator end() { return end_; }
+ const_iterator begin() const { return begin_; }
+ const_iterator end() const { return end_; }
+ const_iterator cbegin() const { return begin_; }
+ const_iterator cend() const { return end_; }
+
+ bool empty() const { return cbegin() == cend(); }
+
+ // Random Access iterators only.
+ reference operator[](difference_type n) { return begin()[n]; }
+ difference_type size() const { return cend() - cbegin(); }
+
+ private:
+ const_iterator const begin_;
+ const_iterator const end_;
+};
+
+} // namespace base
+} // namespace v8
+
+#endif // V8_BASE_ITERATOR_H_
diff --git a/src/base/logging.h b/src/base/logging.h
index 8e24bb0..83c1bb6 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -5,9 +5,9 @@
#ifndef V8_BASE_LOGGING_H_
#define V8_BASE_LOGGING_H_
+#include <stdint.h>
#include <string.h>
-#include "include/v8stdint.h"
#include "src/base/build_config.h"
extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
diff --git a/src/base/macros.h b/src/base/macros.h
index cef088c..371d7da 100644
--- a/src/base/macros.h
+++ b/src/base/macros.h
@@ -5,9 +5,11 @@
#ifndef V8_BASE_MACROS_H_
#define V8_BASE_MACROS_H_
+#include <stddef.h>
+#include <stdint.h>
+
#include <cstring>
-#include "include/v8stdint.h"
#include "src/base/build_config.h"
#include "src/base/compiler-specific.h"
#include "src/base/logging.h"
@@ -18,11 +20,13 @@
// corresponds to 'offsetof' (in stddef.h), except that it doesn't
// use 0 or NULL, which causes a problem with the compiler warnings
// we have enabled (which is also why 'offsetof' doesn't seem to work).
-// Here we simply use the non-zero value 4, which seems to work.
-#define OFFSET_OF(type, field) \
- (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(4)->field)) - 4)
+// Here we simply use the aligned, non-zero value 16.
+#define OFFSET_OF(type, field) \
+ (reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(16)->field)) - 16)
+#if V8_OS_NACL
+
// ARRAYSIZE_UNSAFE performs essentially the same calculation as arraysize,
// but can be used on anonymous types or types defined inside
// functions. It's less safe than arraysize as it accepts some
@@ -63,9 +67,6 @@
((sizeof(a) / sizeof(*(a))) / \
static_cast<size_t>(!(sizeof(a) % sizeof(*(a))))) // NOLINT
-
-#if V8_OS_NACL
-
// TODO(bmeurer): For some reason, the NaCl toolchain cannot handle the correct
// definition of arraysize() below, so we have to use the unsafe version for
// now.
@@ -130,7 +131,7 @@
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<static_cast<bool>(expr)> \
- msg[static_cast<bool>(expr) ? 1 : -1] ALLOW_UNUSED
+ msg[static_cast<bool>(expr) ? 1 : -1] ALLOW_UNUSED_TYPE
// Implementation details of COMPILE_ASSERT:
//
@@ -150,23 +151,11 @@
// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
// // not a compile-time constant.
//
-// - By using the type CompileAssert<(bool(expr))>, we ensures that
+// - By using the type CompileAssert<static_cast<bool>(expr)>, we ensure that
// expr is a compile-time constant. (Template arguments must be
// determined at compile-time.)
//
-// - The outer parentheses in CompileAssert<(bool(expr))> are necessary
-// to work around a bug in gcc 3.4.4 and 4.0.1. If we had written
-//
-// CompileAssert<bool(expr)>
-//
-// instead, these compilers will refuse to compile
-//
-// COMPILE_ASSERT(5 > 0, some_message);
-//
-// (They seem to think the ">" in "5 > 0" marks the end of the
-// template argument list.)
-//
-// - The array size is (bool(expr) ? 1 : -1), instead of simply
+// - The array size is (static_cast<bool>(expr) ? 1 : -1), instead of simply
//
// ((expr) ? 1 : -1).
//
@@ -308,10 +297,10 @@
// actually causes each use to introduce a new defined type with a
// name depending on the source line.
template <int> class StaticAssertionHelper { };
-#define STATIC_ASSERT(test) \
- typedef \
- StaticAssertionHelper<sizeof(StaticAssertion<static_cast<bool>((test))>)> \
- SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) ALLOW_UNUSED
+#define STATIC_ASSERT(test) \
+ typedef StaticAssertionHelper< \
+ sizeof(StaticAssertion<static_cast<bool>((test))>)> \
+ SEMI_STATIC_JOIN(__StaticAssertTypedef__, __LINE__) ALLOW_UNUSED_TYPE
#endif
@@ -408,4 +397,22 @@
return RoundDown<T>(static_cast<T>(x + m - 1), m);
}
+
+namespace v8 {
+namespace base {
+
+// TODO(yangguo): This is a poor man's replacement for std::is_fundamental,
+// which requires C++11. Switch to std::is_fundamental once possible.
+template <typename T>
+inline bool is_fundamental() {
+ return false;
+}
+
+template <>
+inline bool is_fundamental<uint8_t>() {
+ return true;
+}
+}
+} // namespace v8::base
+
#endif // V8_BASE_MACROS_H_
diff --git a/src/base/once.h b/src/base/once.h
index a8e8437..6bf741d 100644
--- a/src/base/once.h
+++ b/src/base/once.h
@@ -52,6 +52,8 @@
#ifndef V8_BASE_ONCE_H_
#define V8_BASE_ONCE_H_
+#include <stddef.h>
+
#include "src/base/atomicops.h"
namespace v8 {
diff --git a/src/base/platform/condition-variable-unittest.cc b/src/base/platform/condition-variable-unittest.cc
deleted file mode 100644
index fe0ad2a..0000000
--- a/src/base/platform/condition-variable-unittest.cc
+++ /dev/null
@@ -1,301 +0,0 @@
-// Copyright 2014 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/platform/condition-variable.h"
-
-#include "src/base/platform/platform.h"
-#include "src/base/platform/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-TEST(ConditionVariable, WaitForAfterNofityOnSameThread) {
- for (int n = 0; n < 10; ++n) {
- Mutex mutex;
- ConditionVariable cv;
-
- LockGuard<Mutex> lock_guard(&mutex);
-
- cv.NotifyOne();
- EXPECT_FALSE(cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n)));
-
- cv.NotifyAll();
- EXPECT_FALSE(cv.WaitFor(&mutex, TimeDelta::FromMicroseconds(n)));
- }
-}
-
-
-namespace {
-
-class ThreadWithMutexAndConditionVariable FINAL : public Thread {
- public:
- ThreadWithMutexAndConditionVariable()
- : Thread(Options("ThreadWithMutexAndConditionVariable")),
- running_(false),
- finished_(false) {}
- virtual ~ThreadWithMutexAndConditionVariable() {}
-
- virtual void Run() OVERRIDE {
- LockGuard<Mutex> lock_guard(&mutex_);
- running_ = true;
- cv_.NotifyOne();
- while (running_) {
- cv_.Wait(&mutex_);
- }
- finished_ = true;
- cv_.NotifyAll();
- }
-
- bool running_;
- bool finished_;
- ConditionVariable cv_;
- Mutex mutex_;
-};
-
-} // namespace
-
-
-TEST(ConditionVariable, MultipleThreadsWithSeparateConditionVariables) {
- static const int kThreadCount = 128;
- ThreadWithMutexAndConditionVariable threads[kThreadCount];
-
- for (int n = 0; n < kThreadCount; ++n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
- EXPECT_FALSE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- threads[n].Start();
- // Wait for nth thread to start.
- while (!threads[n].running_) {
- threads[n].cv_.Wait(&threads[n].mutex_);
- }
- }
-
- for (int n = kThreadCount - 1; n >= 0; --n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
- EXPECT_TRUE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- }
-
- for (int n = 0; n < kThreadCount; ++n) {
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
- EXPECT_TRUE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- // Tell the nth thread to quit.
- threads[n].running_ = false;
- threads[n].cv_.NotifyOne();
- }
-
- for (int n = kThreadCount - 1; n >= 0; --n) {
- // Wait for nth thread to quit.
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
- while (!threads[n].finished_) {
- threads[n].cv_.Wait(&threads[n].mutex_);
- }
- EXPECT_FALSE(threads[n].running_);
- EXPECT_TRUE(threads[n].finished_);
- }
-
- for (int n = 0; n < kThreadCount; ++n) {
- threads[n].Join();
- LockGuard<Mutex> lock_guard(&threads[n].mutex_);
- EXPECT_FALSE(threads[n].running_);
- EXPECT_TRUE(threads[n].finished_);
- }
-}
-
-
-namespace {
-
-class ThreadWithSharedMutexAndConditionVariable FINAL : public Thread {
- public:
- ThreadWithSharedMutexAndConditionVariable()
- : Thread(Options("ThreadWithSharedMutexAndConditionVariable")),
- running_(false),
- finished_(false),
- cv_(NULL),
- mutex_(NULL) {}
- virtual ~ThreadWithSharedMutexAndConditionVariable() {}
-
- virtual void Run() OVERRIDE {
- LockGuard<Mutex> lock_guard(mutex_);
- running_ = true;
- cv_->NotifyAll();
- while (running_) {
- cv_->Wait(mutex_);
- }
- finished_ = true;
- cv_->NotifyAll();
- }
-
- bool running_;
- bool finished_;
- ConditionVariable* cv_;
- Mutex* mutex_;
-};
-
-} // namespace
-
-
-TEST(ConditionVariable, MultipleThreadsWithSharedSeparateConditionVariables) {
- static const int kThreadCount = 128;
- ThreadWithSharedMutexAndConditionVariable threads[kThreadCount];
- ConditionVariable cv;
- Mutex mutex;
-
- for (int n = 0; n < kThreadCount; ++n) {
- threads[n].mutex_ = &mutex;
- threads[n].cv_ = &cv;
- }
-
- // Start all threads.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = 0; n < kThreadCount; ++n) {
- EXPECT_FALSE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- threads[n].Start();
- }
- }
-
- // Wait for all threads to start.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = kThreadCount - 1; n >= 0; --n) {
- while (!threads[n].running_) {
- cv.Wait(&mutex);
- }
- }
- }
-
- // Make sure that all threads are running.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = 0; n < kThreadCount; ++n) {
- EXPECT_TRUE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- }
- }
-
- // Tell all threads to quit.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = kThreadCount - 1; n >= 0; --n) {
- EXPECT_TRUE(threads[n].running_);
- EXPECT_FALSE(threads[n].finished_);
- // Tell the nth thread to quit.
- threads[n].running_ = false;
- }
- cv.NotifyAll();
- }
-
- // Wait for all threads to quit.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = 0; n < kThreadCount; ++n) {
- while (!threads[n].finished_) {
- cv.Wait(&mutex);
- }
- }
- }
-
- // Make sure all threads are finished.
- {
- LockGuard<Mutex> lock_guard(&mutex);
- for (int n = kThreadCount - 1; n >= 0; --n) {
- EXPECT_FALSE(threads[n].running_);
- EXPECT_TRUE(threads[n].finished_);
- }
- }
-
- // Join all threads.
- for (int n = 0; n < kThreadCount; ++n) {
- threads[n].Join();
- }
-}
-
-
-namespace {
-
-class LoopIncrementThread FINAL : public Thread {
- public:
- LoopIncrementThread(int rem, int* counter, int limit, int thread_count,
- ConditionVariable* cv, Mutex* mutex)
- : Thread(Options("LoopIncrementThread")),
- rem_(rem),
- counter_(counter),
- limit_(limit),
- thread_count_(thread_count),
- cv_(cv),
- mutex_(mutex) {
- EXPECT_LT(rem, thread_count);
- EXPECT_EQ(0, limit % thread_count);
- }
-
- virtual void Run() OVERRIDE {
- int last_count = -1;
- while (true) {
- LockGuard<Mutex> lock_guard(mutex_);
- int count = *counter_;
- while (count % thread_count_ != rem_ && count < limit_) {
- cv_->Wait(mutex_);
- count = *counter_;
- }
- if (count >= limit_) break;
- EXPECT_EQ(*counter_, count);
- if (last_count != -1) {
- EXPECT_EQ(last_count + (thread_count_ - 1), count);
- }
- count++;
- *counter_ = count;
- last_count = count;
- cv_->NotifyAll();
- }
- }
-
- private:
- const int rem_;
- int* counter_;
- const int limit_;
- const int thread_count_;
- ConditionVariable* cv_;
- Mutex* mutex_;
-};
-
-} // namespace
-
-
-TEST(ConditionVariable, LoopIncrement) {
- static const int kMaxThreadCount = 16;
- Mutex mutex;
- ConditionVariable cv;
- for (int thread_count = 1; thread_count < kMaxThreadCount; ++thread_count) {
- int limit = thread_count * 10;
- int counter = 0;
-
- // Setup the threads.
- Thread** threads = new Thread* [thread_count];
- for (int n = 0; n < thread_count; ++n) {
- threads[n] = new LoopIncrementThread(n, &counter, limit, thread_count,
- &cv, &mutex);
- }
-
- // Start all threads.
- for (int n = thread_count - 1; n >= 0; --n) {
- threads[n]->Start();
- }
-
- // Join and cleanup all threads.
- for (int n = 0; n < thread_count; ++n) {
- threads[n]->Join();
- delete threads[n];
- }
- delete[] threads;
-
- EXPECT_EQ(limit, counter);
- }
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/platform/mutex-unittest.cc b/src/base/platform/mutex-unittest.cc
deleted file mode 100644
index 5af5efb..0000000
--- a/src/base/platform/mutex-unittest.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// Copyright 2014 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/platform/mutex.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-TEST(Mutex, LockGuardMutex) {
- Mutex mutex;
- { LockGuard<Mutex> lock_guard(&mutex); }
- { LockGuard<Mutex> lock_guard(&mutex); }
-}
-
-
-TEST(Mutex, LockGuardRecursiveMutex) {
- RecursiveMutex recursive_mutex;
- { LockGuard<RecursiveMutex> lock_guard(&recursive_mutex); }
- {
- LockGuard<RecursiveMutex> lock_guard1(&recursive_mutex);
- LockGuard<RecursiveMutex> lock_guard2(&recursive_mutex);
- }
-}
-
-
-TEST(Mutex, LockGuardLazyMutex) {
- LazyMutex lazy_mutex = LAZY_MUTEX_INITIALIZER;
- { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); }
- { LockGuard<Mutex> lock_guard(lazy_mutex.Pointer()); }
-}
-
-
-TEST(Mutex, LockGuardLazyRecursiveMutex) {
- LazyRecursiveMutex lazy_recursive_mutex = LAZY_RECURSIVE_MUTEX_INITIALIZER;
- { LockGuard<RecursiveMutex> lock_guard(lazy_recursive_mutex.Pointer()); }
- {
- LockGuard<RecursiveMutex> lock_guard1(lazy_recursive_mutex.Pointer());
- LockGuard<RecursiveMutex> lock_guard2(lazy_recursive_mutex.Pointer());
- }
-}
-
-
-TEST(Mutex, MultipleMutexes) {
- Mutex mutex1;
- Mutex mutex2;
- Mutex mutex3;
- // Order 1
- mutex1.Lock();
- mutex2.Lock();
- mutex3.Lock();
- mutex1.Unlock();
- mutex2.Unlock();
- mutex3.Unlock();
- // Order 2
- mutex1.Lock();
- mutex2.Lock();
- mutex3.Lock();
- mutex3.Unlock();
- mutex2.Unlock();
- mutex1.Unlock();
-}
-
-
-TEST(Mutex, MultipleRecursiveMutexes) {
- RecursiveMutex recursive_mutex1;
- RecursiveMutex recursive_mutex2;
- // Order 1
- recursive_mutex1.Lock();
- recursive_mutex2.Lock();
- EXPECT_TRUE(recursive_mutex1.TryLock());
- EXPECT_TRUE(recursive_mutex2.TryLock());
- recursive_mutex1.Unlock();
- recursive_mutex1.Unlock();
- recursive_mutex2.Unlock();
- recursive_mutex2.Unlock();
- // Order 2
- recursive_mutex1.Lock();
- EXPECT_TRUE(recursive_mutex1.TryLock());
- recursive_mutex2.Lock();
- EXPECT_TRUE(recursive_mutex2.TryLock());
- recursive_mutex2.Unlock();
- recursive_mutex1.Unlock();
- recursive_mutex2.Unlock();
- recursive_mutex1.Unlock();
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/platform/platform-freebsd.cc b/src/base/platform/platform-freebsd.cc
index 507b946..58316f8 100644
--- a/src/base/platform/platform-freebsd.cc
+++ b/src/base/platform/platform-freebsd.cc
@@ -141,7 +141,7 @@
if (bytes_read < 8) break;
unsigned end = StringToLong(addr_buffer);
char buffer[MAP_LENGTH];
- int bytes_read = -1;
+ bytes_read = -1;
do {
bytes_read++;
if (bytes_read >= MAP_LENGTH - 1)
diff --git a/src/base/platform/platform-linux.cc b/src/base/platform/platform-linux.cc
index eff5ced..36857e6 100644
--- a/src/base/platform/platform-linux.cc
+++ b/src/base/platform/platform-linux.cc
@@ -8,10 +8,10 @@
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
+#include <stdio.h>
#include <stdlib.h>
#include <sys/resource.h>
#include <sys/time.h>
-#include <sys/types.h>
// Ubuntu Dapper requires memory pages to be marked as
// executable. Otherwise, OS raises an exception when executing code
@@ -109,7 +109,7 @@
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv);
- if (NULL == t) return "";
+ if (!t || !t->tm_zone) return "";
return t->tm_zone;
#endif
}
diff --git a/src/base/platform/platform-posix.cc b/src/base/platform/platform-posix.cc
index 99feb65..64aed2b 100644
--- a/src/base/platform/platform-posix.cc
+++ b/src/base/platform/platform-posix.cc
@@ -13,6 +13,7 @@
#include <pthread_np.h> // for pthread_set_name_np
#endif
#include <sched.h> // for sched_yield
+#include <stdio.h>
#include <time.h>
#include <unistd.h>
@@ -253,20 +254,14 @@
int OS::GetCurrentThreadId() {
-#if defined(ANDROID)
-#if defined(__APPLE__)
- uint64_t owner;
- pthread_threadid_np(NULL, &owner); // Requires Mac OS 10.6
- return owner;
-#else
+#if V8_OS_MACOSX || (V8_OS_ANDROID && defined(__APPLE__))
+ return static_cast<int>(pthread_mach_thread_np(pthread_self()));
+#elif V8_OS_LINUX
return static_cast<int>(syscall(__NR_gettid));
-#endif
-#elif defined(SYS_gettid)
- return static_cast<int>(syscall(SYS_gettid));
+#elif V8_OS_ANDROID
+ return static_cast<int>(gettid());
#else
- // PNaCL doesn't have a way to get an integral thread ID, but it doesn't
- // really matter, because we only need it in PerfJitLogger::LogRecordedBuffer.
- return 0;
+ return static_cast<int>(reinterpret_cast<intptr_t>(pthread_self()));
#endif
}
diff --git a/src/base/platform/platform-solaris.cc b/src/base/platform/platform-solaris.cc
index b9ef465..b9a2ec8 100644
--- a/src/base/platform/platform-solaris.cc
+++ b/src/base/platform/platform-solaris.cc
@@ -31,26 +31,6 @@
#include "src/base/platform/platform.h"
-// It seems there is a bug in some Solaris distributions (experienced in
-// SunOS 5.10 Generic_141445-09) which make it difficult or impossible to
-// access signbit() despite the availability of other C99 math functions.
-#ifndef signbit
-namespace std {
-// Test sign - usually defined in math.h
-int signbit(double x) {
- // We need to take care of the special case of both positive and negative
- // versions of zero.
- if (x == 0) {
- return fpclass(x) & FP_NZERO;
- } else {
- // This won't detect negative NaN but that should be okay since we don't
- // assume that behavior.
- return x < 0;
- }
-}
-} // namespace std
-#endif // signbit
-
namespace v8 {
namespace base {
diff --git a/src/base/platform/platform-unittest.cc b/src/base/platform/platform-unittest.cc
deleted file mode 100644
index 06fbee0..0000000
--- a/src/base/platform/platform-unittest.cc
+++ /dev/null
@@ -1,110 +0,0 @@
-// Copyright 2014 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/platform/platform.h"
-
-#if V8_OS_POSIX
-#include <unistd.h> // NOLINT
-#endif
-
-#if V8_OS_WIN
-#include "src/base/win32-headers.h"
-#endif
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-TEST(OS, GetCurrentProcessId) {
-#if V8_OS_POSIX
- EXPECT_EQ(static_cast<int>(getpid()), OS::GetCurrentProcessId());
-#endif
-
-#if V8_OS_WIN
- EXPECT_EQ(static_cast<int>(::GetCurrentProcessId()),
- OS::GetCurrentProcessId());
-#endif
-}
-
-
-namespace {
-
-class SelfJoinThread FINAL : public Thread {
- public:
- SelfJoinThread() : Thread(Options("SelfJoinThread")) {}
- virtual void Run() OVERRIDE { Join(); }
-};
-
-} // namespace
-
-
-TEST(Thread, SelfJoin) {
- SelfJoinThread thread;
- thread.Start();
- thread.Join();
-}
-
-
-namespace {
-
-class ThreadLocalStorageTest : public Thread, public ::testing::Test {
- public:
- ThreadLocalStorageTest() : Thread(Options("ThreadLocalStorageTest")) {
- for (size_t i = 0; i < arraysize(keys_); ++i) {
- keys_[i] = Thread::CreateThreadLocalKey();
- }
- }
- ~ThreadLocalStorageTest() {
- for (size_t i = 0; i < arraysize(keys_); ++i) {
- Thread::DeleteThreadLocalKey(keys_[i]);
- }
- }
-
- virtual void Run() FINAL OVERRIDE {
- for (size_t i = 0; i < arraysize(keys_); i++) {
- CHECK(!Thread::HasThreadLocal(keys_[i]));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- Thread::SetThreadLocal(keys_[i], GetValue(i));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- CHECK(Thread::HasThreadLocal(keys_[i]));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- CHECK_EQ(GetValue(i), Thread::GetThreadLocal(keys_[i]));
- CHECK_EQ(GetValue(i), Thread::GetExistingThreadLocal(keys_[i]));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- Thread::SetThreadLocal(keys_[i], GetValue(arraysize(keys_) - i - 1));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- CHECK(Thread::HasThreadLocal(keys_[i]));
- }
- for (size_t i = 0; i < arraysize(keys_); i++) {
- CHECK_EQ(GetValue(arraysize(keys_) - i - 1),
- Thread::GetThreadLocal(keys_[i]));
- CHECK_EQ(GetValue(arraysize(keys_) - i - 1),
- Thread::GetExistingThreadLocal(keys_[i]));
- }
- }
-
- private:
- static void* GetValue(size_t x) {
- return reinterpret_cast<void*>(static_cast<uintptr_t>(x + 1));
- }
-
- Thread::LocalStorageKey keys_[256];
-};
-
-} // namespace
-
-
-TEST_F(ThreadLocalStorageTest, DoTest) {
- Run();
- Start();
- Join();
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/platform/platform-win32.cc b/src/base/platform/platform-win32.cc
index 10f89de..d68e861 100644
--- a/src/base/platform/platform-win32.cc
+++ b/src/base/platform/platform-win32.cc
@@ -15,9 +15,7 @@
#endif // MINGW_HAS_SECURE_API
#endif // __MINGW32__
-#ifdef _MSC_VER
#include <limits>
-#endif
#include "src/base/win32-headers.h"
@@ -28,16 +26,6 @@
#include "src/base/platform/time.h"
#include "src/base/utils/random-number-generator.h"
-#ifdef _MSC_VER
-
-// Case-insensitive bounded string comparisons. Use stricmp() on Win32. Usually
-// defined in strings.h.
-int strncasecmp(const char* s1, const char* s2, int n) {
- return _strnicmp(s1, s2, n);
-}
-
-#endif // _MSC_VER
-
// Extra functions for MinGW. Most of these are the _s functions which are in
// the Microsoft Visual Studio C++ CRT.
@@ -367,8 +355,8 @@
cache->InitializeIfNeeded();
Win32Time rounded_to_second(*this);
- rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
- 1000 * kTimeScaler;
+ rounded_to_second.t() =
+ rounded_to_second.t() / 1000 / kTimeScaler * 1000 * kTimeScaler;
// Convert to local time using POSIX localtime function.
// Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime()
// very slow. Other browsers use localtime().
@@ -832,7 +820,7 @@
void OS::DebugBreak() {
-#ifdef _MSC_VER
+#if V8_CC_MSVC
// To avoid Visual Studio runtime support the following code can be used
// instead
// __asm { int 3 }
@@ -1175,11 +1163,7 @@
double OS::nan_value() {
-#ifdef _MSC_VER
return std::numeric_limits<double>::quiet_NaN();
-#else // _MSC_VER
- return NAN;
-#endif // _MSC_VER
}
diff --git a/src/base/platform/platform.h b/src/base/platform/platform.h
index 9e20c08..0bf1027 100644
--- a/src/base/platform/platform.h
+++ b/src/base/platform/platform.h
@@ -21,7 +21,7 @@
#ifndef V8_BASE_PLATFORM_PLATFORM_H_
#define V8_BASE_PLATFORM_PLATFORM_H_
-#include <stdarg.h>
+#include <cstdarg>
#include <string>
#include <vector>
@@ -29,48 +29,10 @@
#include "src/base/platform/mutex.h"
#include "src/base/platform/semaphore.h"
-#ifdef __sun
-# ifndef signbit
-namespace std {
-int signbit(double x);
-}
-# endif
-#endif
-
#if V8_OS_QNX
#include "src/base/qnx-math.h"
#endif
-// Microsoft Visual C++ specific stuff.
-#if V8_LIBC_MSVCRT
-
-#include "src/base/win32-headers.h"
-#include "src/base/win32-math.h"
-
-int strncasecmp(const char* s1, const char* s2, int n);
-
-// Visual C++ 2013 and higher implement this function.
-#if (_MSC_VER < 1800)
-inline int lrint(double flt) {
- int intgr;
-#if V8_TARGET_ARCH_IA32 || V8_TARGET_ARCH_X87
- __asm {
- fld flt
- fistp intgr
- };
-#else
- intgr = static_cast<int>(flt + 0.5);
- if ((intgr & 1) != 0 && intgr - flt == 0.5) {
- // If the number is halfway between two integers, round to the even one.
- intgr--;
- }
-#endif
- return intgr;
-}
-#endif // _MSC_VER < 1800
-
-#endif // V8_LIBC_MSVCRT
-
namespace v8 {
namespace base {
@@ -79,7 +41,7 @@
#ifndef V8_NO_FAST_TLS
-#if defined(_MSC_VER) && (V8_HOST_ARCH_IA32)
+#if V8_CC_MSVC && V8_HOST_ARCH_IA32
#define V8_FAST_TLS_SUPPORTED 1
diff --git a/src/base/platform/semaphore-unittest.cc b/src/base/platform/semaphore-unittest.cc
deleted file mode 100644
index c68435f..0000000
--- a/src/base/platform/semaphore-unittest.cc
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright 2014 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 <cstring>
-
-#include "src/base/platform/platform.h"
-#include "src/base/platform/semaphore.h"
-#include "src/base/platform/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-namespace {
-
-static const char kAlphabet[] = "XKOAD";
-static const size_t kAlphabetSize = sizeof(kAlphabet) - 1;
-static const size_t kBufferSize = 987; // GCD(buffer size, alphabet size) = 1
-static const size_t kDataSize = kBufferSize * kAlphabetSize * 10;
-
-
-class ProducerThread FINAL : public Thread {
- public:
- ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space)
- : Thread(Options("ProducerThread")),
- buffer_(buffer),
- free_space_(free_space),
- used_space_(used_space) {}
- virtual ~ProducerThread() {}
-
- virtual void Run() OVERRIDE {
- for (size_t n = 0; n < kDataSize; ++n) {
- free_space_->Wait();
- buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize];
- used_space_->Signal();
- }
- }
-
- private:
- char* buffer_;
- Semaphore* const free_space_;
- Semaphore* const used_space_;
-};
-
-
-class ConsumerThread FINAL : public Thread {
- public:
- ConsumerThread(const char* buffer, Semaphore* free_space,
- Semaphore* used_space)
- : Thread(Options("ConsumerThread")),
- buffer_(buffer),
- free_space_(free_space),
- used_space_(used_space) {}
- virtual ~ConsumerThread() {}
-
- virtual void Run() OVERRIDE {
- for (size_t n = 0; n < kDataSize; ++n) {
- used_space_->Wait();
- EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]);
- free_space_->Signal();
- }
- }
-
- private:
- const char* buffer_;
- Semaphore* const free_space_;
- Semaphore* const used_space_;
-};
-
-
-class WaitAndSignalThread FINAL : public Thread {
- public:
- explicit WaitAndSignalThread(Semaphore* semaphore)
- : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {}
- virtual ~WaitAndSignalThread() {}
-
- virtual void Run() OVERRIDE {
- for (int n = 0; n < 100; ++n) {
- semaphore_->Wait();
- ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1)));
- semaphore_->Signal();
- }
- }
-
- private:
- Semaphore* const semaphore_;
-};
-
-} // namespace
-
-
-TEST(Semaphore, ProducerConsumer) {
- char buffer[kBufferSize];
- std::memset(buffer, 0, sizeof(buffer));
- Semaphore free_space(kBufferSize);
- Semaphore used_space(0);
- ProducerThread producer_thread(buffer, &free_space, &used_space);
- ConsumerThread consumer_thread(buffer, &free_space, &used_space);
- producer_thread.Start();
- consumer_thread.Start();
- producer_thread.Join();
- consumer_thread.Join();
-}
-
-
-TEST(Semaphore, WaitAndSignal) {
- Semaphore semaphore(0);
- WaitAndSignalThread t1(&semaphore);
- WaitAndSignalThread t2(&semaphore);
-
- t1.Start();
- t2.Start();
-
- // Make something available.
- semaphore.Signal();
-
- t1.Join();
- t2.Join();
-
- semaphore.Wait();
-
- EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1)));
-}
-
-
-TEST(Semaphore, WaitFor) {
- Semaphore semaphore(0);
-
- // Semaphore not signalled - timeout.
- ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
- ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
- ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
-
- // Semaphore signalled - no timeout.
- semaphore.Signal();
- ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0)));
- semaphore.Signal();
- ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100)));
- semaphore.Signal();
- ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000)));
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/platform/time-unittest.cc b/src/base/platform/time-unittest.cc
deleted file mode 100644
index b3bfbab..0000000
--- a/src/base/platform/time-unittest.cc
+++ /dev/null
@@ -1,186 +0,0 @@
-// Copyright 2014 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/platform/time.h"
-
-#if V8_OS_MACOSX
-#include <mach/mach_time.h>
-#endif
-#if V8_OS_POSIX
-#include <sys/time.h>
-#endif
-
-#if V8_OS_WIN
-#include "src/base/win32-headers.h"
-#endif
-
-#include "src/base/platform/elapsed-timer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-TEST(TimeDelta, FromAndIn) {
- EXPECT_EQ(TimeDelta::FromDays(2), TimeDelta::FromHours(48));
- EXPECT_EQ(TimeDelta::FromHours(3), TimeDelta::FromMinutes(180));
- EXPECT_EQ(TimeDelta::FromMinutes(2), TimeDelta::FromSeconds(120));
- EXPECT_EQ(TimeDelta::FromSeconds(2), TimeDelta::FromMilliseconds(2000));
- EXPECT_EQ(TimeDelta::FromMilliseconds(2), TimeDelta::FromMicroseconds(2000));
- EXPECT_EQ(static_cast<int>(13), TimeDelta::FromDays(13).InDays());
- EXPECT_EQ(static_cast<int>(13), TimeDelta::FromHours(13).InHours());
- EXPECT_EQ(static_cast<int>(13), TimeDelta::FromMinutes(13).InMinutes());
- EXPECT_EQ(static_cast<int64_t>(13), TimeDelta::FromSeconds(13).InSeconds());
- EXPECT_DOUBLE_EQ(13.0, TimeDelta::FromSeconds(13).InSecondsF());
- EXPECT_EQ(static_cast<int64_t>(13),
- TimeDelta::FromMilliseconds(13).InMilliseconds());
- EXPECT_DOUBLE_EQ(13.0, TimeDelta::FromMilliseconds(13).InMillisecondsF());
- EXPECT_EQ(static_cast<int64_t>(13),
- TimeDelta::FromMicroseconds(13).InMicroseconds());
-}
-
-
-#if V8_OS_MACOSX
-TEST(TimeDelta, MachTimespec) {
- TimeDelta null = TimeDelta();
- EXPECT_EQ(null, TimeDelta::FromMachTimespec(null.ToMachTimespec()));
- TimeDelta delta1 = TimeDelta::FromMilliseconds(42);
- EXPECT_EQ(delta1, TimeDelta::FromMachTimespec(delta1.ToMachTimespec()));
- TimeDelta delta2 = TimeDelta::FromDays(42);
- EXPECT_EQ(delta2, TimeDelta::FromMachTimespec(delta2.ToMachTimespec()));
-}
-#endif
-
-
-TEST(Time, JsTime) {
- Time t = Time::FromJsTime(700000.3);
- EXPECT_DOUBLE_EQ(700000.3, t.ToJsTime());
-}
-
-
-#if V8_OS_POSIX
-TEST(Time, Timespec) {
- Time null;
- EXPECT_TRUE(null.IsNull());
- EXPECT_EQ(null, Time::FromTimespec(null.ToTimespec()));
- Time now = Time::Now();
- EXPECT_EQ(now, Time::FromTimespec(now.ToTimespec()));
- Time now_sys = Time::NowFromSystemTime();
- EXPECT_EQ(now_sys, Time::FromTimespec(now_sys.ToTimespec()));
- Time unix_epoch = Time::UnixEpoch();
- EXPECT_EQ(unix_epoch, Time::FromTimespec(unix_epoch.ToTimespec()));
- Time max = Time::Max();
- EXPECT_TRUE(max.IsMax());
- EXPECT_EQ(max, Time::FromTimespec(max.ToTimespec()));
-}
-
-
-TEST(Time, Timeval) {
- Time null;
- EXPECT_TRUE(null.IsNull());
- EXPECT_EQ(null, Time::FromTimeval(null.ToTimeval()));
- Time now = Time::Now();
- EXPECT_EQ(now, Time::FromTimeval(now.ToTimeval()));
- Time now_sys = Time::NowFromSystemTime();
- EXPECT_EQ(now_sys, Time::FromTimeval(now_sys.ToTimeval()));
- Time unix_epoch = Time::UnixEpoch();
- EXPECT_EQ(unix_epoch, Time::FromTimeval(unix_epoch.ToTimeval()));
- Time max = Time::Max();
- EXPECT_TRUE(max.IsMax());
- EXPECT_EQ(max, Time::FromTimeval(max.ToTimeval()));
-}
-#endif
-
-
-#if V8_OS_WIN
-TEST(Time, Filetime) {
- Time null;
- EXPECT_TRUE(null.IsNull());
- EXPECT_EQ(null, Time::FromFiletime(null.ToFiletime()));
- Time now = Time::Now();
- EXPECT_EQ(now, Time::FromFiletime(now.ToFiletime()));
- Time now_sys = Time::NowFromSystemTime();
- EXPECT_EQ(now_sys, Time::FromFiletime(now_sys.ToFiletime()));
- Time unix_epoch = Time::UnixEpoch();
- EXPECT_EQ(unix_epoch, Time::FromFiletime(unix_epoch.ToFiletime()));
- Time max = Time::Max();
- EXPECT_TRUE(max.IsMax());
- EXPECT_EQ(max, Time::FromFiletime(max.ToFiletime()));
-}
-#endif
-
-
-namespace {
-
-template <typename T>
-static void ResolutionTest(T (*Now)(), TimeDelta target_granularity) {
- // We're trying to measure that intervals increment in a VERY small amount
- // of time -- according to the specified target granularity. Unfortunately,
- // if we happen to have a context switch in the middle of our test, the
- // context switch could easily exceed our limit. So, we iterate on this
- // several times. As long as we're able to detect the fine-granularity
- // timers at least once, then the test has succeeded.
- static const TimeDelta kExpirationTimeout = TimeDelta::FromSeconds(1);
- ElapsedTimer timer;
- timer.Start();
- TimeDelta delta;
- do {
- T start = Now();
- T now = start;
- // Loop until we can detect that the clock has changed. Non-HighRes timers
- // will increment in chunks, i.e. 15ms. By spinning until we see a clock
- // change, we detect the minimum time between measurements.
- do {
- now = Now();
- delta = now - start;
- } while (now <= start);
- EXPECT_NE(static_cast<int64_t>(0), delta.InMicroseconds());
- } while (delta > target_granularity && !timer.HasExpired(kExpirationTimeout));
- EXPECT_LE(delta, target_granularity);
-}
-
-} // namespace
-
-
-TEST(Time, NowResolution) {
- // We assume that Time::Now() has at least 16ms resolution.
- static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
- ResolutionTest<Time>(&Time::Now, kTargetGranularity);
-}
-
-
-TEST(TimeTicks, NowResolution) {
- // We assume that TimeTicks::Now() has at least 16ms resolution.
- static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(16);
- ResolutionTest<TimeTicks>(&TimeTicks::Now, kTargetGranularity);
-}
-
-
-TEST(TimeTicks, HighResolutionNowResolution) {
- if (!TimeTicks::IsHighResolutionClockWorking()) return;
-
- // We assume that TimeTicks::HighResolutionNow() has sub-ms resolution.
- static const TimeDelta kTargetGranularity = TimeDelta::FromMilliseconds(1);
- ResolutionTest<TimeTicks>(&TimeTicks::HighResolutionNow, kTargetGranularity);
-}
-
-
-TEST(TimeTicks, IsMonotonic) {
- TimeTicks previous_normal_ticks;
- TimeTicks previous_highres_ticks;
- ElapsedTimer timer;
- timer.Start();
- while (!timer.HasExpired(TimeDelta::FromMilliseconds(100))) {
- TimeTicks normal_ticks = TimeTicks::Now();
- TimeTicks highres_ticks = TimeTicks::HighResolutionNow();
- EXPECT_GE(normal_ticks, previous_normal_ticks);
- EXPECT_GE((normal_ticks - previous_normal_ticks).InMicroseconds(), 0);
- EXPECT_GE(highres_ticks, previous_highres_ticks);
- EXPECT_GE((highres_ticks - previous_highres_ticks).InMicroseconds(), 0);
- previous_normal_ticks = normal_ticks;
- previous_highres_ticks = highres_ticks;
- }
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc
index d47ccaf..40dd188 100644
--- a/src/base/platform/time.cc
+++ b/src/base/platform/time.cc
@@ -401,7 +401,7 @@
}
virtual ~HighResolutionTickClock() {}
- virtual int64_t Now() OVERRIDE {
+ int64_t Now() OVERRIDE {
LARGE_INTEGER now;
BOOL result = QueryPerformanceCounter(&now);
DCHECK(result);
@@ -419,9 +419,7 @@
return ticks + 1;
}
- virtual bool IsHighResolution() OVERRIDE {
- return true;
- }
+ bool IsHighResolution() OVERRIDE { return true; }
private:
int64_t ticks_per_second_;
@@ -435,7 +433,7 @@
RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
virtual ~RolloverProtectedTickClock() {}
- virtual int64_t Now() OVERRIDE {
+ int64_t Now() OVERRIDE {
LockGuard<Mutex> lock_guard(&mutex_);
// We use timeGetTime() to implement TimeTicks::Now(), which rolls over
// every ~49.7 days. We try to track rollover ourselves, which works if
@@ -454,9 +452,7 @@
return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond;
}
- virtual bool IsHighResolution() OVERRIDE {
- return false;
- }
+ bool IsHighResolution() OVERRIDE { return false; }
private:
Mutex mutex_;
diff --git a/src/base/sys-info-unittest.cc b/src/base/sys-info-unittest.cc
deleted file mode 100644
index a760f94..0000000
--- a/src/base/sys-info-unittest.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2014 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/sys-info.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if V8_OS_NACL
-#define DISABLE_ON_NACL(Name) DISABLED_##Name
-#else
-#define DISABLE_ON_NACL(Name) Name
-#endif
-
-namespace v8 {
-namespace base {
-
-TEST(SysInfoTest, NumberOfProcessors) {
- EXPECT_LT(0, SysInfo::NumberOfProcessors());
-}
-
-
-TEST(SysInfoTest, DISABLE_ON_NACL(AmountOfPhysicalMemory)) {
- EXPECT_LT(0, SysInfo::AmountOfPhysicalMemory());
-}
-
-
-TEST(SysInfoTest, AmountOfVirtualMemory) {
- EXPECT_LE(0, SysInfo::AmountOfVirtualMemory());
-}
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/sys-info.cc b/src/base/sys-info.cc
index 06c4f24..c665771 100644
--- a/src/base/sys-info.cc
+++ b/src/base/sys-info.cc
@@ -34,14 +34,12 @@
int ncpu = 0;
size_t len = sizeof(ncpu);
if (sysctl(mib, arraysize(mib), &ncpu, &len, NULL, 0) != 0) {
- UNREACHABLE();
return 1;
}
return ncpu;
#elif V8_OS_POSIX
long result = sysconf(_SC_NPROCESSORS_ONLN); // NOLINT(runtime/int)
if (result == -1) {
- UNREACHABLE();
return 1;
}
return static_cast<int>(result);
@@ -60,7 +58,6 @@
int64_t memsize = 0;
size_t len = sizeof(memsize);
if (sysctl(mib, arraysize(mib), &memsize, &len, NULL, 0) != 0) {
- UNREACHABLE();
return 0;
}
return memsize;
@@ -70,7 +67,6 @@
sysctlbyname("vm.stats.vm.v_page_count", &pages, &size, NULL, 0);
sysctlbyname("vm.stats.vm.v_page_size", &page_size, &size, NULL, 0);
if (pages == -1 || page_size == -1) {
- UNREACHABLE();
return 0;
}
return static_cast<int64_t>(pages) * page_size;
@@ -78,7 +74,6 @@
MEMORYSTATUSEX memory_info;
memory_info.dwLength = sizeof(memory_info);
if (!GlobalMemoryStatusEx(&memory_info)) {
- UNREACHABLE();
return 0;
}
int64_t result = static_cast<int64_t>(memory_info.ullTotalPhys);
@@ -87,7 +82,6 @@
#elif V8_OS_QNX
struct stat stat_buf;
if (stat("/proc", &stat_buf) != 0) {
- UNREACHABLE();
return 0;
}
return static_cast<int64_t>(stat_buf.st_size);
@@ -98,7 +92,6 @@
long pages = sysconf(_SC_PHYS_PAGES); // NOLINT(runtime/int)
long page_size = sysconf(_SC_PAGESIZE); // NOLINT(runtime/int)
if (pages == -1 || page_size == -1) {
- UNREACHABLE();
return 0;
}
return static_cast<int64_t>(pages) * page_size;
@@ -114,7 +107,6 @@
struct rlimit rlim;
int result = getrlimit(RLIMIT_DATA, &rlim);
if (result != 0) {
- UNREACHABLE();
return 0;
}
return (rlim.rlim_cur == RLIM_INFINITY) ? 0 : rlim.rlim_cur;
diff --git a/src/base/sys-info.h b/src/base/sys-info.h
index d1658fc..377deb0 100644
--- a/src/base/sys-info.h
+++ b/src/base/sys-info.h
@@ -5,7 +5,7 @@
#ifndef V8_BASE_SYS_INFO_H_
#define V8_BASE_SYS_INFO_H_
-#include "include/v8stdint.h"
+#include <stdint.h>
#include "src/base/compiler-specific.h"
namespace v8 {
diff --git a/src/base/utils/random-number-generator-unittest.cc b/src/base/utils/random-number-generator-unittest.cc
deleted file mode 100644
index 7c533db..0000000
--- a/src/base/utils/random-number-generator-unittest.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2014 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 <climits>
-
-#include "src/base/utils/random-number-generator.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace v8 {
-namespace base {
-
-class RandomNumberGeneratorTest : public ::testing::TestWithParam<int> {};
-
-
-static const int kMaxRuns = 12345;
-
-
-TEST_P(RandomNumberGeneratorTest, NextIntWithMaxValue) {
- RandomNumberGenerator rng(GetParam());
- for (int max = 1; max <= kMaxRuns; ++max) {
- int n = rng.NextInt(max);
- EXPECT_LE(0, n);
- EXPECT_LT(n, max);
- }
-}
-
-
-TEST_P(RandomNumberGeneratorTest, NextBooleanReturnsFalseOrTrue) {
- RandomNumberGenerator rng(GetParam());
- for (int k = 0; k < kMaxRuns; ++k) {
- bool b = rng.NextBool();
- EXPECT_TRUE(b == false || b == true);
- }
-}
-
-
-TEST_P(RandomNumberGeneratorTest, NextDoubleReturnsValueBetween0And1) {
- RandomNumberGenerator rng(GetParam());
- for (int k = 0; k < kMaxRuns; ++k) {
- double d = rng.NextDouble();
- EXPECT_LE(0.0, d);
- EXPECT_LT(d, 1.0);
- }
-}
-
-
-INSTANTIATE_TEST_CASE_P(RandomSeeds, RandomNumberGeneratorTest,
- ::testing::Values(INT_MIN, -1, 0, 1, 42, 100,
- 1234567890, 987654321, INT_MAX));
-
-} // namespace base
-} // namespace v8
diff --git a/src/base/utils/random-number-generator.cc b/src/base/utils/random-number-generator.cc
index 9454936..29a48ff 100644
--- a/src/base/utils/random-number-generator.cc
+++ b/src/base/utils/random-number-generator.cc
@@ -79,7 +79,7 @@
int RandomNumberGenerator::NextInt(int max) {
- DCHECK_LE(0, max);
+ DCHECK_LT(0, max);
// Fast path if max is a power of 2.
if (IS_POWER_OF_TWO(max)) {
@@ -102,6 +102,13 @@
}
+int64_t RandomNumberGenerator::NextInt64() {
+ uint64_t lo = bit_cast<unsigned>(Next(32));
+ uint64_t hi = bit_cast<unsigned>(Next(32));
+ return lo | (hi << 32);
+}
+
+
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));
diff --git a/src/base/utils/random-number-generator.h b/src/base/utils/random-number-generator.h
index 479423d..d1294f2 100644
--- a/src/base/utils/random-number-generator.h
+++ b/src/base/utils/random-number-generator.h
@@ -68,6 +68,13 @@
// (exclusive), is pseudorandomly generated and returned.
double NextDouble() WARN_UNUSED_RESULT;
+ // Returns the next pseudorandom, uniformly distributed int64 value from this
+ // random number generator's sequence. The general contract of |NextInt64()|
+ // is that one 64-bit int value is pseudorandomly generated and returned.
+ // All 2^64 possible integer values are produced with (approximately) equal
+ // probability.
+ int64_t NextInt64() WARN_UNUSED_RESULT;
+
// Fills the elements of a specified array of bytes with random numbers.
void NextBytes(void* buffer, size_t buflen);
diff --git a/src/base/win32-math.cc b/src/base/win32-math.cc
deleted file mode 100644
index d6fc78b..0000000
--- a/src/base/win32-math.cc
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2011 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.
-
-// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please
-// refer to The Open Group Base Specification for specification of the correct
-// semantics for these functions.
-// (http://www.opengroup.org/onlinepubs/000095399/)
-#if defined(_MSC_VER) && (_MSC_VER < 1800)
-
-#include "src/base/win32-headers.h"
-#include <float.h> // Required for DBL_MAX and on Win32 for finite()
-#include <limits.h> // Required for INT_MAX etc.
-#include <cmath>
-#include "src/base/win32-math.h"
-
-#include "src/base/logging.h"
-
-
-namespace std {
-
-// Test for a NaN (not a number) value - usually defined in math.h
-int isnan(double x) {
- return _isnan(x);
-}
-
-
-// Test for infinity - usually defined in math.h
-int isinf(double x) {
- return (_fpclass(x) & (_FPCLASS_PINF | _FPCLASS_NINF)) != 0;
-}
-
-
-// Test for finite value - usually defined in math.h
-int isfinite(double x) {
- return _finite(x);
-}
-
-
-// Test if x is less than y and both nominal - usually defined in math.h
-int isless(double x, double y) {
- return isnan(x) || isnan(y) ? 0 : x < y;
-}
-
-
-// Test if x is greater than y and both nominal - usually defined in math.h
-int isgreater(double x, double y) {
- return isnan(x) || isnan(y) ? 0 : x > y;
-}
-
-
-// Classify floating point number - usually defined in math.h
-int fpclassify(double x) {
- // Use the MS-specific _fpclass() for classification.
- int flags = _fpclass(x);
-
- // Determine class. We cannot use a switch statement because
- // the _FPCLASS_ constants are defined as flags.
- if (flags & (_FPCLASS_PN | _FPCLASS_NN)) return FP_NORMAL;
- if (flags & (_FPCLASS_PZ | _FPCLASS_NZ)) return FP_ZERO;
- if (flags & (_FPCLASS_PD | _FPCLASS_ND)) return FP_SUBNORMAL;
- if (flags & (_FPCLASS_PINF | _FPCLASS_NINF)) return FP_INFINITE;
-
- // All cases should be covered by the code above.
- DCHECK(flags & (_FPCLASS_SNAN | _FPCLASS_QNAN));
- return FP_NAN;
-}
-
-
-// Test sign - usually defined in math.h
-int signbit(double x) {
- // We need to take care of the special case of both positive
- // and negative versions of zero.
- if (x == 0)
- return _fpclass(x) & _FPCLASS_NZ;
- else
- return x < 0;
-}
-
-} // namespace std
-
-#endif // _MSC_VER
diff --git a/src/base/win32-math.h b/src/base/win32-math.h
deleted file mode 100644
index e1c0350..0000000
--- a/src/base/win32-math.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright 2011 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.
-
-// Extra POSIX/ANSI routines for Win32 when using Visual Studio C++. Please
-// refer to The Open Group Base Specification for specification of the correct
-// semantics for these functions.
-// (http://www.opengroup.org/onlinepubs/000095399/)
-
-#ifndef V8_BASE_WIN32_MATH_H_
-#define V8_BASE_WIN32_MATH_H_
-
-#ifndef _MSC_VER
-#error Wrong environment, expected MSVC.
-#endif // _MSC_VER
-
-// MSVC 2013+ provides implementations of all standard math functions.
-#if (_MSC_VER < 1800)
-enum {
- FP_NAN,
- FP_INFINITE,
- FP_ZERO,
- FP_SUBNORMAL,
- FP_NORMAL
-};
-
-
-namespace std {
-
-int isfinite(double x);
-int isinf(double x);
-int isnan(double x);
-int isless(double x, double y);
-int isgreater(double x, double y);
-int fpclassify(double x);
-int signbit(double x);
-
-} // namespace std
-
-#endif // _MSC_VER < 1800
-
-#endif // V8_BASE_WIN32_MATH_H_