| Index: src/platform-win32.cc
|
| diff --git a/src/platform-win32.cc b/src/platform-win32.cc
|
| index cdd9a4fb4694c5835648964fa147c273423f8278..c136631f00272659ed76f845ca8fd59c965ddd4d 100644
|
| --- a/src/platform-win32.cc
|
| +++ b/src/platform-win32.cc
|
| @@ -38,6 +38,7 @@
|
| #endif // MINGW_HAS_SECURE_API
|
| #endif // __MINGW32__
|
|
|
| +#define V8_WIN32_HEADERS_FULL
|
| #include "win32-headers.h"
|
|
|
| #include "v8.h"
|
| @@ -245,15 +246,19 @@ void MathSetup() {
|
| // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC,
|
| // January 1, 1970.
|
|
|
| -class Win32Time {
|
| +class Time {
|
| public:
|
| // Constructors.
|
| - explicit Win32Time(double jstime);
|
| - Win32Time(int year, int mon, int day, int hour, int min, int sec);
|
| + Time();
|
| + explicit Time(double jstime);
|
| + Time(int year, int mon, int day, int hour, int min, int sec);
|
|
|
| // Convert timestamp to JavaScript representation.
|
| double ToJSTime();
|
|
|
| + // Set timestamp to current time.
|
| + void SetToCurrentTime();
|
| +
|
| // Returns the local timezone offset in milliseconds east of UTC. This is
|
| // the number of milliseconds you must add to UTC to get local time, i.e.
|
| // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This
|
| @@ -295,6 +300,10 @@ class Win32Time {
|
| // Return whether or not daylight savings time is in effect at this time.
|
| bool InDST();
|
|
|
| + // Return the difference (in milliseconds) between this timestamp and
|
| + // another timestamp.
|
| + int64_t Diff(Time* other);
|
| +
|
| // Accessor for FILETIME representation.
|
| FILETIME& ft() { return time_.ft_; }
|
|
|
| @@ -316,20 +325,26 @@ class Win32Time {
|
|
|
|
|
| // Static variables.
|
| -bool Win32Time::tz_initialized_ = false;
|
| -TIME_ZONE_INFORMATION Win32Time::tzinfo_;
|
| -char Win32Time::std_tz_name_[kTzNameSize];
|
| -char Win32Time::dst_tz_name_[kTzNameSize];
|
| +bool Time::tz_initialized_ = false;
|
| +TIME_ZONE_INFORMATION Time::tzinfo_;
|
| +char Time::std_tz_name_[kTzNameSize];
|
| +char Time::dst_tz_name_[kTzNameSize];
|
| +
|
| +
|
| +// Initialize timestamp to start of epoc.
|
| +Time::Time() {
|
| + t() = 0;
|
| +}
|
|
|
|
|
| // Initialize timestamp from a JavaScript timestamp.
|
| -Win32Time::Win32Time(double jstime) {
|
| +Time::Time(double jstime) {
|
| t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc;
|
| }
|
|
|
|
|
| // Initialize timestamp from date/time components.
|
| -Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) {
|
| +Time::Time(int year, int mon, int day, int hour, int min, int sec) {
|
| SYSTEMTIME st;
|
| st.wYear = year;
|
| st.wMonth = mon;
|
| @@ -343,14 +358,14 @@ Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) {
|
|
|
|
|
| // Convert timestamp to JavaScript timestamp.
|
| -double Win32Time::ToJSTime() {
|
| +double Time::ToJSTime() {
|
| return static_cast<double>((t() - kTimeEpoc) / kTimeScaler);
|
| }
|
|
|
|
|
| // Guess the name of the timezone from the bias.
|
| // The guess is very biased towards the northern hemisphere.
|
| -const char* Win32Time::GuessTimezoneNameFromBias(int bias) {
|
| +const char* Time::GuessTimezoneNameFromBias(int bias) {
|
| static const int kHour = 60;
|
| switch (-bias) {
|
| case -9*kHour: return "Alaska";
|
| @@ -375,7 +390,7 @@ const char* Win32Time::GuessTimezoneNameFromBias(int bias) {
|
| // Initialize timezone information. The timezone information is obtained from
|
| // windows. If we cannot get the timezone information we fall back to CET.
|
| // Please notice that this code is not thread-safe.
|
| -void Win32Time::TzSet() {
|
| +void Time::TzSet() {
|
| // Just return if timezone information has already been initialized.
|
| if (tz_initialized_) return;
|
|
|
| @@ -424,16 +439,78 @@ void Win32Time::TzSet() {
|
| }
|
|
|
|
|
| +// Return the difference in milliseconds between this and another timestamp.
|
| +int64_t Time::Diff(Time* other) {
|
| + return (t() - other->t()) / kTimeScaler;
|
| +}
|
| +
|
| +
|
| +// Set timestamp to current time.
|
| +void Time::SetToCurrentTime() {
|
| + // The default GetSystemTimeAsFileTime has a ~15.5ms resolution.
|
| + // Because we're fast, we like fast timers which have at least a
|
| + // 1ms resolution.
|
| + //
|
| + // 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.
|
| + //
|
| + // Using timeGetTime() has a drawback because it is a 32bit value
|
| + // and hence rolls-over every ~49days.
|
| + //
|
| + // To use the clock, we use GetSystemTimeAsFileTime as our base;
|
| + // and then use timeGetTime to extrapolate current time from the
|
| + // start time. To deal with rollovers, we resync the clock
|
| + // any time when more than kMaxClockElapsedTime has passed or
|
| + // whenever timeGetTime creates a rollover.
|
| +
|
| + static bool initialized = false;
|
| + static TimeStamp init_time;
|
| + static DWORD init_ticks;
|
| + static const int64_t kHundredNanosecondsPerSecond = 10000000;
|
| + static const int64_t kMaxClockElapsedTime =
|
| + 60*kHundredNanosecondsPerSecond; // 1 minute
|
| +
|
| + // If we are uninitialized, we need to resync the clock.
|
| + bool needs_resync = !initialized;
|
| +
|
| + // Get the current time.
|
| + TimeStamp time_now;
|
| + GetSystemTimeAsFileTime(&time_now.ft_);
|
| + DWORD ticks_now = timeGetTime();
|
| +
|
| + // Check if we need to resync due to clock rollover.
|
| + needs_resync |= ticks_now < init_ticks;
|
| +
|
| + // Check if we need to resync due to elapsed time.
|
| + needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime;
|
| +
|
| + // Check if we need to resync due to backwards time change.
|
| + needs_resync |= time_now.t_ < init_time.t_;
|
| +
|
| + // Resync the clock if necessary.
|
| + if (needs_resync) {
|
| + GetSystemTimeAsFileTime(&init_time.ft_);
|
| + init_ticks = ticks_now = timeGetTime();
|
| + initialized = true;
|
| + }
|
| +
|
| + // Finally, compute the actual time. Why is this so hard.
|
| + DWORD elapsed = ticks_now - init_ticks;
|
| + this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000);
|
| +}
|
| +
|
| +
|
| // Return the local timezone offset in milliseconds east of UTC. This
|
| // takes into account whether daylight saving is in effect at the time.
|
| // Only times in the 32-bit Unix range may be passed to this function.
|
| // Also, adding the time-zone offset to the input must not overflow.
|
| // The function EquivalentTime() in date.js guarantees this.
|
| -int64_t Win32Time::LocalOffset() {
|
| +int64_t Time::LocalOffset() {
|
| // Initialize timezone information, if needed.
|
| TzSet();
|
|
|
| - Win32Time rounded_to_second(*this);
|
| + Time rounded_to_second(*this);
|
| rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
|
| 1000 * kTimeScaler;
|
| // Convert to local time using POSIX localtime function.
|
| @@ -464,7 +541,7 @@ int64_t Win32Time::LocalOffset() {
|
|
|
|
|
| // Return whether or not daylight savings time is in effect at this time.
|
| -bool Win32Time::InDST() {
|
| +bool Time::InDST() {
|
| // Initialize timezone information, if needed.
|
| TzSet();
|
|
|
| @@ -488,14 +565,14 @@ bool Win32Time::InDST() {
|
|
|
|
|
| // Return the daylight savings time offset for this time.
|
| -int64_t Win32Time::DaylightSavingsOffset() {
|
| +int64_t Time::DaylightSavingsOffset() {
|
| return InDST() ? 60 * kMsPerMinute : 0;
|
| }
|
|
|
|
|
| // Returns a string identifying the current timezone for the
|
| // timestamp taking into account daylight saving.
|
| -char* Win32Time::LocalTimezone() {
|
| +char* Time::LocalTimezone() {
|
| // Return the standard or DST time zone name based on whether daylight
|
| // saving is in effect at the given time.
|
| return InDST() ? dst_tz_name_ : std_tz_name_;
|
| @@ -537,14 +614,22 @@ int OS::GetUserTime(uint32_t* secs, uint32_t* usecs) {
|
| // Returns current time as the number of milliseconds since
|
| // 00:00:00 UTC, January 1, 1970.
|
| double OS::TimeCurrentMillis() {
|
| - return Time::Now().ToJsTime();
|
| + Time t;
|
| + t.SetToCurrentTime();
|
| + return t.ToJSTime();
|
| +}
|
| +
|
| +
|
| +// Returns the tickcounter based on timeGetTime.
|
| +int64_t OS::Ticks() {
|
| + return timeGetTime() * 1000; // Convert to microseconds.
|
| }
|
|
|
|
|
| // Returns a string identifying the current timezone taking into
|
| // account daylight saving.
|
| const char* OS::LocalTimezone(double time) {
|
| - return Win32Time(time).LocalTimezone();
|
| + return Time(time).LocalTimezone();
|
| }
|
|
|
|
|
| @@ -552,7 +637,7 @@ const char* OS::LocalTimezone(double time) {
|
| // taking daylight savings time into account.
|
| double OS::LocalTimeOffset() {
|
| // Use current time, rounded to the millisecond.
|
| - Win32Time t(TimeCurrentMillis());
|
| + Time t(TimeCurrentMillis());
|
| // Time::LocalOffset inlcudes any daylight savings offset, so subtract it.
|
| return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset());
|
| }
|
| @@ -561,7 +646,7 @@ double OS::LocalTimeOffset() {
|
| // Returns the daylight savings offset in milliseconds for the given
|
| // time.
|
| double OS::DaylightSavingsOffset(double time) {
|
| - int64_t offset = Win32Time(time).DaylightSavingsOffset();
|
| + int64_t offset = Time(time).DaylightSavingsOffset();
|
| return static_cast<double>(offset);
|
| }
|
|
|
|
|