Revision: 10982
Author:   [email protected]
Date:     Fri Mar  9 03:19:55 2012
Log:      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++.

[email protected]
BUG=
TEST=

Review URL: https://chromiumcodereview.appspot.com/9307083
http://code.google.com/p/v8/source/detail?r=10982

Modified:
 /branches/bleeding_edge/src/api.cc
 /branches/bleeding_edge/src/arm/lithium-arm.cc
 /branches/bleeding_edge/src/date.js
 /branches/bleeding_edge/src/ia32/lithium-ia32.cc
 /branches/bleeding_edge/src/macros.py
 /branches/bleeding_edge/src/objects-debug.cc
 /branches/bleeding_edge/src/objects-inl.h
 /branches/bleeding_edge/src/objects-printer.cc
 /branches/bleeding_edge/src/objects.h
 /branches/bleeding_edge/src/x64/lithium-x64.cc

=======================================
--- /branches/bleeding_edge/src/api.cc  Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/api.cc  Fri Mar  9 03:19:55 2012
@@ -4748,7 +4748,7 @@
   ENTER_V8(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 =
       isolate->factory()->LookupAsciiSymbol("ResetDateCache");
   i::MaybeObject* result =
=======================================
--- /branches/bleeding_edge/src/arm/lithium-arm.cc      Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/arm/lithium-arm.cc      Fri Mar  9 03:19:55 2012
@@ -1610,8 +1610,8 @@


 LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
-  LOperand* date = UseRegister(instr->OperandAt(1));
-  LOperand* value = UseRegister(instr->OperandAt(2));
+  LOperand* date = UseTempRegister(instr->OperandAt(1));
+  LOperand* value = UseTempRegister(instr->OperandAt(2));
   LSetDateField* result =
       new LSetDateField(date, value, TempRegister(), instr->index());
   return DefineAsRegister(result);
=======================================
--- /branches/bleeding_edge/src/date.js Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/date.js Fri Mar  9 03:19:55 2012
@@ -47,9 +47,8 @@
 // ECMA 262 - 5.2
 function Modulo(value, remainder) {
   var mod = value % remainder;
-  // Guard against returning -0.
-  if (mod == 0) return 0;
-  return mod >= 0 ? mod : mod + remainder;
+  // All uses of this function for dates should produce a Smi.
+  return (mod >= 0 ? mod : mod + remainder) | 0;
 }


@@ -455,6 +454,34 @@
 });


+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));


@@ -638,11 +665,14 @@

 // ECMA 262 - 15.9.5.10
 function DateGetFullYear() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
+  var t = DATE_YEAR(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  t = DATE_VALUE_UNCHECKED(this);
   var cache = Date_cache;
   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 @@

 // ECMA 262 - 15.9.5.12
 function DateGetMonth() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return MonthFromTime(LocalTimeNoCheck(t));
+  var t = DATE_MONTH(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_MONTH(this);
 }


@@ -672,9 +703,10 @@

 // ECMA 262 - 15.9.5.14
 function DateGetDate() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return DateFromTime(LocalTimeNoCheck(t));
+  var t = DATE_DAY(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_DAY(this);
 }


@@ -687,9 +719,10 @@

 // ECMA 262 - 15.9.5.16
 function DateGetDay() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return WeekDay(LocalTimeNoCheck(t));
+  var t = DATE_WEEKDAY(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_WEEKDAY(this);
 }


@@ -703,9 +736,10 @@

 // ECMA 262 - 15.9.5.18
 function DateGetHours() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return HOUR_FROM_TIME(LocalTimeNoCheck(t));
+  var t = DATE_HOUR(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_HOUR(this);
 }


@@ -719,9 +753,10 @@

 // ECMA 262 - 15.9.5.20
 function DateGetMinutes() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return MIN_FROM_TIME(LocalTimeNoCheck(t));
+  var t = DATE_MIN(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_MIN(this);
 }


@@ -734,9 +769,10 @@

 // ECMA 262 - 15.9.5.22
 function DateGetSeconds() {
-  var t = DATE_VALUE(this);
-  if (NUMBER_IS_NAN(t)) return t;
-  return SEC_FROM_TIME(LocalTimeNoCheck(t));
+  var t = DATE_SEC(this);
+  if (!IS_UNDEFINED(t) && DATE_LOCAL(this) === local_time_offset) return t;
+  ResetDate(this, DATE_VALUE_UNCHECKED(this));
+  return DATE_SEC(this);
 }


@@ -773,7 +809,7 @@
 // ECMA 262 - 15.9.5.27
 function DateSetTime(ms) {
   if (!IS_DATE(this)) ThrowDateTypeError();
-  return SET_DATE_VALUE(this, TimeClip(ToNumber(ms)));
+  return ResetDate(this, TimeClip(ToNumber(ms)));
 }


@@ -785,7 +821,7 @@
                       MIN_FROM_TIME(t),
                       SEC_FROM_TIME(t),
                       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 @@
                       MIN_FROM_TIME(t),
                       SEC_FROM_TIME(t),
                       ms);
-  return SET_DATE_VALUE(this, TimeClip(MakeDate(DAY(t), time)));
+  return ResetDate(this, TimeClip(MakeDate(DAY(t), time)));
 }


@@ -807,7 +843,7 @@
   sec = ToNumber(sec);
   ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   sec = ToNumber(sec);
   ms = %_ArgumentsLength() < 2 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
   ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   sec = argc < 2 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
   ms = argc < 3 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
   ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   sec = argc < 3 ? NAN_OR_SEC_FROM_TIME(t) : ToNumber(sec);
   ms = argc < 4 ? NAN_OR_MS_FROM_TIME(t) : ToNumber(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 @@
   var t = LocalTime(DATE_VALUE(this));
   date = ToNumber(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 @@
   var t = DATE_VALUE(this);
   date = ToNumber(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 @@
   month = ToNumber(month);
date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(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 @@
   month = ToNumber(month);
date = %_ArgumentsLength() < 2 ? NAN_OR_DATE_FROM_TIME(t) : ToNumber(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 @@
   month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
   date = argc < 3 ? DateFromTime(t) : ToNumber(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 @@
   month = argc < 2 ? MonthFromTime(t) : ToNumber(month);
   date = argc < 3 ? DateFromTime(t) : ToNumber(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 @@
   var t = LocalTime(DATE_VALUE(this));
   if (NUMBER_IS_NAN(t)) t = 0;
   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)
       ? 1900 + TO_INTEGER(year) : year;
   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)))));
 }


=======================================
--- /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri Mar 9 03:11:55 2012 +++ /branches/bleeding_edge/src/ia32/lithium-ia32.cc Fri Mar 9 03:19:55 2012
@@ -1656,8 +1656,8 @@


 LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
-  LOperand* date = UseRegister(instr->OperandAt(1));
-  LOperand* value = UseRegister(instr->OperandAt(2));
+  LOperand* date = UseTempRegister(instr->OperandAt(1));
+  LOperand* value = UseTempRegister(instr->OperandAt(2));
   LSetDateField* result =
new(zone()) LSetDateField(date, value, TempRegister(), instr->index());
   return DefineAsRegister(result);
=======================================
--- /branches/bleeding_edge/src/macros.py       Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/macros.py       Fri Mar  9 03:19:55 2012
@@ -164,22 +164,26 @@

 # Gets the value of a Date object. If arg is not a Date object
 # 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_YEAR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 1) : ThrowDateTypeError()); -macro DATE_MONTH(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 2) : ThrowDateTypeError()); -macro DATE_DAY(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 3) : ThrowDateTypeError()); -macro DATE_HOUR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 4) : ThrowDateTypeError()); -macro DATE_MIN(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 5) : ThrowDateTypeError()); -macro DATE_SEC(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 6) : ThrowDateTypeError()); -macro DATE_MS(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 7) : ThrowDateTypeError()); +macro DATE_LOCAL(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 1) : ThrowDateTypeError()); +macro DATE_YEAR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 2) : ThrowDateTypeError()); +macro DATE_MONTH(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 3) : ThrowDateTypeError()); +macro DATE_DAY(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 4) : ThrowDateTypeError()); +macro DATE_HOUR(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 5) : ThrowDateTypeError()); +macro DATE_MIN(arg) = (%_ClassOf(arg) === 'Date' ? %_DateField(arg, 6) : 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_YEAR(arg, value) = (%_SetDateField(arg, 1, value));
-macro SET_DATE_MONTH(arg, value) = (%_SetDateField(arg, 2, value));
-macro SET_DATE_DAY(arg, value) = (%_SetDateField(arg, 3, value));
-macro SET_DATE_HOUR(arg, value) = (%_SetDateField(arg, 4, value));
-macro SET_DATE_MIN(arg, value) = (%_SetDateField(arg, 5, value));
-macro SET_DATE_SEC(arg, value) = (%_SetDateField(arg, 6, value));
-macro SET_DATE_MS(arg, value) = (%_SetDateField(arg, 7, value));
+macro SET_DATE_LOCAL(arg, value) = (%_SetDateField(arg, 1, value));
+macro SET_DATE_YEAR(arg, value) = (%_SetDateField(arg, 2, value));
+macro SET_DATE_MONTH(arg, value) = (%_SetDateField(arg, 3, value));
+macro SET_DATE_DAY(arg, value) = (%_SetDateField(arg, 4, value));
+macro SET_DATE_HOUR(arg, value) = (%_SetDateField(arg, 5, value));
+macro SET_DATE_MIN(arg, value) = (%_SetDateField(arg, 6, 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 NAN_OR_DATE_FROM_TIME(time) = (NUMBER_IS_NAN(time) ? time : DateFromTime(time));
 macro HOUR_FROM_TIME(time) = (Modulo($floor(time / 3600000), 24));
=======================================
--- /branches/bleeding_edge/src/objects-debug.cc        Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/objects-debug.cc        Fri Mar  9 03:19:55 2012
@@ -378,38 +378,42 @@
   if (value()->IsHeapObject()) {
     VerifyHeapPointer(value());
   }
+  if (local()->IsHeapObject()) {
+    VerifyHeapPointer(local());
+  }
CHECK(value()->IsUndefined() || value()->IsSmi() || value()->IsHeapNumber());
-/* Don't check yet, will still be undefined...
- if (value()->IsHeapNumber() && isnan(HeapNumber::cast(value())->value())) { - CHECK(year()->IsHeapNumber() && isnan(HeapNumber::cast(year())->value())); - CHECK(month()->IsHeapNumber() && isnan(HeapNumber::cast(month())->value())); - CHECK(day()->IsHeapNumber() && isnan(HeapNumber::cast(day())->value())); - CHECK(hour()->IsHeapNumber() && isnan(HeapNumber::cast(hour())->value())); - CHECK(min()->IsHeapNumber() && isnan(HeapNumber::cast(min())->value())); - CHECK(sec()->IsHeapNumber() && isnan(HeapNumber::cast(sec())->value()));
-    CHECK(ms()->IsHeapNumber() && isnan(HeapNumber::cast(ms())->value()));
-    return;
-  }
-  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);
-*/
+ CHECK(local()->IsUndefined() || local()->IsSmi() || local()->IsHeapNumber());
+  CHECK(year()->IsUndefined() || year()->IsSmi() || year()->IsNaN());
+  CHECK(month()->IsUndefined() || month()->IsSmi() || month()->IsNaN());
+  CHECK(day()->IsUndefined() || day()->IsSmi() || day()->IsNaN());
+  CHECK(hour()->IsUndefined() || hour()->IsSmi() || hour()->IsNaN());
+  CHECK(min()->IsUndefined() || min()->IsSmi() || min()->IsNaN());
+  CHECK(sec()->IsUndefined() || sec()->IsSmi() || sec()->IsNaN());
+ CHECK(weekday()->IsUndefined() || weekday()->IsSmi() || weekday()->IsNaN());
+  if (month()->IsSmi()) {
+    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);
+  }
 }


=======================================
--- /branches/bleeding_edge/src/objects-inl.h   Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/objects-inl.h   Fri Mar  9 03:19:55 2012
@@ -799,6 +799,11 @@
     ? static_cast<double>(reinterpret_cast<Smi*>(this)->value())
     : reinterpret_cast<HeapNumber*>(this)->value();
 }
+
+
+bool Object::IsNaN() {
+  return this->IsHeapNumber() && isnan(HeapNumber::cast(this)->value());
+}


 MaybeObject* Object::ToSmi() {
@@ -4123,13 +4128,14 @@


 ACCESSORS(JSDate, value, Object, kValueOffset)
+ACCESSORS(JSDate, local, Object, kLocalOffset)
 ACCESSORS(JSDate, year, Object, kYearOffset)
 ACCESSORS(JSDate, month, Object, kMonthOffset)
 ACCESSORS(JSDate, day, Object, kDayOffset)
 ACCESSORS(JSDate, hour, Object, kHourOffset)
 ACCESSORS(JSDate, min, Object, kMinOffset)
 ACCESSORS(JSDate, sec, Object, kSecOffset)
-ACCESSORS(JSDate, ms, Object, kMsOffset)
+ACCESSORS(JSDate, weekday, Object, kWeekdayOffset)


 JSDate* JSDate::cast(Object* obj) {
=======================================
--- /branches/bleeding_edge/src/objects-printer.cc      Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/objects-printer.cc      Fri Mar  9 03:19:55 2012
@@ -663,6 +663,10 @@
 }


+static const char* const weekdays[] = {
+  "???", "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+
 void JSDate::JSDatePrint(FILE* out) {
   HeapObject::PrintHeader(out, "JSDate");
   PrintF(out, " - map = 0x%p\n", reinterpret_cast<void*>(map()));
@@ -671,14 +675,14 @@
   if (!year()->IsSmi()) {
     PrintF(out, " - time = NaN\n");
   } else {
-    PrintF(out, " - time = %04d/%02d/%02d %02d:%02d:%02d.%03d\n",
-           Smi::cast(year())->value(),
-           Smi::cast(month())->value(),
-           Smi::cast(day())->value(),
-           Smi::cast(hour())->value(),
-           Smi::cast(min())->value(),
-           Smi::cast(sec())->value(),
-           Smi::cast(ms())->value());
+    PrintF(out, " - time = %s %04d/%02d/%02d %02d:%02d:%02d\n",
+ weekdays[weekday()->IsSmi() ? Smi::cast(weekday())->value() + 1 : 0],
+           year()->IsSmi() ? Smi::cast(year())->value() : -1,
+           month()->IsSmi() ? Smi::cast(month())->value() : -1,
+           day()->IsSmi() ? Smi::cast(day())->value() : -1,
+           hour()->IsSmi() ? Smi::cast(hour())->value() : -1,
+           min()->IsSmi() ? Smi::cast(min())->value() : -1,
+           sec()->IsSmi() ? Smi::cast(sec())->value() : -1);
   }
 }

=======================================
--- /branches/bleeding_edge/src/objects.h       Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/objects.h       Fri Mar  9 03:19:55 2012
@@ -893,6 +893,7 @@

   // Extract the number.
   inline double Number();
+  inline bool IsNaN();

   // Returns true if the object is of the correct type to be used as a
   // implementation of a JSObject's elements.
@@ -6033,6 +6034,8 @@
   // If one component is NaN, all of them are, indicating a NaN time value.
   // [value]: the time value.
   DECL_ACCESSORS(value, Object)
+  // [local]: the offset for the local time value.
+  DECL_ACCESSORS(local, Object)
   // [year]: caches year. Either undefined, smi, or NaN.
   DECL_ACCESSORS(year, Object)
   // [month]: caches month. Either undefined, smi, or NaN.
@@ -6045,8 +6048,8 @@
   DECL_ACCESSORS(min, Object)
   // [sec]: caches seconds. Either undefined, smi, or NaN.
   DECL_ACCESSORS(sec, Object)
-  // [ms]: caches milliseconds. Either undefined, smi, or NaN.
-  DECL_ACCESSORS(ms, Object)
+  // [weekday]: caches day of week. Either undefined, smi, or NaN.
+  DECL_ACCESSORS(weekday, Object)

   // Casting.
   static inline JSDate* cast(Object* obj);
@@ -6064,17 +6067,18 @@

   // Layout description.
   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 kDayOffset = kMonthOffset + kPointerSize;
   static const int kHourOffset = kDayOffset + kPointerSize;
   static const int kMinOffset = kHourOffset + kPointerSize;
   static const int kSecOffset = kMinOffset + kPointerSize;
-  static const int kMsOffset = kSecOffset + kPointerSize;
-  static const int kSize = kMsOffset + kPointerSize;
+  static const int kWeekdayOffset = kSecOffset + kPointerSize;
+  static const int kSize = kWeekdayOffset + kPointerSize;

   // Index of first field not requiring a write barrier.
-  static const int kFirstBarrierFree = 1;  // year
+  static const int kFirstBarrierFree = 2;  // year

  private:
   DISALLOW_IMPLICIT_CONSTRUCTORS(JSDate);
=======================================
--- /branches/bleeding_edge/src/x64/lithium-x64.cc      Fri Mar  9 03:11:55 2012
+++ /branches/bleeding_edge/src/x64/lithium-x64.cc      Fri Mar  9 03:19:55 2012
@@ -1609,8 +1609,8 @@


 LInstruction* LChunkBuilder::DoSetDateField(HSetDateField* instr) {
-  LOperand* date = UseRegister(instr->OperandAt(1));
-  LOperand* value = UseRegister(instr->OperandAt(2));
+  LOperand* date = UseTempRegister(instr->OperandAt(1));
+  LOperand* value = UseTempRegister(instr->OperandAt(2));
   LSetDateField* result = new LSetDateField(date, value, instr->index());
   return DefineAsRegister(result);
 }

--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev

Reply via email to