Index: src/platform/time.cc |
diff --git a/src/platform/time.cc b/src/platform/time.cc |
index ea6dd2c0bae6cfea3fc947b4c6f841c91a58b875..de0ca16473f6b5106485508653cfe797f6632c37 100644 |
--- a/src/platform/time.cc |
+++ b/src/platform/time.cc |
@@ -43,13 +43,6 @@ |
#include "win32-headers.h" |
#endif |
-#if V8_OS_WIN |
-// Prototype for GetTickCount64() procedure. |
-extern "C" { |
-typedef ULONGLONG (WINAPI *GETTICKCOUNT64PROC)(void); |
-} |
-#endif |
- |
namespace v8 { |
namespace internal { |
@@ -175,43 +168,43 @@ struct timespec TimeDelta::ToTimespec() const { |
// periodically resync the internal clock to the system clock. |
class Clock V8_FINAL { |
public: |
- Clock() : initial_time_(CurrentWallclockTime()), |
- initial_ticks_(TimeTicks::Now()) {} |
+ Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {} |
Time Now() { |
- // This must be executed under lock. |
- LockGuard<Mutex> lock_guard(&mutex_); |
+ // Time between resampling the un-granular clock for this API (1 minute). |
+ const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1); |
- // Calculate the time elapsed since we started our timer. |
- TimeDelta elapsed = TimeTicks::Now() - initial_ticks_; |
+ LockGuard<Mutex> lock_guard(&mutex_); |
- // Check if we don't need to synchronize with the wallclock yet. |
- if (elapsed.InMicroseconds() <= kMaxMicrosecondsToAvoidDrift) { |
- return initial_time_ + elapsed; |
+ // Determine current time and ticks. |
+ TimeTicks ticks = GetSystemTicks(); |
+ Time time = GetSystemTime(); |
+ |
+ // Check if we need to synchronize with the system clock due to a backwards |
+ // time change or the amount of time elapsed. |
+ TimeDelta elapsed = ticks - initial_ticks_; |
+ if (time < initial_time_ || elapsed > kMaxElapsedTime) { |
+ initial_ticks_ = ticks; |
+ initial_time_ = time; |
+ return time; |
} |
- // Resynchronize with the wallclock. |
- initial_ticks_ = TimeTicks::Now(); |
- initial_time_ = CurrentWallclockTime(); |
- return initial_time_; |
+ return initial_time_ + elapsed; |
} |
Time NowFromSystemTime() { |
- // This must be executed under lock. |
LockGuard<Mutex> lock_guard(&mutex_); |
- |
- // Resynchronize with the wallclock. |
- initial_ticks_ = TimeTicks::Now(); |
- initial_time_ = CurrentWallclockTime(); |
+ initial_ticks_ = GetSystemTicks(); |
+ initial_time_ = GetSystemTime(); |
return initial_time_; |
} |
private: |
- // Time between resampling the un-granular clock for this API (1 minute). |
- static const int64_t kMaxMicrosecondsToAvoidDrift = |
- Time::kMicrosecondsPerMinute; |
+ static TimeTicks GetSystemTicks() { |
+ return TimeTicks::Now(); |
+ } |
- static Time CurrentWallclockTime() { |
+ static Time GetSystemTime() { |
FILETIME ft; |
::GetSystemTimeAsFileTime(&ft); |
return Time::FromFiletime(ft); |
@@ -223,9 +216,9 @@ class Clock V8_FINAL { |
}; |
-static LazyDynamicInstance<Clock, |
- DefaultCreateTrait<Clock>, |
- ThreadSafeInitOnceTrait>::type clock = LAZY_DYNAMIC_INSTANCE_INITIALIZER; |
+static LazyStaticInstance<Clock, |
+ DefaultConstructTrait<Clock>, |
+ ThreadSafeInitOnceTrait>::type clock = LAZY_STATIC_INSTANCE_INITIALIZER; |
Time Time::Now() { |
@@ -388,6 +381,7 @@ class TickClock { |
public: |
virtual ~TickClock() {} |
virtual int64_t Now() = 0; |
+ virtual bool IsHighResolution() = 0; |
}; |
@@ -440,42 +434,24 @@ class HighResolutionTickClock V8_FINAL : public TickClock { |
int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) + |
((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_); |
- // Make sure we never return 0 here, so that TimeTicks::HighResNow() |
+ // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow() |
// will never return 0. |
return ticks + 1; |
} |
- private: |
- int64_t ticks_per_second_; |
-}; |
- |
- |
-// The GetTickCount64() API is what we actually want for the regular tick |
-// clock, but this is only available starting with Windows Vista. |
-class WindowsVistaTickClock V8_FINAL : public TickClock { |
- public: |
- explicit WindowsVistaTickClock(GETTICKCOUNT64PROC func) : func_(func) { |
- ASSERT(func_ != NULL); |
- } |
- virtual ~WindowsVistaTickClock() {} |
- |
- virtual int64_t Now() V8_OVERRIDE { |
- // Query the current ticks (in ms). |
- ULONGLONG tick_count_ms = (*func_)(); |
- |
- // Convert to microseconds (make sure to never return 0 here). |
- return (tick_count_ms * Time::kMicrosecondsPerMillisecond) + 1; |
+ virtual bool IsHighResolution() V8_OVERRIDE { |
+ return true; |
} |
private: |
- GETTICKCOUNT64PROC func_; |
+ int64_t ticks_per_second_; |
}; |
class RolloverProtectedTickClock V8_FINAL : public TickClock { |
public: |
// We initialize rollover_ms_ to 1 to ensure that we will never |
- // return 0 from TimeTicks::HighResNow() and TimeTicks::Now() below. |
+ // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below. |
RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {} |
virtual ~RolloverProtectedTickClock() {} |
@@ -487,6 +463,9 @@ class RolloverProtectedTickClock V8_FINAL : public TickClock { |
// Note that we do not use GetTickCount() here, since timeGetTime() gives |
// more predictable delta values, as described here: |
// http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx |
+ // timeGetTime() provides 1ms granularity when combined with |
+ // timeBeginPeriod(). If the host application for V8 wants fast timers, it |
+ // can use timeBeginPeriod() to increase the resolution. |
DWORD now = timeGetTime(); |
if (now < last_seen_now_) { |
rollover_ms_ += V8_INT64_C(0x100000000); // ~49.7 days. |
@@ -495,6 +474,10 @@ class RolloverProtectedTickClock V8_FINAL : public TickClock { |
return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond; |
} |
+ virtual bool IsHighResolution() V8_OVERRIDE { |
+ return false; |
+ } |
+ |
private: |
Mutex mutex_; |
DWORD last_seen_now_; |
@@ -502,27 +485,10 @@ class RolloverProtectedTickClock V8_FINAL : public TickClock { |
}; |
-struct CreateTickClockTrait { |
- static TickClock* Create() { |
- // Try to load GetTickCount64() from kernel32.dll (available since Vista). |
- HMODULE kernel32 = ::GetModuleHandleA("kernel32.dll"); |
- ASSERT(kernel32 != NULL); |
- FARPROC proc = ::GetProcAddress(kernel32, "GetTickCount64"); |
- if (proc != NULL) { |
- return new WindowsVistaTickClock( |
- reinterpret_cast<GETTICKCOUNT64PROC>(proc)); |
- } |
- |
- // Fallback to the rollover protected tick clock. |
- return new RolloverProtectedTickClock; |
- } |
-}; |
- |
- |
-static LazyDynamicInstance<TickClock, |
- CreateTickClockTrait, |
+static LazyStaticInstance<RolloverProtectedTickClock, |
+ DefaultConstructTrait<RolloverProtectedTickClock>, |
ThreadSafeInitOnceTrait>::type tick_clock = |
- LAZY_DYNAMIC_INSTANCE_INITIALIZER; |
+ LAZY_STATIC_INSTANCE_INITIALIZER; |
struct CreateHighResTickClockTrait { |
@@ -560,21 +526,27 @@ TimeTicks TimeTicks::Now() { |
} |
-TimeTicks TimeTicks::HighResNow() { |
+TimeTicks TimeTicks::HighResolutionNow() { |
// Make sure we never return 0 here. |
TimeTicks ticks(high_res_tick_clock.Pointer()->Now()); |
ASSERT(!ticks.IsNull()); |
return ticks; |
} |
+ |
+// static |
+bool TimeTicks::IsHighResolutionClockWorking() { |
+ return high_res_tick_clock.Pointer()->IsHighResolution(); |
+} |
+ |
#else // V8_OS_WIN |
TimeTicks TimeTicks::Now() { |
- return HighResNow(); |
+ return HighResolutionNow(); |
} |
-TimeTicks TimeTicks::HighResNow() { |
+TimeTicks TimeTicks::HighResolutionNow() { |
int64_t ticks; |
#if V8_OS_MACOSX |
static struct mach_timebase_info info; |
@@ -608,6 +580,12 @@ TimeTicks TimeTicks::HighResNow() { |
return TimeTicks(ticks + 1); |
} |
+ |
+// static |
+bool TimeTicks::IsHighResolutionClockWorking() { |
+ return true; |
+} |
+ |
#endif // V8_OS_WIN |
} } // namespace v8::internal |