Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(610)

Side by Side Diff: src/platform-win32.cc

Issue 23295034: Add Chromium-style TimeDelta, Time and TimeTicks classes, and a new ElapsedTimer class. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix typo Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 init_fast_sqrt_function(); 239 init_fast_sqrt_function();
240 } 240 }
241 241
242 242
243 // ---------------------------------------------------------------------------- 243 // ----------------------------------------------------------------------------
244 // The Time class represents time on win32. A timestamp is represented as 244 // The Time class represents time on win32. A timestamp is represented as
245 // a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript 245 // a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript
246 // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC, 246 // timestamps are represented as a doubles in milliseconds since 00:00:00 UTC,
247 // January 1, 1970. 247 // January 1, 1970.
248 248
249 class Time { 249 class Win32Time {
250 public: 250 public:
251 // Constructors. 251 // Constructors.
252 Time(); 252 explicit Win32Time(double jstime);
253 explicit Time(double jstime); 253 Win32Time(int year, int mon, int day, int hour, int min, int sec);
254 Time(int year, int mon, int day, int hour, int min, int sec);
255 254
256 // Convert timestamp to JavaScript representation. 255 // Convert timestamp to JavaScript representation.
257 double ToJSTime(); 256 double ToJSTime();
258 257
259 // Set timestamp to current time.
260 void SetToCurrentTime();
261
262 // Returns the local timezone offset in milliseconds east of UTC. This is 258 // Returns the local timezone offset in milliseconds east of UTC. This is
263 // the number of milliseconds you must add to UTC to get local time, i.e. 259 // the number of milliseconds you must add to UTC to get local time, i.e.
264 // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This 260 // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This
265 // routine also takes into account whether daylight saving is effect 261 // routine also takes into account whether daylight saving is effect
266 // at the time. 262 // at the time.
267 int64_t LocalOffset(); 263 int64_t LocalOffset();
268 264
269 // Returns the daylight savings time offset for the time in milliseconds. 265 // Returns the daylight savings time offset for the time in milliseconds.
270 int64_t DaylightSavingsOffset(); 266 int64_t DaylightSavingsOffset();
271 267
(...skipping 21 matching lines...) Expand all
293 289
294 // Initialize the timezone information (if not already done). 290 // Initialize the timezone information (if not already done).
295 static void TzSet(); 291 static void TzSet();
296 292
297 // Guess the name of the timezone from the bias. 293 // Guess the name of the timezone from the bias.
298 static const char* GuessTimezoneNameFromBias(int bias); 294 static const char* GuessTimezoneNameFromBias(int bias);
299 295
300 // Return whether or not daylight savings time is in effect at this time. 296 // Return whether or not daylight savings time is in effect at this time.
301 bool InDST(); 297 bool InDST();
302 298
303 // Return the difference (in milliseconds) between this timestamp and
304 // another timestamp.
305 int64_t Diff(Time* other);
306
307 // Accessor for FILETIME representation. 299 // Accessor for FILETIME representation.
308 FILETIME& ft() { return time_.ft_; } 300 FILETIME& ft() { return time_.ft_; }
309 301
310 // Accessor for integer representation. 302 // Accessor for integer representation.
311 int64_t& t() { return time_.t_; } 303 int64_t& t() { return time_.t_; }
312 304
313 // Although win32 uses 64-bit integers for representing timestamps, 305 // Although win32 uses 64-bit integers for representing timestamps,
314 // these are packed into a FILETIME structure. The FILETIME structure 306 // these are packed into a FILETIME structure. The FILETIME structure
315 // is just a struct representing a 64-bit integer. The TimeStamp union 307 // is just a struct representing a 64-bit integer. The TimeStamp union
316 // allows access to both a FILETIME and an integer representation of 308 // allows access to both a FILETIME and an integer representation of
317 // the timestamp. 309 // the timestamp.
318 union TimeStamp { 310 union TimeStamp {
319 FILETIME ft_; 311 FILETIME ft_;
320 int64_t t_; 312 int64_t t_;
321 }; 313 };
322 314
323 TimeStamp time_; 315 TimeStamp time_;
324 }; 316 };
325 317
326 318
327 // Static variables. 319 // Static variables.
328 bool Time::tz_initialized_ = false; 320 bool Win32Time::tz_initialized_ = false;
329 TIME_ZONE_INFORMATION Time::tzinfo_; 321 TIME_ZONE_INFORMATION Win32Time::tzinfo_;
330 char Time::std_tz_name_[kTzNameSize]; 322 char Win32Time::std_tz_name_[kTzNameSize];
331 char Time::dst_tz_name_[kTzNameSize]; 323 char Win32Time::dst_tz_name_[kTzNameSize];
332
333
334 // Initialize timestamp to start of epoc.
335 Time::Time() {
336 t() = 0;
337 }
338 324
339 325
340 // Initialize timestamp from a JavaScript timestamp. 326 // Initialize timestamp from a JavaScript timestamp.
341 Time::Time(double jstime) { 327 Win32Time::Win32Time(double jstime) {
342 t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc; 328 t() = static_cast<int64_t>(jstime) * kTimeScaler + kTimeEpoc;
343 } 329 }
344 330
345 331
346 // Initialize timestamp from date/time components. 332 // Initialize timestamp from date/time components.
347 Time::Time(int year, int mon, int day, int hour, int min, int sec) { 333 Win32Time::Win32Time(int year, int mon, int day, int hour, int min, int sec) {
348 SYSTEMTIME st; 334 SYSTEMTIME st;
349 st.wYear = year; 335 st.wYear = year;
350 st.wMonth = mon; 336 st.wMonth = mon;
351 st.wDay = day; 337 st.wDay = day;
352 st.wHour = hour; 338 st.wHour = hour;
353 st.wMinute = min; 339 st.wMinute = min;
354 st.wSecond = sec; 340 st.wSecond = sec;
355 st.wMilliseconds = 0; 341 st.wMilliseconds = 0;
356 SystemTimeToFileTime(&st, &ft()); 342 SystemTimeToFileTime(&st, &ft());
357 } 343 }
358 344
359 345
360 // Convert timestamp to JavaScript timestamp. 346 // Convert timestamp to JavaScript timestamp.
361 double Time::ToJSTime() { 347 double Win32Time::ToJSTime() {
362 return static_cast<double>((t() - kTimeEpoc) / kTimeScaler); 348 return static_cast<double>((t() - kTimeEpoc) / kTimeScaler);
363 } 349 }
364 350
365 351
366 // Guess the name of the timezone from the bias. 352 // Guess the name of the timezone from the bias.
367 // The guess is very biased towards the northern hemisphere. 353 // The guess is very biased towards the northern hemisphere.
368 const char* Time::GuessTimezoneNameFromBias(int bias) { 354 const char* Win32Time::GuessTimezoneNameFromBias(int bias) {
369 static const int kHour = 60; 355 static const int kHour = 60;
370 switch (-bias) { 356 switch (-bias) {
371 case -9*kHour: return "Alaska"; 357 case -9*kHour: return "Alaska";
372 case -8*kHour: return "Pacific"; 358 case -8*kHour: return "Pacific";
373 case -7*kHour: return "Mountain"; 359 case -7*kHour: return "Mountain";
374 case -6*kHour: return "Central"; 360 case -6*kHour: return "Central";
375 case -5*kHour: return "Eastern"; 361 case -5*kHour: return "Eastern";
376 case -4*kHour: return "Atlantic"; 362 case -4*kHour: return "Atlantic";
377 case 0*kHour: return "GMT"; 363 case 0*kHour: return "GMT";
378 case +1*kHour: return "Central Europe"; 364 case +1*kHour: return "Central Europe";
379 case +2*kHour: return "Eastern Europe"; 365 case +2*kHour: return "Eastern Europe";
380 case +3*kHour: return "Russia"; 366 case +3*kHour: return "Russia";
381 case +5*kHour + 30: return "India"; 367 case +5*kHour + 30: return "India";
382 case +8*kHour: return "China"; 368 case +8*kHour: return "China";
383 case +9*kHour: return "Japan"; 369 case +9*kHour: return "Japan";
384 case +12*kHour: return "New Zealand"; 370 case +12*kHour: return "New Zealand";
385 default: return "Local"; 371 default: return "Local";
386 } 372 }
387 } 373 }
388 374
389 375
390 // Initialize timezone information. The timezone information is obtained from 376 // Initialize timezone information. The timezone information is obtained from
391 // windows. If we cannot get the timezone information we fall back to CET. 377 // windows. If we cannot get the timezone information we fall back to CET.
392 // Please notice that this code is not thread-safe. 378 // Please notice that this code is not thread-safe.
393 void Time::TzSet() { 379 void Win32Time::TzSet() {
394 // Just return if timezone information has already been initialized. 380 // Just return if timezone information has already been initialized.
395 if (tz_initialized_) return; 381 if (tz_initialized_) return;
396 382
397 // Initialize POSIX time zone data. 383 // Initialize POSIX time zone data.
398 _tzset(); 384 _tzset();
399 // Obtain timezone information from operating system. 385 // Obtain timezone information from operating system.
400 memset(&tzinfo_, 0, sizeof(tzinfo_)); 386 memset(&tzinfo_, 0, sizeof(tzinfo_));
401 if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) { 387 if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
402 // If we cannot get timezone information we fall back to CET. 388 // If we cannot get timezone information we fall back to CET.
403 tzinfo_.Bias = -60; 389 tzinfo_.Bias = -60;
(...skipping 28 matching lines...) Expand all
432 OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1), 418 OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1),
433 "%s Daylight Time", 419 "%s Daylight Time",
434 GuessTimezoneNameFromBias(tzinfo_.Bias)); 420 GuessTimezoneNameFromBias(tzinfo_.Bias));
435 } 421 }
436 422
437 // Timezone information initialized. 423 // Timezone information initialized.
438 tz_initialized_ = true; 424 tz_initialized_ = true;
439 } 425 }
440 426
441 427
442 // Return the difference in milliseconds between this and another timestamp.
443 int64_t Time::Diff(Time* other) {
444 return (t() - other->t()) / kTimeScaler;
445 }
446
447
448 // Set timestamp to current time.
449 void Time::SetToCurrentTime() {
450 // The default GetSystemTimeAsFileTime has a ~15.5ms resolution.
451 // Because we're fast, we like fast timers which have at least a
452 // 1ms resolution.
453 //
454 // timeGetTime() provides 1ms granularity when combined with
455 // timeBeginPeriod(). If the host application for v8 wants fast
456 // timers, it can use timeBeginPeriod to increase the resolution.
457 //
458 // Using timeGetTime() has a drawback because it is a 32bit value
459 // and hence rolls-over every ~49days.
460 //
461 // To use the clock, we use GetSystemTimeAsFileTime as our base;
462 // and then use timeGetTime to extrapolate current time from the
463 // start time. To deal with rollovers, we resync the clock
464 // any time when more than kMaxClockElapsedTime has passed or
465 // whenever timeGetTime creates a rollover.
466
467 static bool initialized = false;
468 static TimeStamp init_time;
469 static DWORD init_ticks;
470 static const int64_t kHundredNanosecondsPerSecond = 10000000;
471 static const int64_t kMaxClockElapsedTime =
472 60*kHundredNanosecondsPerSecond; // 1 minute
473
474 // If we are uninitialized, we need to resync the clock.
475 bool needs_resync = !initialized;
476
477 // Get the current time.
478 TimeStamp time_now;
479 GetSystemTimeAsFileTime(&time_now.ft_);
480 DWORD ticks_now = timeGetTime();
481
482 // Check if we need to resync due to clock rollover.
483 needs_resync |= ticks_now < init_ticks;
484
485 // Check if we need to resync due to elapsed time.
486 needs_resync |= (time_now.t_ - init_time.t_) > kMaxClockElapsedTime;
487
488 // Check if we need to resync due to backwards time change.
489 needs_resync |= time_now.t_ < init_time.t_;
490
491 // Resync the clock if necessary.
492 if (needs_resync) {
493 GetSystemTimeAsFileTime(&init_time.ft_);
494 init_ticks = ticks_now = timeGetTime();
495 initialized = true;
496 }
497
498 // Finally, compute the actual time. Why is this so hard.
499 DWORD elapsed = ticks_now - init_ticks;
500 this->time_.t_ = init_time.t_ + (static_cast<int64_t>(elapsed) * 10000);
501 }
502
503
504 // Return the local timezone offset in milliseconds east of UTC. This 428 // Return the local timezone offset in milliseconds east of UTC. This
505 // takes into account whether daylight saving is in effect at the time. 429 // takes into account whether daylight saving is in effect at the time.
506 // Only times in the 32-bit Unix range may be passed to this function. 430 // Only times in the 32-bit Unix range may be passed to this function.
507 // Also, adding the time-zone offset to the input must not overflow. 431 // Also, adding the time-zone offset to the input must not overflow.
508 // The function EquivalentTime() in date.js guarantees this. 432 // The function EquivalentTime() in date.js guarantees this.
509 int64_t Time::LocalOffset() { 433 int64_t Win32Time::LocalOffset() {
510 // Initialize timezone information, if needed. 434 // Initialize timezone information, if needed.
511 TzSet(); 435 TzSet();
512 436
513 Time rounded_to_second(*this); 437 Win32Time rounded_to_second(*this);
514 rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * 438 rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
515 1000 * kTimeScaler; 439 1000 * kTimeScaler;
516 // Convert to local time using POSIX localtime function. 440 // Convert to local time using POSIX localtime function.
517 // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime() 441 // Windows XP Service Pack 3 made SystemTimeToTzSpecificLocalTime()
518 // very slow. Other browsers use localtime(). 442 // very slow. Other browsers use localtime().
519 443
520 // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to 444 // Convert from JavaScript milliseconds past 1/1/1970 0:00:00 to
521 // POSIX seconds past 1/1/1970 0:00:00. 445 // POSIX seconds past 1/1/1970 0:00:00.
522 double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000; 446 double unchecked_posix_time = rounded_to_second.ToJSTime() / 1000;
523 if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) { 447 if (unchecked_posix_time > INT_MAX || unchecked_posix_time < 0) {
(...skipping 10 matching lines...) Expand all
534 return (tzinfo_.Bias + tzinfo_.DaylightBias) * -kMsPerMinute; 458 return (tzinfo_.Bias + tzinfo_.DaylightBias) * -kMsPerMinute;
535 } else if (posix_local_time_struct.tm_isdst == 0) { 459 } else if (posix_local_time_struct.tm_isdst == 0) {
536 return (tzinfo_.Bias + tzinfo_.StandardBias) * -kMsPerMinute; 460 return (tzinfo_.Bias + tzinfo_.StandardBias) * -kMsPerMinute;
537 } else { 461 } else {
538 return tzinfo_.Bias * -kMsPerMinute; 462 return tzinfo_.Bias * -kMsPerMinute;
539 } 463 }
540 } 464 }
541 465
542 466
543 // Return whether or not daylight savings time is in effect at this time. 467 // Return whether or not daylight savings time is in effect at this time.
544 bool Time::InDST() { 468 bool Win32Time::InDST() {
545 // Initialize timezone information, if needed. 469 // Initialize timezone information, if needed.
546 TzSet(); 470 TzSet();
547 471
548 // Determine if DST is in effect at the specified time. 472 // Determine if DST is in effect at the specified time.
549 bool in_dst = false; 473 bool in_dst = false;
550 if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { 474 if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) {
551 // Get the local timezone offset for the timestamp in milliseconds. 475 // Get the local timezone offset for the timestamp in milliseconds.
552 int64_t offset = LocalOffset(); 476 int64_t offset = LocalOffset();
553 477
554 // Compute the offset for DST. The bias parameters in the timezone info 478 // Compute the offset for DST. The bias parameters in the timezone info
555 // are specified in minutes. These must be converted to milliseconds. 479 // are specified in minutes. These must be converted to milliseconds.
556 int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; 480 int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute;
557 481
558 // If the local time offset equals the timezone bias plus the daylight 482 // If the local time offset equals the timezone bias plus the daylight
559 // bias then DST is in effect. 483 // bias then DST is in effect.
560 in_dst = offset == dstofs; 484 in_dst = offset == dstofs;
561 } 485 }
562 486
563 return in_dst; 487 return in_dst;
564 } 488 }
565 489
566 490
567 // Return the daylight savings time offset for this time. 491 // Return the daylight savings time offset for this time.
568 int64_t Time::DaylightSavingsOffset() { 492 int64_t Win32Time::DaylightSavingsOffset() {
569 return InDST() ? 60 * kMsPerMinute : 0; 493 return InDST() ? 60 * kMsPerMinute : 0;
570 } 494 }
571 495
572 496
573 // Returns a string identifying the current timezone for the 497 // Returns a string identifying the current timezone for the
574 // timestamp taking into account daylight saving. 498 // timestamp taking into account daylight saving.
575 char* Time::LocalTimezone() { 499 char* Win32Time::LocalTimezone() {
576 // Return the standard or DST time zone name based on whether daylight 500 // Return the standard or DST time zone name based on whether daylight
577 // saving is in effect at the given time. 501 // saving is in effect at the given time.
578 return InDST() ? dst_tz_name_ : std_tz_name_; 502 return InDST() ? dst_tz_name_ : std_tz_name_;
579 } 503 }
580 504
581 505
582 void OS::PostSetUp() { 506 void OS::PostSetUp() {
583 // Math functions depend on CPU features therefore they are initialized after 507 // Math functions depend on CPU features therefore they are initialized after
584 // CPU. 508 // CPU.
585 MathSetup(); 509 MathSetup();
(...skipping 21 matching lines...) Expand all
607 // Convert to seconds and microseconds 531 // Convert to seconds and microseconds
608 *secs = static_cast<uint32_t>(usertime / 1000000); 532 *secs = static_cast<uint32_t>(usertime / 1000000);
609 *usecs = static_cast<uint32_t>(usertime % 1000000); 533 *usecs = static_cast<uint32_t>(usertime % 1000000);
610 return 0; 534 return 0;
611 } 535 }
612 536
613 537
614 // Returns current time as the number of milliseconds since 538 // Returns current time as the number of milliseconds since
615 // 00:00:00 UTC, January 1, 1970. 539 // 00:00:00 UTC, January 1, 1970.
616 double OS::TimeCurrentMillis() { 540 double OS::TimeCurrentMillis() {
617 Time t; 541 return Time::Now().ToJsTime();
618 t.SetToCurrentTime();
619 return t.ToJSTime();
620 }
621
622
623 // Returns the tickcounter based on timeGetTime.
624 int64_t OS::Ticks() {
625 return timeGetTime() * 1000; // Convert to microseconds.
626 } 542 }
627 543
628 544
629 // Returns a string identifying the current timezone taking into 545 // Returns a string identifying the current timezone taking into
630 // account daylight saving. 546 // account daylight saving.
631 const char* OS::LocalTimezone(double time) { 547 const char* OS::LocalTimezone(double time) {
632 return Time(time).LocalTimezone(); 548 return Win32Time(time).LocalTimezone();
633 } 549 }
634 550
635 551
636 // Returns the local time offset in milliseconds east of UTC without 552 // Returns the local time offset in milliseconds east of UTC without
637 // taking daylight savings time into account. 553 // taking daylight savings time into account.
638 double OS::LocalTimeOffset() { 554 double OS::LocalTimeOffset() {
639 // Use current time, rounded to the millisecond. 555 // Use current time, rounded to the millisecond.
640 Time t(TimeCurrentMillis()); 556 Win32Time t(TimeCurrentMillis());
641 // Time::LocalOffset inlcudes any daylight savings offset, so subtract it. 557 // Time::LocalOffset inlcudes any daylight savings offset, so subtract it.
642 return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); 558 return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset());
643 } 559 }
644 560
645 561
646 // Returns the daylight savings offset in milliseconds for the given 562 // Returns the daylight savings offset in milliseconds for the given
647 // time. 563 // time.
648 double OS::DaylightSavingsOffset(double time) { 564 double OS::DaylightSavingsOffset(double time) {
649 int64_t offset = Time(time).DaylightSavingsOffset(); 565 int64_t offset = Win32Time(time).DaylightSavingsOffset();
650 return static_cast<double>(offset); 566 return static_cast<double>(offset);
651 } 567 }
652 568
653 569
654 int OS::GetLastError() { 570 int OS::GetLastError() {
655 return ::GetLastError(); 571 return ::GetLastError();
656 } 572 }
657 573
658 574
659 int OS::GetCurrentProcessId() { 575 int OS::GetCurrentProcessId() {
(...skipping 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after
1993 limit_mutex = CreateMutex(); 1909 limit_mutex = CreateMutex();
1994 } 1910 }
1995 1911
1996 1912
1997 void OS::TearDown() { 1913 void OS::TearDown() {
1998 delete limit_mutex; 1914 delete limit_mutex;
1999 } 1915 }
2000 1916
2001 1917
2002 } } // namespace v8::internal 1918 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/platform-posix.cc ('k') | src/profile-generator.h » ('j') | src/time/elapsed-timer.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698