Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git "a/src/base/\043functional.h\043" "b/src/base/\043functional.h\043"
deleted file mode 100644
index ff0d807..0000000
--- "a/src/base/\043functional.h\043"
+++ /dev/null
@@ -1,227 +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.
-
-#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/OWNERS b/src/base/OWNERS
new file mode 100644
index 0000000..d691287
--- /dev/null
+++ b/src/base/OWNERS
@@ -0,0 +1 @@
+jochen@chromium.org
diff --git a/src/base/adapters.h b/src/base/adapters.h
new file mode 100644
index 0000000..f04391e
--- /dev/null
+++ b/src/base/adapters.h
@@ -0,0 +1,51 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Slightly adapted for inclusion in V8.
+// Copyright 2014 the V8 project authors. All rights reserved.
+
+#ifndef V8_BASE_ADAPTERS_H_
+#define V8_BASE_ADAPTERS_H_
+
+#include "src/base/macros.h"
+
+namespace v8 {
+namespace base {
+
+// Internal adapter class for implementing base::Reversed.
+template <typename T>
+class ReversedAdapter {
+ public:
+ typedef decltype(static_cast<T*>(nullptr)->rbegin()) Iterator;
+
+ explicit ReversedAdapter(T& t) : t_(t) {}
+ ReversedAdapter(const ReversedAdapter& ra) : t_(ra.t_) {}
+
+ Iterator begin() const { return t_.rbegin(); }
+ Iterator end() const { return t_.rend(); }
+
+ private:
+ T& t_;
+
+ DISALLOW_ASSIGN(ReversedAdapter);
+};
+
+// Reversed returns a container adapter usable in a range-based "for" statement
+// for iterating a reversible container in reverse order.
+//
+// Example:
+//
+// std::vector<int> v = ...;
+// for (int i : base::Reversed(v)) {
+// // iterates through v from back to front
+// }
+template <typename T>
+ReversedAdapter<T> Reversed(T& t) {
+ return ReversedAdapter<T>(t);
+}
+
+} // namespace base
+} // namespace v8
+
+#endif // V8_BASE_ADAPTERS_H_
diff --git a/src/base/atomicops.h b/src/base/atomicops.h
index 675e43f..3e628fe 100644
--- a/src/base/atomicops.h
+++ b/src/base/atomicops.h
@@ -133,7 +133,8 @@
Atomic64 Release_Load(volatile const Atomic64* ptr);
#endif // V8_HOST_ARCH_64_BIT
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
// Include our platform specific implementation.
#if defined(THREAD_SANITIZER)
@@ -148,6 +149,8 @@
#include "src/base/atomicops_internals_arm64_gcc.h"
#elif defined(__GNUC__) && V8_HOST_ARCH_ARM
#include "src/base/atomicops_internals_arm_gcc.h"
+#elif defined(__GNUC__) && V8_HOST_ARCH_PPC
+#include "src/base/atomicops_internals_ppc_gcc.h"
#elif defined(__GNUC__) && (V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64)
#include "src/base/atomicops_internals_x86_gcc.h"
#elif defined(__GNUC__) && V8_HOST_ARCH_MIPS
@@ -160,7 +163,7 @@
// On some platforms we need additional declarations to make
// AtomicWord compatible with our other Atomic* types.
-#if defined(__APPLE__) || defined(__OpenBSD__)
+#if defined(__APPLE__) || defined(__OpenBSD__) || defined(V8_OS_AIX)
#include "src/base/atomicops_internals_atomicword_compat.h"
#endif
diff --git a/src/base/atomicops_internals_arm64_gcc.h b/src/base/atomicops_internals_arm64_gcc.h
index b01783e..f24050a 100644
--- a/src/base/atomicops_internals_arm64_gcc.h
+++ b/src/base/atomicops_internals_arm64_gcc.h
@@ -311,6 +311,7 @@
return *ptr;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/src/base/atomicops_internals_arm_gcc.h b/src/base/atomicops_internals_arm_gcc.h
index 069b1ff..6c8b27e 100644
--- a/src/base/atomicops_internals_arm_gcc.h
+++ b/src/base/atomicops_internals_arm_gcc.h
@@ -59,11 +59,12 @@
// variant of the target architecture is being used. This tests against
// any known ARMv6 or ARMv7 variant, where it is possible to directly
// use ldrex/strex instructions to implement fast atomic operations.
-#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
+#if defined(__ARM_ARCH_8A__) || \
+ defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || \
defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || \
- defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
+ defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || \
defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) || \
- defined(__ARM_ARCH_6KZ__) || defined(__ARM_ARCH_6T2__)
+ defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_6T2__)
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
@@ -296,6 +297,7 @@
inline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) { return *ptr; }
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_ARM_GCC_H_
diff --git a/src/base/atomicops_internals_atomicword_compat.h b/src/base/atomicops_internals_atomicword_compat.h
index 0530ced..4f758a7 100644
--- a/src/base/atomicops_internals_atomicword_compat.h
+++ b/src/base/atomicops_internals_atomicword_compat.h
@@ -92,7 +92,8 @@
reinterpret_cast<volatile const Atomic32*>(ptr));
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // !defined(V8_HOST_ARCH_64_BIT)
diff --git a/src/base/atomicops_internals_mac.h b/src/base/atomicops_internals_mac.h
index 84f9dbc..c112506 100644
--- a/src/base/atomicops_internals_mac.h
+++ b/src/base/atomicops_internals_mac.h
@@ -210,6 +210,7 @@
#endif // defined(__LP64__)
#undef ATOMICOPS_COMPILER_BARRIER
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_MAC_H_
diff --git a/src/base/atomicops_internals_mips64_gcc.h b/src/base/atomicops_internals_mips64_gcc.h
index ccb973c..85b4e46 100644
--- a/src/base/atomicops_internals_mips64_gcc.h
+++ b/src/base/atomicops_internals_mips64_gcc.h
@@ -302,6 +302,7 @@
return *ptr;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/src/base/atomicops_internals_mips_gcc.h b/src/base/atomicops_internals_mips_gcc.h
index 442fdd0..8d65db2 100644
--- a/src/base/atomicops_internals_mips_gcc.h
+++ b/src/base/atomicops_internals_mips_gcc.h
@@ -155,6 +155,7 @@
return *ptr;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_MIPS_GCC_H_
diff --git a/src/base/atomicops_internals_portable.h b/src/base/atomicops_internals_portable.h
index a3a6e74..bb99973 100644
--- a/src/base/atomicops_internals_portable.h
+++ b/src/base/atomicops_internals_portable.h
@@ -132,7 +132,7 @@
inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
return __sync_add_and_fetch(ptr, 0);
}
-}
-} // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_
diff --git a/src/base/atomicops_internals_ppc_gcc.h b/src/base/atomicops_internals_ppc_gcc.h
new file mode 100644
index 0000000..0d16500
--- /dev/null
+++ b/src/base/atomicops_internals_ppc_gcc.h
@@ -0,0 +1,168 @@
+// 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_PPC_H_
+#define V8_BASE_ATOMICOPS_INTERNALS_PPC_H_
+
+namespace v8 {
+namespace base {
+
+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) {
+ Atomic32 old_value;
+ do {
+ old_value = *ptr;
+ } while (__sync_bool_compare_and_swap(ptr, old_value, new_value) == false);
+ return old_value;
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ for (;;) {
+ Atomic32 old_value = *ptr;
+ Atomic32 new_value = old_value + increment;
+ if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
+ return new_value;
+ // The exchange took place as expected.
+ }
+ // Otherwise, *ptr changed mid-loop and we need to retry.
+ }
+}
+
+inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value, Atomic32 new_value) {
+ return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic8* ptr, Atomic8 value) {
+ *ptr = value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+}
+
+inline void MemoryBarrier() {
+ __asm__ __volatile__("sync" : : : "memory"); }
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
+ MemoryBarrier();
+ *ptr = value;
+}
+
+inline Atomic8 NoBarrier_Load(volatile const Atomic8* ptr) { return *ptr; }
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) { return *ptr; }
+
+inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
+ Atomic32 value = *ptr;
+ MemoryBarrier();
+ return value;
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#ifdef V8_TARGET_ARCH_PPC64
+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) {
+ Atomic64 old_value;
+ do {
+ old_value = *ptr;
+ } while (__sync_bool_compare_and_swap(ptr, old_value, new_value) == false);
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return Barrier_AtomicIncrement(ptr, increment);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ for (;;) {
+ Atomic64 old_value = *ptr;
+ Atomic64 new_value = old_value + increment;
+ if (__sync_bool_compare_and_swap(ptr, old_value, new_value)) {
+ return new_value;
+ // The exchange took place as expected.
+ }
+ // Otherwise, *ptr changed mid-loop and we need to retry.
+ }
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value, Atomic64 new_value) {
+ return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value, Atomic64 new_value) {
+ return NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ *ptr = value;
+ MemoryBarrier();
+}
+
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ MemoryBarrier();
+ *ptr = value;
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) { return *ptr; }
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ Atomic64 value = *ptr;
+ MemoryBarrier();
+ return value;
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return *ptr;
+}
+
+#endif
+} // namespace base
+} // namespace v8
+
+#endif // V8_BASE_ATOMICOPS_INTERNALS_PPC_GCC_H_
diff --git a/src/base/atomicops_internals_x86_gcc.cc b/src/base/atomicops_internals_x86_gcc.cc
index 969f237..c031030 100644
--- a/src/base/atomicops_internals_x86_gcc.cc
+++ b/src/base/atomicops_internals_x86_gcc.cc
@@ -5,7 +5,7 @@
// This module gets enough CPU information to optimize the
// atomicops module on x86.
-#include <string.h>
+#include <string.h> // NOLINT(build/include)
#include "src/base/atomicops.h"
@@ -47,7 +47,8 @@
#endif
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
namespace {
diff --git a/src/base/atomicops_internals_x86_gcc.h b/src/base/atomicops_internals_x86_gcc.h
index ec87c42..55bc44c 100644
--- a/src/base/atomicops_internals_x86_gcc.h
+++ b/src/base/atomicops_internals_x86_gcc.h
@@ -267,7 +267,8 @@
#endif // defined(__x86_64__)
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#undef ATOMICOPS_COMPILER_BARRIER
diff --git a/src/base/atomicops_internals_x86_msvc.h b/src/base/atomicops_internals_x86_msvc.h
index adc4031..c37bc78 100644
--- a/src/base/atomicops_internals_x86_msvc.h
+++ b/src/base/atomicops_internals_x86_msvc.h
@@ -197,6 +197,7 @@
#endif // defined(_WIN64)
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ATOMICOPS_INTERNALS_X86_MSVC_H_
diff --git a/src/base/bits.h b/src/base/bits.h
index 0f4d4c7..4ba3c47 100644
--- a/src/base/bits.h
+++ b/src/base/bits.h
@@ -44,6 +44,17 @@
}
+// Overloaded versions of CountPopulation32/64.
+inline unsigned CountPopulation(uint32_t value) {
+ return CountPopulation32(value);
+}
+
+
+inline unsigned CountPopulation(uint64_t value) {
+ return CountPopulation64(value);
+}
+
+
// 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 unsigned CountLeadingZeros32(uint32_t value) {
@@ -94,8 +105,8 @@
#else
if (value == 0) return 32;
unsigned count = 0;
- for (value ^= value - 1; value >>= 1; ++count)
- ;
+ for (value ^= value - 1; value >>= 1; ++count) {
+ }
return count;
#endif
}
@@ -110,8 +121,8 @@
#else
if (value == 0) return 64;
unsigned count = 0;
- for (value ^= value - 1; value >>= 1; ++count)
- ;
+ for (value ^= value - 1; value >>= 1; ++count) {
+ }
return count;
#endif
}
@@ -148,17 +159,30 @@
}
+// Precondition: 0 <= shift < 32
inline uint32_t RotateRight32(uint32_t value, uint32_t shift) {
if (shift == 0) return value;
return (value >> shift) | (value << (32 - shift));
}
+// Precondition: 0 <= shift < 32
+inline uint32_t RotateLeft32(uint32_t value, uint32_t shift) {
+ if (shift == 0) return value;
+ return (value << shift) | (value >> (32 - shift));
+}
+// Precondition: 0 <= shift < 64
inline uint64_t RotateRight64(uint64_t value, uint64_t shift) {
if (shift == 0) return value;
return (value >> shift) | (value << (64 - shift));
}
+// Precondition: 0 <= shift < 64
+inline uint64_t RotateLeft64(uint64_t value, uint64_t shift) {
+ if (shift == 0) return value;
+ return (value << shift) | (value >> (64 - shift));
+}
+
// SignedAddOverflow32(lhs,rhs,val) performs a signed summation of |lhs| and
// |rhs| and stores the result into the variable pointed to by |val| and
@@ -188,6 +212,26 @@
}
+// SignedAddOverflow64(lhs,rhs,val) performs a signed summation of |lhs| and
+// |rhs| and stores the result into the variable pointed to by |val| and
+// returns true if the signed summation resulted in an overflow.
+inline bool SignedAddOverflow64(int64_t lhs, int64_t rhs, int64_t* val) {
+ uint64_t res = static_cast<uint64_t>(lhs) + static_cast<uint64_t>(rhs);
+ *val = bit_cast<int64_t>(res);
+ return ((res ^ lhs) & (res ^ rhs) & (1ULL << 63)) != 0;
+}
+
+
+// SignedSubOverflow64(lhs,rhs,val) performs a signed subtraction of |lhs| and
+// |rhs| and stores the result into the variable pointed to by |val| and
+// returns true if the signed subtraction resulted in an overflow.
+inline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) {
+ uint64_t res = static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs);
+ *val = bit_cast<int64_t>(res);
+ return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0;
+}
+
+
// SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and
// |rhs|, extracts the most significant 32 bits of the result, and returns
// those.
@@ -212,6 +256,19 @@
int32_t SignedMod32(int32_t lhs, int32_t rhs);
+// UnsignedAddOverflow32(lhs,rhs,val) performs an unsigned summation of |lhs|
+// and |rhs| and stores the result into the variable pointed to by |val| and
+// returns true if the unsigned summation resulted in an overflow.
+inline bool UnsignedAddOverflow32(uint32_t lhs, uint32_t rhs, uint32_t* val) {
+#if V8_HAS_BUILTIN_SADD_OVERFLOW
+ return __builtin_uadd_overflow(lhs, rhs, val);
+#else
+ *val = lhs + rhs;
+ return *val < (lhs | rhs);
+#endif
+}
+
+
// 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) {
diff --git a/src/base/build_config.h b/src/base/build_config.h
index f528776..9637f65 100644
--- a/src/base/build_config.h
+++ b/src/base/build_config.h
@@ -48,6 +48,20 @@
#elif defined(__MIPSEB__) || defined(__MIPSEL__)
#define V8_HOST_ARCH_MIPS 1
#define V8_HOST_ARCH_32_BIT 1
+#elif defined(__PPC__) || defined(_ARCH_PPC)
+#define V8_HOST_ARCH_PPC 1
+#if defined(__PPC64__) || defined(_ARCH_PPC64)
+#define V8_HOST_ARCH_64_BIT 1
+#else
+#define V8_HOST_ARCH_32_BIT 1
+#endif
+#elif defined(__s390__) || defined(__s390x__)
+#define V8_HOST_ARCH_S390 1
+#if defined(__s390x__)
+#define V8_HOST_ARCH_64_BIT 1
+#else
+#define V8_HOST_ARCH_32_BIT 1
+#endif
#else
#error "Host architecture was not detected as supported by v8"
#endif
@@ -61,13 +75,17 @@
# endif
#endif
+#if defined(__ARM_ARCH_8A__)
+# define CAN_USE_ARMV8_INSTRUCTIONS 1
+#endif
+
// Target architecture detection. This may be set externally. If not, detect
// in the same way as the host architecture, that is, target the native
// environment as presented by the compiler.
-#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_X87 && \
+#if !V8_TARGET_ARCH_X64 && !V8_TARGET_ARCH_IA32 && !V8_TARGET_ARCH_X87 && \
!V8_TARGET_ARCH_ARM && !V8_TARGET_ARCH_ARM64 && !V8_TARGET_ARCH_MIPS && \
- !V8_TARGET_ARCH_MIPS64
+ !V8_TARGET_ARCH_MIPS64 && !V8_TARGET_ARCH_PPC && !V8_TARGET_ARCH_S390
#if defined(_M_X64) || defined(__x86_64__)
#define V8_TARGET_ARCH_X64 1
#elif defined(_M_IX86) || defined(__i386__)
@@ -104,6 +122,18 @@
#define V8_TARGET_ARCH_32_BIT 1
#elif V8_TARGET_ARCH_MIPS64
#define V8_TARGET_ARCH_64_BIT 1
+#elif V8_TARGET_ARCH_PPC
+#if V8_TARGET_ARCH_PPC64
+#define V8_TARGET_ARCH_64_BIT 1
+#else
+#define V8_TARGET_ARCH_32_BIT 1
+#endif
+#elif V8_TARGET_ARCH_S390
+#if V8_TARGET_ARCH_S390X
+#define V8_TARGET_ARCH_64_BIT 1
+#else
+#define V8_TARGET_ARCH_32_BIT 1
+#endif
#elif V8_TARGET_ARCH_X87
#define V8_TARGET_ARCH_32_BIT 1
#else
@@ -151,15 +181,41 @@
#define V8_TARGET_LITTLE_ENDIAN 1
#endif
#elif V8_TARGET_ARCH_MIPS64
+#if defined(__MIPSEB__) || defined(V8_TARGET_ARCH_MIPS64_BE)
+#define V8_TARGET_BIG_ENDIAN 1
+#else
#define V8_TARGET_LITTLE_ENDIAN 1
+#endif
#elif V8_TARGET_ARCH_X87
#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_PPC_LE
+#define V8_TARGET_LITTLE_ENDIAN 1
+#elif V8_TARGET_ARCH_PPC_BE
+#define V8_TARGET_BIG_ENDIAN 1
+#elif V8_TARGET_ARCH_S390
+#if V8_TARGET_ARCH_S390_LE_SIM
+#define V8_TARGET_LITTLE_ENDIAN 1
+#else
+#define V8_TARGET_BIG_ENDIAN 1
+#endif
#else
#error Unknown target architecture endianness
#endif
+#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) || \
+ defined(V8_TARGET_ARCH_X87)
+#define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK 1
+#else
+#define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK 0
+#endif
+
// Number of bits to represent the page size for paged spaces. The value of 20
// gives 1Mb bytes per page.
+#if V8_HOST_ARCH_PPC && V8_TARGET_ARCH_PPC && V8_OS_LINUX
+// Bump up for Power Linux due to larger (64K) page size.
+const int kPageSizeBits = 22;
+#else
const int kPageSizeBits = 20;
+#endif
#endif // V8_BASE_BUILD_CONFIG_H_
diff --git a/src/base/compiler-specific.h b/src/base/compiler-specific.h
index 9755fc1..ffd5a44 100644
--- a/src/base/compiler-specific.h
+++ b/src/base/compiler-specific.h
@@ -17,31 +17,6 @@
#endif
-// Annotate a virtual method indicating it must be overriding a virtual
-// method in the parent class.
-// Use like:
-// virtual void bar() OVERRIDE;
-#if V8_HAS_CXX11_OVERRIDE
-#define OVERRIDE override
-#else
-#define OVERRIDE /* NOT SUPPORTED */
-#endif
-
-
-// Annotate a virtual method indicating that subclasses must not override it,
-// or annotate a class to indicate that it cannot be subclassed.
-// Use like:
-// class B FINAL : public A {};
-// virtual void bar() FINAL;
-#if V8_HAS_CXX11_FINAL
-#define FINAL final
-#elif V8_HAS___FINAL
-#define FINAL __final
-#else
-#define FINAL /* NOT SUPPORTED */
-#endif
-
-
// Annotate a function indicating the caller must examine the return value.
// Use like:
// int foo() WARN_UNUSED_RESULT;
@@ -51,4 +26,27 @@
#define WARN_UNUSED_RESULT /* NOT SUPPORTED */
#endif
+
+// The C++ standard requires that static const members have an out-of-class
+// definition (in a single compilation unit), but MSVC chokes on this (when
+// language extensions, which are required, are enabled). (You're only likely to
+// notice the need for a definition if you take the address of the member or,
+// more commonly, pass it to a function that takes it as a reference argument --
+// probably an STL function.) This macro makes MSVC do the right thing. See
+// http://msdn.microsoft.com/en-us/library/34h23df8(v=vs.100).aspx for more
+// information. Use like:
+//
+// In .h file:
+// struct Foo {
+// static const int kBar = 5;
+// };
+//
+// In .cc file:
+// STATIC_CONST_MEMBER_DEFINITION const int Foo::kBar;
+#if V8_HAS_DECLSPEC_SELECTANY
+#define STATIC_CONST_MEMBER_DEFINITION __declspec(selectany)
+#else
+#define STATIC_CONST_MEMBER_DEFINITION
+#endif
+
#endif // V8_BASE_COMPILER_SPECIFIC_H_
diff --git a/src/base/cpu.cc b/src/base/cpu.cc
index daf3302..692494a 100644
--- a/src/base/cpu.cc
+++ b/src/base/cpu.cc
@@ -16,6 +16,15 @@
#if V8_OS_QNX
#include <sys/syspage.h> // cpuinfo
#endif
+#if V8_OS_LINUX && V8_HOST_ARCH_PPC
+#include <elf.h>
+#endif
+#if V8_OS_AIX
+#include <sys/systemcfg.h> // _system_configuration
+#ifndef POWER_8
+#define POWER_8 0x10000
+#endif
+#endif
#if V8_OS_POSIX
#include <unistd.h> // sysconf()
#endif
@@ -43,22 +52,23 @@
#if !V8_LIBC_MSVCRT
static V8_INLINE void __cpuid(int cpu_info[4], int info_type) {
+// Clear ecx to align with __cpuid() of MSVC:
+// https://msdn.microsoft.com/en-us/library/hskdteyh.aspx
#if defined(__i386__) && defined(__pic__)
// Make sure to preserve ebx, which contains the pointer
// to the GOT in case we're generating PIC.
- __asm__ volatile (
- "mov %%ebx, %%edi\n\t"
- "cpuid\n\t"
- "xchg %%edi, %%ebx\n\t"
- : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type)
- );
+ __asm__ volatile(
+ "mov %%ebx, %%edi\n\t"
+ "cpuid\n\t"
+ "xchg %%edi, %%ebx\n\t"
+ : "=a"(cpu_info[0]), "=D"(cpu_info[1]), "=c"(cpu_info[2]),
+ "=d"(cpu_info[3])
+ : "a"(info_type), "c"(0));
#else
- __asm__ volatile (
- "cpuid \n\t"
- : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]), "=d"(cpu_info[3])
- : "a"(info_type)
- );
+ __asm__ volatile("cpuid \n\t"
+ : "=a"(cpu_info[0]), "=b"(cpu_info[1]), "=c"(cpu_info[2]),
+ "=d"(cpu_info[3])
+ : "a"(info_type), "c"(0));
#endif // defined(__i386__) && defined(__pic__)
}
@@ -168,7 +178,7 @@
#endif
// Extract the information exposed by the kernel via /proc/cpuinfo.
-class CPUInfo FINAL {
+class CPUInfo final {
public:
CPUInfo() : datalen_(0) {
// Get the size of the cpuinfo file by reading it until the end. This is
@@ -312,8 +322,14 @@
has_ssse3_(false),
has_sse41_(false),
has_sse42_(false),
+ is_atom_(false),
+ has_osxsave_(false),
has_avx_(false),
has_fma3_(false),
+ has_bmi1_(false),
+ has_bmi2_(false),
+ has_lzcnt_(false),
+ has_popcnt_(false),
has_idiva_(false),
has_neon_(false),
has_thumb2_(false),
@@ -360,14 +376,35 @@
has_ssse3_ = (cpu_info[2] & 0x00000200) != 0;
has_sse41_ = (cpu_info[2] & 0x00080000) != 0;
has_sse42_ = (cpu_info[2] & 0x00100000) != 0;
+ has_popcnt_ = (cpu_info[2] & 0x00800000) != 0;
+ has_osxsave_ = (cpu_info[2] & 0x08000000) != 0;
has_avx_ = (cpu_info[2] & 0x10000000) != 0;
- if (has_avx_) has_fma3_ = (cpu_info[2] & 0x00001000) != 0;
+ has_fma3_ = (cpu_info[2] & 0x00001000) != 0;
+
+ if (family_ == 0x6) {
+ switch (model_) {
+ case 0x1c: // SLT
+ case 0x26:
+ case 0x36:
+ case 0x27:
+ case 0x35:
+ case 0x37: // SLM
+ case 0x4a:
+ case 0x4d:
+ case 0x4c: // AMT
+ case 0x6e:
+ is_atom_ = true;
+ }
+ }
}
-#if V8_HOST_ARCH_IA32
- // SAHF is always available in compat/legacy mode,
- has_sahf_ = true;
-#else
+ // There are separate feature flags for VEX-encoded GPR instructions.
+ if (num_ids >= 7) {
+ __cpuid(cpu_info, 7);
+ has_bmi1_ = (cpu_info[1] & 0x00000008) != 0;
+ has_bmi2_ = (cpu_info[1] & 0x00000100) != 0;
+ }
+
// Query extended IDs.
__cpuid(cpu_info, 0x80000000);
unsigned num_ext_ids = cpu_info[0];
@@ -375,10 +412,10 @@
// Interpret extended CPU feature information.
if (num_ext_ids > 0x80000000) {
__cpuid(cpu_info, 0x80000001);
+ has_lzcnt_ = (cpu_info[2] & 0x00000020) != 0;
// SAHF must be probed in long mode.
has_sahf_ = (cpu_info[2] & 0x00000001) != 0;
}
-#endif
#elif V8_HOST_ARCH_ARM
@@ -589,7 +626,70 @@
delete[] part;
}
+#elif V8_HOST_ARCH_PPC
+
+#ifndef USE_SIMULATOR
+#if V8_OS_LINUX
+ // Read processor info from /proc/self/auxv.
+ char* auxv_cpu_type = NULL;
+ FILE* fp = fopen("/proc/self/auxv", "r");
+ if (fp != NULL) {
+#if V8_TARGET_ARCH_PPC64
+ Elf64_auxv_t entry;
+#else
+ Elf32_auxv_t entry;
#endif
+ for (;;) {
+ size_t n = fread(&entry, sizeof(entry), 1, fp);
+ if (n == 0 || entry.a_type == AT_NULL) {
+ break;
+ }
+ if (entry.a_type == AT_PLATFORM) {
+ auxv_cpu_type = reinterpret_cast<char*>(entry.a_un.a_val);
+ break;
+ }
+ }
+ fclose(fp);
+ }
+
+ part_ = -1;
+ if (auxv_cpu_type) {
+ if (strcmp(auxv_cpu_type, "power8") == 0) {
+ part_ = PPC_POWER8;
+ } else if (strcmp(auxv_cpu_type, "power7") == 0) {
+ part_ = PPC_POWER7;
+ } else if (strcmp(auxv_cpu_type, "power6") == 0) {
+ part_ = PPC_POWER6;
+ } else if (strcmp(auxv_cpu_type, "power5") == 0) {
+ part_ = PPC_POWER5;
+ } else if (strcmp(auxv_cpu_type, "ppc970") == 0) {
+ part_ = PPC_G5;
+ } else if (strcmp(auxv_cpu_type, "ppc7450") == 0) {
+ part_ = PPC_G4;
+ } else if (strcmp(auxv_cpu_type, "pa6t") == 0) {
+ part_ = PPC_PA6T;
+ }
+ }
+
+#elif V8_OS_AIX
+ switch (_system_configuration.implementation) {
+ case POWER_8:
+ part_ = PPC_POWER8;
+ break;
+ case POWER_7:
+ part_ = PPC_POWER7;
+ break;
+ case POWER_6:
+ part_ = PPC_POWER6;
+ break;
+ case POWER_5:
+ part_ = PPC_POWER5;
+ break;
+ }
+#endif // V8_OS_AIX
+#endif // !USE_SIMULATOR
+#endif // V8_HOST_ARCH_PPC
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/cpu.h b/src/base/cpu.h
index 8c41f9d..ca108fa 100644
--- a/src/base/cpu.h
+++ b/src/base/cpu.h
@@ -28,7 +28,7 @@
// architectures. For each architecture the file cpu_<arch>.cc contains the
// implementation of these static functions.
-class CPU FINAL {
+class CPU final {
public:
CPU();
@@ -50,6 +50,8 @@
int variant() const { return variant_; }
static const int NVIDIA_DENVER = 0x0;
int part() const { return part_; }
+
+ // ARM-specific part codes
static const int ARM_CORTEX_A5 = 0xc05;
static const int ARM_CORTEX_A7 = 0xc07;
static const int ARM_CORTEX_A8 = 0xc08;
@@ -57,6 +59,20 @@
static const int ARM_CORTEX_A12 = 0xc0c;
static const int ARM_CORTEX_A15 = 0xc0f;
+ // Denver-specific part code
+ static const int NVIDIA_DENVER_V10 = 0x002;
+
+ // PPC-specific part codes
+ enum {
+ PPC_POWER5,
+ PPC_POWER6,
+ PPC_POWER7,
+ PPC_POWER8,
+ PPC_G4,
+ PPC_G5,
+ PPC_PA6T
+ };
+
// General features
bool has_fpu() const { return has_fpu_; }
@@ -70,8 +86,14 @@
bool has_ssse3() const { return has_ssse3_; }
bool has_sse41() const { return has_sse41_; }
bool has_sse42() const { return has_sse42_; }
+ bool has_osxsave() const { return has_osxsave_; }
bool has_avx() const { return has_avx_; }
bool has_fma3() const { return has_fma3_; }
+ bool has_bmi1() const { return has_bmi1_; }
+ bool has_bmi2() const { return has_bmi2_; }
+ bool has_lzcnt() const { return has_lzcnt_; }
+ bool has_popcnt() const { return has_popcnt_; }
+ bool is_atom() const { return is_atom_; }
// arm features
bool has_idiva() const { return has_idiva_; }
@@ -106,8 +128,14 @@
bool has_ssse3_;
bool has_sse41_;
bool has_sse42_;
+ bool is_atom_;
+ bool has_osxsave_;
bool has_avx_;
bool has_fma3_;
+ bool has_bmi1_;
+ bool has_bmi2_;
+ bool has_lzcnt_;
+ bool has_popcnt_;
bool has_idiva_;
bool has_neon_;
bool has_thumb2_;
@@ -117,6 +145,7 @@
bool is_fp64_mode_;
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_CPU_H_
diff --git a/src/base/flags.h b/src/base/flags.h
index 060dba8..6bdb693 100644
--- a/src/base/flags.h
+++ b/src/base/flags.h
@@ -5,6 +5,8 @@
#ifndef V8_BASE_FLAGS_H_
#define V8_BASE_FLAGS_H_
+#include <cstddef>
+
#include "src/base/compiler-specific.h"
namespace v8 {
@@ -20,7 +22,7 @@
// other enum value and passed on to a function that takes an int or unsigned
// int.
template <typename T, typename S = int>
-class Flags FINAL {
+class Flags final {
public:
typedef T flag_type;
typedef S mask_type;
@@ -30,6 +32,13 @@
: mask_(static_cast<S>(flag)) {}
explicit Flags(mask_type mask) : mask_(static_cast<S>(mask)) {}
+ bool operator==(flag_type flag) const {
+ return mask_ == static_cast<S>(flag);
+ }
+ bool operator!=(flag_type flag) const {
+ return mask_ != static_cast<S>(flag);
+ }
+
Flags& operator&=(const Flags& flags) {
mask_ &= flags.mask_;
return *this;
@@ -60,6 +69,8 @@
operator mask_type() const { return mask_; }
bool operator!() const { return !mask_; }
+ friend size_t hash_value(const Flags& flags) { return flags.mask_; }
+
private:
mask_type mask_;
};
@@ -97,13 +108,17 @@
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) \
+ } 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 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 val)ALLOW_UNUSED_TYPE; \
+ inline Type operator~(Type::flag_type val) { return ~Type(val); }
} // namespace base
} // namespace v8
diff --git a/src/base/lazy-instance.h b/src/base/lazy-instance.h
index a20689a..4c0a3f8 100644
--- a/src/base/lazy-instance.h
+++ b/src/base/lazy-instance.h
@@ -232,6 +232,7 @@
CreateTrait, InitOnceTrait, DestroyTrait> type;
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_LAZY_INSTANCE_H_
diff --git a/src/base/logging.cc b/src/base/logging.cc
index c3f609f..a2688c9 100644
--- a/src/base/logging.cc
+++ b/src/base/logging.cc
@@ -5,46 +5,74 @@
#include "src/base/logging.h"
#if V8_LIBC_GLIBC || V8_OS_BSD
-# include <cxxabi.h>
-# include <execinfo.h>
+#include <cxxabi.h>
+#include <dlfcn.h>
+#include <execinfo.h>
#elif V8_OS_QNX
-# include <backtrace.h>
+#include <backtrace.h>
#endif // V8_LIBC_GLIBC || V8_OS_BSD
-#include <stdio.h>
-#include <stdlib.h>
+
+#include <cstdio>
+#include <cstdlib>
#include "src/base/platform/platform.h"
namespace v8 {
namespace base {
+// Explicit instantiations for commonly used comparisons.
+#define DEFINE_MAKE_CHECK_OP_STRING(type) \
+ template std::string* MakeCheckOpString<type, type>( \
+ type const&, type const&, char const*);
+DEFINE_MAKE_CHECK_OP_STRING(int)
+DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned long long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(char const*)
+DEFINE_MAKE_CHECK_OP_STRING(void const*)
+#undef DEFINE_MAKE_CHECK_OP_STRING
+
+
+// Explicit instantiations for floating point checks.
+#define DEFINE_CHECK_OP_IMPL(NAME) \
+ template std::string* Check##NAME##Impl<float, float>( \
+ float const& lhs, float const& rhs, char const* msg); \
+ template std::string* Check##NAME##Impl<double, double>( \
+ double const& lhs, double const& rhs, char const* msg);
+DEFINE_CHECK_OP_IMPL(EQ)
+DEFINE_CHECK_OP_IMPL(NE)
+DEFINE_CHECK_OP_IMPL(LE)
+DEFINE_CHECK_OP_IMPL(LT)
+DEFINE_CHECK_OP_IMPL(GE)
+DEFINE_CHECK_OP_IMPL(GT)
+#undef DEFINE_CHECK_OP_IMPL
+
+
// Attempts to dump a backtrace (if supported).
void DumpBacktrace() {
#if V8_LIBC_GLIBC || V8_OS_BSD
void* trace[100];
int size = backtrace(trace, arraysize(trace));
- char** symbols = backtrace_symbols(trace, size);
OS::PrintError("\n==== C stack trace ===============================\n\n");
if (size == 0) {
OS::PrintError("(empty)\n");
- } else if (symbols == NULL) {
- OS::PrintError("(no symbols)\n");
} else {
for (int i = 1; i < size; ++i) {
OS::PrintError("%2d: ", i);
- char mangled[201];
- if (sscanf(symbols[i], "%*[^(]%*[(]%200[^)+]", mangled) == 1) { // NOLINT
- int status;
- size_t length;
- char* demangled = abi::__cxa_demangle(mangled, NULL, &length, &status);
- OS::PrintError("%s\n", demangled != NULL ? demangled : mangled);
+ Dl_info info;
+ char* demangled = NULL;
+ if (!dladdr(trace[i], &info) || !info.dli_sname) {
+ OS::PrintError("%p\n", trace[i]);
+ } else if ((demangled = abi::__cxa_demangle(info.dli_sname, 0, 0, 0))) {
+ OS::PrintError("%s\n", demangled);
free(demangled);
} else {
- OS::PrintError("??\n");
+ OS::PrintError("%s\n", info.dli_sname);
}
}
}
- free(symbols);
#elif V8_OS_QNX
char out[1024];
bt_accessor_t acc;
@@ -68,7 +96,8 @@
#endif // V8_LIBC_GLIBC || V8_OS_BSD
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
// Contains protection against recursive calls (faults while handling faults).
diff --git a/src/base/logging.h b/src/base/logging.h
index 83c1bb6..e4e3f49 100644
--- a/src/base/logging.h
+++ b/src/base/logging.h
@@ -5,12 +5,14 @@
#ifndef V8_BASE_LOGGING_H_
#define V8_BASE_LOGGING_H_
-#include <stdint.h>
-#include <string.h>
+#include <cstring>
+#include <sstream>
+#include <string>
#include "src/base/build_config.h"
-extern "C" void V8_Fatal(const char* file, int line, const char* format, ...);
+extern "C" V8_NORETURN void V8_Fatal(const char* file, int line,
+ const char* format, ...);
// The FATAL, UNREACHABLE and UNIMPLEMENTED macros are useful during
@@ -27,197 +29,149 @@
V8_Fatal("", 0, "%s", (msg))
#define UNIMPLEMENTED() \
V8_Fatal("", 0, "unimplemented code")
-#define UNREACHABLE() ((void) 0)
+#define UNREACHABLE() V8_Fatal("", 0, "unreachable code")
#endif
-// The CHECK macro checks that the given condition is true; if not, it
-// prints a message to stderr and aborts.
-#define CHECK(condition) do { \
- if (!(condition)) { \
- V8_Fatal(__FILE__, __LINE__, "CHECK(%s) failed", #condition); \
- } \
- } while (0)
-
-
-// Helper function used by the CHECK_EQ function when given int
-// arguments. Should not be called directly.
-inline void CheckEqualsHelper(const char* file, int line,
- const char* expected_source, int expected,
- const char* value_source, int value) {
- if (expected != value) {
- V8_Fatal(file, line,
- "CHECK_EQ(%s, %s) failed\n# Expected: %i\n# Found: %i",
- expected_source, value_source, expected, value);
- }
-}
-
-
-// Helper function used by the CHECK_EQ function when given int64_t
-// arguments. Should not be called directly.
-inline void CheckEqualsHelper(const char* file, int line,
- const char* expected_source,
- int64_t expected,
- const char* value_source,
- int64_t value) {
- if (expected != value) {
- // Print int64_t values in hex, as two int32s,
- // to avoid platform-dependencies.
- V8_Fatal(file, line,
- "CHECK_EQ(%s, %s) failed\n#"
- " Expected: 0x%08x%08x\n# Found: 0x%08x%08x",
- expected_source, value_source,
- static_cast<uint32_t>(expected >> 32),
- static_cast<uint32_t>(expected),
- static_cast<uint32_t>(value >> 32),
- static_cast<uint32_t>(value));
- }
-}
-
-
-// Helper function used by the CHECK_NE function when given int
-// arguments. Should not be called directly.
-inline void CheckNonEqualsHelper(const char* file,
- int line,
- const char* unexpected_source,
- int unexpected,
- const char* value_source,
- int value) {
- if (unexpected == value) {
- V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %i",
- unexpected_source, value_source, value);
- }
-}
-
-
-// Helper function used by the CHECK function when given string
-// arguments. Should not be called directly.
-inline void CheckEqualsHelper(const char* file,
- int line,
- const char* expected_source,
- const char* expected,
- const char* value_source,
- const char* value) {
- if ((expected == NULL && value != NULL) ||
- (expected != NULL && value == NULL) ||
- (expected != NULL && value != NULL && strcmp(expected, value) != 0)) {
- V8_Fatal(file, line,
- "CHECK_EQ(%s, %s) failed\n# Expected: %s\n# Found: %s",
- expected_source, value_source, expected, value);
- }
-}
-
-
-inline void CheckNonEqualsHelper(const char* file,
- int line,
- const char* expected_source,
- const char* expected,
- const char* value_source,
- const char* value) {
- if (expected == value ||
- (expected != NULL && value != NULL && strcmp(expected, value) == 0)) {
- V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %s",
- expected_source, value_source, value);
- }
-}
-
-
-// Helper function used by the CHECK function when given pointer
-// arguments. Should not be called directly.
-inline void CheckEqualsHelper(const char* file,
- int line,
- const char* expected_source,
- const void* expected,
- const char* value_source,
- const void* value) {
- if (expected != value) {
- V8_Fatal(file, line,
- "CHECK_EQ(%s, %s) failed\n# Expected: %p\n# Found: %p",
- expected_source, value_source,
- expected, value);
- }
-}
-
-
-inline void CheckNonEqualsHelper(const char* file,
- int line,
- const char* expected_source,
- const void* expected,
- const char* value_source,
- const void* value) {
- if (expected == value) {
- V8_Fatal(file, line, "CHECK_NE(%s, %s) failed\n# Value: %p",
- expected_source, value_source, value);
- }
-}
-
-
-inline void CheckNonEqualsHelper(const char* file,
- int line,
- const char* expected_source,
- int64_t expected,
- const char* value_source,
- int64_t value) {
- if (expected == value) {
- V8_Fatal(file, line,
- "CHECK_EQ(%s, %s) failed\n# Expected: %f\n# Found: %f",
- expected_source, value_source, expected, value);
- }
-}
-
-
-#define CHECK_EQ(expected, value) CheckEqualsHelper(__FILE__, __LINE__, \
- #expected, expected, #value, value)
-
-
-#define CHECK_NE(unexpected, value) CheckNonEqualsHelper(__FILE__, __LINE__, \
- #unexpected, unexpected, #value, value)
-
-
-#define CHECK_GT(a, b) CHECK((a) > (b))
-#define CHECK_GE(a, b) CHECK((a) >= (b))
-#define CHECK_LT(a, b) CHECK((a) < (b))
-#define CHECK_LE(a, b) CHECK((a) <= (b))
-
-
namespace v8 {
namespace base {
+// CHECK dies with a fatal error if condition is not true. It is *not*
+// controlled by DEBUG, so the check will be executed regardless of
+// compilation mode.
+//
+// We make sure CHECK et al. always evaluates their arguments, as
+// doing CHECK(FunctionWithSideEffect()) is a common idiom.
+#define CHECK(condition) \
+ do { \
+ if (V8_UNLIKELY(!(condition))) { \
+ V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", #condition); \
+ } \
+ } while (0)
+
+
+#ifdef DEBUG
+
+// Helper macro for binary operators.
+// Don't use this macro directly in your code, use CHECK_EQ et al below.
+#define CHECK_OP(name, op, lhs, rhs) \
+ do { \
+ if (std::string* _msg = ::v8::base::Check##name##Impl( \
+ (lhs), (rhs), #lhs " " #op " " #rhs)) { \
+ V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str()); \
+ delete _msg; \
+ } \
+ } while (0)
+
+#else
+
+// Make all CHECK functions discard their log strings to reduce code
+// bloat for official release builds.
+
+#define CHECK_OP(name, op, lhs, rhs) CHECK((lhs)op(rhs))
+
+#endif
+
+
+// Build the error message string. This is separate from the "Impl"
+// function template because it is not performance critical and so can
+// be out of line, while the "Impl" code should be inline. Caller
+// takes ownership of the returned string.
+template <typename Lhs, typename Rhs>
+std::string* MakeCheckOpString(Lhs const& lhs, Rhs const& rhs,
+ char const* msg) {
+ std::ostringstream ss;
+ ss << msg << " (" << lhs << " vs. " << rhs << ")";
+ return new std::string(ss.str());
+}
+
+// Commonly used instantiations of MakeCheckOpString<>. Explicitly instantiated
+// in logging.cc.
+#define DEFINE_MAKE_CHECK_OP_STRING(type) \
+ extern template std::string* MakeCheckOpString<type, type>( \
+ type const&, type const&, char const*);
+DEFINE_MAKE_CHECK_OP_STRING(int)
+DEFINE_MAKE_CHECK_OP_STRING(long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(long long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(unsigned long long) // NOLINT(runtime/int)
+DEFINE_MAKE_CHECK_OP_STRING(char const*)
+DEFINE_MAKE_CHECK_OP_STRING(void const*)
+#undef DEFINE_MAKE_CHECK_OP_STRING
+
+
+// Helper functions for CHECK_OP macro.
+// The (int, int) specialization works around the issue that the compiler
+// will not instantiate the template version of the function on values of
+// unnamed enum type - see comment below.
+// The (float, float) and (double, double) instantiations are explicitly
+// externialized to ensure proper 32/64-bit comparisons on x86.
+#define DEFINE_CHECK_OP_IMPL(NAME, op) \
+ template <typename Lhs, typename Rhs> \
+ V8_INLINE std::string* Check##NAME##Impl(Lhs const& lhs, Rhs const& rhs, \
+ char const* msg) { \
+ return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \
+ } \
+ V8_INLINE std::string* Check##NAME##Impl(int lhs, int rhs, \
+ char const* msg) { \
+ return V8_LIKELY(lhs op rhs) ? nullptr : MakeCheckOpString(lhs, rhs, msg); \
+ } \
+ extern template std::string* Check##NAME##Impl<float, float>( \
+ float const& lhs, float const& rhs, char const* msg); \
+ extern template std::string* Check##NAME##Impl<double, double>( \
+ double const& lhs, double const& rhs, char const* msg);
+DEFINE_CHECK_OP_IMPL(EQ, ==)
+DEFINE_CHECK_OP_IMPL(NE, !=)
+DEFINE_CHECK_OP_IMPL(LE, <=)
+DEFINE_CHECK_OP_IMPL(LT, < )
+DEFINE_CHECK_OP_IMPL(GE, >=)
+DEFINE_CHECK_OP_IMPL(GT, > )
+#undef DEFINE_CHECK_OP_IMPL
+
+#define CHECK_EQ(lhs, rhs) CHECK_OP(EQ, ==, lhs, rhs)
+#define CHECK_NE(lhs, rhs) CHECK_OP(NE, !=, lhs, rhs)
+#define CHECK_LE(lhs, rhs) CHECK_OP(LE, <=, lhs, rhs)
+#define CHECK_LT(lhs, rhs) CHECK_OP(LT, <, lhs, rhs)
+#define CHECK_GE(lhs, rhs) CHECK_OP(GE, >=, lhs, rhs)
+#define CHECK_GT(lhs, rhs) CHECK_OP(GT, >, lhs, rhs)
+#define CHECK_NULL(val) CHECK((val) == nullptr)
+#define CHECK_NOT_NULL(val) CHECK((val) != nullptr)
+#define CHECK_IMPLIES(lhs, rhs) CHECK(!(lhs) || (rhs))
+
+
// Exposed for making debugging easier (to see where your function is being
// called, just add a call to DumpBacktrace).
void DumpBacktrace();
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
// The DCHECK macro is equivalent to CHECK except that it only
// generates code in debug builds.
#ifdef DEBUG
-#define DCHECK_RESULT(expr) CHECK(expr)
#define DCHECK(condition) CHECK(condition)
#define DCHECK_EQ(v1, v2) CHECK_EQ(v1, v2)
#define DCHECK_NE(v1, v2) CHECK_NE(v1, v2)
+#define DCHECK_GT(v1, v2) CHECK_GT(v1, v2)
#define DCHECK_GE(v1, v2) CHECK_GE(v1, v2)
#define DCHECK_LT(v1, v2) CHECK_LT(v1, v2)
#define DCHECK_LE(v1, v2) CHECK_LE(v1, v2)
+#define DCHECK_NULL(val) CHECK_NULL(val)
+#define DCHECK_NOT_NULL(val) CHECK_NOT_NULL(val)
+#define DCHECK_IMPLIES(v1, v2) CHECK_IMPLIES(v1, v2)
#else
-#define DCHECK_RESULT(expr) (expr)
#define DCHECK(condition) ((void) 0)
#define DCHECK_EQ(v1, v2) ((void) 0)
#define DCHECK_NE(v1, v2) ((void) 0)
+#define DCHECK_GT(v1, v2) ((void) 0)
#define DCHECK_GE(v1, v2) ((void) 0)
#define DCHECK_LT(v1, v2) ((void) 0)
#define DCHECK_LE(v1, v2) ((void) 0)
-#endif
-
-#define DCHECK_NOT_NULL(p) DCHECK_NE(NULL, p)
-
-// "Extra checks" are lightweight checks that are enabled in some release
-// builds.
-#ifdef ENABLE_EXTRA_CHECKS
-#define EXTRA_CHECK(condition) CHECK(condition)
-#else
-#define EXTRA_CHECK(condition) ((void) 0)
+#define DCHECK_NULL(val) ((void) 0)
+#define DCHECK_NOT_NULL(val) ((void) 0)
+#define DCHECK_IMPLIES(v1, v2) ((void) 0)
#endif
#endif // V8_BASE_LOGGING_H_
diff --git a/src/base/macros.h b/src/base/macros.h
index 371d7da..10cab4b 100644
--- a/src/base/macros.h
+++ b/src/base/macros.h
@@ -15,12 +15,9 @@
#include "src/base/logging.h"
-// The expression OFFSET_OF(type, field) computes the byte-offset
-// of the specified field relative to the containing type. This
-// 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 aligned, non-zero value 16.
+// TODO(all) Replace all uses of this macro with C++'s offsetof. To do that, we
+// have to make sure that only standard-layout types and simple field
+// designators are used.
#define OFFSET_OF(type, field) \
(reinterpret_cast<intptr_t>(&(reinterpret_cast<type*>(16)->field)) - 16)
@@ -105,66 +102,6 @@
#endif // V8_OS_NACL
-// The COMPILE_ASSERT macro can be used to verify that a compile time
-// expression is true. For example, you could use it to verify the
-// size of a static array:
-//
-// COMPILE_ASSERT(ARRAYSIZE_UNSAFE(content_type_names) == CONTENT_NUM_TYPES,
-// content_type_names_incorrect_size);
-//
-// or to make sure a struct is smaller than a certain size:
-//
-// COMPILE_ASSERT(sizeof(foo) < 128, foo_too_large);
-//
-// The second argument to the macro is the name of the variable. If
-// the expression is false, most compilers will issue a warning/error
-// containing the name of the variable.
-#if V8_HAS_CXX11_STATIC_ASSERT
-
-// Under C++11, just use static_assert.
-#define COMPILE_ASSERT(expr, msg) static_assert(expr, #msg)
-
-#else
-
-template <bool>
-struct CompileAssert {};
-
-#define COMPILE_ASSERT(expr, msg) \
- typedef CompileAssert<static_cast<bool>(expr)> \
- msg[static_cast<bool>(expr) ? 1 : -1] ALLOW_UNUSED_TYPE
-
-// Implementation details of COMPILE_ASSERT:
-//
-// - COMPILE_ASSERT works by defining an array type that has -1
-// elements (and thus is invalid) when the expression is false.
-//
-// - The simpler definition
-//
-// #define COMPILE_ASSERT(expr, msg) typedef char msg[(expr) ? 1 : -1]
-//
-// does not work, as gcc supports variable-length arrays whose sizes
-// are determined at run-time (this is gcc's extension and not part
-// of the C++ standard). As a result, gcc fails to reject the
-// following code with the simple definition:
-//
-// int foo;
-// COMPILE_ASSERT(foo, msg); // not supposed to compile as foo is
-// // not a compile-time constant.
-//
-// - 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 array size is (static_cast<bool>(expr) ? 1 : -1), instead of simply
-//
-// ((expr) ? 1 : -1).
-//
-// This is to avoid running into a bug in MS VC 7.1, which
-// causes ((0.0) ? 1 : -1) to incorrectly evaluate to 1.
-
-#endif
-
-
// bit_cast<Dest,Source> is a template function that implements the
// equivalent of "*reinterpret_cast<Dest*>(&source)". We need this in
// very low-level functions like the protobuf library and fast math
@@ -220,19 +157,23 @@
// is likely to surprise you.
template <class Dest, class Source>
V8_INLINE Dest bit_cast(Source const& source) {
- COMPILE_ASSERT(sizeof(Dest) == sizeof(Source), VerifySizesAreEqual);
-
+ static_assert(sizeof(Dest) == sizeof(Source),
+ "source and dest must be same size");
Dest dest;
memcpy(&dest, &source, sizeof(dest));
return dest;
}
+// Put this in the private: declarations for a class to be unassignable.
+#define DISALLOW_ASSIGN(TypeName) void operator=(const TypeName&)
+
+
// A macro to disallow the evil copy constructor and operator= functions
// This should be used in the private: declarations for a class
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&) V8_DELETE; \
- void operator=(const TypeName&) V8_DELETE
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
// A macro to disallow all the implicit constructors, namely the
@@ -241,8 +182,8 @@
// This should be used in the private: declarations for a class
// that wants to prevent anyone from instantiating it. This is
// especially useful for classes containing only static methods.
-#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
- TypeName() V8_DELETE; \
+#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
+ TypeName() = delete; \
DISALLOW_COPY_AND_ASSIGN(TypeName)
@@ -277,32 +218,8 @@
#endif
-// Use C++11 static_assert if possible, which gives error
-// messages that are easier to understand on first sight.
-#if V8_HAS_CXX11_STATIC_ASSERT
+// TODO(all) Replace all uses of this macro with static_assert, remove macro.
#define STATIC_ASSERT(test) static_assert(test, #test)
-#else
-// This is inspired by the static assertion facility in boost. This
-// is pretty magical. If it causes you trouble on a platform you may
-// find a fix in the boost code.
-template <bool> class StaticAssertion;
-template <> class StaticAssertion<true> { };
-// This macro joins two tokens. If one of the tokens is a macro the
-// helper call causes it to be resolved before joining.
-#define SEMI_STATIC_JOIN(a, b) SEMI_STATIC_JOIN_HELPER(a, b)
-#define SEMI_STATIC_JOIN_HELPER(a, b) a##b
-// Causes an error during compilation of the condition is not
-// statically known to be true. It is formulated as a typedef so that
-// it can be used wherever a typedef can be used. Beware that this
-// 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_TYPE
-
-#endif
// The USE(x) template is used to silence C++ compiler warnings
@@ -333,7 +250,7 @@
# define V8_INTPTR_C(x) (x ## LL)
# define V8_PTR_PREFIX "I64"
#elif V8_HOST_ARCH_64_BIT
-# if V8_OS_MACOSX
+# if V8_OS_MACOSX || V8_OS_OPENBSD
# define V8_UINT64_C(x) (x ## ULL)
# define V8_INT64_C(x) (x ## LL)
# else
@@ -346,8 +263,12 @@
# define V8_UINT64_C(x) (x ## ULL)
# define V8_INT64_C(x) (x ## LL)
# define V8_INTPTR_C(x) (x)
+#if V8_OS_AIX
+#define V8_PTR_PREFIX "l"
+#else
# define V8_PTR_PREFIX ""
#endif
+#endif
#define V8PRIxPTR V8_PTR_PREFIX "x"
#define V8PRIdPTR V8_PTR_PREFIX "d"
@@ -412,7 +333,8 @@
inline bool is_fundamental<uint8_t>() {
return true;
}
-}
-} // namespace v8::base
+
+} // namespace base
+} // namespace v8
#endif // V8_BASE_MACROS_H_
diff --git a/src/base/once.cc b/src/base/once.cc
index eaabf40..818a9f2 100644
--- a/src/base/once.cc
+++ b/src/base/once.cc
@@ -50,4 +50,5 @@
}
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/once.h b/src/base/once.h
index 6bf741d..790a886 100644
--- a/src/base/once.h
+++ b/src/base/once.h
@@ -97,6 +97,7 @@
}
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_ONCE_H_
diff --git a/src/base/platform/condition-variable.cc b/src/base/platform/condition-variable.cc
index 4547b66..fcd6cf7 100644
--- a/src/base/platform/condition-variable.cc
+++ b/src/base/platform/condition-variable.cc
@@ -15,11 +15,8 @@
#if V8_OS_POSIX
ConditionVariable::ConditionVariable() {
- // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
- // hack to support cross-compiling Chrome for Android in AOSP. Remove
- // this once AOSP is fixed.
#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
- (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
+ (V8_OS_LINUX && V8_LIBC_GLIBC))
// On Free/Net/OpenBSD and Linux with glibc we can change the time
// source for pthread_cond_timedwait() to use the monotonic clock.
pthread_condattr_t attr;
@@ -81,11 +78,8 @@
result = pthread_cond_timedwait_relative_np(
&native_handle_, &mutex->native_handle(), &ts);
#else
- // TODO(bmeurer): The test for V8_LIBRT_NOT_AVAILABLE is a temporary
- // hack to support cross-compiling Chrome for Android in AOSP. Remove
- // this once AOSP is fixed.
#if (V8_OS_FREEBSD || V8_OS_NETBSD || V8_OS_OPENBSD || \
- (V8_OS_LINUX && V8_LIBC_GLIBC)) && !V8_LIBRT_NOT_AVAILABLE
+ (V8_OS_LINUX && V8_LIBC_GLIBC))
// On Free/Net/OpenBSD and Linux with glibc we can change the time
// source for pthread_cond_timedwait() to use the monotonic clock.
result = clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -182,7 +176,7 @@
// Remove the event from the wait list.
for (Event** wep = &waitlist_;; wep = &(*wep)->next_) {
- DCHECK_NE(NULL, *wep);
+ DCHECK(*wep);
if (*wep == event) {
*wep = event->next_;
break;
@@ -270,8 +264,8 @@
mutex->Unlock();
// Wait on the wait event.
- while (!event->WaitFor(INFINITE))
- ;
+ while (!event->WaitFor(INFINITE)) {
+ }
// Reaquire the user mutex.
mutex->Lock();
@@ -319,4 +313,5 @@
#endif // V8_OS_POSIX
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/condition-variable.h b/src/base/platform/condition-variable.h
index b5a6c3f..72d6f28 100644
--- a/src/base/platform/condition-variable.h
+++ b/src/base/platform/condition-variable.h
@@ -28,7 +28,7 @@
// the mutex and suspend the execution of the calling thread. When the condition
// variable is notified, the thread is awakened, and the mutex is reacquired.
-class ConditionVariable FINAL {
+class ConditionVariable final {
public:
ConditionVariable();
~ConditionVariable();
@@ -63,7 +63,7 @@
typedef pthread_cond_t NativeHandle;
#elif V8_OS_WIN
struct Event;
- class NativeHandle FINAL {
+ class NativeHandle final {
public:
NativeHandle() : waitlist_(NULL), freelist_(NULL) {}
~NativeHandle();
@@ -113,6 +113,7 @@
#define LAZY_CONDITION_VARIABLE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_CONDITION_VARIABLE_H_
diff --git a/src/base/platform/elapsed-timer.h b/src/base/platform/elapsed-timer.h
index dccba3a..f9a9ef4 100644
--- a/src/base/platform/elapsed-timer.h
+++ b/src/base/platform/elapsed-timer.h
@@ -11,7 +11,7 @@
namespace v8 {
namespace base {
-class ElapsedTimer FINAL {
+class ElapsedTimer final {
public:
#ifdef DEBUG
ElapsedTimer() : started_(false) {}
@@ -92,6 +92,7 @@
#endif
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_ELAPSED_TIMER_H_
diff --git a/src/base/platform/mutex.cc b/src/base/platform/mutex.cc
index 8b1e305..1401605 100644
--- a/src/base/platform/mutex.cc
+++ b/src/base/platform/mutex.cc
@@ -188,4 +188,5 @@
return true;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/mutex.h b/src/base/platform/mutex.h
index 5d0e57b..61df19d 100644
--- a/src/base/platform/mutex.h
+++ b/src/base/platform/mutex.h
@@ -33,7 +33,7 @@
// |TryLock()|. The behavior of a program is undefined if a mutex is destroyed
// while still owned by some thread. The Mutex class is non-copyable.
-class Mutex FINAL {
+class Mutex final {
public:
Mutex();
~Mutex();
@@ -127,7 +127,7 @@
// The behavior of a program is undefined if a recursive mutex is destroyed
// while still owned by some thread. The RecursiveMutex class is non-copyable.
-class RecursiveMutex FINAL {
+class RecursiveMutex final {
public:
RecursiveMutex();
~RecursiveMutex();
@@ -199,7 +199,7 @@
// The LockGuard class is non-copyable.
template <typename Mutex>
-class LockGuard FINAL {
+class LockGuard final {
public:
explicit LockGuard(Mutex* mutex) : mutex_(mutex) { mutex_->Lock(); }
~LockGuard() { mutex_->Unlock(); }
@@ -210,6 +210,7 @@
DISALLOW_COPY_AND_ASSIGN(LockGuard);
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_MUTEX_H_
diff --git a/src/base/platform/platform-aix.cc b/src/base/platform/platform-aix.cc
new file mode 100644
index 0000000..ea2824d
--- /dev/null
+++ b/src/base/platform/platform-aix.cc
@@ -0,0 +1,243 @@
+// 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.
+
+// Platform specific code for AIX goes here. For the POSIX comaptible parts
+// the implementation is in platform-posix.cc.
+
+#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/ucontext.h>
+
+#include <errno.h>
+#include <fcntl.h> // open
+#include <limits.h>
+#include <stdarg.h>
+#include <strings.h> // index
+#include <sys/mman.h> // mmap & munmap
+#include <sys/stat.h> // open
+#include <sys/types.h> // mmap & munmap
+#include <unistd.h> // getpagesize
+
+#include <cmath>
+
+#undef MAP_TYPE
+
+#include "src/base/macros.h"
+#include "src/base/platform/platform.h"
+
+
+namespace v8 {
+namespace base {
+
+
+static inline void* mmapHelper(size_t len, int prot, int flags, int fildes,
+ off_t off) {
+ void* addr = OS::GetRandomMmapAddr();
+ return mmap(addr, len, prot, flags, fildes, off);
+}
+
+
+const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
+ if (std::isnan(time)) return "";
+ time_t tv = static_cast<time_t>(floor(time / msPerSecond));
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
+ if (NULL == t) return "";
+ return tzname[0]; // The location of the timezone string on AIX.
+}
+
+
+double OS::LocalTimeOffset(TimezoneCache* cache) {
+ // On AIX, struct tm does not contain a tm_gmtoff field.
+ time_t utc = time(NULL);
+ DCHECK(utc != -1);
+ struct tm* loc = localtime(&utc); // NOLINT(runtime/threadsafe_fn)
+ DCHECK(loc != NULL);
+ return static_cast<double>((mktime(loc) - utc) * msPerSecond);
+}
+
+
+void* OS::Allocate(const size_t requested, size_t* allocated, bool executable) {
+ const size_t msize = RoundUp(requested, getpagesize());
+ int prot = PROT_READ | PROT_WRITE | (executable ? PROT_EXEC : 0);
+ void* mbase = mmapHelper(msize, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+
+ if (mbase == MAP_FAILED) return NULL;
+ *allocated = msize;
+ return mbase;
+}
+
+
+static unsigned StringToLong(char* buffer) {
+ return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT
+}
+
+
+std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
+ std::vector<SharedLibraryAddress> result;
+ static const int MAP_LENGTH = 1024;
+ int fd = open("/proc/self/maps", O_RDONLY);
+ if (fd < 0) return result;
+ while (true) {
+ char addr_buffer[11];
+ addr_buffer[0] = '0';
+ addr_buffer[1] = 'x';
+ addr_buffer[10] = 0;
+ ssize_t rc = read(fd, addr_buffer + 2, 8);
+ if (rc < 8) break;
+ unsigned start = StringToLong(addr_buffer);
+ rc = read(fd, addr_buffer + 2, 1);
+ if (rc < 1) break;
+ if (addr_buffer[2] != '-') break;
+ rc = read(fd, addr_buffer + 2, 8);
+ if (rc < 8) break;
+ unsigned end = StringToLong(addr_buffer);
+ char buffer[MAP_LENGTH];
+ int bytes_read = -1;
+ do {
+ bytes_read++;
+ if (bytes_read >= MAP_LENGTH - 1) break;
+ rc = read(fd, buffer + bytes_read, 1);
+ if (rc < 1) break;
+ } while (buffer[bytes_read] != '\n');
+ buffer[bytes_read] = 0;
+ // Ignore mappings that are not executable.
+ if (buffer[3] != 'x') continue;
+ char* start_of_path = index(buffer, '/');
+ // There may be no filename in this line. Skip to next.
+ if (start_of_path == NULL) continue;
+ buffer[bytes_read] = 0;
+ result.push_back(SharedLibraryAddress(start_of_path, start, end));
+ }
+ close(fd);
+ return result;
+}
+
+
+void OS::SignalCodeMovingGC() {}
+
+
+// Constants used for mmap.
+static const int kMmapFd = -1;
+static const int kMmapFdOffset = 0;
+
+VirtualMemory::VirtualMemory() : address_(NULL), size_(0) {}
+
+
+VirtualMemory::VirtualMemory(size_t size)
+ : address_(ReserveRegion(size)), size_(size) {}
+
+
+VirtualMemory::VirtualMemory(size_t size, size_t alignment)
+ : address_(NULL), size_(0) {
+ DCHECK((alignment % OS::AllocateAlignment()) == 0);
+ size_t request_size =
+ RoundUp(size + alignment, static_cast<intptr_t>(OS::AllocateAlignment()));
+ void* reservation =
+ mmapHelper(request_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, kMmapFd,
+ kMmapFdOffset);
+ if (reservation == MAP_FAILED) return;
+
+ uint8_t* base = static_cast<uint8_t*>(reservation);
+ uint8_t* aligned_base = RoundUp(base, alignment);
+ DCHECK_LE(base, aligned_base);
+
+ // Unmap extra memory reserved before and after the desired block.
+ if (aligned_base != base) {
+ size_t prefix_size = static_cast<size_t>(aligned_base - base);
+ OS::Free(base, prefix_size);
+ request_size -= prefix_size;
+ }
+
+ size_t aligned_size = RoundUp(size, OS::AllocateAlignment());
+ DCHECK_LE(aligned_size, request_size);
+
+ if (aligned_size != request_size) {
+ size_t suffix_size = request_size - aligned_size;
+ OS::Free(aligned_base + aligned_size, suffix_size);
+ request_size -= suffix_size;
+ }
+
+ DCHECK(aligned_size == request_size);
+
+ address_ = static_cast<void*>(aligned_base);
+ size_ = aligned_size;
+}
+
+
+VirtualMemory::~VirtualMemory() {
+ if (IsReserved()) {
+ bool result = ReleaseRegion(address(), size());
+ DCHECK(result);
+ USE(result);
+ }
+}
+
+
+bool VirtualMemory::IsReserved() { return address_ != NULL; }
+
+
+void VirtualMemory::Reset() {
+ address_ = NULL;
+ size_ = 0;
+}
+
+
+bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+ return CommitRegion(address, size, is_executable);
+}
+
+
+bool VirtualMemory::Uncommit(void* address, size_t size) {
+ return UncommitRegion(address, size);
+}
+
+
+bool VirtualMemory::Guard(void* address) {
+ OS::Guard(address, OS::CommitPageSize());
+ return true;
+}
+
+
+void* VirtualMemory::ReserveRegion(size_t size) {
+ void* result = mmapHelper(size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS,
+ kMmapFd, kMmapFdOffset);
+
+ if (result == MAP_FAILED) return NULL;
+
+ return result;
+}
+
+
+bool VirtualMemory::CommitRegion(void* base, size_t size, bool is_executable) {
+#if defined(__native_client__)
+ // The Native Client port of V8 uses an interpreter,
+ // so code pages don't need PROT_EXEC.
+ int prot = PROT_READ | PROT_WRITE;
+#else
+ int prot = PROT_READ | PROT_WRITE | (is_executable ? PROT_EXEC : 0);
+#endif
+ if (mprotect(base, size, prot) == -1) return false;
+
+ return true;
+}
+
+
+bool VirtualMemory::UncommitRegion(void* base, size_t size) {
+ return mprotect(base, size, PROT_NONE) != -1;
+}
+
+
+bool VirtualMemory::ReleaseRegion(void* base, size_t size) {
+ return munmap(base, size) == 0;
+}
+
+
+bool VirtualMemory::HasLazyCommits() { return true; }
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-cygwin.cc b/src/base/platform/platform-cygwin.cc
index 8a767cf..a49e287 100644
--- a/src/base/platform/platform-cygwin.cc
+++ b/src/base/platform/platform-cygwin.cc
@@ -29,7 +29,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return tzname[0]; // The location of the timezone string on Cygwin.
}
@@ -39,7 +39,7 @@
// On Cygwin, struct tm does not contain a tm_gmtoff field.
time_t utc = time(NULL);
DCHECK(utc != -1);
- struct tm* loc = localtime(&utc);
+ struct tm* loc = localtime(&utc); // NOLINT(runtime/threadsafe_fn)
DCHECK(loc != NULL);
// time - localtime includes any daylight savings offset, so subtract it.
return static_cast<double>((mktime(loc) - utc) * msPerSecond -
@@ -59,54 +59,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) munmap(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
std::vector<SharedLibraryAddresses> result;
// This function assumes that the layout of the file is as follows:
@@ -300,4 +252,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-freebsd.cc b/src/base/platform/platform-freebsd.cc
index 58316f8..8b33980 100644
--- a/src/base/platform/platform-freebsd.cc
+++ b/src/base/platform/platform-freebsd.cc
@@ -17,7 +17,6 @@
#include <sys/fcntl.h> // open
#include <sys/mman.h> // mmap & munmap
#include <sys/stat.h> // open
-#include <sys/types.h> // mmap & munmap
#include <unistd.h> // getpagesize
// If you don't have execinfo.h then you need devel/libexecinfo from ports.
#include <errno.h>
@@ -40,7 +39,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return t->tm_zone;
}
@@ -48,7 +47,7 @@
double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL);
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
// tm_gmtoff includes any daylight savings offset, so subtract it.
return static_cast<double>(t->tm_gmtoff * msPerSecond -
(t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
@@ -68,54 +67,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) munmap(memory_, size_);
- fclose(file_);
-}
-
-
static unsigned StringToLong(char* buffer) {
return static_cast<unsigned>(strtol(buffer, NULL, 16)); // NOLINT
}
@@ -188,7 +139,7 @@
void* reservation = mmap(OS::GetRandomMmapAddr(),
request_size,
PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ MAP_PRIVATE | MAP_ANON,
kMmapFd,
kMmapFdOffset);
if (reservation == MAP_FAILED) return;
@@ -260,7 +211,7 @@
void* result = mmap(OS::GetRandomMmapAddr(),
size,
PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_NORESERVE,
+ MAP_PRIVATE | MAP_ANON,
kMmapFd,
kMmapFdOffset);
@@ -288,7 +239,7 @@
return mmap(base,
size,
PROT_NONE,
- MAP_PRIVATE | MAP_ANON | MAP_NORESERVE | MAP_FIXED,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED,
kMmapFd,
kMmapFdOffset) != MAP_FAILED;
}
@@ -304,4 +255,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-linux.cc b/src/base/platform/platform-linux.cc
index 36857e6..a4b742a 100644
--- a/src/base/platform/platform-linux.cc
+++ b/src/base/platform/platform-linux.cc
@@ -108,7 +108,7 @@
#else
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (!t || !t->tm_zone) return "";
return t->tm_zone;
#endif
@@ -121,7 +121,7 @@
return 0;
#else
time_t tv = time(NULL);
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
// tm_gmtoff includes any daylight savings offset, so subtract it.
return static_cast<double>(t->tm_gmtoff * msPerSecond -
(t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
@@ -142,64 +142,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) OS::Free(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
std::vector<SharedLibraryAddress> result;
// This function assumes that the layout of the file is as follows:
@@ -271,7 +213,7 @@
// it. This injects a GC marker into the stream of events generated
// by the kernel and allows us to synchronize V8 code log and the
// kernel log.
- int size = sysconf(_SC_PAGESIZE);
+ long size = sysconf(_SC_PAGESIZE); // NOLINT(runtime/int)
FILE* f = fopen(OS::GetGCFakeMMapFile(), "w+");
if (f == NULL) {
OS::PrintError("Failed to open %s\n", OS::GetGCFakeMMapFile());
@@ -286,7 +228,7 @@
PROT_READ | PROT_EXEC,
#endif
MAP_PRIVATE, fileno(f), 0);
- DCHECK(addr != MAP_FAILED);
+ DCHECK_NE(MAP_FAILED, addr);
OS::Free(addr, size);
fclose(f);
}
@@ -368,16 +310,19 @@
bool VirtualMemory::Commit(void* address, size_t size, bool is_executable) {
+ CHECK(InVM(address, size));
return CommitRegion(address, size, is_executable);
}
bool VirtualMemory::Uncommit(void* address, size_t size) {
+ CHECK(InVM(address, size));
return UncommitRegion(address, size);
}
bool VirtualMemory::Guard(void* address) {
+ CHECK(InVM(address, OS::CommitPageSize()));
OS::Guard(address, OS::CommitPageSize());
return true;
}
@@ -443,4 +388,5 @@
return true;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-macos.cc b/src/base/platform/platform-macos.cc
index 77893ee..419281f 100644
--- a/src/base/platform/platform-macos.cc
+++ b/src/base/platform/platform-macos.cc
@@ -68,64 +68,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) OS::Free(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
std::vector<SharedLibraryAddress> result;
unsigned int images_count = _dyld_image_count();
@@ -160,7 +102,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return t->tm_zone;
}
@@ -168,7 +110,7 @@
double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL);
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
// tm_gmtoff includes any daylight savings offset, so subtract it.
return static_cast<double>(t->tm_gmtoff * msPerSecond -
(t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
@@ -307,4 +249,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-openbsd.cc b/src/base/platform/platform-openbsd.cc
index 4e706cb..af145e2 100644
--- a/src/base/platform/platform-openbsd.cc
+++ b/src/base/platform/platform-openbsd.cc
@@ -20,7 +20,6 @@
#include <strings.h> // index
#include <sys/mman.h> // mmap & munmap
#include <sys/stat.h> // open
-#include <sys/types.h> // mmap & munmap
#include <unistd.h> // sysconf
#include <cmath>
@@ -38,7 +37,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return t->tm_zone;
}
@@ -46,7 +45,7 @@
double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL);
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
// tm_gmtoff includes any daylight savings offset, so subtract it.
return static_cast<double>(t->tm_gmtoff * msPerSecond -
(t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
@@ -66,54 +65,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) OS::Free(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
std::vector<SharedLibraryAddress> result;
// This function assumes that the layout of the file is as follows:
@@ -335,4 +286,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-posix.cc b/src/base/platform/platform-posix.cc
index 64aed2b..046dbb6 100644
--- a/src/base/platform/platform-posix.cc
+++ b/src/base/platform/platform-posix.cc
@@ -55,7 +55,7 @@
#include <sys/prctl.h> // NOLINT, for prctl
#endif
-#if !V8_OS_NACL
+#if !defined(V8_OS_NACL) && !defined(_AIX)
#include <sys/syscall.h>
#endif
@@ -85,8 +85,8 @@
// Otherwise we just assume 16 byte alignment, i.e.:
// - With gcc 4.4 the tree vectorization optimizer can generate code
// that requires 16 byte alignment such as movdqa on x86.
- // - Mac OS X and Solaris (64-bit) activation frames must be 16 byte-aligned;
- // see "Mac OS X ABI Function Call Guide"
+ // - Mac OS X, PPC and Solaris (64-bit) activation frames must
+ // be 16 byte-aligned; see "Mac OS X ABI Function Call Guide"
return 16;
#endif
}
@@ -171,6 +171,20 @@
// the hint address to 46 bits to give the kernel a fighting chance of
// fulfilling our placement request.
raw_addr &= V8_UINT64_C(0x3ffffffff000);
+#elif V8_TARGET_ARCH_PPC64
+#if V8_OS_AIX
+ // AIX: 64 bits of virtual addressing, but we limit address range to:
+ // a) minimize Segment Lookaside Buffer (SLB) misses and
+ raw_addr &= V8_UINT64_C(0x3ffff000);
+ // Use extra address space to isolate the mmap regions.
+ raw_addr += V8_UINT64_C(0x400000000000);
+#elif V8_TARGET_BIG_ENDIAN
+ // Big-endian Linux: 44 bits of virtual addressing.
+ raw_addr &= V8_UINT64_C(0x03fffffff000);
+#else
+ // Little-endian Linux: 48 bits of virtual addressing.
+ raw_addr &= V8_UINT64_C(0x3ffffffff000);
+#endif
#else
raw_addr &= 0x3ffff000;
@@ -185,6 +199,10 @@
// no hint at all. The high hint prevents the break from getting hemmed in
// at low values, ceding half of the address space to the system heap.
raw_addr += 0x80000000;
+#elif V8_OS_AIX
+ // The range 0x30000000 - 0xD0000000 is available on AIX;
+ // choose the upper range.
+ raw_addr += 0x90000000;
# else
// The range 0x20000000 - 0x60000000 is relatively unpopulated across a
// variety of ASLR modes (PAE kernel, NX compat mode, etc) and on macos
@@ -201,9 +219,8 @@
}
-void OS::Sleep(int milliseconds) {
- useconds_t ms = static_cast<useconds_t>(milliseconds);
- usleep(1000 * ms);
+void OS::Sleep(TimeDelta interval) {
+ usleep(static_cast<useconds_t>(interval.InMicroseconds()));
}
@@ -225,6 +242,8 @@
asm("break");
#elif V8_HOST_ARCH_MIPS64
asm("break");
+#elif V8_HOST_ARCH_PPC
+ asm("twge 2,2");
#elif V8_HOST_ARCH_IA32
#if V8_OS_NACL
asm("hlt");
@@ -239,12 +258,62 @@
}
-// ----------------------------------------------------------------------------
-// Math functions
+class PosixMemoryMappedFile final : public OS::MemoryMappedFile {
+ public:
+ PosixMemoryMappedFile(FILE* file, void* memory, size_t size)
+ : file_(file), memory_(memory), size_(size) {}
+ ~PosixMemoryMappedFile() final;
+ void* memory() const final { return memory_; }
+ size_t size() const final { return size_; }
-double OS::nan_value() {
- // NAN from math.h is defined in C99 and not in POSIX.
- return NAN;
+ private:
+ FILE* const file_;
+ void* const memory_;
+ size_t const size_;
+};
+
+
+// static
+OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
+ if (FILE* file = fopen(name, "r+")) {
+ if (fseek(file, 0, SEEK_END) == 0) {
+ long size = ftell(file); // NOLINT(runtime/int)
+ if (size >= 0) {
+ void* const memory =
+ mmap(OS::GetRandomMmapAddr(), size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fileno(file), 0);
+ if (memory != MAP_FAILED) {
+ return new PosixMemoryMappedFile(file, memory, size);
+ }
+ }
+ }
+ fclose(file);
+ }
+ return nullptr;
+}
+
+
+// static
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name,
+ size_t size, void* initial) {
+ if (FILE* file = fopen(name, "w+")) {
+ size_t result = fwrite(initial, 1, size, file);
+ if (result == size && !ferror(file)) {
+ void* memory = mmap(OS::GetRandomMmapAddr(), result,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
+ if (memory != MAP_FAILED) {
+ return new PosixMemoryMappedFile(file, memory, result);
+ }
+ }
+ fclose(file);
+ }
+ return nullptr;
+}
+
+
+PosixMemoryMappedFile::~PosixMemoryMappedFile() {
+ if (memory_) OS::Free(memory_, size_);
+ fclose(file_);
}
@@ -260,6 +329,10 @@
return static_cast<int>(syscall(__NR_gettid));
#elif V8_OS_ANDROID
return static_cast<int>(gettid());
+#elif V8_OS_AIX
+ return static_cast<int>(thread_self());
+#elif V8_OS_SOLARIS
+ return static_cast<int>(pthread_self());
#else
return static_cast<int>(reinterpret_cast<intptr_t>(pthread_self()));
#endif
@@ -270,7 +343,7 @@
// POSIX date/time support.
//
-int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
+int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
#if V8_OS_NACL
// Optionally used in Logger::ResourceEvent.
return -1;
@@ -278,8 +351,8 @@
struct rusage usage;
if (getrusage(RUSAGE_SELF, &usage) < 0) return -1;
- *secs = usage.ru_utime.tv_sec;
- *usecs = usage.ru_utime.tv_usec;
+ *secs = static_cast<uint32_t>(usage.ru_utime.tv_sec);
+ *usecs = static_cast<uint32_t>(usage.ru_utime.tv_usec);
return 0;
#endif
}
@@ -309,10 +382,10 @@
double OS::DaylightSavingsOffset(double time, TimezoneCache*) {
- if (std::isnan(time)) return nan_value();
+ if (std::isnan(time)) return std::numeric_limits<double>::quiet_NaN();
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
- if (NULL == t) return nan_value();
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
+ if (NULL == t) return std::numeric_limits<double>::quiet_NaN();
return t->tm_isdst > 0 ? 3600 * msPerSecond : 0;
}
@@ -343,6 +416,11 @@
}
+bool OS::isDirectorySeparator(const char ch) {
+ return ch == '/';
+}
+
+
FILE* OS::OpenTemporaryFile() {
return tmpfile();
}
@@ -523,8 +601,15 @@
DCHECK_EQ(0, result);
// Native client uses default stack size.
#if !V8_OS_NACL
- if (stack_size_ > 0) {
- result = pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
+ size_t stack_size = stack_size_;
+#if V8_OS_AIX
+ if (stack_size == 0) {
+ // Default on AIX is 96KB -- bump up to 2MB
+ stack_size = 2 * 1024 * 1024;
+ }
+#endif
+ if (stack_size > 0) {
+ result = pthread_attr_setstacksize(&attr, stack_size);
DCHECK_EQ(0, result);
}
#endif
@@ -545,13 +630,6 @@
}
-void Thread::YieldCPU() {
- int result = sched_yield();
- DCHECK_EQ(0, result);
- USE(result);
-}
-
-
static Thread::LocalStorageKey PthreadKeyToLocalKey(pthread_key_t pthread_key) {
#if V8_OS_CYGWIN
// We need to cast pthread_key_t to Thread::LocalStorageKey in two steps
@@ -675,5 +753,5 @@
USE(result);
}
-
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-qnx.cc b/src/base/platform/platform-qnx.cc
index 2cb3228..3c90467 100644
--- a/src/base/platform/platform-qnx.cc
+++ b/src/base/platform/platform-qnx.cc
@@ -24,7 +24,6 @@
#include <sys/mman.h> // mmap & munmap
#include <sys/procfs.h>
#include <sys/stat.h> // open
-#include <sys/types.h> // mmap & munmap
#include <unistd.h> // sysconf
#include <cmath>
@@ -89,7 +88,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return t->tm_zone;
}
@@ -97,7 +96,7 @@
double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL);
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
// tm_gmtoff includes any daylight savings offset, so subtract it.
return static_cast<double>(t->tm_gmtoff * msPerSecond -
(t->tm_isdst > 0 ? 3600 * msPerSecond : 0));
@@ -117,64 +116,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(OS::GetRandomMmapAddr(),
- size,
- PROT_READ | PROT_WRITE,
- MAP_SHARED,
- fileno(file),
- 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) OS::Free(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
std::vector<SharedLibraryAddress> result;
procfs_mapinfo *mapinfos = NULL, *mapinfo;
@@ -371,4 +312,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-solaris.cc b/src/base/platform/platform-solaris.cc
index b9a2ec8..a2ce2c1 100644
--- a/src/base/platform/platform-solaris.cc
+++ b/src/base/platform/platform-solaris.cc
@@ -38,7 +38,7 @@
const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
- struct tm* t = localtime(&tv);
+ struct tm* t = localtime(&tv); // NOLINT(runtime/threadsafe_fn)
if (NULL == t) return "";
return tzname[0]; // The location of the timezone string on Solaris.
}
@@ -63,54 +63,6 @@
}
-class PosixMemoryMappedFile : public OS::MemoryMappedFile {
- public:
- PosixMemoryMappedFile(FILE* file, void* memory, int size)
- : file_(file), memory_(memory), size_(size) { }
- virtual ~PosixMemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
- private:
- FILE* file_;
- void* memory_;
- int size_;
-};
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
- FILE* file = fopen(name, "r+");
- if (file == NULL) return NULL;
-
- fseek(file, 0, SEEK_END);
- int size = ftell(file);
-
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
- FILE* file = fopen(name, "w+");
- if (file == NULL) return NULL;
- int result = fwrite(initial, size, 1, file);
- if (result < 1) {
- fclose(file);
- return NULL;
- }
- void* memory =
- mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(file), 0);
- return new PosixMemoryMappedFile(file, memory, size);
-}
-
-
-PosixMemoryMappedFile::~PosixMemoryMappedFile() {
- if (memory_) munmap(memory_, size_);
- fclose(file_);
-}
-
-
std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() {
return std::vector<SharedLibraryAddress>();
}
@@ -256,4 +208,5 @@
return false;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform-win32.cc b/src/base/platform/platform-win32.cc
index d68e861..6afa6f9 100644
--- a/src/base/platform/platform-win32.cc
+++ b/src/base/platform/platform-win32.cc
@@ -46,7 +46,7 @@
int localtime_s(tm* out_tm, const time_t* time) {
- tm* posix_local_time_struct = localtime(time);
+ tm* posix_local_time_struct = localtime(time); // NOLINT
if (posix_local_time_struct == NULL) return 1;
*out_tm = *posix_local_time_struct;
return 0;
@@ -575,6 +575,11 @@
}
+bool OS::isDirectorySeparator(const char ch) {
+ return ch == '/' || ch == '\\';
+}
+
+
FILE* OS::OpenTemporaryFile() {
// tmpfile_s tries to use the root dir, don't use it.
char tempPathBuffer[MAX_PATH];
@@ -728,15 +733,17 @@
// Note: This does not guarantee RWX regions will be within the
// range kAllocationRandomAddressMin to kAllocationRandomAddressMax
#ifdef V8_HOST_ARCH_64_BIT
- static const intptr_t kAllocationRandomAddressMin = 0x0000000080000000;
- static const intptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
+ static const uintptr_t kAllocationRandomAddressMin = 0x0000000080000000;
+ static const uintptr_t kAllocationRandomAddressMax = 0x000003FFFFFF0000;
#else
- static const intptr_t kAllocationRandomAddressMin = 0x04000000;
- static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
+ static const uintptr_t kAllocationRandomAddressMin = 0x04000000;
+ static const uintptr_t kAllocationRandomAddressMax = 0x3FFF0000;
#endif
- uintptr_t address =
- (platform_random_number_generator.Pointer()->NextInt() << kPageSizeBits) |
- kAllocationRandomAddressMin;
+ uintptr_t address;
+ platform_random_number_generator.Pointer()->NextBytes(&address,
+ sizeof(address));
+ address <<= kPageSizeBits;
+ address += kAllocationRandomAddressMin;
address &= kAllocationRandomAddressMax;
return reinterpret_cast<void *>(address);
}
@@ -744,9 +751,19 @@
static void* RandomizedVirtualAlloc(size_t size, int action, int protection) {
LPVOID base = NULL;
+ static BOOL use_aslr = -1;
+#ifdef V8_HOST_ARCH_32_BIT
+ // Don't bother randomizing on 32-bit hosts, because they lack the room and
+ // don't have viable ASLR anyway.
+ if (use_aslr == -1 && !IsWow64Process(GetCurrentProcess(), &use_aslr))
+ use_aslr = FALSE;
+#else
+ use_aslr = TRUE;
+#endif
- if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) {
- // For exectutable pages try and randomize the allocation address
+ if (use_aslr &&
+ (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS)) {
+ // For executable pages try and randomize the allocation address
for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) {
base = VirtualAlloc(OS::GetRandomMmapAddr(), size, action, protection);
}
@@ -805,8 +822,8 @@
}
-void OS::Sleep(int milliseconds) {
- ::Sleep(milliseconds);
+void OS::Sleep(TimeDelta interval) {
+ ::Sleep(static_cast<DWORD>(interval.InMilliseconds()));
}
@@ -816,6 +833,9 @@
}
// Make the MSVCRT do a silent abort.
raise(SIGABRT);
+
+ // Make sure function doesn't return.
+ abort();
}
@@ -831,38 +851,38 @@
}
-class Win32MemoryMappedFile : public OS::MemoryMappedFile {
+class Win32MemoryMappedFile final : public OS::MemoryMappedFile {
public:
- Win32MemoryMappedFile(HANDLE file,
- HANDLE file_mapping,
- void* memory,
- int size)
+ Win32MemoryMappedFile(HANDLE file, HANDLE file_mapping, void* memory,
+ size_t size)
: file_(file),
file_mapping_(file_mapping),
memory_(memory),
- size_(size) { }
- virtual ~Win32MemoryMappedFile();
- virtual void* memory() { return memory_; }
- virtual int size() { return size_; }
+ size_(size) {}
+ ~Win32MemoryMappedFile() final;
+ void* memory() const final { return memory_; }
+ size_t size() const final { return size_; }
+
private:
- HANDLE file_;
- HANDLE file_mapping_;
- void* memory_;
- int size_;
+ HANDLE const file_;
+ HANDLE const file_mapping_;
+ void* const memory_;
+ size_t const size_;
};
+// static
OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) {
// Open a physical file
HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (file == INVALID_HANDLE_VALUE) return NULL;
- int size = static_cast<int>(GetFileSize(file, NULL));
+ DWORD size = GetFileSize(file, NULL);
// Create a file mapping for the physical file
- HANDLE file_mapping = CreateFileMapping(file, NULL,
- PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
+ HANDLE file_mapping =
+ CreateFileMapping(file, NULL, PAGE_READWRITE, 0, size, NULL);
if (file_mapping == NULL) return NULL;
// Map a view of the file into memory
@@ -871,15 +891,17 @@
}
-OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, int size,
- void* initial) {
+// static
+OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name,
+ size_t size, void* initial) {
// Open a physical file
HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE,
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL);
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_ALWAYS, 0, NULL);
if (file == NULL) return NULL;
// Create a file mapping for the physical file
- HANDLE file_mapping = CreateFileMapping(file, NULL,
- PAGE_READWRITE, 0, static_cast<DWORD>(size), NULL);
+ HANDLE file_mapping = CreateFileMapping(file, NULL, PAGE_READWRITE, 0,
+ static_cast<DWORD>(size), NULL);
if (file_mapping == NULL) return NULL;
// Map a view of the file into memory
void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size);
@@ -889,8 +911,7 @@
Win32MemoryMappedFile::~Win32MemoryMappedFile() {
- if (memory_ != NULL)
- UnmapViewOfFile(memory_);
+ if (memory_) UnmapViewOfFile(memory_);
CloseHandle(file_mapping_);
CloseHandle(file_);
}
@@ -1125,9 +1146,9 @@
WideCharToMultiByte(CP_UTF8, 0, module_entry.szExePath, -1, &lib_name[0],
lib_name_length, NULL, NULL);
result.push_back(OS::SharedLibraryAddress(
- lib_name, reinterpret_cast<unsigned int>(module_entry.modBaseAddr),
- reinterpret_cast<unsigned int>(module_entry.modBaseAddr +
- module_entry.modBaseSize)));
+ lib_name, reinterpret_cast<uintptr_t>(module_entry.modBaseAddr),
+ reinterpret_cast<uintptr_t>(module_entry.modBaseAddr +
+ module_entry.modBaseSize)));
cont = _Module32NextW(snapshot, &module_entry);
}
CloseHandle(snapshot);
@@ -1162,11 +1183,6 @@
#endif // __MINGW32__
-double OS::nan_value() {
- return std::numeric_limits<double>::quiet_NaN();
-}
-
-
int OS::ActivationFrameAlignment() {
#ifdef _WIN64
return 16; // Windows 64-bit ABI requires the stack to be 16-byte aligned.
@@ -1381,10 +1397,5 @@
DCHECK(result);
}
-
-
-void Thread::YieldCPU() {
- Sleep(0);
-}
-
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/platform.h b/src/base/platform/platform.h
index 0bf1027..89d6225 100644
--- a/src/base/platform/platform.h
+++ b/src/base/platform/platform.h
@@ -142,6 +142,8 @@
static FILE* FOpen(const char* path, const char* mode);
static bool Remove(const char* path);
+ static bool isDirectorySeparator(const char ch);
+
// Opens a temporary file, the file is auto removed on close.
static FILE* OpenTemporaryFile();
@@ -188,11 +190,11 @@
// Get the Alignment guaranteed by Allocate().
static size_t AllocateAlignment();
- // Sleep for a number of milliseconds.
- static void Sleep(const int milliseconds);
+ // Sleep for a specified time interval.
+ static void Sleep(TimeDelta interval);
// Abort the current process.
- static void Abort();
+ V8_NORETURN static void Abort();
// Debug break.
static void DebugBreak();
@@ -208,11 +210,13 @@
class MemoryMappedFile {
public:
+ virtual ~MemoryMappedFile() {}
+ virtual void* memory() const = 0;
+ virtual size_t size() const = 0;
+
static MemoryMappedFile* open(const char* name);
- static MemoryMappedFile* create(const char* name, int size, void* initial);
- virtual ~MemoryMappedFile() { }
- virtual void* memory() = 0;
- virtual int size() = 0;
+ static MemoryMappedFile* create(const char* name, size_t size,
+ void* initial);
};
// Safe formatting print. Ensures that str is always null-terminated.
@@ -246,9 +250,6 @@
// using --never-compact) if accurate profiling is desired.
static void SignalCodeMovingGC();
- // Returns the double constant NAN
- static double nan_value();
-
// Support runtime detection of whether the hard float option of the
// EABI is used.
static bool ArmUsingHardFloat();
@@ -271,6 +272,7 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(OS);
};
+
// Represents and controls an area of reserved memory.
// Control of the reserved memory can be assigned to another VirtualMemory
// object by assignment or copy-contructing. This removes the reserved memory
@@ -328,6 +330,7 @@
// inside the allocated region.
void* address = address_;
size_t size = size_;
+ CHECK(InVM(address, size));
Reset();
bool result = ReleaseRegion(address, size);
USE(result);
@@ -359,6 +362,13 @@
static bool HasLazyCommits();
private:
+ bool InVM(void* address, size_t size) {
+ return (reinterpret_cast<uintptr_t>(address_) <=
+ reinterpret_cast<uintptr_t>(address)) &&
+ ((reinterpret_cast<uintptr_t>(address_) + size_) >=
+ (reinterpret_cast<uintptr_t>(address) + size));
+ }
+
void* address_; // Start address of the virtual memory.
size_t size_; // Size of the virtual memory.
};
@@ -445,10 +455,6 @@
}
#endif
- // A hint to the scheduler to let another thread run.
- static void YieldCPU();
-
-
// The thread name length is limited to 16 based on Linux's implementation of
// prctl().
static const int kMaxThreadNameLength = 16;
@@ -473,6 +479,7 @@
DISALLOW_COPY_AND_ASSIGN(Thread);
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_PLATFORM_H_
diff --git a/src/base/platform/semaphore.cc b/src/base/platform/semaphore.cc
index 0679c00..9e7b59a 100644
--- a/src/base/platform/semaphore.cc
+++ b/src/base/platform/semaphore.cc
@@ -75,6 +75,10 @@
Semaphore::Semaphore(int count) {
DCHECK(count >= 0);
+#if V8_LIBC_GLIBC
+ // sem_init in glibc prior to 2.1 does not zero out semaphores.
+ memset(&native_handle_, 0, sizeof(native_handle_));
+#endif
int result = sem_init(&native_handle_, 0, count);
DCHECK_EQ(0, result);
USE(result);
@@ -201,4 +205,5 @@
#endif // V8_OS_MACOSX
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/semaphore.h b/src/base/platform/semaphore.h
index cbf8df2..18700d1 100644
--- a/src/base/platform/semaphore.h
+++ b/src/base/platform/semaphore.h
@@ -31,7 +31,7 @@
// count reaches zero, threads waiting for the semaphore blocks until the
// count becomes non-zero.
-class Semaphore FINAL {
+class Semaphore final {
public:
explicit Semaphore(int count);
~Semaphore();
@@ -96,6 +96,7 @@
#define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_SEMAPHORE_H_
diff --git a/src/base/platform/time.cc b/src/base/platform/time.cc
index 40dd188..e847d54 100644
--- a/src/base/platform/time.cc
+++ b/src/base/platform/time.cc
@@ -13,9 +13,11 @@
#include <mach/mach_time.h>
#endif
-#include <string.h>
+#include <cstring>
+#include <ostream>
#if V8_OS_WIN
+#include "src/base/atomicops.h"
#include "src/base/lazy-instance.h"
#include "src/base/win32-headers.h"
#endif
@@ -110,7 +112,7 @@
struct mach_timespec TimeDelta::ToMachTimespec() const {
struct mach_timespec ts;
DCHECK(delta_ >= 0);
- ts.tv_sec = delta_ / Time::kMicrosecondsPerSecond;
+ ts.tv_sec = static_cast<unsigned>(delta_ / Time::kMicrosecondsPerSecond);
ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
Time::kNanosecondsPerMicrosecond;
return ts;
@@ -132,7 +134,7 @@
struct timespec TimeDelta::ToTimespec() const {
struct timespec ts;
- ts.tv_sec = delta_ / Time::kMicrosecondsPerSecond;
+ ts.tv_sec = static_cast<time_t>(delta_ / Time::kMicrosecondsPerSecond);
ts.tv_nsec = (delta_ % Time::kMicrosecondsPerSecond) *
Time::kNanosecondsPerMicrosecond;
return ts;
@@ -146,7 +148,7 @@
// We implement time using the high-resolution timers so that we can get
// timeouts which are smaller than 10-15ms. To avoid any drift, we
// periodically resync the internal clock to the system clock.
-class Clock FINAL {
+class Clock final {
public:
Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {}
@@ -291,7 +293,7 @@
ts.tv_nsec = static_cast<long>(kNanosecondsPerSecond - 1); // NOLINT
return ts;
}
- ts.tv_sec = us_ / kMicrosecondsPerSecond;
+ ts.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
ts.tv_nsec = (us_ % kMicrosecondsPerSecond) * kNanosecondsPerMicrosecond;
return ts;
}
@@ -323,7 +325,7 @@
tv.tv_usec = static_cast<suseconds_t>(kMicrosecondsPerSecond - 1);
return tv;
}
- tv.tv_sec = us_ / kMicrosecondsPerSecond;
+ tv.tv_sec = static_cast<time_t>(us_ / kMicrosecondsPerSecond);
tv.tv_usec = us_ % kMicrosecondsPerSecond;
return tv;
}
@@ -355,6 +357,11 @@
}
+std::ostream& operator<<(std::ostream& os, const Time& time) {
+ return os << time.ToJsTime();
+}
+
+
#if V8_OS_WIN
class TickClock {
@@ -393,7 +400,7 @@
// (3) System time. The system time provides a low-resolution (typically 10ms
// to 55 milliseconds) time stamp but is comparatively less expensive to
// retrieve and more reliable.
-class HighResolutionTickClock FINAL : public TickClock {
+class HighResolutionTickClock final : public TickClock {
public:
explicit HighResolutionTickClock(int64_t ticks_per_second)
: ticks_per_second_(ticks_per_second) {
@@ -401,7 +408,7 @@
}
virtual ~HighResolutionTickClock() {}
- int64_t Now() OVERRIDE {
+ int64_t Now() override {
LARGE_INTEGER now;
BOOL result = QueryPerformanceCounter(&now);
DCHECK(result);
@@ -419,45 +426,44 @@
return ticks + 1;
}
- bool IsHighResolution() OVERRIDE { return true; }
+ bool IsHighResolution() override { return true; }
private:
int64_t ticks_per_second_;
};
-class RolloverProtectedTickClock FINAL : public TickClock {
+class RolloverProtectedTickClock final : public TickClock {
public:
- // We initialize rollover_ms_ to 1 to ensure that we will never
- // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below.
- RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
+ RolloverProtectedTickClock() : rollover_(0) {}
virtual ~RolloverProtectedTickClock() {}
- int64_t Now() OVERRIDE {
- LockGuard<Mutex> lock_guard(&mutex_);
+ int64_t Now() override {
// We use timeGetTime() to implement TimeTicks::Now(), which rolls over
// every ~49.7 days. We try to track rollover ourselves, which works if
- // TimeTicks::Now() is called at least every 49 days.
+ // TimeTicks::Now() is called at least every 24 days.
// Note that we do not use GetTickCount() here, since timeGetTime() gives
// more predictable delta values, as described here:
// http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx
// timeGetTime() provides 1ms granularity when combined with
// timeBeginPeriod(). If the host application for V8 wants fast timers, it
// can use timeBeginPeriod() to increase the resolution.
- DWORD now = timeGetTime();
- if (now < last_seen_now_) {
- rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days.
+ // We use a lock-free version because the sampler thread calls it
+ // while having the rest of the world stopped, that could cause a deadlock.
+ base::Atomic32 rollover = base::Acquire_Load(&rollover_);
+ uint32_t now = static_cast<uint32_t>(timeGetTime());
+ if ((now >> 31) != static_cast<uint32_t>(rollover & 1)) {
+ base::Release_CompareAndSwap(&rollover_, rollover, rollover + 1);
+ ++rollover;
}
- last_seen_now_ = now;
- return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond;
+ uint64_t ms = (static_cast<uint64_t>(rollover) << 31) | now;
+ return static_cast<int64_t>(ms * Time::kMicrosecondsPerMillisecond);
}
- bool IsHighResolution() OVERRIDE { return false; }
+ bool IsHighResolution() override { return false; }
private:
- Mutex mutex_;
- DWORD last_seen_now_;
- int64_t rollover_ms_;
+ base::Atomic32 rollover_;
};
@@ -542,15 +548,6 @@
info.numer / info.denom);
#elif V8_OS_SOLARIS
ticks = (gethrtime() / Time::kNanosecondsPerMicrosecond);
-#elif V8_LIBRT_NOT_AVAILABLE
- // TODO(bmeurer): This is a temporary hack to support cross-compiling
- // Chrome for Android in AOSP. Remove this once AOSP is fixed, also
- // cleanup the tools/gyp/v8.gyp file.
- struct timeval tv;
- int result = gettimeofday(&tv, NULL);
- DCHECK_EQ(0, result);
- USE(result);
- ticks = (tv.tv_sec * Time::kMicrosecondsPerSecond + tv.tv_usec);
#elif V8_OS_POSIX
struct timespec ts;
int result = clock_gettime(CLOCK_MONOTONIC, &ts);
@@ -570,7 +567,7 @@
}
-#if V8_OS_LINUX && !V8_LIBRT_NOT_AVAILABLE
+#if V8_OS_LINUX
class KernelTimestampClock {
public:
@@ -626,7 +623,7 @@
bool Available() { return false; }
};
-#endif // V8_OS_LINUX && !V8_LIBRT_NOT_AVAILABLE
+#endif // V8_OS_LINUX
static LazyStaticInstance<KernelTimestampClock,
DefaultConstructTrait<KernelTimestampClock>,
@@ -647,4 +644,5 @@
#endif // V8_OS_WIN
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
diff --git a/src/base/platform/time.h b/src/base/platform/time.h
index 9dfa47d..29300e5 100644
--- a/src/base/platform/time.h
+++ b/src/base/platform/time.h
@@ -5,7 +5,8 @@
#ifndef V8_BASE_PLATFORM_TIME_H_
#define V8_BASE_PLATFORM_TIME_H_
-#include <time.h>
+#include <ctime>
+#include <iosfwd>
#include <limits>
#include "src/base/macros.h"
@@ -30,7 +31,7 @@
// This class represents a duration of time, internally represented in
// microseonds.
-class TimeDelta FINAL {
+class TimeDelta final {
public:
TimeDelta() : delta_(0) {}
@@ -158,7 +159,7 @@
// This class represents an absolute point in time, internally represented as
// microseconds (s/1,000,000) since 00:00:00 UTC, January 1, 1970.
-class Time FINAL {
+class Time final {
public:
static const int64_t kMillisecondsPerSecond = 1000;
static const int64_t kMicrosecondsPerMillisecond = 1000;
@@ -280,6 +281,8 @@
int64_t us_;
};
+std::ostream& operator<<(std::ostream&, const Time&);
+
inline Time operator+(const TimeDelta& delta, const Time& time) {
return time + delta;
}
@@ -295,7 +298,7 @@
// Time::Now() may actually decrease or jump). But note that TimeTicks may
// "stand still", for example if the computer suspended.
-class TimeTicks FINAL {
+class TimeTicks final {
public:
TimeTicks() : ticks_(0) {}
@@ -395,6 +398,7 @@
return ticks + delta;
}
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_PLATFORM_TIME_H_
diff --git a/src/base/safe_math_impl.h b/src/base/safe_math_impl.h
index 055e2a0..eb2a151 100644
--- a/src/base/safe_math_impl.h
+++ b/src/base/safe_math_impl.h
@@ -208,8 +208,8 @@
(sizeof(T) * 2 > sizeof(uintmax_t)),
T>::type
CheckedMul(T x, T y, RangeConstraint* validity) {
- // if either side is zero then the result will be zero.
- if (!(x || y)) {
+ // If either side is zero then the result will be zero.
+ if (!x || !y) {
return RANGE_VALID;
} else if (x > 0) {
diff --git a/src/base/smart-pointers.h b/src/base/smart-pointers.h
new file mode 100644
index 0000000..df3fcac
--- /dev/null
+++ b/src/base/smart-pointers.h
@@ -0,0 +1,124 @@
+// 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.
+
+#ifndef V8_BASE_SMART_POINTERS_H_
+#define V8_BASE_SMART_POINTERS_H_
+
+#include "src/base/logging.h"
+
+namespace v8 {
+namespace base {
+
+template <typename Deallocator, typename T>
+class SmartPointerBase {
+ public:
+ // Default constructor. Constructs an empty scoped pointer.
+ SmartPointerBase() : p_(NULL) {}
+
+ // Constructs a scoped pointer from a plain one.
+ explicit SmartPointerBase(T* ptr) : p_(ptr) {}
+
+ // Copy constructor removes the pointer from the original to avoid double
+ // freeing.
+ SmartPointerBase(const SmartPointerBase<Deallocator, T>& rhs) : p_(rhs.p_) {
+ const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
+ }
+
+ T* operator->() const { return p_; }
+
+ T& operator*() const { return *p_; }
+
+ T* get() const { return p_; }
+
+ // You can use [n] to index as if it was a plain pointer.
+ T& operator[](size_t i) { return p_[i]; }
+
+ // You can use [n] to index as if it was a plain pointer.
+ const T& operator[](size_t i) const { return p_[i]; }
+
+ // We don't have implicit conversion to a T* since that hinders migration:
+ // You would not be able to change a method from returning a T* to
+ // returning an SmartArrayPointer<T> and then get errors wherever it is used.
+
+
+ // If you want to take out the plain pointer and don't want it automatically
+ // deleted then call Detach(). Afterwards, the smart pointer is empty
+ // (NULL).
+ T* Detach() {
+ T* temp = p_;
+ p_ = NULL;
+ return temp;
+ }
+
+ void Reset(T* new_value) {
+ DCHECK(p_ == NULL || p_ != new_value);
+ if (p_) Deallocator::Delete(p_);
+ p_ = new_value;
+ }
+
+ // Assignment requires an empty (NULL) SmartArrayPointer as the receiver. Like
+ // the copy constructor it removes the pointer in the original to avoid
+ // double freeing.
+ SmartPointerBase<Deallocator, T>& operator=(
+ const SmartPointerBase<Deallocator, T>& rhs) {
+ DCHECK(is_empty());
+ T* tmp = rhs.p_; // swap to handle self-assignment
+ const_cast<SmartPointerBase<Deallocator, T>&>(rhs).p_ = NULL;
+ p_ = tmp;
+ return *this;
+ }
+
+ bool is_empty() const { return p_ == NULL; }
+
+ protected:
+ // When the destructor of the scoped pointer is executed the plain pointer
+ // is deleted using DeleteArray. This implies that you must allocate with
+ // NewArray.
+ ~SmartPointerBase() {
+ if (p_) Deallocator::Delete(p_);
+ }
+
+ private:
+ T* p_;
+};
+
+// A 'scoped array pointer' that calls DeleteArray on its pointer when the
+// destructor is called.
+
+template <typename T>
+struct ArrayDeallocator {
+ static void Delete(T* array) { delete[] array; }
+};
+
+
+template <typename T>
+class SmartArrayPointer : public SmartPointerBase<ArrayDeallocator<T>, T> {
+ public:
+ SmartArrayPointer() {}
+ explicit SmartArrayPointer(T* ptr)
+ : SmartPointerBase<ArrayDeallocator<T>, T>(ptr) {}
+ SmartArrayPointer(const SmartArrayPointer<T>& rhs)
+ : SmartPointerBase<ArrayDeallocator<T>, T>(rhs) {}
+};
+
+
+template <typename T>
+struct ObjectDeallocator {
+ static void Delete(T* object) { delete object; }
+};
+
+template <typename T>
+class SmartPointer : public SmartPointerBase<ObjectDeallocator<T>, T> {
+ public:
+ SmartPointer() {}
+ explicit SmartPointer(T* ptr)
+ : SmartPointerBase<ObjectDeallocator<T>, T>(ptr) {}
+ SmartPointer(const SmartPointer<T>& rhs)
+ : SmartPointerBase<ObjectDeallocator<T>, T>(rhs) {}
+};
+
+} // namespace base
+} // namespace v8
+
+#endif // V8_SMART_POINTERS_H_
diff --git a/src/base/sys-info.cc b/src/base/sys-info.cc
index c665771..a2dc6ab 100644
--- a/src/base/sys-info.cc
+++ b/src/base/sys-info.cc
@@ -44,7 +44,7 @@
}
return static_cast<int>(result);
#elif V8_OS_WIN
- SYSTEM_INFO system_info = {0};
+ SYSTEM_INFO system_info = {};
::GetNativeSystemInfo(&system_info);
return static_cast<int>(system_info.dwNumberOfProcessors);
#endif
@@ -88,6 +88,9 @@
#elif V8_OS_NACL
// No support for _SC_PHYS_PAGES, assume 2GB.
return static_cast<int64_t>(1) << 31;
+#elif V8_OS_AIX
+ int64_t result = sysconf(_SC_AIX_REALMEM);
+ return static_cast<int64_t>(result) * 1024L;
#elif V8_OS_POSIX
long pages = sysconf(_SC_PHYS_PAGES); // NOLINT(runtime/int)
long page_size = sysconf(_SC_PAGESIZE); // NOLINT(runtime/int)
diff --git a/src/base/sys-info.h b/src/base/sys-info.h
index 377deb0..4504c82 100644
--- a/src/base/sys-info.h
+++ b/src/base/sys-info.h
@@ -11,7 +11,7 @@
namespace v8 {
namespace base {
-class SysInfo FINAL {
+class SysInfo final {
public:
// Returns the number of logical processors/core on the current machine.
static int NumberOfProcessors();
diff --git a/src/base/utils/random-number-generator.cc b/src/base/utils/random-number-generator.cc
index 29a48ff..ff42840 100644
--- a/src/base/utils/random-number-generator.cc
+++ b/src/base/utils/random-number-generator.cc
@@ -97,15 +97,14 @@
double RandomNumberGenerator::NextDouble() {
- return ((static_cast<int64_t>(Next(26)) << 27) + Next(27)) /
- static_cast<double>(static_cast<int64_t>(1) << 53);
+ XorShift128(&state0_, &state1_);
+ return ToDouble(state0_, state1_);
}
int64_t RandomNumberGenerator::NextInt64() {
- uint64_t lo = bit_cast<unsigned>(Next(32));
- uint64_t hi = bit_cast<unsigned>(Next(32));
- return lo | (hi << 32);
+ XorShift128(&state0_, &state1_);
+ return bit_cast<int64_t>(state0_ + state1_);
}
@@ -119,21 +118,27 @@
int RandomNumberGenerator::Next(int bits) {
DCHECK_LT(0, bits);
DCHECK_GE(32, bits);
- // Do unsigned multiplication, which has the intended modulo semantics, while
- // signed multiplication would expose undefined behavior.
- uint64_t product = static_cast<uint64_t>(seed_) * kMultiplier;
- // Assigning a uint64_t to an int64_t is implementation defined, but this
- // should be OK. Use a static_cast to explicitly state that we know what we're
- // doing. (Famous last words...)
- int64_t seed = static_cast<int64_t>((product + kAddend) & kMask);
- seed_ = seed;
- return static_cast<int>(seed >> (48 - bits));
+ XorShift128(&state0_, &state1_);
+ return static_cast<int>((state0_ + state1_) >> (64 - bits));
}
void RandomNumberGenerator::SetSeed(int64_t seed) {
+ if (seed == 0) seed = 1;
initial_seed_ = seed;
- seed_ = (seed ^ kMultiplier) & kMask;
+ state0_ = MurmurHash3(bit_cast<uint64_t>(seed));
+ state1_ = MurmurHash3(state0_);
}
-} } // namespace v8::base
+
+uint64_t RandomNumberGenerator::MurmurHash3(uint64_t h) {
+ h ^= h >> 33;
+ h *= V8_UINT64_C(0xFF51AFD7ED558CCD);
+ h ^= h >> 33;
+ h *= V8_UINT64_C(0xC4CEB9FE1A85EC53);
+ h ^= h >> 33;
+ return h;
+}
+
+} // namespace base
+} // namespace v8
diff --git a/src/base/utils/random-number-generator.h b/src/base/utils/random-number-generator.h
index d1294f2..cd3e6bf 100644
--- a/src/base/utils/random-number-generator.h
+++ b/src/base/utils/random-number-generator.h
@@ -12,10 +12,16 @@
// -----------------------------------------------------------------------------
// RandomNumberGenerator
-//
-// This class is used to generate a stream of pseudorandom numbers. The class
-// uses a 48-bit seed, which is modified using a linear congruential formula.
-// (See Donald Knuth, The Art of Computer Programming, Volume 3, Section 3.2.1.)
+
+// This class is used to generate a stream of pseudo-random numbers. The class
+// uses a 64-bit seed, which is passed through MurmurHash3 to create two 64-bit
+// state values. This pair of state values is then used in xorshift128+.
+// The resulting stream of pseudo-random numbers has a period length of 2^128-1.
+// See Marsaglia: http://www.jstatsoft.org/v08/i14/paper
+// And Vigna: http://vigna.di.unimi.it/ftp/papers/xorshiftplus.pdf
+// NOTE: Any changes to the algorithm must be tested against TestU01.
+// Please find instructions for this in the internal repository.
+
// If two instances of RandomNumberGenerator are created with the same seed, and
// the same sequence of method calls is made for each, they will generate and
// return identical sequences of numbers.
@@ -25,7 +31,7 @@
// https://code.google.com/p/v8/issues/detail?id=2905
// This class is neither reentrant nor threadsafe.
-class RandomNumberGenerator FINAL {
+class RandomNumberGenerator final {
public:
// EntropySource is used as a callback function when V8 needs a source of
// entropy.
@@ -83,6 +89,27 @@
int64_t initial_seed() const { return initial_seed_; }
+ // Static and exposed for external use.
+ static inline double ToDouble(uint64_t state0, uint64_t state1) {
+ // Exponent for double values for [1.0 .. 2.0)
+ static const uint64_t kExponentBits = V8_UINT64_C(0x3FF0000000000000);
+ static const uint64_t kMantissaMask = V8_UINT64_C(0x000FFFFFFFFFFFFF);
+ uint64_t random = ((state0 + state1) & kMantissaMask) | kExponentBits;
+ return bit_cast<double>(random) - 1;
+ }
+
+ // Static and exposed for external use.
+ static inline void XorShift128(uint64_t* state0, uint64_t* state1) {
+ uint64_t s1 = *state0;
+ uint64_t s0 = *state1;
+ *state0 = s0;
+ s1 ^= s1 << 23;
+ s1 ^= s1 >> 17;
+ s1 ^= s0;
+ s1 ^= s0 >> 26;
+ *state1 = s1;
+ }
+
private:
static const int64_t kMultiplier = V8_2PART_UINT64_C(0x5, deece66d);
static const int64_t kAddend = 0xb;
@@ -90,10 +117,14 @@
int Next(int bits) WARN_UNUSED_RESULT;
+ static uint64_t MurmurHash3(uint64_t);
+
int64_t initial_seed_;
- int64_t seed_;
+ uint64_t state0_;
+ uint64_t state1_;
};
-} } // namespace v8::base
+} // namespace base
+} // namespace v8
#endif // V8_BASE_UTILS_RANDOM_NUMBER_GENERATOR_H_