From f59bcf2f3b90141d0f5672ff68abec76ef22ae81 Mon Sep 17 00:00:00 2001 From: "hpayer@chromium.org" Date: Wed, 25 Sep 2013 09:50:48 +0000 Subject: [PATCH] Revert OS::TimeCurrentMillis on Windows introduced in r16413. BUG=chromium:288924 R=danno@chromium.org, jkummerow@chromium.org Review URL: https://codereview.chromium.org/24529002 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@16938 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/platform-win32.cc | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++- test/mjsunit/timer.js | 35 ++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 test/mjsunit/timer.js diff --git a/src/platform-win32.cc b/src/platform-win32.cc index 7b26dfb..41a4f14 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -240,12 +240,16 @@ void MathSetup() { class Win32Time { public: // Constructors. + Win32Time(); explicit Win32Time(double jstime); Win32Time(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 @@ -314,6 +318,12 @@ char Win32Time::std_tz_name_[kTzNameSize]; char Win32Time::dst_tz_name_[kTzNameSize]; +// Initialize timestamp to start of epoc. +Win32Time::Win32Time() { + t() = 0; +} + + // Initialize timestamp from a JavaScript timestamp. Win32Time::Win32Time(double jstime) { t() = static_cast(jstime) * kTimeScaler + kTimeEpoc; @@ -340,6 +350,62 @@ double Win32Time::ToJSTime() { } +// Set timestamp to current time. +void Win32Time::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(elapsed) * 10000); +} + + // Guess the name of the timezone from the bias. // The guess is very biased towards the northern hemisphere. const char* Win32Time::GuessTimezoneNameFromBias(int bias) { @@ -529,7 +595,9 @@ 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(); + Win32Time t; + t.SetToCurrentTime(); + return t.ToJSTime(); } diff --git a/test/mjsunit/timer.js b/test/mjsunit/timer.js new file mode 100644 index 0000000..9b8dc29 --- /dev/null +++ b/test/mjsunit/timer.js @@ -0,0 +1,35 @@ +// Copyright 2013 the V8 project authors. All rights reserved. +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following +// disclaimer in the documentation and/or other materials provided +// with the distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// Tests timer milliseconds granularity. + +var start = Date.now(); +var end = Date.now(); +while (end - start == 0) { + end = Date.now(); +} +assertTrue(end - start <= 2); -- 2.7.4