Revision f230a1cf deps/v8/src/platform/time.cc

View differences:

deps/v8/src/platform/time.cc
43 43
#include "win32-headers.h"
44 44
#endif
45 45

  
46
#if V8_OS_WIN
47
// Prototype for GetTickCount64() procedure.
48
extern "C" {
49
typedef ULONGLONG (WINAPI *GETTICKCOUNT64PROC)(void);
50
}
51
#endif
52

  
53 46
namespace v8 {
54 47
namespace internal {
55 48

  
......
175 168
// periodically resync the internal clock to the system clock.
176 169
class Clock V8_FINAL {
177 170
 public:
178
  Clock() : initial_time_(CurrentWallclockTime()),
179
            initial_ticks_(TimeTicks::Now()) {}
171
  Clock() : initial_ticks_(GetSystemTicks()), initial_time_(GetSystemTime()) {}
180 172

  
181 173
  Time Now() {
182
    // This must be executed under lock.
183
    LockGuard<Mutex> lock_guard(&mutex_);
174
    // Time between resampling the un-granular clock for this API (1 minute).
175
    const TimeDelta kMaxElapsedTime = TimeDelta::FromMinutes(1);
184 176

  
185
    // Calculate the time elapsed since we started our timer.
186
    TimeDelta elapsed = TimeTicks::Now() - initial_ticks_;
177
    LockGuard<Mutex> lock_guard(&mutex_);
187 178

  
188
    // Check if we don't need to synchronize with the wallclock yet.
189
    if (elapsed.InMicroseconds() <= kMaxMicrosecondsToAvoidDrift) {
190
      return initial_time_ + elapsed;
179
    // Determine current time and ticks.
180
    TimeTicks ticks = GetSystemTicks();
181
    Time time = GetSystemTime();
182

  
183
    // Check if we need to synchronize with the system clock due to a backwards
184
    // time change or the amount of time elapsed.
185
    TimeDelta elapsed = ticks - initial_ticks_;
186
    if (time < initial_time_ || elapsed > kMaxElapsedTime) {
187
      initial_ticks_ = ticks;
188
      initial_time_ = time;
189
      return time;
191 190
    }
192 191

  
193
    // Resynchronize with the wallclock.
194
    initial_ticks_ = TimeTicks::Now();
195
    initial_time_ = CurrentWallclockTime();
196
    return initial_time_;
192
    return initial_time_ + elapsed;
197 193
  }
198 194

  
199 195
  Time NowFromSystemTime() {
200
    // This must be executed under lock.
201 196
    LockGuard<Mutex> lock_guard(&mutex_);
202

  
203
    // Resynchronize with the wallclock.
204
    initial_ticks_ = TimeTicks::Now();
205
    initial_time_ = CurrentWallclockTime();
197
    initial_ticks_ = GetSystemTicks();
198
    initial_time_ = GetSystemTime();
206 199
    return initial_time_;
207 200
  }
208 201

  
209 202
 private:
210
  // Time between resampling the un-granular clock for this API (1 minute).
211
  static const int64_t kMaxMicrosecondsToAvoidDrift =
212
      Time::kMicrosecondsPerMinute;
203
  static TimeTicks GetSystemTicks() {
204
    return TimeTicks::Now();
205
  }
213 206

  
214
  static Time CurrentWallclockTime() {
207
  static Time GetSystemTime() {
215 208
    FILETIME ft;
216 209
    ::GetSystemTimeAsFileTime(&ft);
217 210
    return Time::FromFiletime(ft);
......
223 216
};
224 217

  
225 218

  
226
static LazyDynamicInstance<Clock,
227
    DefaultCreateTrait<Clock>,
228
    ThreadSafeInitOnceTrait>::type clock = LAZY_DYNAMIC_INSTANCE_INITIALIZER;
219
static LazyStaticInstance<Clock,
220
    DefaultConstructTrait<Clock>,
221
    ThreadSafeInitOnceTrait>::type clock = LAZY_STATIC_INSTANCE_INITIALIZER;
229 222

  
230 223

  
231 224
Time Time::Now() {
......
388 381
 public:
389 382
  virtual ~TickClock() {}
390 383
  virtual int64_t Now() = 0;
384
  virtual bool IsHighResolution() = 0;
391 385
};
392 386

  
393 387

  
......
440 434
    int64_t ticks = (whole_seconds * Time::kMicrosecondsPerSecond) +
441 435
        ((leftover_ticks * Time::kMicrosecondsPerSecond) / ticks_per_second_);
442 436

  
443
    // Make sure we never return 0 here, so that TimeTicks::HighResNow()
437
    // Make sure we never return 0 here, so that TimeTicks::HighResolutionNow()
444 438
    // will never return 0.
445 439
    return ticks + 1;
446 440
  }
447 441

  
448
 private:
449
  int64_t ticks_per_second_;
450
};
451

  
452

  
453
// The GetTickCount64() API is what we actually want for the regular tick
454
// clock, but this is only available starting with Windows Vista.
455
class WindowsVistaTickClock V8_FINAL : public TickClock {
456
 public:
457
  explicit WindowsVistaTickClock(GETTICKCOUNT64PROC func) : func_(func) {
458
    ASSERT(func_ != NULL);
459
  }
460
  virtual ~WindowsVistaTickClock() {}
461

  
462
  virtual int64_t Now() V8_OVERRIDE {
463
    // Query the current ticks (in ms).
464
    ULONGLONG tick_count_ms = (*func_)();
465

  
466
    // Convert to microseconds (make sure to never return 0 here).
467
    return (tick_count_ms * Time::kMicrosecondsPerMillisecond) + 1;
442
  virtual bool IsHighResolution() V8_OVERRIDE {
443
    return true;
468 444
  }
469 445

  
470 446
 private:
471
  GETTICKCOUNT64PROC func_;
447
  int64_t ticks_per_second_;
472 448
};
473 449

  
474 450

  
475 451
class RolloverProtectedTickClock V8_FINAL : public TickClock {
476 452
 public:
477 453
  // We initialize rollover_ms_ to 1 to ensure that we will never
478
  // return 0 from TimeTicks::HighResNow() and TimeTicks::Now() below.
454
  // return 0 from TimeTicks::HighResolutionNow() and TimeTicks::Now() below.
479 455
  RolloverProtectedTickClock() : last_seen_now_(0), rollover_ms_(1) {}
480 456
  virtual ~RolloverProtectedTickClock() {}
481 457

  
......
487 463
    // Note that we do not use GetTickCount() here, since timeGetTime() gives
488 464
    // more predictable delta values, as described here:
489 465
    // http://blogs.msdn.com/b/larryosterman/archive/2009/09/02/what-s-the-difference-between-gettickcount-and-timegettime.aspx
466
    // timeGetTime() provides 1ms granularity when combined with
467
    // timeBeginPeriod(). If the host application for V8 wants fast timers, it
468
    // can use timeBeginPeriod() to increase the resolution.
490 469
    DWORD now = timeGetTime();
491 470
    if (now < last_seen_now_) {
492 471
      rollover_ms_ += V8_INT64_C(0x100000000);  // ~49.7 days.
......
495 474
    return (now + rollover_ms_) * Time::kMicrosecondsPerMillisecond;
496 475
  }
497 476

  
477
  virtual bool IsHighResolution() V8_OVERRIDE {
478
    return false;
479
  }
480

  
498 481
 private:
499 482
  Mutex mutex_;
500 483
  DWORD last_seen_now_;
......
502 485
};
503 486

  
504 487

  
505
struct CreateTickClockTrait {
506
  static TickClock* Create() {
507
    // Try to load GetTickCount64() from kernel32.dll (available since Vista).
508
    HMODULE kernel32 = ::GetModuleHandleA("kernel32.dll");
509
    ASSERT(kernel32 != NULL);
510
    FARPROC proc = ::GetProcAddress(kernel32, "GetTickCount64");
511
    if (proc != NULL) {
512
      return new WindowsVistaTickClock(
513
          reinterpret_cast<GETTICKCOUNT64PROC>(proc));
514
    }
515

  
516
    // Fallback to the rollover protected tick clock.
517
    return new RolloverProtectedTickClock;
518
  }
519
};
520

  
521

  
522
static LazyDynamicInstance<TickClock,
523
    CreateTickClockTrait,
488
static LazyStaticInstance<RolloverProtectedTickClock,
489
    DefaultConstructTrait<RolloverProtectedTickClock>,
524 490
    ThreadSafeInitOnceTrait>::type tick_clock =
525
        LAZY_DYNAMIC_INSTANCE_INITIALIZER;
491
        LAZY_STATIC_INSTANCE_INITIALIZER;
526 492

  
527 493

  
528 494
struct CreateHighResTickClockTrait {
......
560 526
}
561 527

  
562 528

  
563
TimeTicks TimeTicks::HighResNow() {
529
TimeTicks TimeTicks::HighResolutionNow() {
564 530
  // Make sure we never return 0 here.
565 531
  TimeTicks ticks(high_res_tick_clock.Pointer()->Now());
566 532
  ASSERT(!ticks.IsNull());
567 533
  return ticks;
568 534
}
569 535

  
536

  
537
// static
538
bool TimeTicks::IsHighResolutionClockWorking() {
539
  return high_res_tick_clock.Pointer()->IsHighResolution();
540
}
541

  
570 542
#else  // V8_OS_WIN
571 543

  
572 544
TimeTicks TimeTicks::Now() {
573
  return HighResNow();
545
  return HighResolutionNow();
574 546
}
575 547

  
576 548

  
577
TimeTicks TimeTicks::HighResNow() {
549
TimeTicks TimeTicks::HighResolutionNow() {
578 550
  int64_t ticks;
579 551
#if V8_OS_MACOSX
580 552
  static struct mach_timebase_info info;
......
608 580
  return TimeTicks(ticks + 1);
609 581
}
610 582

  
583

  
584
// static
585
bool TimeTicks::IsHighResolutionClockWorking() {
586
  return true;
587
}
588

  
611 589
#endif  // V8_OS_WIN
612 590

  
613 591
} }  // namespace v8::internal

Also available in: Unified diff