Changeset 31813 in webkit for trunk/JavaScriptCore/kjs


Ignore:
Timestamp:
Apr 11, 2008, 9:40:15 AM (17 years ago)
Author:
[email protected]
Message:

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().
Location:
trunk/JavaScriptCore/kjs
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/kjs/DateMath.cpp

    r31745 r31813  
    318318}
    319319
    320 // It is ok if the cached year is not the current year (e.g. Dec 31st)
    321 // so long as the rules for DST did not change between the two years, if it does
    322 // the app would need to be restarted.
    323 static int mimimumYearForDST()
     320static inline int mimimumYearForDST()
    324321{
    325322    // Because of the 2038 issue (see maximumYearForDST) if the current year is
     
    327324    // minus 27 instead, to ensure there is a range of 28 years that all years
    328325    // can map to.
    329     static int minYear = std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
    330     return minYear;
     326    return std::min(msToYear(getCurrentUTCTime()), maximumYearForDST() - 27) ;
    331327}
    332328
     
    343339int equivalentYearForDST(int year)
    344340{
     341    // It is ok if the cached year is not the current year as long as the rules
     342    // for DST did not change between the two years; if they did the app would need
     343    // to be restarted.
    345344    static int minYear = mimimumYearForDST();
    346     static int maxYear = maximumYearForDST();
     345    int maxYear = maximumYearForDST();
    347346
    348347    int difference;
     
    362361}
    363362
     363static int32_t calculateUTCOffset()
     364{
     365    tm localt;
     366    memset(&localt, 0, sizeof(localt));
     367 
     368    // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
     369    localt.tm_mday = 1;
     370    localt.tm_year = 100;
     371    time_t utcOffset = 946684800 - mktime(&localt);
     372
     373    return static_cast<int32_t>(utcOffset * 1000);
     374}
     375
     376#if PLATFORM(DARWIN)
     377static 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.
     378static bool s_haveCachedUTCOffset;
     379static int s_notificationToken;
     380#endif
     381
    364382/*
    365383 * Get the difference in milliseconds between this time zone and UTC (GMT)
     
    369387{
    370388#if PLATFORM(DARWIN)
    371     // Register for a notification whenever the time zone changes.
    372     static bool triedToRegister = false;
    373     static bool haveNotificationToken = false;
    374     static int notificationToken;
    375     if (!triedToRegister) {
    376         triedToRegister = true;
    377         uint32_t status = notify_register_check("com.apple.system.timezone", &notificationToken);
    378         if (status == NOTIFY_STATUS_OK)
    379             haveNotificationToken = true;
     389    if (s_haveCachedUTCOffset) {
     390        int notified;
     391        uint32_t status = notify_check(s_notificationToken, &notified);
     392        if (status == NOTIFY_STATUS_OK && !notified)
     393            return s_cachedUTCOffset;
    380394    }
    381 
    382     // If we can verify that we have not received a time zone notification,
    383     // then use the cached offset from the last time this function was called.
    384     static bool haveCachedOffset = false;
    385     static double cachedOffset;
    386     if (haveNotificationToken && haveCachedOffset) {
    387         int notified;
    388         uint32_t status = notify_check(notificationToken, &notified);
    389         if (status == NOTIFY_STATUS_OK && !notified)
    390             return cachedOffset;
    391     }
    392 #endif
    393 
    394     tm localt;
    395 
    396     memset(&localt, 0, sizeof(localt));
    397 
    398     // get the difference between this time zone and UTC on Jan 01, 2000 12:00:00 AM
    399     localt.tm_mday = 1;
    400     localt.tm_year = 100;
    401     double utcOffset = 946684800.0 - mktime(&localt);
    402 
    403     utcOffset *= msPerSecond;
     395#endif
     396
     397    int32_t utcOffset = calculateUTCOffset();
    404398
    405399#if PLATFORM(DARWIN)
    406     haveCachedOffset = true;
    407     cachedOffset = utcOffset;
     400    // Theoretically, it is possible that several threads will be executing this code at once, in which case we will have a race condition,
     401    // and a newer value may be overwritten. In practice, time zones don't change that often.
     402    s_cachedUTCOffset = utcOffset;
    408403#endif
    409404
     
    507502}
    508503
     504void initDateMath()
     505{
     506#ifndef NDEBUG
     507    static bool alreadyInitialized;
     508    ASSERT(!alreadyInitialized++);
     509#endif
     510
     511    equivalentYearForDST(2000); // Need to call once to initialize a static used in this function.
     512#if PLATFORM(DARWIN)
     513    // Register for a notification whenever the time zone changes.
     514    uint32_t status = notify_register_check("com.apple.system.timezone", &s_notificationToken);
     515    if (status == NOTIFY_STATUS_OK) {
     516        s_cachedUTCOffset = calculateUTCOffset();
     517        s_haveCachedUTCOffset = true;
     518    }
     519#endif
     520}
     521
    509522} // namespace KJS
  • trunk/JavaScriptCore/kjs/DateMath.h

    r31057 r31813  
    5050struct GregorianDateTime;
    5151
     52void initDateMath();
    5253void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&);
    5354double gregorianDateTimeToMS(const GregorianDateTime&, double, bool inputIsUTC);
  • trunk/JavaScriptCore/kjs/InitializeThreading.cpp

    r31677 r31813  
    3030#include "InitializeThreading.h"
    3131
     32#include "DateMath.h"
    3233#include "dtoa.h"
    3334#include "ustring.h"
     
    4041    WTF::initializeThreading();
    4142#if USE(MULTIPLE_THREADS)
    42     if (!s_dtoaP5Mutex)
     43    if (!s_dtoaP5Mutex) {
    4344        s_dtoaP5Mutex = new Mutex;
    44     UString::null();
     45        UString::null();
     46        initDateMath();
     47    }
    4548#endif
    4649}
Note: See TracChangeset for help on using the changeset viewer.