summaryrefslogtreecommitdiff
path: root/deps/v8/src/base
diff options
context:
space:
mode:
authorMyles Borins <mylesborins@google.com>2018-04-10 21:39:51 -0400
committerMyles Borins <mylesborins@google.com>2018-04-11 13:22:42 -0400
commit12a1b9b8049462e47181a298120243dc83e81c55 (patch)
tree8605276308c8b4e3597516961266bae1af57557a /deps/v8/src/base
parent78cd8263354705b767ef8c6a651740efe4931ba0 (diff)
downloadnode-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.h6
-rw-r--r--deps/v8/src/base/atomicops_internals_portable.h4
-rw-r--r--deps/v8/src/base/atomicops_internals_std.h4
-rw-r--r--deps/v8/src/base/cpu.cc3
-rw-r--r--deps/v8/src/base/file-utils.h2
-rw-r--r--deps/v8/src/base/format-macros.h6
-rw-r--r--deps/v8/src/base/logging.cc38
-rw-r--r--deps/v8/src/base/logging.h12
-rw-r--r--deps/v8/src/base/macros.h2
-rw-r--r--deps/v8/src/base/optional.h8
-rw-r--r--deps/v8/src/base/platform/platform-cygwin.cc2
-rw-r--r--deps/v8/src/base/platform/platform-fuchsia.cc16
-rw-r--r--deps/v8/src/base/platform/platform-posix.cc21
-rw-r--r--deps/v8/src/base/platform/platform-win32.cc9
-rw-r--r--deps/v8/src/base/platform/time.cc370
-rw-r--r--deps/v8/src/base/platform/time.h138
-rw-r--r--deps/v8/src/base/qnx-math.h2
-rw-r--r--deps/v8/src/base/sys-info.cc6
-rw-r--r--deps/v8/src/base/template-utils.h6
-rw-r--r--deps/v8/src/base/v8-fallthrough.h21
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_