diff options
author | Myles Borins <mylesborins@google.com> | 2018-04-10 21:39:51 -0400 |
---|---|---|
committer | Myles Borins <mylesborins@google.com> | 2018-04-11 13:22:42 -0400 |
commit | 12a1b9b8049462e47181a298120243dc83e81c55 (patch) | |
tree | 8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/base | |
parent | 78cd8263354705b767ef8c6a651740efe4931ba0 (diff) | |
download | node-new-12a1b9b8049462e47181a298120243dc83e81c55.tar.gz |
deps: update V8 to 6.6.346.23
PR-URL: https://github.com/nodejs/node/pull/19201
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Diffstat (limited to 'deps/v8/src/base')
-rw-r--r-- | deps/v8/src/base/atomic-utils.h | 6 | ||||
-rw-r--r-- | deps/v8/src/base/atomicops_internals_portable.h | 4 | ||||
-rw-r--r-- | deps/v8/src/base/atomicops_internals_std.h | 4 | ||||
-rw-r--r-- | deps/v8/src/base/cpu.cc | 3 | ||||
-rw-r--r-- | deps/v8/src/base/file-utils.h | 2 | ||||
-rw-r--r-- | deps/v8/src/base/format-macros.h | 6 | ||||
-rw-r--r-- | deps/v8/src/base/logging.cc | 38 | ||||
-rw-r--r-- | deps/v8/src/base/logging.h | 12 | ||||
-rw-r--r-- | deps/v8/src/base/macros.h | 2 | ||||
-rw-r--r-- | deps/v8/src/base/optional.h | 8 | ||||
-rw-r--r-- | deps/v8/src/base/platform/platform-cygwin.cc | 2 | ||||
-rw-r--r-- | deps/v8/src/base/platform/platform-fuchsia.cc | 16 | ||||
-rw-r--r-- | deps/v8/src/base/platform/platform-posix.cc | 21 | ||||
-rw-r--r-- | deps/v8/src/base/platform/platform-win32.cc | 9 | ||||
-rw-r--r-- | deps/v8/src/base/platform/time.cc | 370 | ||||
-rw-r--r-- | deps/v8/src/base/platform/time.h | 138 | ||||
-rw-r--r-- | deps/v8/src/base/qnx-math.h | 2 | ||||
-rw-r--r-- | deps/v8/src/base/sys-info.cc | 6 | ||||
-rw-r--r-- | deps/v8/src/base/template-utils.h | 6 | ||||
-rw-r--r-- | deps/v8/src/base/v8-fallthrough.h | 21 |
20 files changed, 456 insertions, 220 deletions
diff --git a/deps/v8/src/base/atomic-utils.h b/deps/v8/src/base/atomic-utils.h index 854d846cc0..5ba1ad4246 100644 --- a/deps/v8/src/base/atomic-utils.h +++ b/deps/v8/src/base/atomic-utils.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_ATOMIC_UTILS_H_ -#define V8_ATOMIC_UTILS_H_ +#ifndef V8_BASE_ATOMIC_UTILS_H_ +#define V8_BASE_ATOMIC_UTILS_H_ #include <limits.h> #include <type_traits> @@ -419,4 +419,4 @@ class AtomicElement { } // namespace base } // namespace v8 -#endif // #define V8_ATOMIC_UTILS_H_ +#endif // V8_BASE_ATOMIC_UTILS_H_ diff --git a/deps/v8/src/base/atomicops_internals_portable.h b/deps/v8/src/base/atomicops_internals_portable.h index 0779bfbd25..bd79558313 100644 --- a/deps/v8/src/base/atomicops_internals_portable.h +++ b/deps/v8/src/base/atomicops_internals_portable.h @@ -26,8 +26,8 @@ // needs to increment twice (which the compiler should be able to detect and // optimize). -#ifndef BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ -#define BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ +#ifndef V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ +#define V8_BASE_ATOMICOPS_INTERNALS_PORTABLE_H_ #include <atomic> diff --git a/deps/v8/src/base/atomicops_internals_std.h b/deps/v8/src/base/atomicops_internals_std.h index f47152aa8c..4ce7b461e0 100644 --- a/deps/v8/src/base/atomicops_internals_std.h +++ b/deps/v8/src/base/atomicops_internals_std.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_ATOMICOPS_INTERNALS_STD_H_ -#define BASE_ATOMICOPS_INTERNALS_STD_H_ +#ifndef V8_BASE_ATOMICOPS_INTERNALS_STD_H_ +#define V8_BASE_ATOMICOPS_INTERNALS_STD_H_ #include <atomic> diff --git a/deps/v8/src/base/cpu.cc b/deps/v8/src/base/cpu.cc index 22e0511dc7..6ab0ffee29 100644 --- a/deps/v8/src/base/cpu.cc +++ b/deps/v8/src/base/cpu.cc @@ -335,7 +335,8 @@ CPU::CPU() has_vfp3_(false), has_vfp3_d32_(false), is_fp64_mode_(false), - has_non_stop_time_stamp_counter_(false) { + has_non_stop_time_stamp_counter_(false), + has_msa_(false) { memcpy(vendor_, "Unknown", 8); #if V8_HOST_ARCH_IA32 || V8_HOST_ARCH_X64 int cpu_info[4]; diff --git a/deps/v8/src/base/file-utils.h b/deps/v8/src/base/file-utils.h index 271f0ffb05..afd9a1fc25 100644 --- a/deps/v8/src/base/file-utils.h +++ b/deps/v8/src/base/file-utils.h @@ -18,4 +18,4 @@ V8_BASE_EXPORT char* RelativePath(char** buffer, const char* exec_path, } // namespace base } // namespace v8 -#endif // V8_FILE_UTILS_H_ +#endif // V8_BASE_FILE_UTILS_H_ diff --git a/deps/v8/src/base/format-macros.h b/deps/v8/src/base/format-macros.h index 5f5fe5df24..e2234684a8 100644 --- a/deps/v8/src/base/format-macros.h +++ b/deps/v8/src/base/format-macros.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef BASE_FORMAT_MACROS_H_ -#define BASE_FORMAT_MACROS_H_ +#ifndef V8_BASE_FORMAT_MACROS_H_ +#define V8_BASE_FORMAT_MACROS_H_ // This file defines the format macros for some integer types. @@ -94,4 +94,4 @@ #endif -#endif // BASE_FORMAT_MACROS_H_ +#endif // V8_BASE_FORMAT_MACROS_H_ diff --git a/deps/v8/src/base/logging.cc b/deps/v8/src/base/logging.cc index ad5349ac7e..e58fdba09f 100644 --- a/deps/v8/src/base/logging.cc +++ b/deps/v8/src/base/logging.cc @@ -119,16 +119,50 @@ DEFINE_CHECK_OP_IMPL(GT) } // namespace base } // namespace v8 +namespace { + +// FailureMessage is a stack allocated object which has a special marker field +// at the start and at the end. This makes it possible to retrieve the embedded +// message from the stack. +// +class FailureMessage { + public: + explicit FailureMessage(const char* format, va_list arguments) { + memset(&message_, 0, arraysize(message_)); + v8::base::OS::VSNPrintF(&message_[0], arraysize(message_), format, + arguments); + } + + static const uintptr_t kStartMarker = 0xdecade10; + static const uintptr_t kEndMarker = 0xdecade11; + static const int kMessageBufferSize = 1024; + + uintptr_t start_marker_ = kStartMarker; + char message_[kMessageBufferSize]; + uintptr_t end_marker_ = kEndMarker; +}; + +} // namespace + void V8_Fatal(const char* file, int line, const char* format, ...) { + va_list arguments; + va_start(arguments, format); + // Format the error message into a stack object for later retrieveal by the + // crash processor. + FailureMessage message(format, arguments); + va_end(arguments); + fflush(stdout); fflush(stderr); v8::base::OS::PrintError("\n\n#\n# Fatal error in %s, line %d\n# ", file, line); - va_list arguments; + + // Print the error message. va_start(arguments, format); v8::base::OS::VPrintError(format, arguments); va_end(arguments); - v8::base::OS::PrintError("\n#\n"); + // Print the message object's address to force stack allocation. + v8::base::OS::PrintError("\n#\n#\n#\n#FailureMessage Object: %p", &message); if (v8::base::g_print_stack_trace) v8::base::g_print_stack_trace(); diff --git a/deps/v8/src/base/logging.h b/deps/v8/src/base/logging.h index 5275fdc6a6..a21bc5e423 100644 --- a/deps/v8/src/base/logging.h +++ b/deps/v8/src/base/logging.h @@ -44,11 +44,11 @@ V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int, // // We make sure CHECK et al. always evaluates their arguments, as // doing CHECK(FunctionWithSideEffect()) is a common idiom. -#define CHECK_WITH_MSG(condition, message) \ - do { \ - if (V8_UNLIKELY(!(condition))) { \ - V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", message); \ - } \ +#define CHECK_WITH_MSG(condition, message) \ + do { \ + if (V8_UNLIKELY(!(condition))) { \ + FATAL("Check failed: %s.", message); \ + } \ } while (0) #define CHECK(condition) CHECK_WITH_MSG(condition, #condition) @@ -70,7 +70,7 @@ V8_BASE_EXPORT void SetDcheckFunction(void (*dcheck_Function)(const char*, int, typename ::v8::base::pass_value_or_ref<decltype(lhs)>::type, \ typename ::v8::base::pass_value_or_ref<decltype(rhs)>::type>( \ (lhs), (rhs), #lhs " " #op " " #rhs)) { \ - V8_Fatal(__FILE__, __LINE__, "Check failed: %s.", _msg->c_str()); \ + FATAL("Check failed: %s.", _msg->c_str()); \ delete _msg; \ } \ } while (0) diff --git a/deps/v8/src/base/macros.h b/deps/v8/src/base/macros.h index a265408d91..9de42131a4 100644 --- a/deps/v8/src/base/macros.h +++ b/deps/v8/src/base/macros.h @@ -338,4 +338,4 @@ bool is_inbounds(float_t v) { (kUpperBoundIsMax ? (v <= kUpperBound) : (v < kUpperBound)); } -#endif // V8_BASE_MACROS_H_ +#endif // V8_BASE_MACROS_H_ diff --git a/deps/v8/src/base/optional.h b/deps/v8/src/base/optional.h index a229745f84..ea32c403ac 100644 --- a/deps/v8/src/base/optional.h +++ b/deps/v8/src/base/optional.h @@ -125,7 +125,7 @@ class Optional { constexpr Optional() {} - explicit constexpr Optional(base::nullopt_t) {} + constexpr Optional(base::nullopt_t) {} // NOLINT(runtime/explicit) Optional(const Optional& other) { if (!other.storage_.is_null_) Init(other.value()); @@ -135,10 +135,12 @@ class Optional { if (!other.storage_.is_null_) Init(std::move(other.value())); } - explicit constexpr Optional(const T& value) : storage_(value) {} + constexpr Optional(const T& value) // NOLINT(runtime/explicit) + : storage_(value) {} // TODO(alshabalin): Can't use 'constexpr' with std::move until C++14. - explicit Optional(T&& value) : storage_(std::move(value)) {} + Optional(T&& value) // NOLINT(runtime/explicit) + : storage_(std::move(value)) {} // TODO(alshabalin): Can't use 'constexpr' with std::forward until C++14. template <class... Args> diff --git a/deps/v8/src/base/platform/platform-cygwin.cc b/deps/v8/src/base/platform/platform-cygwin.cc index eabd53570f..0d4ec9a10d 100644 --- a/deps/v8/src/base/platform/platform-cygwin.cc +++ b/deps/v8/src/base/platform/platform-cygwin.cc @@ -139,7 +139,7 @@ void* OS::Allocate(void* address, size_t size, size_t alignment, // base will be nullptr. if (base != nullptr) break; } - DCHECK_EQ(base, aligned_base); + DCHECK_IMPLIES(base, base == aligned_base); return reinterpret_cast<void*>(base); } diff --git a/deps/v8/src/base/platform/platform-fuchsia.cc b/deps/v8/src/base/platform/platform-fuchsia.cc index 38a7070e85..bba3f1baba 100644 --- a/deps/v8/src/base/platform/platform-fuchsia.cc +++ b/deps/v8/src/base/platform/platform-fuchsia.cc @@ -131,5 +131,21 @@ void OS::SignalCodeMovingGC() { UNREACHABLE(); // TODO(scottmg): Port, https://crbug.com/731217. } +int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { + const auto kNanosPerMicrosecond = 1000ULL; + const auto kMicrosPerSecond = 1000000ULL; + const zx_time_t nanos_since_thread_started = zx_clock_get(ZX_CLOCK_THREAD); + + // First convert to microseconds, rounding up. + const uint64_t micros_since_thread_started = + (nanos_since_thread_started + kNanosPerMicrosecond - 1ULL) / + kNanosPerMicrosecond; + + *secs = static_cast<uint32_t>(micros_since_thread_started / kMicrosPerSecond); + *usecs = + static_cast<uint32_t>(micros_since_thread_started % kMicrosPerSecond); + return 0; +} + } // 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 5edbd7648b..f85f7fe942 100644 --- a/deps/v8/src/base/platform/platform-posix.cc +++ b/deps/v8/src/base/platform/platform-posix.cc @@ -18,7 +18,6 @@ #include <unistd.h> #include <sys/mman.h> -#include <sys/resource.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> @@ -55,6 +54,12 @@ #include <sys/prctl.h> // NOLINT, for prctl #endif +#if defined(V8_OS_FUCHSIA) +#include <zircon/process.h> +#else +#include <sys/resource.h> +#endif + #if !defined(_AIX) && !defined(V8_OS_FUCHSIA) #include <sys/syscall.h> #endif @@ -245,6 +250,10 @@ void* OS::GetRandomMmapAddr() { // Little-endian Linux: 48 bits of virtual addressing. raw_addr &= uint64_t{0x3FFFFFFFF000}; #endif +#elif V8_TARGET_ARCH_MIPS64 + // We allocate code in 256 MB aligned segments because of optimizations using + // J instruction that require that all code is within a single 256 MB segment + raw_addr &= uint64_t{0x3FFFE0000000}; #elif V8_TARGET_ARCH_S390X // Linux on Z uses bits 22-32 for Region Indexing, which translates to 42 bits // of virtual addressing. Truncate to 40 bits to allow kernel chance to @@ -474,7 +483,7 @@ int OS::GetCurrentThreadId() { #elif V8_OS_AIX return static_cast<int>(thread_self()); #elif V8_OS_FUCHSIA - return static_cast<int>(pthread_self()); + return static_cast<int>(zx_thread_self()); #elif V8_OS_SOLARIS return static_cast<int>(pthread_self()); #else @@ -487,6 +496,7 @@ int OS::GetCurrentThreadId() { // POSIX date/time support. // +#if !defined(V8_OS_FUCHSIA) int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { struct rusage usage; @@ -495,7 +505,7 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) { *usecs = static_cast<uint32_t>(usage.ru_utime.tv_usec); return 0; } - +#endif double OS::TimeCurrentMillis() { return Time::Now().ToJsTime(); @@ -788,7 +798,7 @@ static void InitializeTlsBaseOffset() { size_t buffer_size = kBufferSize; int ctl_name[] = { CTL_KERN , KERN_OSRELEASE }; if (sysctl(ctl_name, 2, buffer, &buffer_size, nullptr, 0) != 0) { - V8_Fatal(__FILE__, __LINE__, "V8 failed to get kernel version"); + FATAL("V8 failed to get kernel version"); } // The buffer now contains a string of the form XX.YY.ZZ, where // XX is the major kernel version component. @@ -822,8 +832,7 @@ static void CheckFastTls(Thread::LocalStorageKey key) { Thread::SetThreadLocal(key, expected); void* actual = Thread::GetExistingThreadLocal(key); if (expected != actual) { - V8_Fatal(__FILE__, __LINE__, - "V8 failed to initialize fast TLS on current kernel"); + FATAL("V8 failed to initialize fast TLS on current kernel"); } Thread::SetThreadLocal(key, nullptr); } diff --git a/deps/v8/src/base/platform/platform-win32.cc b/deps/v8/src/base/platform/platform-win32.cc index 22580cc407..3f1a586840 100644 --- a/deps/v8/src/base/platform/platform-win32.cc +++ b/deps/v8/src/base/platform/platform-win32.cc @@ -829,15 +829,14 @@ void* OS::Allocate(void* address, size_t size, size_t alignment, // base will be nullptr. if (base != nullptr) break; } - DCHECK_EQ(base, aligned_base); + DCHECK_IMPLIES(base, base == aligned_base); return reinterpret_cast<void*>(base); } // static bool OS::Free(void* address, const size_t size) { DCHECK_EQ(0, reinterpret_cast<uintptr_t>(address) % AllocatePageSize()); - // TODO(bbudge) Add DCHECK_EQ(0, size % AllocatePageSize()) when callers - // pass the correct size on Windows. + DCHECK_EQ(0, size % AllocatePageSize()); USE(size); return VirtualFree(address, 0, MEM_RELEASE) != 0; } @@ -872,6 +871,10 @@ void OS::Sleep(TimeDelta interval) { void OS::Abort() { + // Before aborting, make sure to flush output buffers. + fflush(stdout); + fflush(stderr); + if (g_hard_abort) { V8_IMMEDIATE_CRASH(); } diff --git a/deps/v8/src/base/platform/time.cc b/deps/v8/src/base/platform/time.cc index 1fcd7aecce..cf34af646c 100644 --- a/deps/v8/src/base/platform/time.cc +++ b/deps/v8/src/base/platform/time.cc @@ -143,41 +143,83 @@ TimeDelta TimeDelta::FromNanoseconds(int64_t nanoseconds) { int TimeDelta::InDays() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int>::max(); + } return static_cast<int>(delta_ / Time::kMicrosecondsPerDay); } - int TimeDelta::InHours() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int>::max(); + } return static_cast<int>(delta_ / Time::kMicrosecondsPerHour); } - int TimeDelta::InMinutes() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int>::max(); + } return static_cast<int>(delta_ / Time::kMicrosecondsPerMinute); } - double TimeDelta::InSecondsF() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<double>::infinity(); + } return static_cast<double>(delta_) / Time::kMicrosecondsPerSecond; } - int64_t TimeDelta::InSeconds() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } return delta_ / Time::kMicrosecondsPerSecond; } - double TimeDelta::InMillisecondsF() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<double>::infinity(); + } return static_cast<double>(delta_) / Time::kMicrosecondsPerMillisecond; } - int64_t TimeDelta::InMilliseconds() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } return delta_ / Time::kMicrosecondsPerMillisecond; } +int64_t TimeDelta::InMillisecondsRoundedUp() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } + return (delta_ + Time::kMicrosecondsPerMillisecond - 1) / + Time::kMicrosecondsPerMillisecond; +} + +int64_t TimeDelta::InMicroseconds() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } + return delta_; +} int64_t TimeDelta::InNanoseconds() const { + if (IsMax()) { + // Preserve max to prevent overflow. + return std::numeric_limits<int64_t>::max(); + } return delta_ * Time::kNanosecondsPerMicrosecond; } @@ -415,6 +457,15 @@ struct timeval Time::ToTimeval() const { #endif // V8_OS_WIN +// static +TimeTicks TimeTicks::HighResolutionNow() { + // a DCHECK of TimeTicks::IsHighResolution() was removed from here + // as it turns out this path is used in the wild for logs and counters. + // + // TODO(hpayer) We may eventually want to split TimedHistograms based + // on low resolution clocks to avoid polluting metrics + return TimeTicks::Now(); +} Time Time::FromJsTime(double ms_since_epoch) { // The epoch is a valid time, so this constructor doesn't interpret @@ -447,165 +498,221 @@ std::ostream& operator<<(std::ostream& os, const Time& time) { #if V8_OS_WIN -class TickClock { - public: - virtual ~TickClock() {} - virtual int64_t Now() = 0; - virtual bool IsHighResolution() = 0; +namespace { + +// We define a wrapper to adapt between the __stdcall and __cdecl call of the +// mock function, and to avoid a static constructor. Assigning an import to a +// function pointer directly would require setup code to fetch from the IAT. +DWORD timeGetTimeWrapper() { return timeGetTime(); } + +DWORD (*g_tick_function)(void) = &timeGetTimeWrapper; + +// A structure holding the most significant bits of "last seen" and a +// "rollover" counter. +union LastTimeAndRolloversState { + // The state as a single 32-bit opaque value. + base::Atomic32 as_opaque_32; + + // The state as usable values. + struct { + // The top 8-bits of the "last" time. This is enough to check for rollovers + // and the small bit-size means fewer CompareAndSwap operations to store + // changes in state, which in turn makes for fewer retries. + uint8_t last_8; + // A count of the number of detected rollovers. Using this as bits 47-32 + // of the upper half of a 64-bit value results in a 48-bit tick counter. + // This extends the total rollover period from about 49 days to about 8800 + // years while still allowing it to be stored with last_8 in a single + // 32-bit value. + uint16_t rollovers; + } as_values; }; +base::Atomic32 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"); + +// We use timeGetTime() to implement TimeTicks::Now(). This can be problematic +// because it returns the number of milliseconds since Windows has started, +// which will roll over the 32-bit value every ~49 days. We try to track +// rollover ourselves, which works if TimeTicks::Now() is called at least every +// 48.8 days (not 49 days because only changes in the top 8 bits get noticed). +TimeTicks RolloverProtectedNow() { + LastTimeAndRolloversState state; + DWORD now; // DWORD is always unsigned 32 bits. + + 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); + if (now_8 < state.as_values.last_8) ++state.as_values.rollovers; + state.as_values.last_8 = now_8; + + // If the state hasn't changed, exit the loop. + if (state.as_opaque_32 == original) break; + + // 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; + + // Another thread has done something in between so retry from the top. + } + return TimeTicks() + + TimeDelta::FromMilliseconds( + now + (static_cast<uint64_t>(state.as_values.rollovers) << 32)); +} -// Overview of time counters: +// Discussion of tick counter options on Windows: +// // (1) CPU cycle counter. (Retrieved via RDTSC) // The CPU counter provides the highest resolution time stamp and is the least -// expensive to retrieve. However, the CPU counter is unreliable and should not -// be used in production. Its biggest issue is that it is per processor and it -// is not synchronized between processors. Also, on some computers, the counters -// will change frequency due to thermal and power changes, and stop in some -// states. +// expensive to retrieve. However, on older CPUs, two issues can affect its +// reliability: First it is maintained per processor and not synchronized +// between processors. Also, the counters will change frequency due to thermal +// and power changes, and stop in some states. // // (2) QueryPerformanceCounter (QPC). The QPC counter provides a high- -// resolution (100 nanoseconds) time stamp but is comparatively more expensive -// to retrieve. What QueryPerformanceCounter actually does is up to the HAL. -// (with some help from ACPI). -// According to http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx -// in the worst case, it gets the counter from the rollover interrupt on the +// resolution (<1 microsecond) time stamp. On most hardware running today, it +// auto-detects and uses the constant-rate RDTSC counter to provide extremely +// efficient and reliable time stamps. +// +// On older CPUs where RDTSC is unreliable, it falls back to using more +// expensive (20X to 40X more costly) alternate clocks, such as HPET or the ACPI +// PM timer, and can involve system calls; and all this is up to the HAL (with +// some help from ACPI). According to +// http://blogs.msdn.com/oldnewthing/archive/2005/09/02/459952.aspx, in the +// worst case, it gets the counter from the rollover interrupt on the // programmable interrupt timer. In best cases, the HAL may conclude that the // RDTSC counter runs at a constant frequency, then it uses that instead. On // multiprocessor machines, it will try to verify the values returned from // RDTSC on each processor are consistent with each other, and apply a handful // of workarounds for known buggy hardware. In other words, QPC is supposed to -// give consistent result on a multiprocessor computer, but it is unreliable in -// reality due to bugs in BIOS or HAL on some, especially old computers. -// With recent updates on HAL and newer BIOS, QPC is getting more reliable but -// it should be used with caution. +// give consistent results on a multiprocessor computer, but for older CPUs it +// can be unreliable due bugs in BIOS or HAL. // -// (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 { - public: - explicit HighResolutionTickClock(int64_t ticks_per_second) - : ticks_per_second_(ticks_per_second) { - DCHECK_LT(0, ticks_per_second); +// (3) System time. The system time provides a low-resolution (from ~1 to ~15.6 +// milliseconds) time stamp but is comparatively less expensive to retrieve and +// more reliable. Time::EnableHighResolutionTimer() and +// Time::ActivateHighResolutionTimer() can be called to alter the resolution of +// this timer; and also other Windows applications can alter it, affecting this +// one. + +TimeTicks InitialTimeTicksNowFunction(); + +// See "threading notes" in InitializeNowFunctionPointer() for details on how +// concurrent reads/writes to these globals has been made safe. +using TimeTicksNowFunction = decltype(&TimeTicks::Now); +TimeTicksNowFunction g_time_ticks_now_function = &InitialTimeTicksNowFunction; +int64_t g_qpc_ticks_per_second = 0; + +// As of January 2015, use of <atomic> is forbidden in Chromium code. This is +// what std::atomic_thread_fence does on Windows on all Intel architectures when +// the memory_order argument is anything but std::memory_order_seq_cst: +#define ATOMIC_THREAD_FENCE(memory_order) _ReadWriteBarrier(); + +TimeDelta QPCValueToTimeDelta(LONGLONG qpc_value) { + // Ensure that the assignment to |g_qpc_ticks_per_second|, made in + // InitializeNowFunctionPointer(), has happened by this point. + ATOMIC_THREAD_FENCE(memory_order_acquire); + + DCHECK_GT(g_qpc_ticks_per_second, 0); + + // If the QPC Value is below the overflow threshold, we proceed with + // simple multiply and divide. + if (qpc_value < TimeTicks::kQPCOverflowThreshold) { + return TimeDelta::FromMicroseconds( + qpc_value * TimeTicks::kMicrosecondsPerSecond / g_qpc_ticks_per_second); } - virtual ~HighResolutionTickClock() {} - - int64_t Now() override { - uint64_t now = QPCNowRaw(); - - // Intentionally calculate microseconds in a round about manner to avoid - // overflow and precision issues. Think twice before simplifying! - int64_t whole_seconds = now / ticks_per_second_; - int64_t leftover_ticks = now % ticks_per_second_; - int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) + - ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); - - // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow() - // will never return 0. - return ticks + 1; - } - - bool IsHighResolution() override { return true; } + // Otherwise, calculate microseconds in a round about manner to avoid + // overflow and precision issues. + int64_t whole_seconds = qpc_value / g_qpc_ticks_per_second; + int64_t leftover_ticks = qpc_value - (whole_seconds * g_qpc_ticks_per_second); + return TimeDelta::FromMicroseconds( + (whole_seconds * TimeTicks::kMicrosecondsPerSecond) + + ((leftover_ticks * TimeTicks::kMicrosecondsPerSecond) / + g_qpc_ticks_per_second)); +} - private: - int64_t ticks_per_second_; -}; +TimeTicks QPCNow() { return TimeTicks() + QPCValueToTimeDelta(QPCNowRaw()); } +bool IsBuggyAthlon(const CPU& cpu) { + // On Athlon X2 CPUs (e.g. model 15) QueryPerformanceCounter is unreliable. + return strcmp(cpu.vendor(), "AuthenticAMD") == 0 && cpu.family() == 15; +} -class RolloverProtectedTickClock final : public TickClock { - public: - RolloverProtectedTickClock() : rollover_(0) {} - virtual ~RolloverProtectedTickClock() {} - - 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 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. - // 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; - } - uint64_t ms = (static_cast<uint64_t>(rollover) << 31) | now; - return static_cast<int64_t>(ms * Time::kMicrosecondsPerMillisecond); +void InitializeTimeTicksNowFunctionPointer() { + LARGE_INTEGER ticks_per_sec = {}; + if (!QueryPerformanceFrequency(&ticks_per_sec)) ticks_per_sec.QuadPart = 0; + + // If Windows cannot provide a QPC implementation, TimeTicks::Now() must use + // the low-resolution clock. + // + // If the QPC implementation is expensive and/or unreliable, TimeTicks::Now() + // will still use the low-resolution clock. A CPU lacking a non-stop time + // counter will cause Windows to provide an alternate QPC implementation that + // works, but is expensive to use. Certain Athlon CPUs are known to make the + // QPC implementation unreliable. + // + // Otherwise, Now uses the high-resolution QPC clock. As of 21 August 2015, + // ~72% of users fall within this category. + TimeTicksNowFunction now_function; + CPU cpu; + if (ticks_per_sec.QuadPart <= 0 || !cpu.has_non_stop_time_stamp_counter() || + IsBuggyAthlon(cpu)) { + now_function = &RolloverProtectedNow; + } else { + now_function = &QPCNow; } - bool IsHighResolution() override { return false; } - - private: - base::Atomic32 rollover_; -}; - - -static LazyStaticInstance<RolloverProtectedTickClock, - DefaultConstructTrait<RolloverProtectedTickClock>, - ThreadSafeInitOnceTrait>::type tick_clock = - LAZY_STATIC_INSTANCE_INITIALIZER; - - -struct CreateHighResTickClockTrait { - static TickClock* Create() { - // Check if the installed hardware supports a high-resolution performance - // counter, and if not fallback to the low-resolution tick clock. - LARGE_INTEGER ticks_per_second; - if (!QueryPerformanceFrequency(&ticks_per_second)) { - return tick_clock.Pointer(); - } - - // If QPC not reliable, fallback to low-resolution tick clock. - if (IsQPCReliable()) { - return tick_clock.Pointer(); - } + // Threading note 1: In an unlikely race condition, it's possible for two or + // more threads to enter InitializeNowFunctionPointer() in parallel. This is + // not a problem since all threads should end up writing out the same values + // to the global variables. + // + // Threading note 2: A release fence is placed here to ensure, from the + // perspective of other threads using the function pointers, that the + // assignment to |g_qpc_ticks_per_second| happens before the function pointers + // are changed. + g_qpc_ticks_per_second = ticks_per_sec.QuadPart; + ATOMIC_THREAD_FENCE(memory_order_release); + g_time_ticks_now_function = now_function; +} - return new HighResolutionTickClock(ticks_per_second.QuadPart); - } -}; +TimeTicks InitialTimeTicksNowFunction() { + InitializeTimeTicksNowFunctionPointer(); + return g_time_ticks_now_function(); +} +#undef ATOMIC_THREAD_FENCE -static LazyDynamicInstance<TickClock, CreateHighResTickClockTrait, - ThreadSafeInitOnceTrait>::type high_res_tick_clock = - LAZY_DYNAMIC_INSTANCE_INITIALIZER; +} // namespace // static TimeTicks TimeTicks::Now() { // Make sure we never return 0 here. - TimeTicks ticks(tick_clock.Pointer()->Now()); + TimeTicks ticks(g_time_ticks_now_function()); DCHECK(!ticks.IsNull()); return ticks; } // static -TimeTicks TimeTicks::HighResolutionNow() { - // Make sure we never return 0 here. - TimeTicks ticks(high_res_tick_clock.Pointer()->Now()); - DCHECK(!ticks.IsNull()); - return ticks; -} - - -// static -bool TimeTicks::IsHighResolutionClockWorking() { - return high_res_tick_clock.Pointer()->IsHighResolution(); +bool TimeTicks::IsHighResolution() { + if (g_time_ticks_now_function == &InitialTimeTicksNowFunction) + InitializeTimeTicksNowFunctionPointer(); + return g_time_ticks_now_function == &QPCNow; } #else // V8_OS_WIN TimeTicks TimeTicks::Now() { - return HighResolutionNow(); -} - - -TimeTicks TimeTicks::HighResolutionNow() { int64_t ticks; #if V8_OS_MACOSX static struct mach_timebase_info info; @@ -627,11 +734,8 @@ TimeTicks TimeTicks::HighResolutionNow() { return TimeTicks(ticks + 1); } - // static -bool TimeTicks::IsHighResolutionClockWorking() { - return true; -} +bool TimeTicks::IsHighResolution() { return true; } #endif // V8_OS_WIN diff --git a/deps/v8/src/base/platform/time.h b/deps/v8/src/base/platform/time.h index 25dee1c419..161092ad8b 100644 --- a/deps/v8/src/base/platform/time.h +++ b/deps/v8/src/base/platform/time.h @@ -5,6 +5,8 @@ #ifndef V8_BASE_PLATFORM_TIME_H_ #define V8_BASE_PLATFORM_TIME_H_ +#include <stdint.h> + #include <ctime> #include <iosfwd> #include <limits> @@ -45,7 +47,7 @@ class TimeBase; class V8_BASE_EXPORT TimeDelta final { public: - TimeDelta() : delta_(0) {} + constexpr TimeDelta() : delta_(0) {} // Converts units of time to TimeDeltas. static TimeDelta FromDays(int days); @@ -58,6 +60,27 @@ class V8_BASE_EXPORT TimeDelta final { } static TimeDelta FromNanoseconds(int64_t nanoseconds); + // Returns the maximum time delta, which should be greater than any reasonable + // time delta we might compare it to. Adding or subtracting the maximum time + // delta to a time or another time delta has an undefined result. + static constexpr TimeDelta Max(); + + // Returns the minimum time delta, which should be less than than any + // reasonable time delta we might compare it to. Adding or subtracting the + // minimum time delta to a time or another time delta has an undefined result. + static constexpr TimeDelta Min(); + + // Returns true if the time delta is zero. + constexpr bool IsZero() const { return delta_ == 0; } + + // Returns true if the time delta is the maximum/minimum time delta. + constexpr bool IsMax() const { + return delta_ == std::numeric_limits<int64_t>::max(); + } + constexpr bool IsMin() const { + return delta_ == std::numeric_limits<int64_t>::min(); + } + // Returns the time delta in some unit. The F versions return a floating // point value, the "regular" versions return a rounded-down value. // @@ -71,7 +94,7 @@ class V8_BASE_EXPORT TimeDelta final { double InMillisecondsF() const; int64_t InMilliseconds() const; int64_t InMillisecondsRoundedUp() const; - int64_t InMicroseconds() const { return delta_; } + int64_t InMicroseconds() const; int64_t InNanoseconds() const; // Converts to/from Mach time specs. @@ -103,9 +126,7 @@ class V8_BASE_EXPORT TimeDelta final { delta_ -= other.delta_; return *this; } - TimeDelta operator-() const { - return TimeDelta(-delta_); - } + constexpr TimeDelta operator-() const { return TimeDelta(-delta_); } double TimesOf(const TimeDelta& other) const { return static_cast<double>(delta_) / static_cast<double>(other.delta_); @@ -135,22 +156,22 @@ class V8_BASE_EXPORT TimeDelta final { } // Comparison operators. - bool operator==(const TimeDelta& other) const { + constexpr bool operator==(const TimeDelta& other) const { return delta_ == other.delta_; } - bool operator!=(const TimeDelta& other) const { + constexpr bool operator!=(const TimeDelta& other) const { return delta_ != other.delta_; } - bool operator<(const TimeDelta& other) const { + constexpr bool operator<(const TimeDelta& other) const { return delta_ < other.delta_; } - bool operator<=(const TimeDelta& other) const { + constexpr bool operator<=(const TimeDelta& other) const { return delta_ <= other.delta_; } - bool operator>(const TimeDelta& other) const { + constexpr bool operator>(const TimeDelta& other) const { return delta_ > other.delta_; } - bool operator>=(const TimeDelta& other) const { + constexpr bool operator>=(const TimeDelta& other) const { return delta_ >= other.delta_; } @@ -159,12 +180,21 @@ class V8_BASE_EXPORT TimeDelta final { // Constructs a delta given the duration in microseconds. This is private // to avoid confusion by callers with an integer constructor. Use // FromSeconds, FromMilliseconds, etc. instead. - explicit TimeDelta(int64_t delta) : delta_(delta) {} + explicit constexpr TimeDelta(int64_t delta) : delta_(delta) {} // Delta in microseconds. int64_t delta_; }; +// static +constexpr TimeDelta TimeDelta::Max() { + return TimeDelta(std::numeric_limits<int64_t>::max()); +} + +// static +constexpr TimeDelta TimeDelta::Min() { + return TimeDelta(std::numeric_limits<int64_t>::min()); +} namespace time_internal { @@ -177,33 +207,52 @@ namespace time_internal { template<class TimeClass> class TimeBase { public: - static const int64_t kHoursPerDay = 24; - static const int64_t kMillisecondsPerSecond = 1000; - static const int64_t kMillisecondsPerDay = + static constexpr int64_t kHoursPerDay = 24; + static constexpr int64_t kMillisecondsPerSecond = 1000; + static constexpr int64_t kMillisecondsPerDay = kMillisecondsPerSecond * 60 * 60 * kHoursPerDay; - static const int64_t kMicrosecondsPerMillisecond = 1000; - static const int64_t kMicrosecondsPerSecond = + static constexpr int64_t kMicrosecondsPerMillisecond = 1000; + static constexpr int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * kMillisecondsPerSecond; - static const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; - static const int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; - static const int64_t kMicrosecondsPerDay = + static constexpr int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60; + static constexpr int64_t kMicrosecondsPerHour = kMicrosecondsPerMinute * 60; + static constexpr int64_t kMicrosecondsPerDay = kMicrosecondsPerHour * kHoursPerDay; - static const int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; - static const int64_t kNanosecondsPerMicrosecond = 1000; - static const int64_t kNanosecondsPerSecond = + static constexpr int64_t kMicrosecondsPerWeek = kMicrosecondsPerDay * 7; + static constexpr int64_t kNanosecondsPerMicrosecond = 1000; + static constexpr int64_t kNanosecondsPerSecond = kNanosecondsPerMicrosecond * kMicrosecondsPerSecond; +#if V8_OS_WIN + // To avoid overflow in QPC to Microseconds calculations, since we multiply + // by kMicrosecondsPerSecond, then the QPC value should not exceed + // (2^63 - 1) / 1E6. If it exceeds that threshold, we divide then multiply. + static constexpr int64_t kQPCOverflowThreshold = INT64_C(0x8637BD05AF7); +#endif + // Returns true if this object has not been initialized. // // Warning: Be careful when writing code that performs math on time values, // since it's possible to produce a valid "zero" result that should not be // interpreted as a "null" value. - bool IsNull() const { - return us_ == 0; + constexpr bool IsNull() const { return us_ == 0; } + + // Returns the maximum/minimum times, which should be greater/less than any + // reasonable time with which we might compare it. + static TimeClass Max() { + return TimeClass(std::numeric_limits<int64_t>::max()); + } + static TimeClass Min() { + return TimeClass(std::numeric_limits<int64_t>::min()); } - // Returns true if this object represents the maximum time. - bool IsMax() const { return us_ == std::numeric_limits<int64_t>::max(); } + // Returns true if this object represents the maximum/minimum time. + constexpr bool IsMax() const { + return us_ == std::numeric_limits<int64_t>::max(); + } + constexpr bool IsMin() const { + return us_ == std::numeric_limits<int64_t>::min(); + } // For serializing only. Use FromInternalValue() to reconstitute. Please don't // use this and do arithmetic on it, as it is more error prone than using the @@ -263,7 +312,7 @@ class TimeBase { static TimeClass FromInternalValue(int64_t us) { return TimeClass(us); } protected: - explicit TimeBase(int64_t us) : us_(us) {} + explicit constexpr TimeBase(int64_t us) : us_(us) {} // Time value in a microsecond timebase. int64_t us_; @@ -281,7 +330,7 @@ class TimeBase { class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> { public: // Contains the nullptr time. Use Time::Now() to get the current time. - Time() : TimeBase(0) {} + constexpr Time() : TimeBase(0) {} // Returns the current time. Watch out, the system might adjust its clock // in which case time will actually go backwards. We don't guarantee that @@ -297,10 +346,6 @@ class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> { // Returns the time for epoch in Unix-like system (Jan 1, 1970). static Time UnixEpoch() { return Time(0); } - // Returns the maximum time, which should be greater than any reasonable time - // with which we might compare it. - static Time Max() { return Time(std::numeric_limits<int64_t>::max()); } - // Converts to/from POSIX time specs. static Time FromTimespec(struct timespec ts); struct timespec ToTimespec() const; @@ -320,7 +365,7 @@ class V8_BASE_EXPORT Time final : public time_internal::TimeBase<Time> { private: friend class time_internal::TimeBase<Time>; - explicit Time(int64_t us) : TimeBase(us) {} + explicit constexpr Time(int64_t us) : TimeBase(us) {} }; V8_BASE_EXPORT std::ostream& operator<<(std::ostream&, const Time&); @@ -343,30 +388,29 @@ inline Time operator+(const TimeDelta& delta, const Time& time) { class V8_BASE_EXPORT TimeTicks final : public time_internal::TimeBase<TimeTicks> { public: - TimeTicks() : TimeBase(0) {} + constexpr TimeTicks() : TimeBase(0) {} - // Platform-dependent tick count representing "right now." - // The resolution of this clock is ~1-15ms. Resolution varies depending - // on hardware/operating system configuration. + // Platform-dependent tick count representing "right now." When + // IsHighResolution() returns false, the resolution of the clock could be as + // coarse as ~15.6ms. Otherwise, the resolution should be no worse than one + // microsecond. // This method never returns a null TimeTicks. static TimeTicks Now(); - // Returns a platform-dependent high-resolution tick count. Implementation - // is hardware dependent and may or may not return sub-millisecond - // resolution. THIS CALL IS GENERALLY MUCH MORE EXPENSIVE THAN Now() AND - // SHOULD ONLY BE USED WHEN IT IS REALLY NEEDED. - // This method never returns a null TimeTicks. + // This is equivalent to Now() but DCHECKs that IsHighResolution(). Useful for + // test frameworks that rely on high resolution clocks (in practice all + // platforms but low-end Windows devices have high resolution clocks). static TimeTicks HighResolutionNow(); // Returns true if the high-resolution clock is working on this system. - static bool IsHighResolutionClockWorking(); + static bool IsHighResolution(); private: friend class time_internal::TimeBase<TimeTicks>; // Please use Now() to create a new object. This is for internal use // and testing. Ticks are in microseconds. - explicit TimeTicks(int64_t ticks) : TimeBase(ticks) {} + explicit constexpr TimeTicks(int64_t ticks) : TimeBase(ticks) {} }; inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) { @@ -381,7 +425,7 @@ inline TimeTicks operator+(const TimeDelta& delta, const TimeTicks& ticks) { class V8_BASE_EXPORT ThreadTicks final : public time_internal::TimeBase<ThreadTicks> { public: - ThreadTicks() : TimeBase(0) {} + constexpr ThreadTicks() : TimeBase(0) {} // Returns true if ThreadTicks::Now() is supported on this system. static bool IsSupported(); @@ -416,7 +460,7 @@ class V8_BASE_EXPORT ThreadTicks final // Please use Now() or GetForThread() to create a new object. This is for // internal use and testing. Ticks are in microseconds. - explicit ThreadTicks(int64_t ticks) : TimeBase(ticks) {} + explicit constexpr ThreadTicks(int64_t ticks) : TimeBase(ticks) {} #if V8_OS_WIN // Returns the frequency of the TSC in ticks per second, or 0 if it hasn't diff --git a/deps/v8/src/base/qnx-math.h b/deps/v8/src/base/qnx-math.h index 6ff18f8d12..1503c164fa 100644 --- a/deps/v8/src/base/qnx-math.h +++ b/deps/v8/src/base/qnx-math.h @@ -3,7 +3,7 @@ // found in the LICENSE file. #ifndef V8_BASE_QNX_MATH_H_ -#define V8_QBASE_NX_MATH_H_ +#define V8_BASE_QNX_MATH_H_ #include <cmath> diff --git a/deps/v8/src/base/sys-info.cc b/deps/v8/src/base/sys-info.cc index 28ff780dd3..3d47ebe8f7 100644 --- a/deps/v8/src/base/sys-info.cc +++ b/deps/v8/src/base/sys-info.cc @@ -5,11 +5,13 @@ #include "src/base/sys-info.h" #if V8_OS_POSIX -#include <sys/resource.h> #include <sys/stat.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> +#if !V8_OS_FUCHSIA +#include <sys/resource.h> +#endif #endif #if V8_OS_BSD @@ -101,7 +103,7 @@ int64_t SysInfo::AmountOfPhysicalMemory() { // static int64_t SysInfo::AmountOfVirtualMemory() { -#if V8_OS_WIN +#if V8_OS_WIN || V8_OS_FUCHSIA return 0; #elif V8_OS_POSIX struct rlimit rlim; diff --git a/deps/v8/src/base/template-utils.h b/deps/v8/src/base/template-utils.h index 18850695cb..18b50fe70c 100644 --- a/deps/v8/src/base/template-utils.h +++ b/deps/v8/src/base/template-utils.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef V8_BASE_TEMPLATE_UTILS_H -#define V8_BASE_TEMPLATE_UTILS_H +#ifndef V8_BASE_TEMPLATE_UTILS_H_ +#define V8_BASE_TEMPLATE_UTILS_H_ #include <array> #include <memory> @@ -131,4 +131,4 @@ constexpr auto fold(Func func, Ts&&... more) -> } // namespace base } // namespace v8 -#endif // V8_BASE_TEMPLATE_UTILS_H +#endif // V8_BASE_TEMPLATE_UTILS_H_ diff --git a/deps/v8/src/base/v8-fallthrough.h b/deps/v8/src/base/v8-fallthrough.h new file mode 100644 index 0000000000..f61238de06 --- /dev/null +++ b/deps/v8/src/base/v8-fallthrough.h @@ -0,0 +1,21 @@ +// Copyright 2018 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_V8_FALLTHROUGH_H_ +#define V8_BASE_V8_FALLTHROUGH_H_ + +// When clang suggests inserting [[clang::fallthrough]], it first checks if +// it knows of a macro expanding to it, and if so suggests inserting the +// macro. This means that this macro must be used only in code internal +// to v8, so that v8's user code doesn't end up getting suggestions +// for V8_FALLTHROUGH instead of the user-specific fallthrough macro. +// So do not include this header in any of v8's public headers -- only +// use it in src/, not in include/. +#if defined(__clang__) +#define V8_FALLTHROUGH [[clang::fallthrough]] // NOLINT(whitespace/braces) +#else +#define V8_FALLTHROUGH +#endif + +#endif // V8_BASE_V8_FALLTHROUGH_H_ |