Commit 13d31b65 authored by rossberg@chromium.org's avatar rossberg@chromium.org

Implement caching scheme for Date fields.

This is based on https://chromiumcodereview.appspot.com/9117034/

Doesn't have much impact on its own, but is the basis for Ulan's CL https://chromiumcodereview.appspot.com/9117034/, which moves the logic to C++.

R=ulan@chromium.org
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9307083

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10982 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent 8604da7f
...@@ -4748,7 +4748,7 @@ void v8::Date::DateTimeConfigurationChangeNotification() { ...@@ -4748,7 +4748,7 @@ void v8::Date::DateTimeConfigurationChangeNotification() {
ENTER_V8(isolate); ENTER_V8(isolate);
i::HandleScope scope(isolate); i::HandleScope scope(isolate);
// Get the function ResetDateCache (defined in date-delay.js). // Get the function ResetDateCache (defined in date.js).
i::Handle<i::String> func_name_str = i::Handle<i::String> func_name_str =
isolate->factory()->LookupAsciiSymbol("ResetDateCache"); isolate->factory()->LookupAsciiSymbol("ResetDateCache");
i::MaybeObject* result = i::MaybeObject* result =
......
...@@ -1610,8 +1610,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { ...@@ -1610,8 +1610,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) { LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
LOperand* date = UseRegister(instr->OperandAt(1)); LOperand* date = UseTempRegister(instr->OperandAt(1));
LOperand* value = UseRegister(instr->OperandAt(2)); LOperand* value = UseTempRegister(instr->OperandAt(2));
LSetDateField* result = LSetDateField* result =
new LSetDateField(date, value, TempRegister(), instr->index()); new LSetDateField(date, value, TempRegister(), instr->index());
return DefineAsRegister(result); return DefineAsRegister(result);
......
...@@ -47,9 +47,8 @@ function ThrowDateTypeError() { ...@@ -47,9 +47,8 @@ function ThrowDateTypeError() {
// ECMA 262 - 5.2 // ECMA 262 - 5.2
function Modulo(value, remainder) { function Modulo(value, remainder) {
var mod = value % remainder; var mod = value % remainder;
// Guard against returning -0. // All uses of this function for dates should produce a Smi.
if (mod == 0) return 0; return (mod >= 0 ? mod : mod + remainder) | 0;
return mod >= 0 ? mod : mod + remainder;
} }
...@@ -455,6 +454,34 @@ var Date_cache = { ...@@ -455,6 +454,34 @@ var Date_cache = {
}); });
function ResetDate(date, time) {
SET_DATE_VALUE(date, time);
// Cache aggressively in case of a reset - we will typically use most fields.
if (NUMBER_IS_NAN(time)) {
SET_DATE_LOCAL(date, time);
SET_DATE_YEAR(date, time);
SET_DATE_MONTH(date, time);
SET_DATE_DAY(date, time);
SET_DATE_HOUR(date, time);
SET_DATE_MIN(date, time);
SET_DATE_SEC(date, time);
SET_DATE_WEEKDAY(date, time);
} else {
var local = LocalTimeNoCheck(time);
SET_DATE_LOCAL(date, local_time_offset);
SET_DATE_YEAR(date, YearFromTime(local));
SET_DATE_MONTH(date, MonthFromTime(local));
SET_DATE_DAY(date, DateFromTime(local));
SET_DATE_HOUR(date, HOUR_FROM_TIME(local));
SET_DATE_MIN(date, MIN_FROM_TIME(local));
SET_DATE_SEC(date, SEC_FROM_TIME(local));
SET_DATE_WEEKDAY(date, WeekDay(local));
}
return time;
}
%FunctionSetPrototype($Date, new $Date($NaN)); %FunctionSetPrototype($Date, new $Date($NaN));
...@@ -638,11 +665,14 @@ function DateGetTime() { ...@@ -638,11 +665,14 @@ function DateGetTime() {
// ECMA 262 - 15.9.5.10 // ECMA 262 - 15.9.5.10
function DateGetFullYear() { function DateGetFullYear() {
var t = DATE_VALUE(this); var t = DATE_YEAR(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
t = DATE_VALUE_UNCHECKED(this);
var cache = Date_cache; var cache = Date_cache;
if (cache.time === t) return cache.year; if (cache.time === t) return cache.year;
return YearFromTime(LocalTimeNoCheck(t)); t = LocalTimeNoCheck(t);
if (!NUMBER_IS_NAN(t)) t = YearFromTime(t);
return t;
} }
...@@ -656,9 +686,10 @@ function DateGetUTCFullYear() { ...@@ -656,9 +686,10 @@ function DateGetUTCFullYear() {
// ECMA 262 - 15.9.5.12 // ECMA 262 - 15.9.5.12
function DateGetMonth() { function DateGetMonth() {
var t = DATE_VALUE(this); var t = DATE_MONTH(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return MonthFromTime(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_MONTH(this);
} }
...@@ -672,9 +703,10 @@ function DateGetUTCMonth() { ...@@ -672,9 +703,10 @@ function DateGetUTCMonth() {
// ECMA 262 - 15.9.5.14 // ECMA 262 - 15.9.5.14
function DateGetDate() { function DateGetDate() {
var t = DATE_VALUE(this); var t = DATE_DAY(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return DateFromTime(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_DAY(this);
} }
...@@ -687,9 +719,10 @@ function DateGetUTCDate() { ...@@ -687,9 +719,10 @@ function DateGetUTCDate() {
// ECMA 262 - 15.9.5.16 // ECMA 262 - 15.9.5.16
function DateGetDay() { function DateGetDay() {
var t = DATE_VALUE(this); var t = DATE_WEEKDAY(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return WeekDay(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_WEEKDAY(this);
} }
...@@ -703,9 +736,10 @@ function DateGetUTCDay() { ...@@ -703,9 +736,10 @@ function DateGetUTCDay() {
// ECMA 262 - 15.9.5.18 // ECMA 262 - 15.9.5.18
function DateGetHours() { function DateGetHours() {
var t = DATE_VALUE(this); var t = DATE_HOUR(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return HOUR_FROM_TIME(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_HOUR(this);
} }
...@@ -719,9 +753,10 @@ function DateGetUTCHours() { ...@@ -719,9 +753,10 @@ function DateGetUTCHours() {
// ECMA 262 - 15.9.5.20 // ECMA 262 - 15.9.5.20
function DateGetMinutes() { function DateGetMinutes() {
var t = DATE_VALUE(this); var t = DATE_MIN(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return MIN_FROM_TIME(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_MIN(this);
} }
...@@ -734,9 +769,10 @@ function DateGetUTCMinutes() { ...@@ -734,9 +769,10 @@ function DateGetUTCMinutes() {
// ECMA 262 - 15.9.5.22 // ECMA 262 - 15.9.5.22
function DateGetSeconds() { function DateGetSeconds() {
var t = DATE_VALUE(this); var t = DATE_SEC(this);
if (NUMBER_IS_NAN(t)) return t; if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
return SEC_FROM_TIME(LocalTimeNoCheck(t)); ResetDate(this, DATE_VALUE_UNCHECKED(this));
return DATE_SEC(this);
} }
...@@ -773,7 +809,7 @@ function DateGetTimezoneOffset() { ...@@ -773,7 +809,7 @@ function DateGetTimezoneOffset() {
// ECMA 262 - 15.9.5.27 // ECMA 262 - 15.9.5.27
function DateSetTime(ms) { function DateSetTime(ms) {
if (!IS_DATE(this)) ThrowDateTypeError(); if (!IS_DATE(this)) ThrowDateTypeError();
return SET_DATE_VALUE(this, TimeClip(ToNumber(ms))); return ResetDate(this, TimeClip(ToNumber(ms)));
} }
...@@ -785,7 +821,7 @@ function DateSetMilliseconds(ms) { ...@@ -785,7 +821,7 @@ function DateSetMilliseconds(ms) {
MIN_FROM_TIME(t), MIN_FROM_TIME(t),
SEC_FROM_TIME(t), SEC_FROM_TIME(t),
ms); ms);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(DAY(t), time)))); return ResetDate(this, TimeClip(UTC(MakeDate(DAY(t), time))));
} }
...@@ -797,7 +833,7 @@ function DateSetUTCMilliseconds(ms) { ...@@ -797,7 +833,7 @@ function DateSetUTCMilliseconds(ms) {
MIN_FROM_TIME(t), MIN_FROM_TIME(t),
SEC_FROM_TIME(t), SEC_FROM_TIME(t),
ms); ms);
return SET_DATE_VALUE(this, TimeClip(MakeDate(DAY(t), time))); return ResetDate(this, TimeClip(MakeDate(DAY(t), time)));
} }
...@@ -807,7 +843,7 @@ function DateSetSeconds(sec, ms) { ...@@ -807,7 +843,7 @@ function DateSetSeconds(sec, ms) {
sec = ToNumber(sec); sec = ToNumber(sec);
ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(DAY(t), time)))); return ResetDate(this, TimeClip(UTC(MakeDate(DAY(t), time))));
} }
...@@ -817,7 +853,7 @@ function DateSetUTCSeconds(sec, ms) { ...@@ -817,7 +853,7 @@ function DateSetUTCSeconds(sec, ms) {
sec = ToNumber(sec); sec = ToNumber(sec);
ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms); var time = MakeTime(HOUR_FROM_TIME(t), MIN_FROM_TIME(t), sec, ms);
return SET_DATE_VALUE(this, TimeClip(MakeDate(DAY(t), time))); return ResetDate(this, TimeClip(MakeDate(DAY(t), time)));
} }
...@@ -829,7 +865,7 @@ function DateSetMinutes(min, sec, ms) { ...@@ -829,7 +865,7 @@ function DateSetMinutes(min, sec, ms) {
sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(DAY(t), time)))); return ResetDate(this, TimeClip(UTC(MakeDate(DAY(t), time))));
} }
...@@ -841,7 +877,7 @@ function DateSetUTCMinutes(min, sec, ms) { ...@@ -841,7 +877,7 @@ function DateSetUTCMinutes(min, sec, ms) {
sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms); var time = MakeTime(HOUR_FROM_TIME(t), min, sec, ms);
return SET_DATE_VALUE(this, TimeClip(MakeDate(DAY(t), time))); return ResetDate(this, TimeClip(MakeDate(DAY(t), time)));
} }
...@@ -854,7 +890,7 @@ function DateSetHours(hour, min, sec, ms) { ...@@ -854,7 +890,7 @@ function DateSetHours(hour, min, sec, ms) {
sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(hour, min, sec, ms); var time = MakeTime(hour, min, sec, ms);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(DAY(t), time)))); return ResetDate(this, TimeClip(UTC(MakeDate(DAY(t), time))));
} }
...@@ -867,7 +903,7 @@ function DateSetUTCHours(hour, min, sec, ms) { ...@@ -867,7 +903,7 @@ function DateSetUTCHours(hour, min, sec, ms) {
sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec); sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms); ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(ms);
var time = MakeTime(hour, min, sec, ms); var time = MakeTime(hour, min, sec, ms);
return SET_DATE_VALUE(this, TimeClip(MakeDate(DAY(t), time))); return ResetDate(this, TimeClip(MakeDate(DAY(t), time)));
} }
...@@ -876,7 +912,7 @@ function DateSetDate(date) { ...@@ -876,7 +912,7 @@ function DateSetDate(date) {
var t = LocalTime(DATE_VALUE(this)); var t = LocalTime(DATE_VALUE(this));
date = ToNumber(date); date = ToNumber(date);
var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); return ResetDate(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
} }
...@@ -885,7 +921,7 @@ function DateSetUTCDate(date) { ...@@ -885,7 +921,7 @@ function DateSetUTCDate(date) {
var t = DATE_VALUE(this); var t = DATE_VALUE(this);
date = ToNumber(date); date = ToNumber(date);
var day = MakeDay(YearFromTime(t), MonthFromTime(t), date); var day = MakeDay(YearFromTime(t), MonthFromTime(t), date);
return SET_DATE_VALUE(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); return ResetDate(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
} }
...@@ -895,7 +931,7 @@ function DateSetMonth(month, date) { ...@@ -895,7 +931,7 @@ function DateSetMonth(month, date) {
month = ToNumber(month); month = ToNumber(month);
date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date);
var day = MakeDay(YearFromTime(t), month, date); var day = MakeDay(YearFromTime(t), month, date);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); return ResetDate(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
} }
...@@ -905,7 +941,7 @@ function DateSetUTCMonth(month, date) { ...@@ -905,7 +941,7 @@ function DateSetUTCMonth(month, date) {
month = ToNumber(month); month = ToNumber(month);
date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date); date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(date);
var day = MakeDay(YearFromTime(t), month, date); var day = MakeDay(YearFromTime(t), month, date);
return SET_DATE_VALUE(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); return ResetDate(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
} }
...@@ -918,7 +954,7 @@ function DateSetFullYear(year, month, date) { ...@@ -918,7 +954,7 @@ function DateSetFullYear(year, month, date) {
month = argc < 2 ? MonthFromTime(t) : ToNumber(month); month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
date = argc < 3 ? DateFromTime(t) : ToNumber(date); date = argc < 3 ? DateFromTime(t) : ToNumber(date);
var day = MakeDay(year, month, date); var day = MakeDay(year, month, date);
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); return ResetDate(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
} }
...@@ -931,7 +967,7 @@ function DateSetUTCFullYear(year, month, date) { ...@@ -931,7 +967,7 @@ function DateSetUTCFullYear(year, month, date) {
month = argc < 2 ? MonthFromTime(t) : ToNumber(month); month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
date = argc < 3 ? DateFromTime(t) : ToNumber(date); date = argc < 3 ? DateFromTime(t) : ToNumber(date);
var day = MakeDay(year, month, date); var day = MakeDay(year, month, date);
return SET_DATE_VALUE(this, TimeClip(MakeDate(day, TimeWithinDay(t)))); return ResetDate(this, TimeClip(MakeDate(day, TimeWithinDay(t))));
} }
...@@ -961,11 +997,11 @@ function DateSetYear(year) { ...@@ -961,11 +997,11 @@ function DateSetYear(year) {
var t = LocalTime(DATE_VALUE(this)); var t = LocalTime(DATE_VALUE(this));
if (NUMBER_IS_NAN(t)) t = 0; if (NUMBER_IS_NAN(t)) t = 0;
year = ToNumber(year); year = ToNumber(year);
if (NUMBER_IS_NAN(year)) return SET_DATE_VALUE(this, $NaN); if (NUMBER_IS_NAN(year)) return ResetDate(this, $NaN);
year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99) year = (0 <= TO_INTEGER(year) && TO_INTEGER(year) <= 99)
? 1900 + TO_INTEGER(year) : year; ? 1900 + TO_INTEGER(year) : year;
var day = MakeDay(year, MonthFromTime(t), DateFromTime(t)); var day = MakeDay(year, MonthFromTime(t), DateFromTime(t));
return SET_DATE_VALUE(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t))))); return ResetDate(this, TimeClip(UTC(MakeDate(day, TimeWithinDay(t)))));
} }
......
...@@ -1656,8 +1656,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { ...@@ -1656,8 +1656,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) { LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
LOperand* date = UseRegister(instr->OperandAt(1)); LOperand* date = UseTempRegister(instr->OperandAt(1));
LOperand* value = UseRegister(instr->OperandAt(2)); LOperand* value = UseTempRegister(instr->OperandAt(2));
LSetDateField* result = LSetDateField* result =
new(zone()) LSetDateField(date, value, TempRegister(), instr->index()); new(zone()) LSetDateField(date, value, TempRegister(), instr->index());
return DefineAsRegister(result); return DefineAsRegister(result);
......
...@@ -164,22 +164,26 @@ const MAX_TIME_BEFORE_UTC = 8640002592000000; ...@@ -164,22 +164,26 @@ const MAX_TIME_BEFORE_UTC = 8640002592000000;
# Gets the value of a Date object. If arg is not a Date object # Gets the value of a Date object. If arg is not a Date object
# a type error is thrown. # a type error is thrown.
macro DATE_VALUE_UNCHECKED(arg) = (%_DateField(arg, 0));
macro DATE_LOCAL_UNCHECKED(arg) = (%_DateField(arg, 1));
macro DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 0) : ThrowDateTypeError()); macro DATE_VALUE(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 0) : ThrowDateTypeError());
macro DATE_YEAR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 1) : ThrowDateTypeError()); macro DATE_LOCAL(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 1) : ThrowDateTypeError());
macro DATE_MONTH(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 2) : ThrowDateTypeError()); macro DATE_YEAR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 2) : ThrowDateTypeError());
macro DATE_DAY(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 3) : ThrowDateTypeError()); macro DATE_MONTH(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 3) : ThrowDateTypeError());
macro DATE_HOUR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 4) : ThrowDateTypeError()); macro DATE_DAY(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 4) : ThrowDateTypeError());
macro DATE_MIN(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 5) : ThrowDateTypeError()); macro DATE_HOUR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 5) : ThrowDateTypeError());
macro DATE_SEC(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 6) : ThrowDateTypeError()); macro DATE_MIN(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 6) : ThrowDateTypeError());
macro DATE_MS(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 7) : ThrowDateTypeError()); macro DATE_SEC(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 7) : ThrowDateTypeError());
macro DATE_WEEKDAY(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 8) : ThrowDateTypeError());
macro SET_DATE_VALUE(arg, value) = (%_SetDateField(arg, 0, value)); macro SET_DATE_VALUE(arg, value) = (%_SetDateField(arg, 0, value));
macro SET_DATE_YEAR(arg, value) = (%_SetDateField(arg, 1, value)); macro SET_DATE_LOCAL(arg, value) = (%_SetDateField(arg, 1, value));
macro SET_DATE_MONTH(arg, value) = (%_SetDateField(arg, 2, value)); macro SET_DATE_YEAR(arg, value) = (%_SetDateField(arg, 2, value));
macro SET_DATE_DAY(arg, value) = (%_SetDateField(arg, 3, value)); macro SET_DATE_MONTH(arg, value) = (%_SetDateField(arg, 3, value));
macro SET_DATE_HOUR(arg, value) = (%_SetDateField(arg, 4, value)); macro SET_DATE_DAY(arg, value) = (%_SetDateField(arg, 4, value));
macro SET_DATE_MIN(arg, value) = (%_SetDateField(arg, 5, value)); macro SET_DATE_HOUR(arg, value) = (%_SetDateField(arg, 5, value));
macro SET_DATE_SEC(arg, value) = (%_SetDateField(arg, 6, value)); macro SET_DATE_MIN(arg, value) = (%_SetDateField(arg, 6, value));
macro SET_DATE_MS(arg, value) = (%_SetDateField(arg, 7, value)); macro SET_DATE_SEC(arg, value) = (%_SetDateField(arg, 7, value));
macro SET_DATE_WEEKDAY(arg, value) = (%_SetDateField(arg, 8, value));
macro DAY(time) = ($floor(time / 86400000)); macro DAY(time) = ($floor(time / 86400000));
macro NAN_OR_DATE_FROM_TIME(time) = (NUMBER_IS_NAN(time) ? time : DateFromTime(time)); macro NAN_OR_DATE_FROM_TIME(time) = (NUMBER_IS_NAN(time) ? time : DateFromTime(time));
macro HOUR_FROM_TIME(time) = (Modulo($floor(time / 3600000), 24)); macro HOUR_FROM_TIME(time) = (Modulo($floor(time / 3600000), 24));
......
...@@ -378,38 +378,42 @@ void JSDate::JSDateVerify() { ...@@ -378,38 +378,42 @@ void JSDate::JSDateVerify() {
if (value()->IsHeapObject()) { if (value()->IsHeapObject()) {
VerifyHeapPointer(value()); VerifyHeapPointer(value());
} }
if (local()->IsHeapObject()) {
VerifyHeapPointer(local());
}
CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber()); CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
/* Don't check yet, will still be undefined... CHECK(local()->IsUndefined() || local()->IsSmi() || local()->IsHeapNumber());
if (value()->IsHeapNumber() && isnan(HeapNumber::cast(value())->value())) { CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
CHECK(year()->IsHeapNumber() && isnan(HeapNumber::cast(year())->value())); CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
CHECK(month()->IsHeapNumber() && isnan(HeapNumber::cast(month())->value())); CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
CHECK(day()->IsHeapNumber() && isnan(HeapNumber::cast(day())->value())); CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
CHECK(hour()->IsHeapNumber() && isnan(HeapNumber::cast(hour())->value())); CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
CHECK(min()->IsHeapNumber() && isnan(HeapNumber::cast(min())->value())); CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
CHECK(sec()->IsHeapNumber() && isnan(HeapNumber::cast(sec())->value())); CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
CHECK(ms()->IsHeapNumber() && isnan(HeapNumber::cast(ms())->value())); if (month()->IsSmi()) {
return; int month = Smi::cast(this->month())->value();
CHECK(0 <= month && month <= 11);
}
if (day()->IsSmi()) {
int day = Smi::cast(this->day())->value();
CHECK(1 <= day && day <= 31);
}
if (hour()->IsSmi()) {
int hour = Smi::cast(this->hour())->value();
CHECK(0 <= hour && hour <= 23);
}
if (min()->IsSmi()) {
int min = Smi::cast(this->min())->value();
CHECK(0 <= min && min <= 59);
}
if (sec()->IsSmi()) {
int sec = Smi::cast(this->sec())->value();
CHECK(0 <= sec && sec <= 59);
}
if (weekday()->IsSmi()) {
int weekday = Smi::cast(this->weekday())->value();
CHECK(0 <= weekday && weekday <= 6);
} }
CHECK(year()->IsSmi());
CHECK(month()->IsSmi());
CHECK(day()->IsSmi());
CHECK(hour()->IsSmi());
CHECK(min()->IsSmi());
CHECK(sec()->IsSmi());
CHECK(ms()->IsSmi());
int month = Smi::cast(this->month())->value();
int day = Smi::cast(this->day())->value();
int hour = Smi::cast(this->hour())->value();
int min = Smi::cast(this->min())->value();
int sec = Smi::cast(this->sec())->value();
int ms = Smi::cast(this->ms())->value();
CHECK(1 <= month && month <= 12);
CHECK(1 <= day && day <= 31);
CHECK(0 <= hour && hour <= 23);
CHECK(0 <= min && min <= 59);
CHECK(0 <= sec && sec <= 59);
CHECK(0 <= ms && ms <= 999);
*/
} }
......
...@@ -801,6 +801,11 @@ double Object::Number() { ...@@ -801,6 +801,11 @@ double Object::Number() {
} }
bool Object::IsNaN() {
return this->IsHeapNumber() && isnan(HeapNumber::cast(this)->value());
}
MaybeObject* Object::ToSmi() { MaybeObject* Object::ToSmi() {
if (IsSmi()) return this; if (IsSmi()) return this;
if (IsHeapNumber()) { if (IsHeapNumber()) {
...@@ -4123,13 +4128,14 @@ JSValue* JSValue::cast(Object* obj) { ...@@ -4123,13 +4128,14 @@ JSValue* JSValue::cast(Object* obj) {
ACCESSORS(JSDate, value, Object, kValueOffset) ACCESSORS(JSDate, value, Object, kValueOffset)
ACCESSORS(JSDate, local, Object, kLocalOffset)
ACCESSORS(JSDate, year, Object, kYearOffset) ACCESSORS(JSDate, year, Object, kYearOffset)
ACCESSORS(JSDate, month, Object, kMonthOffset) ACCESSORS(JSDate, month, Object, kMonthOffset)
ACCESSORS(JSDate, day, Object, kDayOffset) ACCESSORS(JSDate, day, Object, kDayOffset)
ACCESSORS(JSDate, hour, Object, kHourOffset) ACCESSORS(JSDate, hour, Object, kHourOffset)
ACCESSORS(JSDate, min, Object, kMinOffset) ACCESSORS(JSDate, min, Object, kMinOffset)
ACCESSORS(JSDate, sec, Object, kSecOffset) ACCESSORS(JSDate, sec, Object, kSecOffset)
ACCESSORS(JSDate, ms, Object, kMsOffset) ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)
JSDate* JSDate::cast(Object* obj) { JSDate* JSDate::cast(Object* obj) {
......
...@@ -663,6 +663,10 @@ char* String::ToAsciiArray() { ...@@ -663,6 +663,10 @@ char* String::ToAsciiArray() {
} }
static const char* const weekdays[] = {
"???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
void JSDate::JSDatePrint(FILE* out) { void JSDate::JSDatePrint(FILE* out) {
HeapObject::PrintHeader(out, "JSDate"); HeapObject::PrintHeader(out, "JSDate");
PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map())); PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
...@@ -671,14 +675,14 @@ void JSDate::JSDatePrint(FILE* out) { ...@@ -671,14 +675,14 @@ void JSDate::JSDatePrint(FILE* out) {
if (!year()->IsSmi()) { if (!year()->IsSmi()) {
PrintF(out, " - time = NaN\n"); PrintF(out, " - time = NaN\n");
} else { } else {
PrintF(out, " - time = %04d/%02d/%02d %02d:%02d:%02d.%03d\n", PrintF(out, " - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
Smi::cast(year())->value(), weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0],
Smi::cast(month())->value(), year()->IsSmi() ? Smi::cast(year())->value() : -1,
Smi::cast(day())->value(), month()->IsSmi() ? Smi::cast(month())->value() : -1,
Smi::cast(hour())->value(), day()->IsSmi() ? Smi::cast(day())->value() : -1,
Smi::cast(min())->value(), hour()->IsSmi() ? Smi::cast(hour())->value() : -1,
Smi::cast(sec())->value(), min()->IsSmi() ? Smi::cast(min())->value() : -1,
Smi::cast(ms())->value()); sec()->IsSmi() ? Smi::cast(sec())->value() : -1);
} }
} }
......
...@@ -893,6 +893,7 @@ class Object : public MaybeObject { ...@@ -893,6 +893,7 @@ class Object : public MaybeObject {
// Extract the number. // Extract the number.
inline double Number(); inline double Number();
inline bool IsNaN();
// Returns true if the object is of the correct type to be used as a // Returns true if the object is of the correct type to be used as a
// implementation of a JSObject's elements. // implementation of a JSObject's elements.
...@@ -6033,6 +6034,8 @@ class JSDate: public JSObject { ...@@ -6033,6 +6034,8 @@ class JSDate: public JSObject {
// If one component is NaN, all of them are, indicating a NaN time value. // If one component is NaN, all of them are, indicating a NaN time value.
// [value]: the time value. // [value]: the time value.
DECL_ACCESSORS(value, Object) DECL_ACCESSORS(value, Object)
// [local]: the offset for the local time value.
DECL_ACCESSORS(local, Object)
// [year]: caches year. Either undefined, smi, or NaN. // [year]: caches year. Either undefined, smi, or NaN.
DECL_ACCESSORS(year, Object) DECL_ACCESSORS(year, Object)
// [month]: caches month. Either undefined, smi, or NaN. // [month]: caches month. Either undefined, smi, or NaN.
...@@ -6045,8 +6048,8 @@ class JSDate: public JSObject { ...@@ -6045,8 +6048,8 @@ class JSDate: public JSObject {
DECL_ACCESSORS(min, Object) DECL_ACCESSORS(min, Object)
// [sec]: caches seconds. Either undefined, smi, or NaN. // [sec]: caches seconds. Either undefined, smi, or NaN.
DECL_ACCESSORS(sec, Object) DECL_ACCESSORS(sec, Object)
// [ms]: caches milliseconds. Either undefined, smi, or NaN. // [weekday]: caches day of week. Either undefined, smi, or NaN.
DECL_ACCESSORS(ms, Object) DECL_ACCESSORS(weekday, Object)
// Casting. // Casting.
static inline JSDate* cast(Object* obj); static inline JSDate* cast(Object* obj);
...@@ -6064,17 +6067,18 @@ class JSDate: public JSObject { ...@@ -6064,17 +6067,18 @@ class JSDate: public JSObject {
// Layout description. // Layout description.
static const int kValueOffset = JSObject::kHeaderSize; static const int kValueOffset = JSObject::kHeaderSize;
static const int kYearOffset = kValueOffset + kPointerSize; static const int kLocalOffset = kValueOffset + kPointerSize;
static const int kYearOffset = kLocalOffset + kPointerSize;
static const int kMonthOffset = kYearOffset + kPointerSize; static const int kMonthOffset = kYearOffset + kPointerSize;
static const int kDayOffset = kMonthOffset + kPointerSize; static const int kDayOffset = kMonthOffset + kPointerSize;
static const int kHourOffset = kDayOffset + kPointerSize; static const int kHourOffset = kDayOffset + kPointerSize;
static const int kMinOffset = kHourOffset + kPointerSize; static const int kMinOffset = kHourOffset + kPointerSize;
static const int kSecOffset = kMinOffset + kPointerSize; static const int kSecOffset = kMinOffset + kPointerSize;
static const int kMsOffset = kSecOffset + kPointerSize; static const int kWeekdayOffset = kSecOffset + kPointerSize;
static const int kSize = kMsOffset + kPointerSize; static const int kSize = kWeekdayOffset + kPointerSize;
// Index of first field not requiring a write barrier. // Index of first field not requiring a write barrier.
static const int kFirstBarrierFree = 1; // year static const int kFirstBarrierFree = 2; // year
private: private:
DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate); DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate);
......
...@@ -1609,8 +1609,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) { ...@@ -1609,8 +1609,8 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) { LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
LOperand* date = UseRegister(instr->OperandAt(1)); LOperand* date = UseTempRegister(instr->OperandAt(1));
LOperand* value = UseRegister(instr->OperandAt(2)); LOperand* value = UseTempRegister(instr->OperandAt(2));
LSetDateField* result = new LSetDateField(date, value, instr->index()); LSetDateField* result = new LSetDateField(date, value, instr->index());
return DefineAsRegister(result); return DefineAsRegister(result);
} }
......
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