Commit 0fe258b0 authored by ap@webkit.org's avatar ap@webkit.org

Reviewed by Adam Roben.

        Cache Gregorian date/time structure on DateInstance objects for 1.027x SunSpider speedup
        (1.65x on date-format-xparb, 1.13x on date-format-tofte).

        * kjs/DateMath.h:
        (KJS::GregorianDateTime::copyFrom): Added. It presumably makes sense to keep GregorianDateTime
        Noncopiable, so it's not just operator=.

        * kjs/date_object.h: Added a per-object cache.

        * kjs/date_object.cpp:
        (KJS::DateInstance::DateInstance):
        (KJS::DateInstance::msToGregorianDateTime):
        (KJS::dateProtoFuncToString):
        (KJS::dateProtoFuncToUTCString):
        (KJS::dateProtoFuncToDateString):
        (KJS::dateProtoFuncToTimeString):
        (KJS::dateProtoFuncToLocaleString):
        (KJS::dateProtoFuncToLocaleDateString):
        (KJS::dateProtoFuncToLocaleTimeString):
        (KJS::dateProtoFuncGetFullYear):
        (KJS::dateProtoFuncGetUTCFullYear):
        (KJS::dateProtoFuncToGMTString):
        (KJS::dateProtoFuncGetMonth):
        (KJS::dateProtoFuncGetUTCMonth):
        (KJS::dateProtoFuncGetDate):
        (KJS::dateProtoFuncGetUTCDate):
        (KJS::dateProtoFuncGetDay):
        (KJS::dateProtoFuncGetUTCDay):
        (KJS::dateProtoFuncGetHours):
        (KJS::dateProtoFuncGetUTCHours):
        (KJS::dateProtoFuncGetMinutes):
        (KJS::dateProtoFuncGetUTCMinutes):
        (KJS::dateProtoFuncGetSeconds):
        (KJS::dateProtoFuncGetUTCSeconds):
        (KJS::dateProtoFuncGetTimezoneOffset):
        (KJS::setNewValueFromTimeArgs):
        (KJS::setNewValueFromDateArgs):
        (KJS::dateProtoFuncSetYear):
        (KJS::dateProtoFuncGetYear):
        Use the cache when converting.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@31937 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 3bfd7d04
2008-04-16 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Adam Roben.
Cache Gregorian date/time structure on DateInstance objects for 1.027x SunSpider speedup
(1.65x on date-format-xparb, 1.13x on date-format-tofte).
* kjs/DateMath.h:
(KJS::GregorianDateTime::copyFrom): Added. It presumably makes sense to keep GregorianDateTime
Noncopiable, so it's not just operator=.
* kjs/date_object.h: Added a per-object cache.
* kjs/date_object.cpp:
(KJS::DateInstance::DateInstance):
(KJS::DateInstance::msToGregorianDateTime):
(KJS::dateProtoFuncToString):
(KJS::dateProtoFuncToUTCString):
(KJS::dateProtoFuncToDateString):
(KJS::dateProtoFuncToTimeString):
(KJS::dateProtoFuncToLocaleString):
(KJS::dateProtoFuncToLocaleDateString):
(KJS::dateProtoFuncToLocaleTimeString):
(KJS::dateProtoFuncGetFullYear):
(KJS::dateProtoFuncGetUTCFullYear):
(KJS::dateProtoFuncToGMTString):
(KJS::dateProtoFuncGetMonth):
(KJS::dateProtoFuncGetUTCMonth):
(KJS::dateProtoFuncGetDate):
(KJS::dateProtoFuncGetUTCDate):
(KJS::dateProtoFuncGetDay):
(KJS::dateProtoFuncGetUTCDay):
(KJS::dateProtoFuncGetHours):
(KJS::dateProtoFuncGetUTCHours):
(KJS::dateProtoFuncGetMinutes):
(KJS::dateProtoFuncGetUTCMinutes):
(KJS::dateProtoFuncGetSeconds):
(KJS::dateProtoFuncGetUTCSeconds):
(KJS::dateProtoFuncGetTimezoneOffset):
(KJS::setNewValueFromTimeArgs):
(KJS::setNewValueFromDateArgs):
(KJS::dateProtoFuncSetYear):
(KJS::dateProtoFuncGetYear):
Use the cache when converting.
2008-04-16 Alexey Proskuryakov <ap@webkit.org>
Reviewed by Darin.
......
......@@ -92,7 +92,7 @@ struct GregorianDateTime : Noncopyable {
{
delete [] timeZone;
}
GregorianDateTime(const tm& inTm)
: second(inTm.tm_sec)
, minute(inTm.tm_min)
......@@ -139,6 +139,26 @@ struct GregorianDateTime : Noncopyable {
return ret;
}
void copyFrom(const GregorianDateTime& rhs)
{
second = rhs.second;
minute = rhs.minute;
hour = rhs.hour;
weekDay = rhs.weekDay;
monthDay = rhs.monthDay;
yearDay = rhs.yearDay;
month = rhs.month;
year = rhs.year;
isDST = rhs.isDST;
utcOffset = rhs.utcOffset;
if (rhs.timeZone) {
int inZoneSize = strlen(rhs.timeZone) + 1;
timeZone = new char[inZoneSize];
strncpy(timeZone, rhs.timeZone, inZoneSize);
} else
timeZone = 0;
}
int second;
int minute;
int hour;
......
......@@ -327,9 +327,38 @@ const ClassInfo DateInstance::info = {"Date", 0, 0};
DateInstance::DateInstance(JSObject *proto)
: JSWrapperObject(proto)
, m_cache(0)
{
}
DateInstance::~DateInstance()
{
delete m_cache;
}
void DateInstance::msToGregorianDateTime(double milli, bool outputIsUTC, GregorianDateTime& t) const
{
if (!m_cache) {
m_cache = new Cache;
m_cache->m_gregorianDateTimeCachedForMS = NaN;
m_cache->m_gregorianDateTimeUTCCachedForMS = NaN;
}
if (outputIsUTC) {
if (m_cache->m_gregorianDateTimeUTCCachedForMS != milli) {
::msToGregorianDateTime(milli, true, m_cache->m_cachedGregorianDateTimeUTC);
m_cache->m_gregorianDateTimeUTCCachedForMS = milli;
}
t.copyFrom(m_cache->m_cachedGregorianDateTimeUTC);
} else {
if (m_cache->m_gregorianDateTimeCachedForMS != milli) {
::msToGregorianDateTime(milli, false, m_cache->m_cachedGregorianDateTime);
m_cache->m_gregorianDateTimeCachedForMS = milli;
}
t.copyFrom(m_cache->m_cachedGregorianDateTime);
}
}
bool DateInstance::getTime(GregorianDateTime &t, int &offset) const
{
double milli = internalValue()->getNumber();
......@@ -954,7 +983,7 @@ JSValue* dateProtoFuncToString(ExecState* exec, JSObject* thisObj, const List&)
return jsString("Invalid Date");
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsString(formatDate(t) + " " + formatTime(t, utc));
}
......@@ -972,7 +1001,7 @@ JSValue* dateProtoFuncToUTCString(ExecState* exec, JSObject* thisObj, const List
return jsString("Invalid Date");
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
}
......@@ -990,7 +1019,7 @@ JSValue* dateProtoFuncToDateString(ExecState* exec, JSObject* thisObj, const Lis
return jsString("Invalid Date");
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsString(formatDate(t));
}
......@@ -1008,7 +1037,7 @@ JSValue* dateProtoFuncToTimeString(ExecState* exec, JSObject* thisObj, const Lis
return jsString("Invalid Date");
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsString(formatTime(t, utc));
}
......@@ -1032,7 +1061,7 @@ JSValue* dateProtoFuncToLocaleString(ExecState* exec, JSObject* thisObj, const L
const bool utc = false;
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return formatLocaleDate(t, LocaleDateAndTime);
#endif
}
......@@ -1057,7 +1086,7 @@ JSValue* dateProtoFuncToLocaleDateString(ExecState* exec, JSObject* thisObj, con
const bool utc = false;
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return formatLocaleDate(t, LocaleDate);
#endif
}
......@@ -1082,7 +1111,7 @@ JSValue* dateProtoFuncToLocaleTimeString(ExecState* exec, JSObject* thisObj, con
const bool utc = false;
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return formatLocaleDate(t, LocaleTime);
#endif
}
......@@ -1129,7 +1158,7 @@ JSValue* dateProtoFuncGetFullYear(ExecState* exec, JSObject* thisObj, const List
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(1900 + t.year);
}
......@@ -1147,7 +1176,7 @@ JSValue* dateProtoFuncGetUTCFullYear(ExecState* exec, JSObject* thisObj, const L
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(1900 + t.year);
}
......@@ -1165,7 +1194,7 @@ JSValue* dateProtoFuncToGMTString(ExecState* exec, JSObject* thisObj, const List
return jsString("Invalid Date");
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsString(formatDateUTCVariant(t) + " " + formatTime(t, utc));
}
......@@ -1183,7 +1212,7 @@ JSValue* dateProtoFuncGetMonth(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.month);
}
......@@ -1201,7 +1230,7 @@ JSValue* dateProtoFuncGetUTCMonth(ExecState* exec, JSObject* thisObj, const List
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.month);
}
......@@ -1219,7 +1248,7 @@ JSValue* dateProtoFuncGetDate(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.monthDay);
}
......@@ -1237,7 +1266,7 @@ JSValue* dateProtoFuncGetUTCDate(ExecState* exec, JSObject* thisObj, const List&
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.monthDay);
}
......@@ -1255,7 +1284,7 @@ JSValue* dateProtoFuncGetDay(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.weekDay);
}
......@@ -1273,7 +1302,7 @@ JSValue* dateProtoFuncGetUTCDay(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.weekDay);
}
......@@ -1291,7 +1320,7 @@ JSValue* dateProtoFuncGetHours(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.hour);
}
......@@ -1309,7 +1338,7 @@ JSValue* dateProtoFuncGetUTCHours(ExecState* exec, JSObject* thisObj, const List
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.hour);
}
......@@ -1327,7 +1356,7 @@ JSValue* dateProtoFuncGetMinutes(ExecState* exec, JSObject* thisObj, const List&
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.minute);
}
......@@ -1345,7 +1374,7 @@ JSValue* dateProtoFuncGetUTCMinutes(ExecState* exec, JSObject* thisObj, const Li
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.minute);
}
......@@ -1363,7 +1392,7 @@ JSValue* dateProtoFuncGetSeconds(ExecState* exec, JSObject* thisObj, const List&
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.second);
}
......@@ -1381,7 +1410,7 @@ JSValue* dateProtoFuncGetUTCSeconds(ExecState* exec, JSObject* thisObj, const Li
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(t.second);
}
......@@ -1431,7 +1460,7 @@ JSValue* dateProtoFuncGetTimezoneOffset(ExecState* exec, JSObject* thisObj, cons
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
return jsNumber(-gmtoffset(t) / minutesPerHour);
}
......@@ -1467,7 +1496,7 @@ static JSValue* setNewValueFromTimeArgs(ExecState* exec, JSObject* thisObj, cons
double ms = milli - secs * msPerSecond;
GregorianDateTime t;
msToGregorianDateTime(milli, inputIsUTC, t);
thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
if (!fillStructuresUsingTimeArgs(exec, args, numArgsToUse, &ms, &t)) {
JSValue* result = jsNaN();
......@@ -1500,11 +1529,11 @@ static JSValue* setNewValueFromDateArgs(ExecState* exec, JSObject* thisObj, cons
if (numArgsToUse == 3 && isnan(milli))
// Based on ECMA 262 15.9.5.40 - .41 (set[UTC]FullYear)
// the time must be reset to +0 if it is NaN.
msToGregorianDateTime(0, true, t);
thisDateObj->msToGregorianDateTime(0, true, t);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
msToGregorianDateTime(milli, inputIsUTC, t);
thisDateObj->msToGregorianDateTime(milli, inputIsUTC, t);
}
if (!fillStructuresUsingDateArgs(exec, args, numArgsToUse, &ms, &t)) {
......@@ -1624,11 +1653,11 @@ JSValue* dateProtoFuncSetYear(ExecState* exec, JSObject* thisObj, const List& ar
if (isnan(milli))
// Based on ECMA 262 B.2.5 (setYear)
// the time must be reset to +0 if it is NaN.
msToGregorianDateTime(0, true, t);
thisDateObj->msToGregorianDateTime(0, true, t);
else {
double secs = floor(milli / msPerSecond);
ms = milli - secs * msPerSecond;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
}
bool ok = true;
......@@ -1659,7 +1688,7 @@ JSValue* dateProtoFuncGetYear(ExecState* exec, JSObject* thisObj, const List&)
return jsNaN();
GregorianDateTime t;
msToGregorianDateTime(milli, utc, t);
thisDateObj->msToGregorianDateTime(milli, utc, t);
// NOTE: IE returns the full year even in getYear.
return jsNumber(t.year);
......
......@@ -21,20 +21,20 @@
#ifndef DATE_OBJECT_H
#define DATE_OBJECT_H
#include "DateMath.h"
#include "function.h"
#include "JSWrapperObject.h"
#include "lookup.h"
namespace KJS {
struct GregorianDateTime;
class FunctionPrototype;
class ObjectPrototype;
class DateInstance : public JSWrapperObject {
public:
DateInstance(JSObject *proto);
virtual ~DateInstance();
bool getTime(GregorianDateTime&, int& offset) const;
bool getUTCTime(GregorianDateTime&) const;
......@@ -43,6 +43,18 @@ namespace KJS {
virtual const ClassInfo *classInfo() const { return &info; }
static const ClassInfo info;
void msToGregorianDateTime(double, bool outputIsUTC, GregorianDateTime&) const;
private:
struct Cache {
double m_gregorianDateTimeCachedForMS;
GregorianDateTime m_cachedGregorianDateTime;
double m_gregorianDateTimeUTCCachedForMS;
GregorianDateTime m_cachedGregorianDateTimeUTC;
};
mutable Cache* m_cache;
};
/**
......
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