Reviewed by Geoff.
Make DateMath.cpp thread safe.
No measurable change on SunSpider (should be a very small speedup).
* kjs/DateMath.cpp:
(KJS::mimimumYearForDST): (KJS::equivalentYearForDST): Got rid of double caching of the
same precomputed value.
(KJS::calculateUTCOffset): (KJS::getUTCOffset): Factored actual UTC offset calculation code
out of getUTCOffset(), and notification setup into initDateMath().
(KJS::initDateMath): Added.
* kjs/DateMath.h:
* kjs/InitializeThreading.cpp:
(KJS::initializeThreading):
Added initDateMath().
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31813 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/JavaScriptCore/kjs/DateMath.cpp b/JavaScriptCore/kjs/DateMath.cpp
index 9610bd8..3c0d55c 100644
--- a/JavaScriptCore/kjs/DateMath.cpp
+++ b/JavaScriptCore/kjs/DateMath.cpp
@@ -317,17 +317,13 @@
return 2037;
}
-// It is ok if the cached year is not the current year (e.g. Dec 31st)
-// so long as the rules for DST did not change between the two years, if it does
-// the app would need to be restarted.
-static int mimimumYearForDST()
+static inline int mimimumYearForDST()
{
// Because of the 2038 issue (see maximumYearForDST) if the current year is
// greater than the max year minus 27 (2010), we want to use the max year
// minus 27 instead, to ensure there is a range of 28 years that all years
// can map to.
- static int minYear = std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
- return minYear;
+ return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
}
/*
@@ -342,8 +338,11 @@
*/
int equivalentYearForDST(int year)
{
+ // It is ok if the cached year is not the current year as long as the rules
+ // for DST did not change between the two years; if they did the app would need
+ // to be restarted.
static int minYear = mimimumYearForDST();
- static int maxYear = maximumYearForDST();
+ int maxYear = maximumYearForDST();
int difference;
if (year > maxYear)
@@ -361,6 +360,25 @@
return year;
}
+static int32_t calculateUTCOffset()
+{
+ tm localt;
+ memset(&localt, 0, sizeof(localt));
+
+ // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
+ localt.tm_mday = 1;
+ localt.tm_year = 100;
+ time_t utcOffset = 946684800 - mktime(&localt);
+
+ return static_cast<int32_t>(utcOffset * 1000);
+}
+
+#if PLATFORM(DARWIN)
+static int32_t s_cachedUTCOffset; // In milliseconds. An assumption here is that access to an int32_t variable is atomic on platforms that take this code path.
+static bool s_haveCachedUTCOffset;
+static int s_notificationToken;
+#endif
+
/*
* Get the difference in milliseconds between this time zone and UTC (GMT)
* NOT including DST.
@@ -368,43 +386,20 @@
double getUTCOffset()
{
#if PLATFORM(DARWIN)
- // Register for a notification whenever the time zone changes.
- static bool triedToRegister = false;
- static bool haveNotificationToken = false;
- static int notificationToken;
- if (!triedToRegister) {
- triedToRegister = true;
- uint32_t status = notify_register_check("com.apple.system.timezone", ¬ificationToken);
- if (status == NOTIFY_STATUS_OK)
- haveNotificationToken = true;
- }
-
- // If we can verify that we have not received a time zone notification,
- // then use the cached offset from the last time this function was called.
- static bool haveCachedOffset = false;
- static double cachedOffset;
- if (haveNotificationToken && haveCachedOffset) {
+ if (s_haveCachedUTCOffset) {
int notified;
- uint32_t status = notify_check(notificationToken, ¬ified);
+ uint32_t status = notify_check(s_notificationToken, ¬ified);
if (status == NOTIFY_STATUS_OK && !notified)
- return cachedOffset;
+ return s_cachedUTCOffset;
}
#endif
- tm localt;
-
- memset(&localt, 0, sizeof(localt));
-
- // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
- localt.tm_mday = 1;
- localt.tm_year = 100;
- double utcOffset = 946684800.0 - mktime(&localt);
-
- utcOffset *= msPerSecond;
+ int32_t utcOffset = calculateUTCOffset();
#if PLATFORM(DARWIN)
- haveCachedOffset = true;
- cachedOffset = utcOffset;
+ // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition,
+ // and a newer value may be overwritten. In practice, time zones don't change that often.
+ s_cachedUTCOffset = utcOffset;
#endif
return utcOffset;
@@ -506,4 +501,22 @@
tm.timeZone = NULL;
}
+void initDateMath()
+{
+#ifndef NDEBUG
+ static bool alreadyInitialized;
+ ASSERT(!alreadyInitialized++);
+#endif
+
+ equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
+#if PLATFORM(DARWIN)
+ // Register for a notification whenever the time zone changes.
+ uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken);
+ if (status == NOTIFY_STATUS_OK) {
+ s_cachedUTCOffset = calculateUTCOffset();
+ s_haveCachedUTCOffset = true;
+ }
+#endif
+}
+
} // namespace KJS