diff options
author | Refael Ackermann <refack@gmail.com> | 2019-05-28 08:46:21 -0400 |
---|---|---|
committer | Refael Ackermann <refack@gmail.com> | 2019-06-01 09:55:12 -0400 |
commit | ed74896b1fae1c163b3906163f3bf46326618ddb (patch) | |
tree | 7fb05c5a19808e0c5cd95837528e9005999cf540 /deps/v8/src/base | |
parent | 2a850cd0664a4eee51f44d0bb8c2f7a3fe444154 (diff) | |
download | node-new-ed74896b1fae1c163b3906163f3bf46326618ddb.tar.gz |
deps: update V8 to 7.5.288.22
PR-URL: https://github.com/nodejs/node/pull/27375
Reviewed-By: Michaƫl Zasso <targos@protonmail.com>
Reviewed-By: Ujjwal Sharma <usharma1998@gmail.com>
Reviewed-By: Refael Ackermann <refack@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
Diffstat (limited to 'deps/v8/src/base')
39 files changed, 264 insertions, 1050 deletions
diff --git a/deps/v8/src/base/address-region.h b/deps/v8/src/base/address-region.h index 6b733cfe4d..1fdc479f6f 100644 --- a/deps/v8/src/base/address-region.h +++ b/deps/v8/src/base/address-region.h @@ -15,7 +15,7 @@ namespace base { // Helper class representing an address region of certain size. class AddressRegion { public: - typedef uintptr_t Address; + using Address = uintptr_t; AddressRegion() = default; diff --git a/deps/v8/src/base/atomicops.h b/deps/v8/src/base/atomicops.h index 4c7a5ebe0f..d0944c1df6 100644 --- a/deps/v8/src/base/atomicops.h +++ b/deps/v8/src/base/atomicops.h @@ -39,22 +39,22 @@ namespace v8 { namespace base { -typedef char Atomic8; -typedef int16_t Atomic16; -typedef int32_t Atomic32; +using Atomic8 = char; +using Atomic16 = int16_t; +using Atomic32 = int32_t; #if defined(V8_HOST_ARCH_64_BIT) // We need to be able to go between Atomic64 and AtomicWord implicitly. This // means Atomic64 and AtomicWord should be the same type on 64-bit. #if defined(__ILP32__) -typedef int64_t Atomic64; +using Atomic64 = int64_t; #else -typedef intptr_t Atomic64; +using Atomic64 = intptr_t; #endif // defined(__ILP32__) #endif // defined(V8_HOST_ARCH_64_BIT) // Use AtomicWord for a machine-sized pointer. It will use the Atomic32 or // Atomic64 routines below, depending on your architecture. -typedef intptr_t AtomicWord; +using AtomicWord = intptr_t; // Atomically execute: // result = *ptr; diff --git a/deps/v8/src/base/bits.cc b/deps/v8/src/base/bits.cc index c0db7d0457..7b6dd57d8f 100644 --- a/deps/v8/src/base/bits.cc +++ b/deps/v8/src/base/bits.cc @@ -7,7 +7,6 @@ #include <limits> #include "src/base/logging.h" -#include "src/base/safe_math.h" namespace v8 { namespace base { @@ -71,49 +70,30 @@ int32_t SignedMod32(int32_t lhs, int32_t rhs) { return lhs % rhs; } - -int64_t FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value) { - if (value.IsValid()) - return value.ValueUnsafe(); - - // We could return max/min but we don't really expose what the maximum delta - // is. Instead, return max/(-max), which is something that clients can reason - // about. - // TODO(rvargas) crbug.com/332611: don't use internal values. - int64_t limit = std::numeric_limits<int64_t>::max(); - if (value.validity() == internal::RANGE_UNDERFLOW) - limit = -limit; - return value.ValueOrDefault(limit); -} - - int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs) { - internal::CheckedNumeric<int64_t> rv(lhs); - rv += rhs; - return FromCheckedNumeric(rv); + using limits = std::numeric_limits<int64_t>; + // Underflow if {lhs + rhs < min}. In that case, return {min}. + if (rhs < 0 && lhs < limits::min() - rhs) return limits::min(); + // Overflow if {lhs + rhs > max}. In that case, return {max}. + if (rhs >= 0 && lhs > limits::max() - rhs) return limits::max(); + return lhs + rhs; } - int64_t SignedSaturatedSub64(int64_t lhs, int64_t rhs) { - internal::CheckedNumeric<int64_t> rv(lhs); - rv -= rhs; - return FromCheckedNumeric(rv); + using limits = std::numeric_limits<int64_t>; + // Underflow if {lhs - rhs < min}. In that case, return {min}. + if (rhs > 0 && lhs < limits::min() + rhs) return limits::min(); + // Overflow if {lhs - rhs > max}. In that case, return {max}. + if (rhs <= 0 && lhs > limits::max() + rhs) return limits::max(); + return lhs - rhs; } bool SignedMulOverflow32(int32_t lhs, int32_t rhs, int32_t* val) { - internal::CheckedNumeric<int32_t> rv(lhs); - rv *= rhs; - int32_t limit = std::numeric_limits<int32_t>::max(); - *val = rv.ValueOrDefault(limit); - return !rv.IsValid(); -} - -bool SignedMulOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { - internal::CheckedNumeric<int64_t> rv(lhs); - rv *= rhs; - int64_t limit = std::numeric_limits<int64_t>::max(); - *val = rv.ValueOrDefault(limit); - return !rv.IsValid(); + // Compute the result as {int64_t}, then check for overflow. + int64_t result = int64_t{lhs} * int64_t{rhs}; + *val = static_cast<int32_t>(result); + using limits = std::numeric_limits<int32_t>; + return result < limits::min() || result > limits::max(); } } // namespace bits diff --git a/deps/v8/src/base/bits.h b/deps/v8/src/base/bits.h index 147a1730b2..ac228b8ae1 100644 --- a/deps/v8/src/base/bits.h +++ b/deps/v8/src/base/bits.h @@ -19,12 +19,6 @@ namespace v8 { namespace base { - -namespace internal { -template <typename T> -class CheckedNumeric; -} - namespace bits { // CountPopulation(value) returns the number of bits set in |value|. @@ -242,11 +236,6 @@ inline bool SignedSubOverflow64(int64_t lhs, int64_t rhs, int64_t* val) { return ((res ^ lhs) & (res ^ ~rhs) & (1ULL << 63)) != 0; } -// SignedMulOverflow64(lhs,rhs,val) performs a signed multiplication of |lhs| -// and |rhs| and stores the result into the variable pointed to by |val| and -// returns true if the signed multiplication resulted in an overflow. -V8_BASE_EXPORT bool SignedMulOverflow64(int64_t lhs, int64_t rhs, int64_t* val); - // SignedMulHigh32(lhs, rhs) multiplies two signed 32-bit values |lhs| and // |rhs|, extracts the most significant 32 bits of the result, and returns // those. @@ -295,10 +284,6 @@ inline uint32_t UnsignedMod32(uint32_t lhs, uint32_t rhs) { } -// Clamp |value| on overflow and underflow conditions. -V8_BASE_EXPORT int64_t -FromCheckedNumeric(const internal::CheckedNumeric<int64_t> value); - // SignedSaturatedAdd64(lhs, rhs) adds |lhs| and |rhs|, // checks and returns the result. V8_BASE_EXPORT int64_t SignedSaturatedAdd64(int64_t lhs, int64_t rhs); diff --git a/deps/v8/src/base/bounded-page-allocator.h b/deps/v8/src/base/bounded-page-allocator.h index b1289c4c62..f1b85f23aa 100644 --- a/deps/v8/src/base/bounded-page-allocator.h +++ b/deps/v8/src/base/bounded-page-allocator.h @@ -25,7 +25,7 @@ namespace base { // The implementation is thread-safe. class V8_BASE_EXPORT BoundedPageAllocator : public v8::PageAllocator { public: - typedef uintptr_t Address; + using Address = uintptr_t; BoundedPageAllocator(v8::PageAllocator* page_allocator, Address start, size_t size, size_t allocate_page_size); diff --git a/deps/v8/src/base/build_config.h b/deps/v8/src/base/build_config.h index 88073dd520..f4300824eb 100644 --- a/deps/v8/src/base/build_config.h +++ b/deps/v8/src/base/build_config.h @@ -201,8 +201,12 @@ #define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK false #endif -// Number of bits to represent the page size for paged spaces. The value of 19 -// gives 512Kb bytes per page. +// Number of bits to represent the page size for paged spaces. +#if defined(V8_TARGET_ARCH_PPC) || defined(V8_TARGET_ARCH_PPC64) +// PPC has large (64KB) physical pages. const int kPageSizeBits = 19; +#else +const int kPageSizeBits = 18; +#endif #endif // V8_BASE_BUILD_CONFIG_H_ diff --git a/deps/v8/src/base/debug/stack_trace_win.cc b/deps/v8/src/base/debug/stack_trace_win.cc index 090137b9f0..f981bec610 100644 --- a/deps/v8/src/base/debug/stack_trace_win.cc +++ b/deps/v8/src/base/debug/stack_trace_win.cc @@ -16,11 +16,11 @@ #include <windows.h> #include <dbghelp.h> -#include <Shlwapi.h> #include <stddef.h> #include <iostream> #include <memory> +#include <string> #include "src/base/logging.h" #include "src/base/macros.h" @@ -49,12 +49,6 @@ long WINAPI StackDumpExceptionFilter(EXCEPTION_POINTERS* info) { // NOLINT return EXCEPTION_CONTINUE_SEARCH; } -void GetExePath(wchar_t* path_out) { - GetModuleFileName(nullptr, path_out, MAX_PATH); - path_out[MAX_PATH - 1] = L'\0'; - PathRemoveFileSpec(path_out); -} - bool InitializeSymbols() { if (g_initialized_symbols) return g_init_error == ERROR_SUCCESS; g_initialized_symbols = true; @@ -87,9 +81,13 @@ bool InitializeSymbols() { } wchar_t exe_path[MAX_PATH]; - GetExePath(exe_path); - std::wstring new_path(std::wstring(symbols_path.get()) + L";" + - std::wstring(exe_path)); + GetModuleFileName(nullptr, exe_path, MAX_PATH); + std::wstring exe_path_wstring(exe_path); + // To get the path without the filename, we just need to remove the final + // slash and everything after it. + std::wstring new_path( + std::wstring(symbols_path.get()) + L";" + + exe_path_wstring.substr(0, exe_path_wstring.find_last_of(L"\\/"))); if (!SymSetSearchPathW(GetCurrentProcess(), new_path.c_str())) { g_init_error = GetLastError(); return false; diff --git a/deps/v8/src/base/flags.h b/deps/v8/src/base/flags.h index c1637de81c..2c30fe7613 100644 --- a/deps/v8/src/base/flags.h +++ b/deps/v8/src/base/flags.h @@ -24,8 +24,8 @@ namespace base { template <typename T, typename S = int> class Flags final { public: - typedef T flag_type; - typedef S mask_type; + using flag_type = T; + using mask_type = S; constexpr Flags() : mask_(0) {} constexpr Flags(flag_type flag) // NOLINT(runtime/explicit) diff --git a/deps/v8/src/base/hashmap.h b/deps/v8/src/base/hashmap.h index d2b5810c1c..4ad946d0dd 100644 --- a/deps/v8/src/base/hashmap.h +++ b/deps/v8/src/base/hashmap.h @@ -27,7 +27,7 @@ class DefaultAllocationPolicy { template <typename Key, typename Value, class MatchFun, class AllocationPolicy> class TemplateHashMapImpl { public: - typedef TemplateHashMapEntry<Key, Value> Entry; + using Entry = TemplateHashMapEntry<Key, Value>; // The default capacity. This is used by the call sites which want // to pass in a non-default AllocationPolicy but want to use the @@ -389,13 +389,12 @@ class CustomMatcherTemplateHashMapImpl void*, void*, HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>, AllocationPolicy> { - typedef TemplateHashMapImpl< + using Base = TemplateHashMapImpl< void*, void*, HashEqualityThenKeyMatcher<void*, bool (*)(void*, void*)>, - AllocationPolicy> - Base; + AllocationPolicy>; public: - typedef bool (*MatchFun)(void*, void*); + using MatchFun = bool (*)(void*, void*); CustomMatcherTemplateHashMapImpl( MatchFun match, uint32_t capacity = Base::kDefaultHashMapCapacity, @@ -412,8 +411,8 @@ class CustomMatcherTemplateHashMapImpl DISALLOW_COPY_AND_ASSIGN(CustomMatcherTemplateHashMapImpl); }; -typedef CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy> - CustomMatcherHashMap; +using CustomMatcherHashMap = + CustomMatcherTemplateHashMapImpl<DefaultAllocationPolicy>; // Match function which compares keys directly by equality. template <typename Key> @@ -429,9 +428,8 @@ template <typename AllocationPolicy> class PointerTemplateHashMapImpl : public TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>, AllocationPolicy> { - typedef TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>, - AllocationPolicy> - Base; + using Base = TemplateHashMapImpl<void*, void*, KeyEqualityMatcher<void*>, + AllocationPolicy>; public: PointerTemplateHashMapImpl(uint32_t capacity = Base::kDefaultHashMapCapacity, @@ -439,7 +437,7 @@ class PointerTemplateHashMapImpl : Base(capacity, KeyEqualityMatcher<void*>(), allocator) {} }; -typedef PointerTemplateHashMapImpl<DefaultAllocationPolicy> HashMap; +using HashMap = PointerTemplateHashMapImpl<DefaultAllocationPolicy>; // A hash map for pointer keys and values with an STL-like interface. template <class Key, class Value, class MatchFun, class AllocationPolicy> @@ -447,10 +445,9 @@ class TemplateHashMap : private TemplateHashMapImpl<void*, void*, HashEqualityThenKeyMatcher<void*, MatchFun>, AllocationPolicy> { - typedef TemplateHashMapImpl<void*, void*, - HashEqualityThenKeyMatcher<void*, MatchFun>, - AllocationPolicy> - Base; + using Base = TemplateHashMapImpl<void*, void*, + HashEqualityThenKeyMatcher<void*, MatchFun>, + AllocationPolicy>; public: STATIC_ASSERT(sizeof(Key*) == sizeof(void*)); // NOLINT diff --git a/deps/v8/src/base/ieee754.cc b/deps/v8/src/base/ieee754.cc index 4fcb4df001..7bdac9e67e 100644 --- a/deps/v8/src/base/ieee754.cc +++ b/deps/v8/src/base/ieee754.cc @@ -57,7 +57,7 @@ namespace { #if V8_TARGET_LITTLE_ENDIAN -typedef union { +union ieee_double_shape_type { double value; struct { uint32_t lsw; @@ -66,11 +66,11 @@ typedef union { struct { uint64_t w; } xparts; -} ieee_double_shape_type; +}; #else -typedef union { +union ieee_double_shape_type { double value; struct { uint32_t msw; @@ -79,7 +79,7 @@ typedef union { struct { uint64_t w; } xparts; -} ieee_double_shape_type; +}; #endif diff --git a/deps/v8/src/base/iterator.h b/deps/v8/src/base/iterator.h index 59d9fda6f1..b081af62ae 100644 --- a/deps/v8/src/base/iterator.h +++ b/deps/v8/src/base/iterator.h @@ -13,11 +13,11 @@ namespace base { template <class Category, class Type, class Diff = std::ptrdiff_t, class Pointer = Type*, class Reference = Type&> struct iterator { - typedef Category iterator_category; - typedef Type value_type; - typedef Diff difference_type; - typedef Pointer pointer; - typedef Reference reference; + using iterator_category = Category; + using value_type = Type; + using difference_type = Diff; + using pointer = Pointer; + using reference = Reference; }; // The intention of the base::iterator_range class is to encapsulate two @@ -27,13 +27,13 @@ struct iterator { template <typename ForwardIterator> class iterator_range { public: - typedef ForwardIterator iterator; - typedef ForwardIterator const_iterator; - typedef typename std::iterator_traits<iterator>::pointer pointer; - typedef typename std::iterator_traits<iterator>::reference reference; - typedef typename std::iterator_traits<iterator>::value_type value_type; - typedef - typename std::iterator_traits<iterator>::difference_type difference_type; + using iterator = ForwardIterator; + using const_iterator = ForwardIterator; + using pointer = typename std::iterator_traits<iterator>::pointer; + using reference = typename std::iterator_traits<iterator>::reference; + using value_type = typename std::iterator_traits<iterator>::value_type; + using difference_type = + typename std::iterator_traits<iterator>::difference_type; iterator_range() : begin_(), end_() {} template <typename ForwardIterator1, typename ForwardIterator2> diff --git a/deps/v8/src/base/lazy-instance.h b/deps/v8/src/base/lazy-instance.h index bebb4e1bdc..3ea5fc9575 100644 --- a/deps/v8/src/base/lazy-instance.h +++ b/deps/v8/src/base/lazy-instance.h @@ -199,8 +199,8 @@ template <typename T, typename InitOnceTrait = ThreadSafeInitOnceTrait, typename DestroyTrait = LeakyInstanceTrait<T> > struct LazyStaticInstance { - typedef LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>, - CreateTrait, InitOnceTrait, DestroyTrait> type; + using type = LazyInstanceImpl<T, StaticallyAllocatedInstanceTrait<T>, + CreateTrait, InitOnceTrait, DestroyTrait>; }; @@ -210,8 +210,8 @@ template <typename T, typename DestroyTrait = LeakyInstanceTrait<T> > struct LazyInstance { // A LazyInstance is a LazyStaticInstance. - typedef typename LazyStaticInstance<T, CreateTrait, InitOnceTrait, - DestroyTrait>::type type; + using type = typename LazyStaticInstance<T, CreateTrait, InitOnceTrait, + DestroyTrait>::type; }; @@ -220,8 +220,8 @@ template <typename T, typename InitOnceTrait = ThreadSafeInitOnceTrait, typename DestroyTrait = LeakyInstanceTrait<T> > struct LazyDynamicInstance { - typedef LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>, - CreateTrait, InitOnceTrait, DestroyTrait> type; + using type = LazyInstanceImpl<T, DynamicallyAllocatedInstanceTrait<T>, + CreateTrait, InitOnceTrait, DestroyTrait>; }; // LeakyObject<T> wraps an object of type T, which is initialized in the diff --git a/deps/v8/src/base/once.cc b/deps/v8/src/base/once.cc index 3e5e21925d..dbf6500746 100644 --- a/deps/v8/src/base/once.cc +++ b/deps/v8/src/base/once.cc @@ -10,15 +10,12 @@ #include <sched.h> #endif -#include "src/base/atomicops.h" - namespace v8 { namespace base { void CallOnceImpl(OnceType* once, std::function<void()> init_func) { - AtomicWord state = Acquire_Load(once); // Fast path. The provided function was already executed. - if (state == ONCE_STATE_DONE) { + if (once->load(std::memory_order_acquire) == ONCE_STATE_DONE) { return; } @@ -29,23 +26,23 @@ void CallOnceImpl(OnceType* once, std::function<void()> init_func) { // // First, try to change the state from UNINITIALIZED to EXECUTING_FUNCTION // atomically. - state = Acquire_CompareAndSwap( - once, ONCE_STATE_UNINITIALIZED, ONCE_STATE_EXECUTING_FUNCTION); - if (state == ONCE_STATE_UNINITIALIZED) { + uint8_t expected = ONCE_STATE_UNINITIALIZED; + if (once->compare_exchange_strong(expected, ONCE_STATE_EXECUTING_FUNCTION, + std::memory_order_acq_rel)) { // We are the first thread to call this function, so we have to call the // function. init_func(); - Release_Store(once, ONCE_STATE_DONE); + once->store(ONCE_STATE_DONE, std::memory_order_release); } else { // Another thread has already started executing the function. We need to // wait until it completes the initialization. - while (state == ONCE_STATE_EXECUTING_FUNCTION) { + while (once->load(std::memory_order_acquire) == + ONCE_STATE_EXECUTING_FUNCTION) { #ifdef _WIN32 ::Sleep(0); #else sched_yield(); #endif - state = Acquire_Load(once); } } } diff --git a/deps/v8/src/base/once.h b/deps/v8/src/base/once.h index f355ef52ae..dd8b6be621 100644 --- a/deps/v8/src/base/once.h +++ b/deps/v8/src/base/once.h @@ -53,48 +53,47 @@ #define V8_BASE_ONCE_H_ #include <stddef.h> +#include <atomic> #include <functional> -#include "src/base/atomicops.h" #include "src/base/base-export.h" namespace v8 { namespace base { -typedef AtomicWord OnceType; +using OnceType = std::atomic<uint8_t>; -#define V8_ONCE_INIT 0 +#define V8_ONCE_INIT \ + { 0 } #define V8_DECLARE_ONCE(NAME) ::v8::base::OnceType NAME -enum { +enum : uint8_t { ONCE_STATE_UNINITIALIZED = 0, ONCE_STATE_EXECUTING_FUNCTION = 1, ONCE_STATE_DONE = 2 }; -typedef void (*NoArgFunction)(); -typedef void (*PointerArgFunction)(void* arg); +using PointerArgFunction = void (*)(void* arg); template <typename T> struct OneArgFunction { - typedef void (*type)(T); + using type = void (*)(T); }; V8_BASE_EXPORT void CallOnceImpl(OnceType* once, std::function<void()> init_func); -inline void CallOnce(OnceType* once, NoArgFunction init_func) { - if (Acquire_Load(once) != ONCE_STATE_DONE) { +inline void CallOnce(OnceType* once, std::function<void()> init_func) { + if (once->load(std::memory_order_acquire) != ONCE_STATE_DONE) { CallOnceImpl(once, init_func); } } - template <typename Arg> inline void CallOnce(OnceType* once, typename OneArgFunction<Arg*>::type init_func, Arg* arg) { - if (Acquire_Load(once) != ONCE_STATE_DONE) { + if (once->load(std::memory_order_acquire) != ONCE_STATE_DONE) { CallOnceImpl(once, [=]() { init_func(arg); }); } } diff --git a/deps/v8/src/base/optional.h b/deps/v8/src/base/optional.h index 9cadc0fb0b..b8df88d844 100644 --- a/deps/v8/src/base/optional.h +++ b/deps/v8/src/base/optional.h @@ -304,7 +304,7 @@ struct CopyConstructible {}; template <> struct CopyConstructible<false> { constexpr CopyConstructible() = default; - constexpr CopyConstructible(const CopyConstructible&) = delete; + constexpr CopyConstructible(const CopyConstructible&) V8_NOEXCEPT = delete; constexpr CopyConstructible(CopyConstructible&&) V8_NOEXCEPT = default; CopyConstructible& operator=(const CopyConstructible&) V8_NOEXCEPT = default; CopyConstructible& operator=(CopyConstructible&&) V8_NOEXCEPT = default; @@ -317,7 +317,7 @@ template <> struct MoveConstructible<false> { constexpr MoveConstructible() = default; constexpr MoveConstructible(const MoveConstructible&) V8_NOEXCEPT = default; - constexpr MoveConstructible(MoveConstructible&&) = delete; + constexpr MoveConstructible(MoveConstructible&&) V8_NOEXCEPT = delete; MoveConstructible& operator=(const MoveConstructible&) V8_NOEXCEPT = default; MoveConstructible& operator=(MoveConstructible&&) V8_NOEXCEPT = default; }; @@ -330,7 +330,7 @@ struct CopyAssignable<false> { constexpr CopyAssignable() = default; constexpr CopyAssignable(const CopyAssignable&) V8_NOEXCEPT = default; constexpr CopyAssignable(CopyAssignable&&) V8_NOEXCEPT = default; - CopyAssignable& operator=(const CopyAssignable&) = delete; + CopyAssignable& operator=(const CopyAssignable&) V8_NOEXCEPT = delete; CopyAssignable& operator=(CopyAssignable&&) V8_NOEXCEPT = default; }; @@ -343,7 +343,7 @@ struct MoveAssignable<false> { constexpr MoveAssignable(const MoveAssignable&) V8_NOEXCEPT = default; constexpr MoveAssignable(MoveAssignable&&) V8_NOEXCEPT = default; MoveAssignable& operator=(const MoveAssignable&) V8_NOEXCEPT = default; - MoveAssignable& operator=(MoveAssignable&&) = delete; + MoveAssignable& operator=(MoveAssignable&&) V8_NOEXCEPT = delete; }; // Helper to conditionally enable converting constructors and assign operators. diff --git a/deps/v8/src/base/overflowing-math.h b/deps/v8/src/base/overflowing-math.h index fa197a886c..7ca58aefec 100644 --- a/deps/v8/src/base/overflowing-math.h +++ b/deps/v8/src/base/overflowing-math.h @@ -24,7 +24,7 @@ namespace base { template <typename signed_type> \ inline signed_type Name##WithWraparound(signed_type a, signed_type b) { \ ASSERT_SIGNED_INTEGER_TYPE(signed_type); \ - typedef typename std::make_unsigned<signed_type>::type unsigned_type; \ + using unsigned_type = typename std::make_unsigned<signed_type>::type; \ unsigned_type a_unsigned = static_cast<unsigned_type>(a); \ unsigned_type b_unsigned = static_cast<unsigned_type>(b); \ unsigned_type result = a_unsigned OP b_unsigned; \ @@ -57,7 +57,7 @@ inline signed_type NegateWithWraparound(signed_type a) { template <typename signed_type> inline signed_type ShlWithWraparound(signed_type a, signed_type b) { ASSERT_SIGNED_INTEGER_TYPE(signed_type); - typedef typename std::make_unsigned<signed_type>::type unsigned_type; + using unsigned_type = typename std::make_unsigned<signed_type>::type; const unsigned_type kMask = (sizeof(a) * 8) - 1; return static_cast<signed_type>(static_cast<unsigned_type>(a) << (b & kMask)); } diff --git a/deps/v8/src/base/platform/condition-variable.h b/deps/v8/src/base/platform/condition-variable.h index 2cdcb07b59..e864f32872 100644 --- a/deps/v8/src/base/platform/condition-variable.h +++ b/deps/v8/src/base/platform/condition-variable.h @@ -61,9 +61,9 @@ class V8_BASE_EXPORT ConditionVariable final { // The implementation-defined native handle type. #if V8_OS_POSIX - typedef pthread_cond_t NativeHandle; + using NativeHandle = pthread_cond_t; #elif V8_OS_WIN - typedef CONDITION_VARIABLE NativeHandle; + using NativeHandle = CONDITION_VARIABLE; #endif NativeHandle& native_handle() { @@ -89,9 +89,10 @@ class V8_BASE_EXPORT ConditionVariable final { // MutexGuard lock_guard(&my_mutex); // my_condvar.Pointer()->Wait(&my_mutex); // } -typedef LazyStaticInstance< - ConditionVariable, DefaultConstructTrait<ConditionVariable>, - ThreadSafeInitOnceTrait>::type LazyConditionVariable; +using LazyConditionVariable = + LazyStaticInstance<ConditionVariable, + DefaultConstructTrait<ConditionVariable>, + ThreadSafeInitOnceTrait>::type; #define LAZY_CONDITION_VARIABLE_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER diff --git a/deps/v8/src/base/platform/mutex.h b/deps/v8/src/base/platform/mutex.h index ea589d5b98..2b8b55eeb5 100644 --- a/deps/v8/src/base/platform/mutex.h +++ b/deps/v8/src/base/platform/mutex.h @@ -55,9 +55,9 @@ class V8_BASE_EXPORT Mutex final { // The implementation-defined native handle type. #if V8_OS_POSIX - typedef pthread_mutex_t NativeHandle; + using NativeHandle = pthread_mutex_t; #elif V8_OS_WIN - typedef SRWLOCK NativeHandle; + using NativeHandle = SRWLOCK; #endif NativeHandle& native_handle() { @@ -101,8 +101,8 @@ class V8_BASE_EXPORT Mutex final { // // Do something. // } // -typedef LazyStaticInstance<Mutex, DefaultConstructTrait<Mutex>, - ThreadSafeInitOnceTrait>::type LazyMutex; +using LazyMutex = LazyStaticInstance<Mutex, DefaultConstructTrait<Mutex>, + ThreadSafeInitOnceTrait>::type; #define LAZY_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER @@ -153,9 +153,9 @@ class V8_BASE_EXPORT RecursiveMutex final { private: // The implementation-defined native handle type. #if V8_OS_POSIX - typedef pthread_mutex_t NativeHandle; + using NativeHandle = pthread_mutex_t; #elif V8_OS_WIN - typedef CRITICAL_SECTION NativeHandle; + using NativeHandle = CRITICAL_SECTION; #endif NativeHandle native_handle_; @@ -177,9 +177,9 @@ class V8_BASE_EXPORT RecursiveMutex final { // // Do something. // } // -typedef LazyStaticInstance<RecursiveMutex, - DefaultConstructTrait<RecursiveMutex>, - ThreadSafeInitOnceTrait>::type LazyRecursiveMutex; +using LazyRecursiveMutex = + LazyStaticInstance<RecursiveMutex, DefaultConstructTrait<RecursiveMutex>, + ThreadSafeInitOnceTrait>::type; #define LAZY_RECURSIVE_MUTEX_INITIALIZER LAZY_STATIC_INSTANCE_INITIALIZER @@ -241,9 +241,9 @@ class V8_BASE_EXPORT SharedMutex final { private: // The implementation-defined native handle type. #if V8_OS_POSIX - typedef pthread_rwlock_t NativeHandle; + using NativeHandle = pthread_rwlock_t; #elif V8_OS_WIN - typedef SRWLOCK NativeHandle; + using NativeHandle = SRWLOCK; #endif NativeHandle native_handle_; diff --git a/deps/v8/src/base/platform/platform-aix.cc b/deps/v8/src/base/platform/platform-aix.cc index 406462cdd2..e3d7c426b4 100644 --- a/deps/v8/src/base/platform/platform-aix.cc +++ b/deps/v8/src/base/platform/platform-aix.cc @@ -127,5 +127,7 @@ std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { void OS::SignalCodeMovingGC() {} +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-cygwin.cc b/deps/v8/src/base/platform/platform-cygwin.cc index f2976301ed..17f9aa3f17 100644 --- a/deps/v8/src/base/platform/platform-cygwin.cc +++ b/deps/v8/src/base/platform/platform-cygwin.cc @@ -268,5 +268,7 @@ void OS::SignalCodeMovingGC() { // Nothing to do on Cygwin. } +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-freebsd.cc b/deps/v8/src/base/platform/platform-freebsd.cc index 2b9779b843..d40452f3d4 100644 --- a/deps/v8/src/base/platform/platform-freebsd.cc +++ b/deps/v8/src/base/platform/platform-freebsd.cc @@ -86,5 +86,7 @@ std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { void OS::SignalCodeMovingGC() {} +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-fuchsia.cc b/deps/v8/src/base/platform/platform-fuchsia.cc index 7dd29dc39e..5d878c91a6 100644 --- a/deps/v8/src/base/platform/platform-fuchsia.cc +++ b/deps/v8/src/base/platform/platform-fuchsia.cc @@ -163,5 +163,7 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { return 0; } +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-linux.cc b/deps/v8/src/base/platform/platform-linux.cc index 10815f29c5..059f393eb6 100644 --- a/deps/v8/src/base/platform/platform-linux.cc +++ b/deps/v8/src/base/platform/platform-linux.cc @@ -172,5 +172,7 @@ void OS::SignalCodeMovingGC() { fclose(f); } +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-macos.cc b/deps/v8/src/base/platform/platform-macos.cc index 081e434589..72a41c8491 100644 --- a/deps/v8/src/base/platform/platform-macos.cc +++ b/deps/v8/src/base/platform/platform-macos.cc @@ -73,5 +73,25 @@ TimezoneCache* OS::CreateTimezoneCache() { return new PosixDefaultTimezoneCache(); } +void OS::AdjustSchedulingParams() { +#if V8_TARGET_ARCH_X64 || V8_TARGET_ARCH_IA32 + { + // Check availability of scheduling params. + uint32_t val = 0; + size_t valSize = sizeof(val); + int rc = sysctlbyname("kern.tcsm_available", &val, &valSize, NULL, 0); + if (rc < 0 || !val) return; + } + + { + // Adjust scheduling params. + uint32_t val = 1; + int rc = sysctlbyname("kern.tcsm_enable", NULL, NULL, &val, sizeof(val)); + DCHECK_GE(rc, 0); + USE(rc); + } +#endif +} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-openbsd.cc b/deps/v8/src/base/platform/platform-openbsd.cc index 9084c3075e..c133ffb68d 100644 --- a/deps/v8/src/base/platform/platform-openbsd.cc +++ b/deps/v8/src/base/platform/platform-openbsd.cc @@ -120,5 +120,7 @@ void OS::SignalCodeMovingGC() { fclose(f); } +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-posix.cc b/deps/v8/src/base/platform/platform-posix.cc index 33a9371a92..2301c26688 100644 --- a/deps/v8/src/base/platform/platform-posix.cc +++ b/deps/v8/src/base/platform/platform-posix.cc @@ -43,7 +43,7 @@ #include "src/base/utils/random-number-generator.h" #ifdef V8_FAST_TLS_SUPPORTED -#include "src/base/atomicops.h" +#include <atomic> #endif #if V8_OS_MACOSX @@ -444,15 +444,22 @@ class PosixMemoryMappedFile final : public OS::MemoryMappedFile { // static -OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { - if (FILE* file = fopen(name, "r+")) { +OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name, + FileMode mode) { + const char* fopen_mode = (mode == FileMode::kReadOnly) ? "r" : "r+"; + if (FILE* file = fopen(name, fopen_mode)) { if (fseek(file, 0, SEEK_END) == 0) { long size = ftell(file); // NOLINT(runtime/int) if (size == 0) return new PosixMemoryMappedFile(file, nullptr, 0); if (size > 0) { + int prot = PROT_READ; + int flags = MAP_PRIVATE; + if (mode == FileMode::kReadWrite) { + prot |= PROT_WRITE; + flags = MAP_SHARED; + } void* const memory = - mmap(OS::GetRandomMmapAddr(), size, PROT_READ | PROT_WRITE, - MAP_SHARED, fileno(file), 0); + mmap(OS::GetRandomMmapAddr(), size, prot, flags, fileno(file), 0); if (memory != MAP_FAILED) { return new PosixMemoryMappedFile(file, memory, size); } @@ -463,7 +470,6 @@ OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { return nullptr; } - // static OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, size_t size, void* initial) { @@ -815,7 +821,7 @@ static pthread_key_t LocalKeyToPthreadKey(Thread::LocalStorageKey local_key) { #ifdef V8_FAST_TLS_SUPPORTED -static Atomic32 tls_base_offset_initialized = 0; +static std::atomic<bool> tls_base_offset_initialized{false}; intptr_t kMacTlsBaseOffset = 0; // It's safe to do the initialization more that once, but it has to be @@ -851,7 +857,7 @@ static void InitializeTlsBaseOffset() { kMacTlsBaseOffset = 0; } - Release_Store(&tls_base_offset_initialized, 1); + tls_base_offset_initialized.store(true, std::memory_order_release); } @@ -871,7 +877,7 @@ static void CheckFastTls(Thread::LocalStorageKey key) { Thread::LocalStorageKey Thread::CreateThreadLocalKey() { #ifdef V8_FAST_TLS_SUPPORTED bool check_fast_tls = false; - if (tls_base_offset_initialized == 0) { + if (!tls_base_offset_initialized.load(std::memory_order_acquire)) { check_fast_tls = true; InitializeTlsBaseOffset(); } diff --git a/deps/v8/src/base/platform/platform-qnx.cc b/deps/v8/src/base/platform/platform-qnx.cc index 640b77c816..f1ba3c6d45 100644 --- a/deps/v8/src/base/platform/platform-qnx.cc +++ b/deps/v8/src/base/platform/platform-qnx.cc @@ -146,5 +146,7 @@ std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { void OS::SignalCodeMovingGC() {} +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-solaris.cc b/deps/v8/src/base/platform/platform-solaris.cc index 477149db1b..b5b16dac56 100644 --- a/deps/v8/src/base/platform/platform-solaris.cc +++ b/deps/v8/src/base/platform/platform-solaris.cc @@ -63,5 +63,7 @@ std::vector<OS::SharedLibraryAddress> OS::GetSharedLibraryAddresses() { void OS::SignalCodeMovingGC() {} +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform-win32.cc b/deps/v8/src/base/platform/platform-win32.cc index c82ec5335a..6dc2053fcd 100644 --- a/deps/v8/src/base/platform/platform-win32.cc +++ b/deps/v8/src/base/platform/platform-win32.cc @@ -973,27 +973,34 @@ class Win32MemoryMappedFile final : public OS::MemoryMappedFile { // static -OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name) { +OS::MemoryMappedFile* OS::MemoryMappedFile::open(const char* name, + FileMode mode) { // Open a physical file. - HANDLE file = CreateFileA(name, GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, - OPEN_EXISTING, 0, nullptr); + DWORD access = GENERIC_READ; + if (mode == FileMode::kReadWrite) { + access |= GENERIC_WRITE; + } + HANDLE file = CreateFileA(name, access, FILE_SHARE_READ | FILE_SHARE_WRITE, + nullptr, OPEN_EXISTING, 0, nullptr); if (file == INVALID_HANDLE_VALUE) return nullptr; DWORD size = GetFileSize(file, nullptr); if (size == 0) return new Win32MemoryMappedFile(file, nullptr, nullptr, 0); + DWORD protection = + (mode == FileMode::kReadOnly) ? PAGE_READONLY : PAGE_READWRITE; // Create a file mapping for the physical file. HANDLE file_mapping = - CreateFileMapping(file, nullptr, PAGE_READWRITE, 0, size, nullptr); + CreateFileMapping(file, nullptr, protection, 0, size, nullptr); if (file_mapping == nullptr) return nullptr; // Map a view of the file into memory. - void* memory = MapViewOfFile(file_mapping, FILE_MAP_ALL_ACCESS, 0, 0, size); + DWORD view_access = + (mode == FileMode::kReadOnly) ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS; + void* memory = MapViewOfFile(file_mapping, view_access, 0, 0, size); return new Win32MemoryMappedFile(file, file_mapping, memory, size); } - // static OS::MemoryMappedFile* OS::MemoryMappedFile::create(const char* name, size_t size, void* initial) { @@ -1065,58 +1072,44 @@ Win32MemoryMappedFile::~Win32MemoryMappedFile() { // DbgHelp isn't supported on MinGW yet #ifndef __MINGW32__ // DbgHelp.h functions. -typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymInitialize))(IN HANDLE hProcess, - IN PSTR UserSearchPath, - IN BOOL fInvadeProcess); -typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymGetOptions))(VOID); -typedef DWORD (__stdcall *DLL_FUNC_TYPE(SymSetOptions))(IN DWORD SymOptions); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSearchPath))( - IN HANDLE hProcess, - OUT PSTR SearchPath, - IN DWORD SearchPathLength); -typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymLoadModule64))( - IN HANDLE hProcess, - IN HANDLE hFile, - IN PSTR ImageName, - IN PSTR ModuleName, - IN DWORD64 BaseOfDll, - IN DWORD SizeOfDll); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(StackWalk64))( - DWORD MachineType, - HANDLE hProcess, - HANDLE hThread, - LPSTACKFRAME64 StackFrame, - PVOID ContextRecord, +using DLL_FUNC_TYPE(SymInitialize) = BOOL(__stdcall*)(IN HANDLE hProcess, + IN PSTR UserSearchPath, + IN BOOL fInvadeProcess); +using DLL_FUNC_TYPE(SymGetOptions) = DWORD(__stdcall*)(VOID); +using DLL_FUNC_TYPE(SymSetOptions) = DWORD(__stdcall*)(IN DWORD SymOptions); +using DLL_FUNC_TYPE(SymGetSearchPath) = BOOL(__stdcall*)( + IN HANDLE hProcess, OUT PSTR SearchPath, IN DWORD SearchPathLength); +using DLL_FUNC_TYPE(SymLoadModule64) = DWORD64(__stdcall*)( + IN HANDLE hProcess, IN HANDLE hFile, IN PSTR ImageName, IN PSTR ModuleName, + IN DWORD64 BaseOfDll, IN DWORD SizeOfDll); +using DLL_FUNC_TYPE(StackWalk64) = BOOL(__stdcall*)( + DWORD MachineType, HANDLE hProcess, HANDLE hThread, + LPSTACKFRAME64 StackFrame, PVOID ContextRecord, PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetSymFromAddr64))( - IN HANDLE hProcess, - IN DWORD64 qwAddr, - OUT PDWORD64 pdwDisplacement, +using DLL_FUNC_TYPE(SymGetSymFromAddr64) = BOOL(__stdcall*)( + IN HANDLE hProcess, IN DWORD64 qwAddr, OUT PDWORD64 pdwDisplacement, OUT PIMAGEHLP_SYMBOL64 Symbol); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(SymGetLineFromAddr64))( - IN HANDLE hProcess, - IN DWORD64 qwAddr, - OUT PDWORD pdwDisplacement, - OUT PIMAGEHLP_LINE64 Line64); +using DLL_FUNC_TYPE(SymGetLineFromAddr64) = + BOOL(__stdcall*)(IN HANDLE hProcess, IN DWORD64 qwAddr, + OUT PDWORD pdwDisplacement, OUT PIMAGEHLP_LINE64 Line64); // DbgHelp.h typedefs. Implementation found in dbghelp.dll. -typedef PVOID (__stdcall *DLL_FUNC_TYPE(SymFunctionTableAccess64))( +using DLL_FUNC_TYPE(SymFunctionTableAccess64) = PVOID(__stdcall*)( HANDLE hProcess, DWORD64 AddrBase); // DbgHelp.h typedef PFUNCTION_TABLE_ACCESS_ROUTINE64 -typedef DWORD64 (__stdcall *DLL_FUNC_TYPE(SymGetModuleBase64))( +using DLL_FUNC_TYPE(SymGetModuleBase64) = DWORD64(__stdcall*)( HANDLE hProcess, DWORD64 AddrBase); // DbgHelp.h typedef PGET_MODULE_BASE_ROUTINE64 // TlHelp32.h functions. -typedef HANDLE (__stdcall *DLL_FUNC_TYPE(CreateToolhelp32Snapshot))( - DWORD dwFlags, - DWORD th32ProcessID); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32FirstW))(HANDLE hSnapshot, - LPMODULEENTRY32W lpme); -typedef BOOL (__stdcall *DLL_FUNC_TYPE(Module32NextW))(HANDLE hSnapshot, +using DLL_FUNC_TYPE(CreateToolhelp32Snapshot) = + HANDLE(__stdcall*)(DWORD dwFlags, DWORD th32ProcessID); +using DLL_FUNC_TYPE(Module32FirstW) = BOOL(__stdcall*)(HANDLE hSnapshot, LPMODULEENTRY32W lpme); +using DLL_FUNC_TYPE(Module32NextW) = BOOL(__stdcall*)(HANDLE hSnapshot, + LPMODULEENTRY32W lpme); #undef IN #undef VOID @@ -1404,5 +1397,7 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) { DCHECK(result); } +void OS::AdjustSchedulingParams() {} + } // namespace base } // namespace v8 diff --git a/deps/v8/src/base/platform/platform.h b/deps/v8/src/base/platform/platform.h index e51d5cd547..78b1bcbaff 100644 --- a/deps/v8/src/base/platform/platform.h +++ b/deps/v8/src/base/platform/platform.h @@ -188,11 +188,14 @@ class V8_BASE_EXPORT OS { class V8_BASE_EXPORT MemoryMappedFile { public: + enum class FileMode { kReadOnly, kReadWrite }; + virtual ~MemoryMappedFile() = default; virtual void* memory() const = 0; virtual size_t size() const = 0; - static MemoryMappedFile* open(const char* name); + static MemoryMappedFile* open(const char* name, + FileMode mode = FileMode::kReadWrite); static MemoryMappedFile* create(const char* name, size_t size, void* initial); }; @@ -246,6 +249,8 @@ class V8_BASE_EXPORT OS { static int GetCurrentThreadId(); + static void AdjustSchedulingParams(); + static void ExitProcess(int exit_code); private: @@ -308,7 +313,7 @@ inline void EnsureConsoleOutput() { class V8_BASE_EXPORT Thread { public: // Opaque data type for thread-local storage keys. - typedef int32_t LocalStorageKey; + using LocalStorageKey = int32_t; class Options { public: diff --git a/deps/v8/src/base/platform/semaphore.h b/deps/v8/src/base/platform/semaphore.h index 62c9c93988..11ff0b9199 100644 --- a/deps/v8/src/base/platform/semaphore.h +++ b/deps/v8/src/base/platform/semaphore.h @@ -50,11 +50,11 @@ class V8_BASE_EXPORT Semaphore final { bool WaitFor(const TimeDelta& rel_time) V8_WARN_UNUSED_RESULT; #if V8_OS_MACOSX - typedef semaphore_t NativeHandle; + using NativeHandle = semaphore_t; #elif V8_OS_POSIX - typedef sem_t NativeHandle; + using NativeHandle = sem_t; #elif V8_OS_WIN - typedef HANDLE NativeHandle; + using NativeHandle = HANDLE; #endif NativeHandle& native_handle() { @@ -90,8 +90,8 @@ struct CreateSemaphoreTrait { template <int N> struct LazySemaphore { - typedef typename LazyDynamicInstance<Semaphore, CreateSemaphoreTrait<N>, - ThreadSafeInitOnceTrait>::type type; + using typename LazyDynamicInstance<Semaphore, CreateSemaphoreTrait<N>, + ThreadSafeInitOnceTrait>::type; }; #define LAZY_SEMAPHORE_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER diff --git a/deps/v8/src/base/platform/time.cc b/deps/v8/src/base/platform/time.cc index 5339e14ade..ecbd70fd74 100644 --- a/deps/v8/src/base/platform/time.cc +++ b/deps/v8/src/base/platform/time.cc @@ -19,7 +19,6 @@ #include <ostream> #if V8_OS_WIN -#include "src/base/atomicops.h" #include "src/base/lazy-instance.h" #include "src/base/win32-headers.h" #endif @@ -40,13 +39,23 @@ int64_t ComputeThreadTicks() { &thread_info_count); CHECK_EQ(kr, KERN_SUCCESS); - v8::base::CheckedNumeric<int64_t> absolute_micros( - thread_info_data.user_time.seconds + - thread_info_data.system_time.seconds); - absolute_micros *= v8::base::Time::kMicrosecondsPerSecond; - absolute_micros += (thread_info_data.user_time.microseconds + - thread_info_data.system_time.microseconds); - return absolute_micros.ValueOrDie(); + // We can add the seconds into a {int64_t} without overflow. + CHECK_LE(thread_info_data.user_time.seconds, + std::numeric_limits<int64_t>::max() - + thread_info_data.system_time.seconds); + int64_t seconds = + thread_info_data.user_time.seconds + thread_info_data.system_time.seconds; + // Multiplying the seconds by {kMicrosecondsPerSecond}, and adding something + // in [0, 2 * kMicrosecondsPerSecond) must result in a valid {int64_t}. + static constexpr int64_t kSecondsLimit = + (std::numeric_limits<int64_t>::max() / + v8::base::Time::kMicrosecondsPerSecond) - + 2; + CHECK_GT(kSecondsLimit, seconds); + int64_t micros = seconds * v8::base::Time::kMicrosecondsPerSecond; + micros += (thread_info_data.user_time.microseconds + + thread_info_data.system_time.microseconds); + return micros; } #elif V8_OS_POSIX // Helper function to get results from clock_gettime() and convert to a @@ -70,8 +79,14 @@ V8_INLINE int64_t ClockNow(clockid_t clk_id) { if (clock_gettime(clk_id, &ts) != 0) { UNREACHABLE(); } - v8::base::internal::CheckedNumeric<int64_t> result(ts.tv_sec); - result *= v8::base::Time::kMicrosecondsPerSecond; + // Multiplying the seconds by {kMicrosecondsPerSecond}, and adding something + // in [0, kMicrosecondsPerSecond) must result in a valid {int64_t}. + static constexpr int64_t kSecondsLimit = + (std::numeric_limits<int64_t>::max() / + v8::base::Time::kMicrosecondsPerSecond) - + 1; + CHECK_GT(kSecondsLimit, ts.tv_sec); + int64_t result = int64_t{ts.tv_sec} * v8::base::Time::kMicrosecondsPerSecond; #if defined(V8_OS_AIX) if (clk_id == CLOCK_THREAD_CPUTIME_ID) { result += (tc.stime / v8::base::Time::kNanosecondsPerMicrosecond); @@ -81,7 +96,7 @@ V8_INLINE int64_t ClockNow(clockid_t clk_id) { #else result += (ts.tv_nsec / v8::base::Time::kNanosecondsPerMicrosecond); #endif - return result.ValueOrDie(); + return result; #else // Monotonic clock not supported. return 0; #endif @@ -493,7 +508,7 @@ DWORD (*g_tick_function)(void) = &timeGetTimeWrapper; // "rollover" counter. union LastTimeAndRolloversState { // The state as a single 32-bit opaque value. - base::Atomic32 as_opaque_32; + int32_t as_opaque_32; // The state as usable values. struct { @@ -509,7 +524,7 @@ union LastTimeAndRolloversState { uint16_t rollovers; } as_values; }; -base::Atomic32 g_last_time_and_rollovers = 0; +std::atomic<int32_t> g_last_time_and_rollovers{0}; static_assert(sizeof(LastTimeAndRolloversState) <= sizeof(g_last_time_and_rollovers), "LastTimeAndRolloversState does not fit in a single atomic word"); @@ -523,12 +538,12 @@ TimeTicks RolloverProtectedNow() { LastTimeAndRolloversState state; DWORD now; // DWORD is always unsigned 32 bits. + // Fetch the "now" and "last" tick values, updating "last" with "now" and + // incrementing the "rollovers" counter if the tick-value has wrapped back + // around. Atomic operations ensure that both "last" and "rollovers" are + // always updated together. + int32_t original = g_last_time_and_rollovers.load(std::memory_order_acquire); while (true) { - // Fetch the "now" and "last" tick values, updating "last" with "now" and - // incrementing the "rollovers" counter if the tick-value has wrapped back - // around. Atomic operations ensure that both "last" and "rollovers" are - // always updated together. - int32_t original = base::Acquire_Load(&g_last_time_and_rollovers); state.as_opaque_32 = original; now = g_tick_function(); uint8_t now_8 = static_cast<uint8_t>(now >> 24); @@ -540,11 +555,13 @@ TimeTicks RolloverProtectedNow() { // Save the changed state. If the existing value is unchanged from the // original, exit the loop. - int32_t check = base::Release_CompareAndSwap(&g_last_time_and_rollovers, - original, state.as_opaque_32); - if (check == original) break; + if (g_last_time_and_rollovers.compare_exchange_weak( + original, state.as_opaque_32, std::memory_order_acq_rel)) { + break; + } // Another thread has done something in between so retry from the top. + // {original} has been updated by the {compare_exchange_weak}. } return TimeTicks() + diff --git a/deps/v8/src/base/platform/time.h b/deps/v8/src/base/platform/time.h index fd8ef10b55..afe4724382 100644 --- a/deps/v8/src/base/platform/time.h +++ b/deps/v8/src/base/platform/time.h @@ -14,7 +14,6 @@ #include "src/base/base-export.h" #include "src/base/bits.h" #include "src/base/macros.h" -#include "src/base/safe_math.h" #if V8_OS_WIN #include "src/base/win32-headers.h" #endif diff --git a/deps/v8/src/base/region-allocator.h b/deps/v8/src/base/region-allocator.h index 6cf8889530..4b1354adf5 100644 --- a/deps/v8/src/base/region-allocator.h +++ b/deps/v8/src/base/region-allocator.h @@ -25,7 +25,7 @@ namespace base { // Not thread-safe. class V8_BASE_EXPORT RegionAllocator final { public: - typedef uintptr_t Address; + using Address = uintptr_t; static constexpr Address kAllocationFailure = static_cast<Address>(-1); @@ -121,7 +121,7 @@ class V8_BASE_EXPORT RegionAllocator final { } }; // All regions ordered by addresses. - typedef std::set<Region*, AddressEndOrder> AllRegionsSet; + using AllRegionsSet = std::set<Region*, AddressEndOrder>; AllRegionsSet all_regions_; struct SizeAddressOrder { diff --git a/deps/v8/src/base/safe_math.h b/deps/v8/src/base/safe_math.h deleted file mode 100644 index 700bc3387f..0000000000 --- a/deps/v8/src/base/safe_math.h +++ /dev/null @@ -1,276 +0,0 @@ -// 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_SAFE_MATH_H_ -#define V8_BASE_SAFE_MATH_H_ - -#include "src/base/safe_math_impl.h" - -namespace v8 { -namespace base { -namespace internal { - -// CheckedNumeric implements all the logic and operators for detecting integer -// boundary conditions such as overflow, underflow, and invalid conversions. -// The CheckedNumeric type implicitly converts from floating point and integer -// data types, and contains overloads for basic arithmetic operations (i.e.: +, -// -, *, /, %). -// -// The following methods convert from CheckedNumeric to standard numeric values: -// IsValid() - Returns true if the underlying numeric value is valid (i.e. has -// has not wrapped and is not the result of an invalid conversion). -// ValueOrDie() - Returns the underlying value. If the state is not valid this -// call will crash on a CHECK. -// ValueOrDefault() - Returns the current value, or the supplied default if the -// state is not valid. -// ValueFloating() - Returns the underlying floating point value (valid only -// only for floating point CheckedNumeric types). -// -// Bitwise operations are explicitly not supported, because correct -// handling of some cases (e.g. sign manipulation) is ambiguous. Comparison -// operations are explicitly not supported because they could result in a crash -// on a CHECK condition. You should use patterns like the following for these -// operations: -// Bitwise operation: -// CheckedNumeric<int> checked_int = untrusted_input_value; -// int x = checked_int.ValueOrDefault(0) | kFlagValues; -// Comparison: -// CheckedNumeric<size_t> checked_size; -// CheckedNumeric<int> checked_size = untrusted_input_value; -// checked_size = checked_size + HEADER LENGTH; -// if (checked_size.IsValid() && checked_size.ValueOrDie() < buffer_size) -// Do stuff... -template <typename T> -class CheckedNumeric { - public: - typedef T type; - - CheckedNumeric() = default; - - // Copy constructor. - template <typename Src> - CheckedNumeric(const CheckedNumeric<Src>& rhs) - : state_(rhs.ValueUnsafe(), rhs.validity()) {} - - template <typename Src> - CheckedNumeric(Src value, RangeConstraint validity) - : state_(value, validity) {} - - // This is not an explicit constructor because we implicitly upgrade regular - // numerics to CheckedNumerics to make them easier to use. - template <typename Src> - CheckedNumeric(Src value) // NOLINT - : state_(value) { - // Argument must be numeric. - STATIC_ASSERT(std::numeric_limits<Src>::is_specialized); - } - - // IsValid() is the public API to test if a CheckedNumeric is currently valid. - bool IsValid() const { return validity() == RANGE_VALID; } - - // ValueOrDie() The primary accessor for the underlying value. If the current - // state is not valid it will CHECK and crash. - T ValueOrDie() const { - CHECK(IsValid()); - return state_.value(); - } - - // ValueOrDefault(T default_value) A convenience method that returns the - // current value if the state is valid, and the supplied default_value for - // any other state. - T ValueOrDefault(T default_value) const { - return IsValid() ? state_.value() : default_value; - } - - // ValueFloating() - Since floating point values include their validity state, - // we provide an easy method for extracting them directly, without a risk of - // crashing on a CHECK. - T ValueFloating() const { - // Argument must be a floating-point value. - STATIC_ASSERT(std::numeric_limits<T>::is_iec559); - return CheckedNumeric<T>::cast(*this).ValueUnsafe(); - } - - // validity() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now for - // tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: current validity state (i.e. valid, overflow, underflow, nan). - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - RangeConstraint validity() const { return state_.validity(); } - - // ValueUnsafe() - DO NOT USE THIS IN EXTERNAL CODE - It is public right now - // for tests and to avoid a big matrix of friend operator overloads. But the - // values it returns are likely to change in the future. - // Returns: the raw numeric value, regardless of the current state. - // TODO(jschuh): crbug.com/332611 Figure out and implement semantics for - // saturation/wrapping so we can expose this state consistently and implement - // saturated arithmetic. - T ValueUnsafe() const { return state_.value(); } - - // Prototypes for the supported arithmetic operator overloads. - template <typename Src> CheckedNumeric& operator+=(Src rhs); - template <typename Src> CheckedNumeric& operator-=(Src rhs); - template <typename Src> CheckedNumeric& operator*=(Src rhs); - template <typename Src> CheckedNumeric& operator/=(Src rhs); - template <typename Src> CheckedNumeric& operator%=(Src rhs); - - CheckedNumeric operator-() const { - RangeConstraint validity; - T value = CheckedNeg(state_.value(), &validity); - // Negation is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - CheckedNumeric Abs() const { - RangeConstraint validity; - T value = CheckedAbs(state_.value(), &validity); - // Absolute value is always valid for floating point. - if (std::numeric_limits<T>::is_iec559) - return CheckedNumeric<T>(value); - - validity = GetRangeConstraint(state_.validity() | validity); - return CheckedNumeric<T>(value, validity); - } - - CheckedNumeric& operator++() { - *this += 1; - return *this; - } - - CheckedNumeric operator++(int) { - CheckedNumeric value = *this; - *this += 1; - return value; - } - - CheckedNumeric& operator--() { - *this -= 1; - return *this; - } - - CheckedNumeric operator--(int) { - CheckedNumeric value = *this; - *this -= 1; - return value; - } - - // These static methods behave like a convenience cast operator targeting - // the desired CheckedNumeric type. As an optimization, a reference is - // returned when Src is the same type as T. - template <typename Src> - static CheckedNumeric<T> cast( - Src u, - typename enable_if<std::numeric_limits<Src>::is_specialized, int>::type = - 0) { - return u; - } - - template <typename Src> - static CheckedNumeric<T> cast( - const CheckedNumeric<Src>& u, - typename enable_if<!is_same<Src, T>::value, int>::type = 0) { - return u; - } - - static const CheckedNumeric<T>& cast(const CheckedNumeric<T>& u) { return u; } - - private: - CheckedNumericState<T> state_; -}; - -// This is the boilerplate for the standard arithmetic operator overloads. A -// macro isn't the prettiest solution, but it beats rewriting these five times. -// Some details worth noting are: -// * We apply the standard arithmetic promotions. -// * We skip range checks for floating points. -// * We skip range checks for destination integers with sufficient range. -// TODO(jschuh): extract these out into templates. -#define BASE_NUMERIC_ARITHMETIC_OPERATORS(NAME, OP, COMPOUND_OP) \ - /* Binary arithmetic operator for CheckedNumerics of the same type. */ \ - template <typename T> \ - CheckedNumeric<typename ArithmeticPromotion<T>::type> operator OP( \ - const CheckedNumeric<T>& lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T>::type Promotion; \ - /* Floating point always takes the fast path */ \ - if (std::numeric_limits<T>::is_iec559) \ - return CheckedNumeric<T>(lhs.ValueUnsafe() OP rhs.ValueUnsafe()); \ - if (IsIntegerArithmeticSafe<Promotion, T, T>::value) \ - return CheckedNumeric<Promotion>( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - RangeConstraint validity = RANGE_VALID; \ - T result = Checked##NAME(static_cast<Promotion>(lhs.ValueUnsafe()), \ - static_cast<Promotion>(rhs.ValueUnsafe()), \ - &validity); \ - return CheckedNumeric<Promotion>( \ - result, \ - GetRangeConstraint(validity | lhs.validity() | rhs.validity())); \ - } \ - /* Assignment arithmetic operator implementation from CheckedNumeric. */ \ - template <typename T> \ - template <typename Src> \ - CheckedNumeric<T>& CheckedNumeric<T>::operator COMPOUND_OP(Src rhs) { \ - *this = CheckedNumeric<T>::cast(*this) OP CheckedNumeric<Src>::cast(rhs); \ - return *this; \ - } \ - /* Binary arithmetic operator for CheckedNumeric of different type. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<Src>& lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>( \ - lhs.ValueUnsafe() OP rhs.ValueUnsafe(), \ - GetRangeConstraint(rhs.validity() | lhs.validity())); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for left CheckedNumeric and right numeric. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - const CheckedNumeric<T>& lhs, Src rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs.ValueUnsafe() OP rhs, \ - lhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } \ - /* Binary arithmetic operator for right numeric and left CheckedNumeric. */ \ - template <typename T, typename Src> \ - CheckedNumeric<typename ArithmeticPromotion<T, Src>::type> operator OP( \ - Src lhs, const CheckedNumeric<T>& rhs) { \ - typedef typename ArithmeticPromotion<T, Src>::type Promotion; \ - if (IsIntegerArithmeticSafe<Promotion, T, Src>::value) \ - return CheckedNumeric<Promotion>(lhs OP rhs.ValueUnsafe(), \ - rhs.validity()); \ - return CheckedNumeric<Promotion>::cast(lhs) \ - OP CheckedNumeric<Promotion>::cast(rhs); \ - } - -BASE_NUMERIC_ARITHMETIC_OPERATORS(Add, +, += ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Sub, -, -= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mul, *, *= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Div, /, /= ) -BASE_NUMERIC_ARITHMETIC_OPERATORS(Mod, %, %= ) - -#undef BASE_NUMERIC_ARITHMETIC_OPERATORS - -} // namespace internal - -using internal::CheckedNumeric; - -} // namespace base -} // namespace v8 - -#endif // V8_BASE_SAFE_MATH_H_ diff --git a/deps/v8/src/base/safe_math_impl.h b/deps/v8/src/base/safe_math_impl.h deleted file mode 100644 index eb2a151191..0000000000 --- a/deps/v8/src/base/safe_math_impl.h +++ /dev/null @@ -1,531 +0,0 @@ -// 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_SAFE_MATH_IMPL_H_ -#define V8_BASE_SAFE_MATH_IMPL_H_ - -#include <stdint.h> - -#include <cmath> -#include <cstdlib> -#include <limits> - -#include "src/base/macros.h" -#include "src/base/safe_conversions.h" - -namespace v8 { -namespace base { -namespace internal { - - -// From Chromium's base/template_util.h: - -template<class T, T v> -struct integral_constant { - static const T value = v; - typedef T value_type; - typedef integral_constant<T, v> type; -}; - -template <class T, T v> const T integral_constant<T, v>::value; - -typedef integral_constant<bool, true> true_type; -typedef integral_constant<bool, false> false_type; - -template <class T, class U> struct is_same : public false_type {}; -template <class T> struct is_same<T, T> : true_type {}; - -template<bool B, class T = void> -struct enable_if {}; - -template<class T> -struct enable_if<true, T> { typedef T type; }; - -// </template_util.h> - - -// Everything from here up to the floating point operations is portable C++, -// but it may not be fast. This code could be split based on -// platform/architecture and replaced with potentially faster implementations. - -// Integer promotion templates used by the portable checked integer arithmetic. -template <size_t Size, bool IsSigned> -struct IntegerForSizeAndSign; -template <> -struct IntegerForSizeAndSign<1, true> { - typedef int8_t type; -}; -template <> -struct IntegerForSizeAndSign<1, false> { - typedef uint8_t type; -}; -template <> -struct IntegerForSizeAndSign<2, true> { - typedef int16_t type; -}; -template <> -struct IntegerForSizeAndSign<2, false> { - typedef uint16_t type; -}; -template <> -struct IntegerForSizeAndSign<4, true> { - typedef int32_t type; -}; -template <> -struct IntegerForSizeAndSign<4, false> { - typedef uint32_t type; -}; -template <> -struct IntegerForSizeAndSign<8, true> { - typedef int64_t type; -}; -template <> -struct IntegerForSizeAndSign<8, false> { - typedef uint64_t type; -}; - -// WARNING: We have no IntegerForSizeAndSign<16, *>. If we ever add one to -// support 128-bit math, then the ArithmeticPromotion template below will need -// to be updated (or more likely replaced with a decltype expression). - -template <typename Integer> -struct UnsignedIntegerForSize { - typedef typename enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), false>::type>::type type; -}; - -template <typename Integer> -struct SignedIntegerForSize { - typedef typename enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign<sizeof(Integer), true>::type>::type type; -}; - -template <typename Integer> -struct TwiceWiderInteger { - typedef typename enable_if< - std::numeric_limits<Integer>::is_integer, - typename IntegerForSizeAndSign< - sizeof(Integer) * 2, - std::numeric_limits<Integer>::is_signed>::type>::type type; -}; - -template <typename Integer> -struct PositionOfSignBit { - static const typename enable_if<std::numeric_limits<Integer>::is_integer, - size_t>::type value = 8 * sizeof(Integer) - 1; -}; - -// Helper templates for integer manipulations. - -template <typename T> -bool HasSignBit(T x) { - // Cast to unsigned since right shift on signed is undefined. - return !!(static_cast<typename UnsignedIntegerForSize<T>::type>(x) >> - PositionOfSignBit<T>::value); -} - -// This wrapper undoes the standard integer promotions. -template <typename T> -T BinaryComplement(T x) { - return ~x; -} - -// Here are the actual portable checked integer math implementations. -// TODO(jschuh): Break this code out from the enable_if pattern and find a clean -// way to coalesce things into the CheckedNumericState specializations below. - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedAdd(T x, T y, RangeConstraint* validity) { - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = ux + uy; - // Addition is valid if the sign of (x + y) is equal to either that of x or - // that of y. - if (std::numeric_limits<T>::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (uresult ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - - } else { // Unsigned is either valid or overflow. - *validity = BinaryComplement(x) >= y ? RANGE_VALID : RANGE_OVERFLOW; - } - return static_cast<T>(uresult); -} - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_integer, T>::type -CheckedSub(T x, T y, RangeConstraint* validity) { - // Since the value of x+y is undefined if we have a signed type, we compute - // it using the unsigned type of the same size. - typedef typename UnsignedIntegerForSize<T>::type UnsignedDst; - UnsignedDst ux = static_cast<UnsignedDst>(x); - UnsignedDst uy = static_cast<UnsignedDst>(y); - UnsignedDst uresult = ux - uy; - // Subtraction is valid if either x and y have same sign, or (x-y) and x have - // the same sign. - if (std::numeric_limits<T>::is_signed) { - if (HasSignBit(BinaryComplement((uresult ^ ux) & (ux ^ uy)))) - *validity = RANGE_VALID; - else // Direction of wrap is inverse of result sign. - *validity = HasSignBit(uresult) ? RANGE_OVERFLOW : RANGE_UNDERFLOW; - - } else { // Unsigned is either valid or underflow. - *validity = x >= y ? RANGE_VALID : RANGE_UNDERFLOW; - } - return static_cast<T>(uresult); -} - -// Integer multiplication is a bit complicated. In the fast case we just -// we just promote to a twice wider type, and range check the result. In the -// slow case we need to manually check that the result won't be truncated by -// checking with division against the appropriate bound. -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && sizeof(T) * 2 <= sizeof(uintmax_t), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - typedef typename TwiceWiderInteger<T>::type IntermediateType; - IntermediateType tmp = - static_cast<IntermediateType>(x) * static_cast<IntermediateType>(y); - *validity = DstRangeRelationToSrcRange<T>(tmp); - return static_cast<T>(tmp); -} - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed && - (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) { - return RANGE_VALID; - - } else if (x > 0) { - if (y > 0) - *validity = - x <= std::numeric_limits<T>::max() / y ? RANGE_VALID : RANGE_OVERFLOW; - else - *validity = y >= std::numeric_limits<T>::min() / x ? RANGE_VALID - : RANGE_UNDERFLOW; - - } else { - if (y > 0) - *validity = x >= std::numeric_limits<T>::min() / y ? RANGE_VALID - : RANGE_UNDERFLOW; - else - *validity = - y >= std::numeric_limits<T>::max() / x ? RANGE_VALID : RANGE_OVERFLOW; - } - - return x * y; -} - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed && - (sizeof(T) * 2 > sizeof(uintmax_t)), - T>::type -CheckedMul(T x, T y, RangeConstraint* validity) { - *validity = (y == 0 || x <= std::numeric_limits<T>::max() / y) - ? RANGE_VALID - : RANGE_OVERFLOW; - return x * y; -} - -// Division just requires a check for an invalid negation on signed min/-1. -template <typename T> -T CheckedDiv( - T x, - T y, - RangeConstraint* validity, - typename enable_if<std::numeric_limits<T>::is_integer, int>::type = 0) { - if (std::numeric_limits<T>::is_signed && x == std::numeric_limits<T>::min() && - y == static_cast<T>(-1)) { - *validity = RANGE_OVERFLOW; - return std::numeric_limits<T>::min(); - } - - *validity = RANGE_VALID; - return x / y; -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = y > 0 ? RANGE_VALID : RANGE_INVALID; - return x % y; -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedMod(T x, T y, RangeConstraint* validity) { - *validity = RANGE_VALID; - return x % y; -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - // The negation of signed min is min, so catch that one. - return -value; -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedNeg(T value, RangeConstraint* validity) { - // The only legal unsigned negation is zero. - *validity = value ? RANGE_UNDERFLOW : RANGE_VALID; - return static_cast<T>( - -static_cast<typename SignedIntegerForSize<T>::type>(value)); -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { - *validity = - value != std::numeric_limits<T>::min() ? RANGE_VALID : RANGE_OVERFLOW; - return std::abs(value); -} - -template <typename T> -typename enable_if< - std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, - T>::type -CheckedAbs(T value, RangeConstraint* validity) { - // Absolute value of a positive is just its identiy. - *validity = RANGE_VALID; - return value; -} - -// These are the floating point stubs that the compiler needs to see. Only the -// negation operation is ever called. -#define BASE_FLOAT_ARITHMETIC_STUBS(NAME) \ - template <typename T> \ - typename enable_if<std::numeric_limits<T>::is_iec559, T>::type \ - Checked##NAME(T, T, RangeConstraint*) { \ - UNREACHABLE(); \ - return 0; \ - } - -BASE_FLOAT_ARITHMETIC_STUBS(Add) -BASE_FLOAT_ARITHMETIC_STUBS(Sub) -BASE_FLOAT_ARITHMETIC_STUBS(Mul) -BASE_FLOAT_ARITHMETIC_STUBS(Div) -BASE_FLOAT_ARITHMETIC_STUBS(Mod) - -#undef BASE_FLOAT_ARITHMETIC_STUBS - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedNeg( - T value, - RangeConstraint*) { - return -value; -} - -template <typename T> -typename enable_if<std::numeric_limits<T>::is_iec559, T>::type CheckedAbs( - T value, - RangeConstraint*) { - return std::abs(value); -} - -// Floats carry around their validity state with them, but integers do not. So, -// we wrap the underlying value in a specialization in order to hide that detail -// and expose an interface via accessors. -enum NumericRepresentation { - NUMERIC_INTEGER, - NUMERIC_FLOATING, - NUMERIC_UNKNOWN -}; - -template <typename NumericType> -struct GetNumericRepresentation { - static const NumericRepresentation value = - std::numeric_limits<NumericType>::is_integer - ? NUMERIC_INTEGER - : (std::numeric_limits<NumericType>::is_iec559 ? NUMERIC_FLOATING - : NUMERIC_UNKNOWN); -}; - -template <typename T, NumericRepresentation type = - GetNumericRepresentation<T>::value> -class CheckedNumericState {}; - -// Integrals require quite a bit of additional housekeeping to manage state. -template <typename T> -class CheckedNumericState<T, NUMERIC_INTEGER> { - private: - T value_; - RangeConstraint validity_; - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0), validity_(RANGE_VALID) {} - - template <typename Src> - CheckedNumericState(Src value, RangeConstraint validity) - : value_(value), - validity_(GetRangeConstraint(validity | - DstRangeRelationToSrcRange<T>(value))) { - // Argument must be numeric. - STATIC_ASSERT(std::numeric_limits<Src>::is_specialized); - } - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src>& rhs) - : value_(static_cast<T>(rhs.value())), - validity_(GetRangeConstraint( - rhs.validity() | DstRangeRelationToSrcRange<T>(rhs.value()))) {} - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename enable_if<std::numeric_limits<Src>::is_specialized, int>::type = - 0) - : value_(static_cast<T>(value)), - validity_(DstRangeRelationToSrcRange<T>(value)) {} - - RangeConstraint validity() const { return validity_; } - T value() const { return value_; } -}; - -// Floating points maintain their own validity, but need translation wrappers. -template <typename T> -class CheckedNumericState<T, NUMERIC_FLOATING> { - private: - T value_; - - public: - template <typename Src, NumericRepresentation type> - friend class CheckedNumericState; - - CheckedNumericState() : value_(0.0) {} - - template <typename Src> - CheckedNumericState( - Src value, - RangeConstraint validity, - typename enable_if<std::numeric_limits<Src>::is_integer, int>::type = 0) { - switch (DstRangeRelationToSrcRange<T>(value)) { - case RANGE_VALID: - value_ = static_cast<T>(value); - break; - - case RANGE_UNDERFLOW: - value_ = -std::numeric_limits<T>::infinity(); - break; - - case RANGE_OVERFLOW: - value_ = std::numeric_limits<T>::infinity(); - break; - - case RANGE_INVALID: - value_ = std::numeric_limits<T>::quiet_NaN(); - break; - } - } - - template <typename Src> - explicit CheckedNumericState( - Src value, - typename enable_if<std::numeric_limits<Src>::is_specialized, int>::type = - 0) - : value_(static_cast<T>(value)) {} - - // Copy constructor. - template <typename Src> - CheckedNumericState(const CheckedNumericState<Src>& rhs) - : value_(static_cast<T>(rhs.value())) {} - - RangeConstraint validity() const { - return GetRangeConstraint(value_ <= std::numeric_limits<T>::max(), - value_ >= -std::numeric_limits<T>::max()); - } - T value() const { return value_; } -}; - -// For integers less than 128-bit and floats 32-bit or larger, we can distil -// C/C++ arithmetic promotions down to two simple rules: -// 1. The type with the larger maximum exponent always takes precedence. -// 2. The resulting type must be promoted to at least an int. -// The following template specializations implement that promotion logic. -enum ArithmeticPromotionCategory { - LEFT_PROMOTION, - RIGHT_PROMOTION, - DEFAULT_PROMOTION -}; - -template <typename Lhs, - typename Rhs = Lhs, - ArithmeticPromotionCategory Promotion = - (MaxExponent<Lhs>::value > MaxExponent<Rhs>::value) - ? (MaxExponent<Lhs>::value > MaxExponent<int>::value - ? LEFT_PROMOTION - : DEFAULT_PROMOTION) - : (MaxExponent<Rhs>::value > MaxExponent<int>::value - ? RIGHT_PROMOTION - : DEFAULT_PROMOTION) > -struct ArithmeticPromotion; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, LEFT_PROMOTION> { - typedef Lhs type; -}; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, RIGHT_PROMOTION> { - typedef Rhs type; -}; - -template <typename Lhs, typename Rhs> -struct ArithmeticPromotion<Lhs, Rhs, DEFAULT_PROMOTION> { - typedef int type; -}; - -// We can statically check if operations on the provided types can wrap, so we -// can skip the checked operations if they're not needed. So, for an integer we -// care if the destination type preserves the sign and is twice the width of -// the source. -template <typename T, typename Lhs, typename Rhs> -struct IsIntegerArithmeticSafe { - static const bool value = !std::numeric_limits<T>::is_iec559 && - StaticDstRangeRelationToSrcRange<T, Lhs>::value == - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Lhs)) && - StaticDstRangeRelationToSrcRange<T, Rhs>::value != - NUMERIC_RANGE_CONTAINED && - sizeof(T) >= (2 * sizeof(Rhs)); -}; - -} // namespace internal -} // namespace base -} // namespace v8 - -#endif // V8_BASE_SAFE_MATH_IMPL_H_ diff --git a/deps/v8/src/base/small-vector.h b/deps/v8/src/base/small-vector.h index bbfe2e2e9c..9c098c4829 100644 --- a/deps/v8/src/base/small-vector.h +++ b/deps/v8/src/base/small-vector.h @@ -26,6 +26,7 @@ class SmallVector { static constexpr size_t kInlineSize = kSize; SmallVector() = default; + explicit SmallVector(size_t size) { resize_no_init(size); } SmallVector(const SmallVector& other) V8_NOEXCEPT { *this = other; } SmallVector(SmallVector&& other) V8_NOEXCEPT { *this = std::move(other); } diff --git a/deps/v8/src/base/utils/random-number-generator.h b/deps/v8/src/base/utils/random-number-generator.h index 45ec259305..8eb8563175 100644 --- a/deps/v8/src/base/utils/random-number-generator.h +++ b/deps/v8/src/base/utils/random-number-generator.h @@ -39,7 +39,7 @@ class V8_BASE_EXPORT RandomNumberGenerator final { public: // EntropySource is used as a callback function when V8 needs a source of // entropy. - typedef bool (*EntropySource)(unsigned char* buffer, size_t buflen); + using EntropySource = bool (*)(unsigned char* buffer, size_t buflen); static void SetEntropySource(EntropySource entropy_source); RandomNumberGenerator(); diff --git a/deps/v8/src/base/win32-headers.h b/deps/v8/src/base/win32-headers.h index b61ce717e5..82555463c0 100644 --- a/deps/v8/src/base/win32-headers.h +++ b/deps/v8/src/base/win32-headers.h @@ -45,8 +45,9 @@ #define _WIN32_WINNT 0x501 #endif // __MINGW32__ #if !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR) -#include <dbghelp.h> // For SymLoadModule64 and al. -#include <errno.h> // For STRUNCATE +#include <dbghelp.h> // For SymLoadModule64 and al. +#include <errno.h> // For STRUNCATE +#include <versionhelpers.h> // For IsWindows8OrGreater(). #endif // !defined(__MINGW32__) || defined(__MINGW64_VERSION_MAJOR) #include <limits.h> // For INT_MAX and al. #include <tlhelp32.h> // For Module32First and al. |