Commit b927af88 authored by ulan@chromium.org's avatar ulan@chromium.org

Fix a race in initialization of timezone cache in platform-win32.

This allocates a timezone cache per isolate.

BUG=
R=jochen@chromium.org

Review URL: https://codereview.chromium.org/197023002

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19943 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 17d040e2
...@@ -62,7 +62,7 @@ void DateCache::ResetDateCache() { ...@@ -62,7 +62,7 @@ void DateCache::ResetDateCache() {
after_ = &dst_[1]; after_ = &dst_[1];
local_offset_ms_ = kInvalidLocalOffsetInMs; local_offset_ms_ = kInvalidLocalOffsetInMs;
ymd_valid_ = false; ymd_valid_ = false;
OS::TimeZoneChanged(); OS::ClearTimezoneCache(tz_cache_);
} }
......
...@@ -62,11 +62,14 @@ class DateCache { ...@@ -62,11 +62,14 @@ class DateCache {
// It is an invariant of DateCache that cache stamp is non-negative. // It is an invariant of DateCache that cache stamp is non-negative.
static const int kInvalidStamp = -1; static const int kInvalidStamp = -1;
DateCache() : stamp_(0) { DateCache() : stamp_(0), tz_cache_(OS::CreateTimezoneCache()) {
ResetDateCache(); ResetDateCache();
} }
virtual ~DateCache() {} virtual ~DateCache() {
OS::DisposeTimezoneCache(tz_cache_);
tz_cache_ = NULL;
}
// Clears cached timezone information and increments the cache stamp. // Clears cached timezone information and increments the cache stamp.
...@@ -113,7 +116,7 @@ class DateCache { ...@@ -113,7 +116,7 @@ class DateCache {
if (time_ms < 0 || time_ms > kMaxEpochTimeInMs) { if (time_ms < 0 || time_ms > kMaxEpochTimeInMs) {
time_ms = EquivalentTime(time_ms); time_ms = EquivalentTime(time_ms);
} }
return OS::LocalTimezone(static_cast<double>(time_ms)); return OS::LocalTimezone(static_cast<double>(time_ms), tz_cache_);
} }
// ECMA 262 - 15.9.5.26 // ECMA 262 - 15.9.5.26
...@@ -182,11 +185,11 @@ class DateCache { ...@@ -182,11 +185,11 @@ class DateCache {
// These functions are virtual so that we can override them when testing. // These functions are virtual so that we can override them when testing.
virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) { virtual int GetDaylightSavingsOffsetFromOS(int64_t time_sec) {
double time_ms = static_cast<double>(time_sec * 1000); double time_ms = static_cast<double>(time_sec * 1000);
return static_cast<int>(OS::DaylightSavingsOffset(time_ms)); return static_cast<int>(OS::DaylightSavingsOffset(time_ms, tz_cache_));
} }
virtual int GetLocalOffsetFromOS() { virtual int GetLocalOffsetFromOS() {
double offset = OS::LocalTimeOffset(); double offset = OS::LocalTimeOffset(tz_cache_);
ASSERT(offset < kInvalidLocalOffsetInMs); ASSERT(offset < kInvalidLocalOffsetInMs);
return static_cast<int>(offset); return static_cast<int>(offset);
} }
...@@ -253,6 +256,8 @@ class DateCache { ...@@ -253,6 +256,8 @@ class DateCache {
int ymd_year_; int ymd_year_;
int ymd_month_; int ymd_month_;
int ymd_day_; int ymd_day_;
TimezoneCache* tz_cache_;
}; };
} } // namespace v8::internal } } // namespace v8::internal
......
...@@ -51,7 +51,7 @@ namespace v8 { ...@@ -51,7 +51,7 @@ namespace v8 {
namespace internal { namespace internal {
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -60,7 +60,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -60,7 +60,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
// On Cygwin, struct tm does not contain a tm_gmtoff field. // On Cygwin, struct tm does not contain a tm_gmtoff field.
time_t utc = time(NULL); time_t utc = time(NULL);
ASSERT(utc != -1); ASSERT(utc != -1);
......
...@@ -61,7 +61,7 @@ namespace v8 { ...@@ -61,7 +61,7 @@ namespace v8 {
namespace internal { namespace internal {
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -70,7 +70,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -70,7 +70,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL); time_t tv = time(NULL);
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
// tm_gmtoff includes any daylight savings offset, so subtract it. // tm_gmtoff includes any daylight savings offset, so subtract it.
......
...@@ -118,7 +118,7 @@ bool OS::ArmUsingHardFloat() { ...@@ -118,7 +118,7 @@ bool OS::ArmUsingHardFloat() {
#endif // def __arm__ #endif // def __arm__
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -127,7 +127,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -127,7 +127,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL); time_t tv = time(NULL);
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
// tm_gmtoff includes any daylight savings offset, so subtract it. // tm_gmtoff includes any daylight savings offset, so subtract it.
......
...@@ -182,7 +182,7 @@ void OS::SignalCodeMovingGC() { ...@@ -182,7 +182,7 @@ void OS::SignalCodeMovingGC() {
} }
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -191,7 +191,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -191,7 +191,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL); time_t tv = time(NULL);
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
// tm_gmtoff includes any daylight savings offset, so subtract it. // tm_gmtoff includes any daylight savings offset, so subtract it.
......
...@@ -59,7 +59,7 @@ namespace v8 { ...@@ -59,7 +59,7 @@ namespace v8 {
namespace internal { namespace internal {
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -68,7 +68,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -68,7 +68,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL); time_t tv = time(NULL);
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
// tm_gmtoff includes any daylight savings offset, so subtract it. // tm_gmtoff includes any daylight savings offset, so subtract it.
......
...@@ -354,7 +354,25 @@ double OS::TimeCurrentMillis() { ...@@ -354,7 +354,25 @@ double OS::TimeCurrentMillis() {
} }
double OS::DaylightSavingsOffset(double time) { class TimezoneCache {};
TimezoneCache* OS::CreateTimezoneCache() {
return NULL;
}
void OS::DisposeTimezoneCache(TimezoneCache* cache) {
ASSERT(cache == NULL);
}
void OS::ClearTimezoneCache(TimezoneCache* cache) {
ASSERT(cache == NULL);
}
double OS::DaylightSavingsOffset(double time, TimezoneCache*) {
if (std::isnan(time)) return nan_value(); if (std::isnan(time)) return nan_value();
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -363,9 +381,6 @@ double OS::DaylightSavingsOffset(double time) { ...@@ -363,9 +381,6 @@ double OS::DaylightSavingsOffset(double time) {
} }
void OS::TimeZoneChanged() {}
int OS::GetLastError() { int OS::GetLastError() {
return errno; return errno;
} }
......
...@@ -110,7 +110,7 @@ bool OS::ArmUsingHardFloat() { ...@@ -110,7 +110,7 @@ bool OS::ArmUsingHardFloat() {
#endif // __arm__ #endif // __arm__
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -119,7 +119,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -119,7 +119,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
time_t tv = time(NULL); time_t tv = time(NULL);
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
// tm_gmtoff includes any daylight savings offset, so subtract it. // tm_gmtoff includes any daylight savings offset, so subtract it.
......
...@@ -80,7 +80,7 @@ namespace v8 { ...@@ -80,7 +80,7 @@ namespace v8 {
namespace internal { namespace internal {
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
if (std::isnan(time)) return ""; if (std::isnan(time)) return "";
time_t tv = static_cast<time_t>(std::floor(time/msPerSecond)); time_t tv = static_cast<time_t>(std::floor(time/msPerSecond));
struct tm* t = localtime(&tv); struct tm* t = localtime(&tv);
...@@ -89,7 +89,7 @@ const char* OS::LocalTimezone(double time) { ...@@ -89,7 +89,7 @@ const char* OS::LocalTimezone(double time) {
} }
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
tzset(); tzset();
return -static_cast<double>(timezone * msPerSecond); return -static_cast<double>(timezone * msPerSecond);
} }
......
...@@ -218,6 +218,97 @@ void MathSetup() { ...@@ -218,6 +218,97 @@ void MathSetup() {
} }
class TimezoneCache {
public:
TimezoneCache() : initialized_(false) { }
void Clear() {
initialized_ = false;
}
// Initialize timezone information. The timezone information is obtained from
// windows. If we cannot get the timezone information we fall back to CET.
void InitializeIfNeeded() {
// Just return if timezone information has already been initialized.
if (initialized_) return;
// Initialize POSIX time zone data.
_tzset();
// Obtain timezone information from operating system.
memset(&tzinfo_, 0, sizeof(tzinfo_));
if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
// If we cannot get timezone information we fall back to CET.
tzinfo_.Bias = -60;
tzinfo_.StandardDate.wMonth = 10;
tzinfo_.StandardDate.wDay = 5;
tzinfo_.StandardDate.wHour = 3;
tzinfo_.StandardBias = 0;
tzinfo_.DaylightDate.wMonth = 3;
tzinfo_.DaylightDate.wDay = 5;
tzinfo_.DaylightDate.wHour = 2;
tzinfo_.DaylightBias = -60;
}
// Make standard and DST timezone names.
WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1,
std_tz_name_, kTzNameSize, NULL, NULL);
std_tz_name_[kTzNameSize - 1] = '\0';
WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1,
dst_tz_name_, kTzNameSize, NULL, NULL);
dst_tz_name_[kTzNameSize - 1] = '\0';
// If OS returned empty string or resource id (like "@tzres.dll,-211")
// simply guess the name from the UTC bias of the timezone.
// To properly resolve the resource identifier requires a library load,
// which is not possible in a sandbox.
if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') {
OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1),
"%s Standard Time",
GuessTimezoneNameFromBias(tzinfo_.Bias));
}
if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') {
OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1),
"%s Daylight Time",
GuessTimezoneNameFromBias(tzinfo_.Bias));
}
// Timezone information initialized.
initialized_ = true;
}
// Guess the name of the timezone from the bias.
// The guess is very biased towards the northern hemisphere.
const char* GuessTimezoneNameFromBias(int bias) {
static const int kHour = 60;
switch (-bias) {
case -9*kHour: return "Alaska";
case -8*kHour: return "Pacific";
case -7*kHour: return "Mountain";
case -6*kHour: return "Central";
case -5*kHour: return "Eastern";
case -4*kHour: return "Atlantic";
case 0*kHour: return "GMT";
case +1*kHour: return "Central Europe";
case +2*kHour: return "Eastern Europe";
case +3*kHour: return "Russia";
case +5*kHour + 30: return "India";
case +8*kHour: return "China";
case +9*kHour: return "Japan";
case +12*kHour: return "New Zealand";
default: return "Local";
}
}
private:
static const int kTzNameSize = 128;
bool initialized_;
char std_tz_name_[kTzNameSize];
char dst_tz_name_[kTzNameSize];
TIME_ZONE_INFORMATION tzinfo_;
friend class Win32Time;
};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// The Time class represents time on win32. A timestamp is represented as // The Time class represents time on win32. A timestamp is represented as
// a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript // a 64-bit integer in 100 nanoseconds since January 1, 1601 (UTC). JavaScript
...@@ -242,16 +333,14 @@ class Win32Time { ...@@ -242,16 +333,14 @@ class Win32Time {
// LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This // LocalOffset(CET) = 3600000 and LocalOffset(PST) = -28800000. This
// routine also takes into account whether daylight saving is effect // routine also takes into account whether daylight saving is effect
// at the time. // at the time.
int64_t LocalOffset(); int64_t LocalOffset(TimezoneCache* cache);
// Returns the daylight savings time offset for the time in milliseconds. // Returns the daylight savings time offset for the time in milliseconds.
int64_t DaylightSavingsOffset(); int64_t DaylightSavingsOffset(TimezoneCache* cache);
// Returns a string identifying the current timezone for the // Returns a string identifying the current timezone for the
// timestamp taking into account daylight saving. // timestamp taking into account daylight saving.
char* LocalTimezone(); char* LocalTimezone(TimezoneCache* cache);
static void TimeZoneChanged() { tz_initialized_ = false; }
private: private:
// Constants for time conversion. // Constants for time conversion.
...@@ -260,25 +349,10 @@ class Win32Time { ...@@ -260,25 +349,10 @@ class Win32Time {
static const int64_t kMsPerMinute = 60000; static const int64_t kMsPerMinute = 60000;
// Constants for timezone information. // Constants for timezone information.
static const int kTzNameSize = 128;
static const bool kShortTzNames = false; static const bool kShortTzNames = false;
// Timezone information. We need to have static buffers for the
// timezone names because we return pointers to these in
// LocalTimezone().
static bool tz_initialized_;
static TIME_ZONE_INFORMATION tzinfo_;
static char std_tz_name_[kTzNameSize];
static char dst_tz_name_[kTzNameSize];
// Initialize the timezone information (if not already done).
static void TzSet();
// Guess the name of the timezone from the bias.
static const char* GuessTimezoneNameFromBias(int bias);
// Return whether or not daylight savings time is in effect at this time. // Return whether or not daylight savings time is in effect at this time.
bool InDST(); bool InDST(TimezoneCache* cache);
// Accessor for FILETIME representation. // Accessor for FILETIME representation.
FILETIME& ft() { return time_.ft_; } FILETIME& ft() { return time_.ft_; }
...@@ -300,13 +374,6 @@ class Win32Time { ...@@ -300,13 +374,6 @@ 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];
// Initialize timestamp to start of epoc. // Initialize timestamp to start of epoc.
Win32Time::Win32Time() { Win32Time::Win32Time() {
t() = 0; t() = 0;
...@@ -395,90 +462,13 @@ void Win32Time::SetToCurrentTime() { ...@@ -395,90 +462,13 @@ void Win32Time::SetToCurrentTime() {
} }
// Guess the name of the timezone from the bias.
// The guess is very biased towards the northern hemisphere.
const char* Win32Time::GuessTimezoneNameFromBias(int bias) {
static const int kHour = 60;
switch (-bias) {
case -9*kHour: return "Alaska";
case -8*kHour: return "Pacific";
case -7*kHour: return "Mountain";
case -6*kHour: return "Central";
case -5*kHour: return "Eastern";
case -4*kHour: return "Atlantic";
case 0*kHour: return "GMT";
case +1*kHour: return "Central Europe";
case +2*kHour: return "Eastern Europe";
case +3*kHour: return "Russia";
case +5*kHour + 30: return "India";
case +8*kHour: return "China";
case +9*kHour: return "Japan";
case +12*kHour: return "New Zealand";
default: return "Local";
}
}
// 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() {
// Just return if timezone information has already been initialized.
if (tz_initialized_) return;
// Initialize POSIX time zone data.
_tzset();
// Obtain timezone information from operating system.
memset(&tzinfo_, 0, sizeof(tzinfo_));
if (GetTimeZoneInformation(&tzinfo_) == TIME_ZONE_ID_INVALID) {
// If we cannot get timezone information we fall back to CET.
tzinfo_.Bias = -60;
tzinfo_.StandardDate.wMonth = 10;
tzinfo_.StandardDate.wDay = 5;
tzinfo_.StandardDate.wHour = 3;
tzinfo_.StandardBias = 0;
tzinfo_.DaylightDate.wMonth = 3;
tzinfo_.DaylightDate.wDay = 5;
tzinfo_.DaylightDate.wHour = 2;
tzinfo_.DaylightBias = -60;
}
// Make standard and DST timezone names.
WideCharToMultiByte(CP_UTF8, 0, tzinfo_.StandardName, -1,
std_tz_name_, kTzNameSize, NULL, NULL);
std_tz_name_[kTzNameSize - 1] = '\0';
WideCharToMultiByte(CP_UTF8, 0, tzinfo_.DaylightName, -1,
dst_tz_name_, kTzNameSize, NULL, NULL);
dst_tz_name_[kTzNameSize - 1] = '\0';
// If OS returned empty string or resource id (like "@tzres.dll,-211")
// simply guess the name from the UTC bias of the timezone.
// To properly resolve the resource identifier requires a library load,
// which is not possible in a sandbox.
if (std_tz_name_[0] == '\0' || std_tz_name_[0] == '@') {
OS::SNPrintF(Vector<char>(std_tz_name_, kTzNameSize - 1),
"%s Standard Time",
GuessTimezoneNameFromBias(tzinfo_.Bias));
}
if (dst_tz_name_[0] == '\0' || dst_tz_name_[0] == '@') {
OS::SNPrintF(Vector<char>(dst_tz_name_, kTzNameSize - 1),
"%s Daylight Time",
GuessTimezoneNameFromBias(tzinfo_.Bias));
}
// Timezone information initialized.
tz_initialized_ = true;
}
// Return the local timezone offset in milliseconds east of UTC. This // Return the local timezone offset in milliseconds east of UTC. This
// takes into account whether daylight saving is in effect at the time. // 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. // 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. // Also, adding the time-zone offset to the input must not overflow.
// The function EquivalentTime() in date.js guarantees this. // The function EquivalentTime() in date.js guarantees this.
int64_t Win32Time::LocalOffset() { int64_t Win32Time::LocalOffset(TimezoneCache* cache) {
// Initialize timezone information, if needed. cache->InitializeIfNeeded();
TzSet();
Win32Time rounded_to_second(*this); Win32Time rounded_to_second(*this);
rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler * rounded_to_second.t() = rounded_to_second.t() / 1000 / kTimeScaler *
...@@ -501,29 +491,30 @@ int64_t Win32Time::LocalOffset() { ...@@ -501,29 +491,30 @@ int64_t Win32Time::LocalOffset() {
if (localtime_s(&posix_local_time_struct, &posix_time)) return 0; if (localtime_s(&posix_local_time_struct, &posix_time)) return 0;
if (posix_local_time_struct.tm_isdst > 0) { if (posix_local_time_struct.tm_isdst > 0) {
return (tzinfo_.Bias + tzinfo_.DaylightBias) * -kMsPerMinute; return (cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * -kMsPerMinute;
} else if (posix_local_time_struct.tm_isdst == 0) { } else if (posix_local_time_struct.tm_isdst == 0) {
return (tzinfo_.Bias + tzinfo_.StandardBias) * -kMsPerMinute; return (cache->tzinfo_.Bias + cache->tzinfo_.StandardBias) * -kMsPerMinute;
} else { } else {
return tzinfo_.Bias * -kMsPerMinute; return cache->tzinfo_.Bias * -kMsPerMinute;
} }
} }
// Return whether or not daylight savings time is in effect at this time. // Return whether or not daylight savings time is in effect at this time.
bool Win32Time::InDST() { bool Win32Time::InDST(TimezoneCache* cache) {
// Initialize timezone information, if needed. cache->InitializeIfNeeded();
TzSet();
// Determine if DST is in effect at the specified time. // Determine if DST is in effect at the specified time.
bool in_dst = false; bool in_dst = false;
if (tzinfo_.StandardDate.wMonth != 0 || tzinfo_.DaylightDate.wMonth != 0) { if (cache->tzinfo_.StandardDate.wMonth != 0 ||
cache->tzinfo_.DaylightDate.wMonth != 0) {
// Get the local timezone offset for the timestamp in milliseconds. // Get the local timezone offset for the timestamp in milliseconds.
int64_t offset = LocalOffset(); int64_t offset = LocalOffset(cache);
// Compute the offset for DST. The bias parameters in the timezone info // Compute the offset for DST. The bias parameters in the timezone info
// are specified in minutes. These must be converted to milliseconds. // are specified in minutes. These must be converted to milliseconds.
int64_t dstofs = -(tzinfo_.Bias + tzinfo_.DaylightBias) * kMsPerMinute; int64_t dstofs =
-(cache->tzinfo_.Bias + cache->tzinfo_.DaylightBias) * kMsPerMinute;
// If the local time offset equals the timezone bias plus the daylight // If the local time offset equals the timezone bias plus the daylight
// bias then DST is in effect. // bias then DST is in effect.
...@@ -535,17 +526,17 @@ bool Win32Time::InDST() { ...@@ -535,17 +526,17 @@ bool Win32Time::InDST() {
// Return the daylight savings time offset for this time. // Return the daylight savings time offset for this time.
int64_t Win32Time::DaylightSavingsOffset() { int64_t Win32Time::DaylightSavingsOffset(TimezoneCache* cache) {
return InDST() ? 60 * kMsPerMinute : 0; return InDST(cache) ? 60 * kMsPerMinute : 0;
} }
// Returns a string identifying the current timezone for the // Returns a string identifying the current timezone for the
// timestamp taking into account daylight saving. // timestamp taking into account daylight saving.
char* Win32Time::LocalTimezone() { char* Win32Time::LocalTimezone(TimezoneCache* cache) {
// Return the standard or DST time zone name based on whether daylight // Return the standard or DST time zone name based on whether daylight
// saving is in effect at the given time. // saving is in effect at the given time.
return InDST() ? dst_tz_name_ : std_tz_name_; return InDST(cache) ? cache->dst_tz_name_ : cache->std_tz_name_;
} }
...@@ -588,36 +579,47 @@ double OS::TimeCurrentMillis() { ...@@ -588,36 +579,47 @@ double OS::TimeCurrentMillis() {
} }
TimezoneCache* OS::CreateTimezoneCache() {
return new TimezoneCache();
}
void OS::DisposeTimezoneCache(TimezoneCache* cache) {
delete cache;
}
void OS::ClearTimezoneCache(TimezoneCache* cache) {
cache->Clear();
}
// Returns a string identifying the current timezone taking into // Returns a string identifying the current timezone taking into
// account daylight saving. // account daylight saving.
const char* OS::LocalTimezone(double time) { const char* OS::LocalTimezone(double time, TimezoneCache* cache) {
return Win32Time(time).LocalTimezone(); return Win32Time(time).LocalTimezone(cache);
} }
// Returns the local time offset in milliseconds east of UTC without // Returns the local time offset in milliseconds east of UTC without
// taking daylight savings time into account. // taking daylight savings time into account.
double OS::LocalTimeOffset() { double OS::LocalTimeOffset(TimezoneCache* cache) {
// Use current time, rounded to the millisecond. // Use current time, rounded to the millisecond.
Win32Time t(TimeCurrentMillis()); Win32Time t(TimeCurrentMillis());
// Time::LocalOffset inlcudes any daylight savings offset, so subtract it. // Time::LocalOffset inlcudes any daylight savings offset, so subtract it.
return static_cast<double>(t.LocalOffset() - t.DaylightSavingsOffset()); return static_cast<double>(t.LocalOffset(cache) -
t.DaylightSavingsOffset(cache));
} }
// Returns the daylight savings offset in milliseconds for the given // Returns the daylight savings offset in milliseconds for the given
// time. // time.
double OS::DaylightSavingsOffset(double time) { double OS::DaylightSavingsOffset(double time, TimezoneCache* cache) {
int64_t offset = Win32Time(time).DaylightSavingsOffset(); int64_t offset = Win32Time(time).DaylightSavingsOffset(cache);
return static_cast<double>(offset); return static_cast<double>(offset);
} }
void OS::TimeZoneChanged() {
Win32Time::TimeZoneChanged();
}
int OS::GetLastError() { int OS::GetLastError() {
return ::GetLastError(); return ::GetLastError();
} }
......
...@@ -159,6 +159,9 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) { ...@@ -159,6 +159,9 @@ inline intptr_t InternalGetExistingThreadLocal(intptr_t index) {
#endif // V8_NO_FAST_TLS #endif // V8_NO_FAST_TLS
class TimezoneCache;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// OS // OS
// //
...@@ -182,18 +185,20 @@ class OS { ...@@ -182,18 +185,20 @@ class OS {
// 00:00:00 UTC, January 1, 1970. // 00:00:00 UTC, January 1, 1970.
static double TimeCurrentMillis(); static double TimeCurrentMillis();
static TimezoneCache* CreateTimezoneCache();
static void DisposeTimezoneCache(TimezoneCache* cache);
static void ClearTimezoneCache(TimezoneCache* cache);
// Returns a string identifying the current time zone. The // Returns a string identifying the current time zone. The
// timestamp is used for determining if DST is in effect. // timestamp is used for determining if DST is in effect.
static const char* LocalTimezone(double time); static const char* LocalTimezone(double time, TimezoneCache* cache);
// Returns the local time offset in milliseconds east of UTC without // Returns the local time offset in milliseconds east of UTC without
// taking daylight savings time into account. // taking daylight savings time into account.
static double LocalTimeOffset(); static double LocalTimeOffset(TimezoneCache* cache);
// Returns the daylight savings offset for the given time. // Returns the daylight savings offset for the given time.
static double DaylightSavingsOffset(double time); static double DaylightSavingsOffset(double time, TimezoneCache* cache);
static void TimeZoneChanged();
// Returns last OS error. // Returns last OS error.
static int GetLastError(); static int GetLastError();
......
...@@ -9583,8 +9583,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) { ...@@ -9583,8 +9583,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_DateLocalTimezone) {
ASSERT(args.length() == 1); ASSERT(args.length() == 1);
CONVERT_DOUBLE_ARG_CHECKED(x, 0); CONVERT_DOUBLE_ARG_CHECKED(x, 0);
int64_t time = isolate->date_cache()->EquivalentTime(static_cast<int64_t>(x)); const char* zone =
const char* zone = OS::LocalTimezone(static_cast<double>(time)); isolate->date_cache()->LocalTimezone(static_cast<int64_t>(x));
return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone)); return isolate->heap()->AllocateStringFromUtf8(CStrVector(zone));
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment