[date] Refactor the %_DateField intrinsic to be optimizable.
authorbmeurer <bmeurer@chromium.org>
Wed, 3 Jun 2015 08:31:15 +0000 (01:31 -0700)
committerCommit bot <commit-bot@chromium.org>
Wed, 3 Jun 2015 08:31:27 +0000 (08:31 +0000)
Previously the %_DateField intrinsic would also check the object and
throw an exception if you happen to pass something that is not a valid
JSDate, which (a) violates our policy for instrinsics and (b) is hard to
optimize in TurboFan (even Crankshaft has a hard time, but there we will
never inline the relevant builtins, so it doesn't show up). The throwing
part is now a separate intrinsics %_ThrowIfNotADate that throws an
exception in full codegen and deoptimizes in Crankshaft, which means the
code for the current use cases is roughly the same (modulo some register
renamings/gap moves).

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/1167813003

Cr-Commit-Position: refs/heads/master@{#28782}

30 files changed:
src/arm/full-codegen-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-codegen-arm.cc
src/arm64/full-codegen-arm64.cc
src/arm64/lithium-arm64.cc
src/arm64/lithium-codegen-arm64.cc
src/bailout-reason.h
src/compiler/linkage.cc
src/date.js
src/deoptimizer.h
src/full-codegen.h
src/hydrogen-instructions.cc
src/hydrogen-instructions.h
src/hydrogen.cc
src/hydrogen.h
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/macros.py
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/mips64/full-codegen-mips64.cc
src/mips64/lithium-codegen-mips64.cc
src/mips64/lithium-mips64.cc
src/runtime/runtime-date.cc
src/runtime/runtime.h
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc

index 19baa1e..ad74239 100644 (file)
@@ -3912,6 +3912,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done, not_date_object;
+  Register object = r0;
+  Register result = r0;
+  Register scratch0 = r9;
+
+  __ JumpIfSmi(object, &not_date_object);
+  __ CompareObjectType(object, scratch0, scratch0, JS_DATE_TYPE);
+  __ b(eq, &done);
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3920,20 +3942,15 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = r0;
   Register result = r0;
   Register scratch0 = r9;
   Register scratch1 = r1;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
-  __ b(ne, &not_date_object);
-
   if (index->value() == 0) {
     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
-    __ jmp(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ mov(scratch1, Operand(stamp));
@@ -3949,13 +3966,10 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ PrepareCallCFunction(2, scratch1);
     __ mov(r1, Operand(index));
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ jmp(&done);
+    __ bind(&done);
   }
 
-  __ bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ bind(&done);
-  context()->Plug(r0);
+  context()->Plug(result);
 }
 
 
index d8cc7e5..4ee73e8 100644 (file)
@@ -1855,7 +1855,7 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* object = UseFixed(instr->value(), r0);
   LDateField* result =
       new(zone()) LDateField(object, FixedTemp(r1), instr->index());
-  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, r0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
 
index 3c845cb..8a15bd5 100644 (file)
@@ -1930,20 +1930,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register result = ToRegister(instr->result());
   Register scratch = ToRegister(instr->temp());
   Smi* index = instr->index();
-  Label runtime, done;
   DCHECK(object.is(result));
   DCHECK(object.is(r0));
   DCHECK(!scratch.is(scratch0()));
   DCHECK(!scratch.is(object));
 
-  __ SmiTst(object);
-  DeoptimizeIf(eq, instr, Deoptimizer::kSmi);
-  __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
-  DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject);
-
   if (index->value() == 0) {
     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ mov(scratch, Operand(stamp));
index 2b5dc6a..c41c05e 100644 (file)
@@ -3618,6 +3618,26 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done, not_date_object;
+  Register object = x0;
+  Register result = x0;
+
+  __ JumpIfSmi(object, &not_date_object);
+  __ JumpIfObjectType(object, x10, x10, JS_DATE_TYPE, &done);
+  __ Bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ Bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3626,23 +3646,19 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = x0;
   Register result = x0;
   Register stamp_addr = x10;
   Register stamp_cache = x11;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ JumpIfNotObjectType(object, x10, x10, JS_DATE_TYPE, &not_date_object);
-
   if (index->value() == 0) {
     __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
-    __ B(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
-      __ Mov(x10, stamp);
-      __ Ldr(stamp_addr, MemOperand(x10));
+      __ Mov(stamp_addr, stamp);
+      __ Ldr(stamp_addr, MemOperand(stamp_addr));
       __ Ldr(stamp_cache, FieldMemOperand(object, JSDate::kCacheStampOffset));
       __ Cmp(stamp_addr, stamp_cache);
       __ B(ne, &runtime);
@@ -3654,13 +3670,10 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ Bind(&runtime);
     __ Mov(x1, index);
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ B(&done);
+    __ Bind(&done);
   }
 
-  __ Bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ Bind(&done);
-  context()->Plug(x0);
+  context()->Plug(result);
 }
 
 
index d81f78b..dde8ddb 100644 (file)
@@ -1391,7 +1391,7 @@ LInstruction* LChunkBuilder::DoContext(HContext* instr) {
 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* object = UseFixed(instr->value(), x0);
   LDateField* result = new(zone()) LDateField(object, instr->index());
-  return MarkAsCall(DefineFixed(result, x0), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, x0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
 
index f51b3ed..2aea802 100644 (file)
@@ -2628,18 +2628,14 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register temp1 = x10;
   Register temp2 = x11;
   Smi* index = instr->index();
-  Label runtime, done;
 
   DCHECK(object.is(result) && object.Is(x0));
   DCHECK(instr->IsMarkedAsCall());
 
-  DeoptimizeIfSmi(object, instr, Deoptimizer::kSmi);
-  __ CompareObjectType(object, temp1, temp1, JS_DATE_TYPE);
-  DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject);
-
   if (index->value() == 0) {
     __ Ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ Mov(temp1, Operand(stamp));
@@ -2655,9 +2651,8 @@ void LCodeGen::DoDateField(LDateField* instr) {
     __ Bind(&runtime);
     __ Mov(x1, Operand(index));
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
+    __ Bind(&done);
   }
-
-  __ Bind(&done);
 }
 
 
index ed42124..1681634 100644 (file)
@@ -179,6 +179,7 @@ namespace internal {
   V(kOperandIsASmiAndNotAName, "Operand is a smi and not a name")              \
   V(kOperandIsASmiAndNotAString, "Operand is a smi and not a string")          \
   V(kOperandIsASmi, "Operand is a smi")                                        \
+  V(kOperandIsNotADate, "Operand is not a date")                               \
   V(kOperandIsNotAName, "Operand is not a name")                               \
   V(kOperandIsNotANumber, "Operand is not a number")                           \
   V(kOperandIsNotASmi, "Operand is not a smi")                                 \
index 24f5e49..3349c52 100644 (file)
@@ -132,10 +132,11 @@ bool Linkage::NeedsFrameState(Runtime::FunctionId function) {
       return false;
     case Runtime::kInlineArguments:
     case Runtime::kInlineCallFunction:
-    case Runtime::kInlineDateField:
+    case Runtime::kInlineDateField:  // TODO(bmeurer): Remove this.
     case Runtime::kInlineDeoptimizeNow:
     case Runtime::kInlineGetPrototype:
     case Runtime::kInlineRegExpExec:
+    case Runtime::kInlineThrowIfNotADate:
       return true;
     default:
       break;
index 3d494a1..dbf4947 100644 (file)
@@ -202,6 +202,7 @@ function TwoDigitString(value) {
 
 
 function DateString(date) {
+  CHECK_DATE(date);
   return WeekDays[LOCAL_WEEKDAY(date)] + ' '
       + Months[LOCAL_MONTH(date)] + ' '
       + TwoDigitString(LOCAL_DAY(date)) + ' '
@@ -216,6 +217,7 @@ var LongMonths = ['January', 'February', 'March', 'April', 'May', 'June',
 
 
 function LongDateString(date) {
+  CHECK_DATE(date);
   return LongWeekDays[LOCAL_WEEKDAY(date)] + ', '
       + LongMonths[LOCAL_MONTH(date)] + ' '
       + TwoDigitString(LOCAL_DAY(date)) + ', '
@@ -224,6 +226,7 @@ function LongDateString(date) {
 
 
 function TimeString(date) {
+  CHECK_DATE(date);
   return TwoDigitString(LOCAL_HOUR(date)) + ':'
       + TwoDigitString(LOCAL_MIN(date)) + ':'
       + TwoDigitString(LOCAL_SEC(date));
@@ -231,6 +234,7 @@ function TimeString(date) {
 
 
 function TimeStringUTC(date) {
+  CHECK_DATE(date);
   return TwoDigitString(UTC_HOUR(date)) + ':'
       + TwoDigitString(UTC_MIN(date)) + ':'
       + TwoDigitString(UTC_SEC(date));
@@ -238,6 +242,7 @@ function TimeStringUTC(date) {
 
 
 function LocalTimezoneString(date) {
+  CHECK_DATE(date);
   var timezone = LocalTimezone(UTC_DATE_VALUE(date));
 
   var timezoneOffset = -TIMEZONE_OFFSET(date);
@@ -251,6 +256,7 @@ function LocalTimezoneString(date) {
 
 
 function DatePrintString(date) {
+  CHECK_DATE(date);
   return DateString(date) + ' ' + TimeString(date);
 }
 
@@ -303,6 +309,7 @@ function DateNow() {
 
 // ECMA 262 - 15.9.5.2
 function DateToString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this)
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   var time_zone_string = LocalTimezoneString(this)
@@ -312,6 +319,7 @@ function DateToString() {
 
 // ECMA 262 - 15.9.5.3
 function DateToDateString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   return DateString(this);
@@ -320,6 +328,7 @@ function DateToDateString() {
 
 // ECMA 262 - 15.9.5.4
 function DateToTimeString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   var time_zone_string = LocalTimezoneString(this);
@@ -329,12 +338,14 @@ function DateToTimeString() {
 
 // ECMA 262 - 15.9.5.5
 function DateToLocaleString() {
+  CHECK_DATE(this);
   return %_CallFunction(this, DateToString);
 }
 
 
 // ECMA 262 - 15.9.5.6
 function DateToLocaleDateString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   return LongDateString(this);
@@ -343,6 +354,7 @@ function DateToLocaleDateString() {
 
 // ECMA 262 - 15.9.5.7
 function DateToLocaleTimeString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   return TimeString(this);
@@ -351,114 +363,133 @@ function DateToLocaleTimeString() {
 
 // ECMA 262 - 15.9.5.8
 function DateValueOf() {
+  CHECK_DATE(this);
   return UTC_DATE_VALUE(this);
 }
 
 
 // ECMA 262 - 15.9.5.9
 function DateGetTime() {
+  CHECK_DATE(this);
   return UTC_DATE_VALUE(this);
 }
 
 
 // ECMA 262 - 15.9.5.10
 function DateGetFullYear() {
+  CHECK_DATE(this);
   return LOCAL_YEAR(this);
 }
 
 
 // ECMA 262 - 15.9.5.11
 function DateGetUTCFullYear() {
+  CHECK_DATE(this);
   return UTC_YEAR(this);
 }
 
 
 // ECMA 262 - 15.9.5.12
 function DateGetMonth() {
+  CHECK_DATE(this);
   return LOCAL_MONTH(this);
 }
 
 
 // ECMA 262 - 15.9.5.13
 function DateGetUTCMonth() {
+  CHECK_DATE(this);
   return UTC_MONTH(this);
 }
 
 
 // ECMA 262 - 15.9.5.14
 function DateGetDate() {
+  CHECK_DATE(this);
   return LOCAL_DAY(this);
 }
 
 
 // ECMA 262 - 15.9.5.15
 function DateGetUTCDate() {
+  CHECK_DATE(this);
   return UTC_DAY(this);
 }
 
 
 // ECMA 262 - 15.9.5.16
 function DateGetDay() {
+  CHECK_DATE(this);
   return LOCAL_WEEKDAY(this);
 }
 
 
 // ECMA 262 - 15.9.5.17
 function DateGetUTCDay() {
+  CHECK_DATE(this);
   return UTC_WEEKDAY(this);
 }
 
 
 // ECMA 262 - 15.9.5.18
 function DateGetHours() {
+  CHECK_DATE(this);
   return LOCAL_HOUR(this);
 }
 
 
 // ECMA 262 - 15.9.5.19
 function DateGetUTCHours() {
+  CHECK_DATE(this);
   return UTC_HOUR(this);
 }
 
 
 // ECMA 262 - 15.9.5.20
 function DateGetMinutes() {
+  CHECK_DATE(this);
   return LOCAL_MIN(this);
 }
 
 
 // ECMA 262 - 15.9.5.21
 function DateGetUTCMinutes() {
+  CHECK_DATE(this);
   return UTC_MIN(this);
 }
 
 
 // ECMA 262 - 15.9.5.22
 function DateGetSeconds() {
+  CHECK_DATE(this);
   return LOCAL_SEC(this);
 }
 
 
 // ECMA 262 - 15.9.5.23
 function DateGetUTCSeconds() {
+  CHECK_DATE(this);
   return UTC_SEC(this)
 }
 
 
 // ECMA 262 - 15.9.5.24
 function DateGetMilliseconds() {
+  CHECK_DATE(this);
   return LOCAL_MS(this);
 }
 
 
 // ECMA 262 - 15.9.5.25
 function DateGetUTCMilliseconds() {
+  CHECK_DATE(this);
   return UTC_MS(this);
 }
 
 
 // ECMA 262 - 15.9.5.26
 function DateGetTimezoneOffset() {
+  CHECK_DATE(this);
   return TIMEZONE_OFFSET(this);
 }
 
@@ -473,6 +504,7 @@ function DateSetTime(ms) {
 
 // ECMA 262 - 15.9.5.28
 function DateSetMilliseconds(ms) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   ms = $toNumber(ms);
   var time = MakeTime(LOCAL_HOUR(this), LOCAL_MIN(this), LOCAL_SEC(this), ms);
@@ -482,6 +514,7 @@ function DateSetMilliseconds(ms) {
 
 // ECMA 262 - 15.9.5.29
 function DateSetUTCMilliseconds(ms) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   ms = $toNumber(ms);
   var time = MakeTime(UTC_HOUR(this),
@@ -494,6 +527,7 @@ function DateSetUTCMilliseconds(ms) {
 
 // ECMA 262 - 15.9.5.30
 function DateSetSeconds(sec, ms) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   sec = $toNumber(sec);
   ms = %_ArgumentsLength() < 2 ? LOCAL_MS(this) : $toNumber(ms);
@@ -504,6 +538,7 @@ function DateSetSeconds(sec, ms) {
 
 // ECMA 262 - 15.9.5.31
 function DateSetUTCSeconds(sec, ms) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   sec = $toNumber(sec);
   ms = %_ArgumentsLength() < 2 ? UTC_MS(this) : $toNumber(ms);
@@ -514,6 +549,7 @@ function DateSetUTCSeconds(sec, ms) {
 
 // ECMA 262 - 15.9.5.33
 function DateSetMinutes(min, sec, ms) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   min = $toNumber(min);
   var argc = %_ArgumentsLength();
@@ -526,6 +562,7 @@ function DateSetMinutes(min, sec, ms) {
 
 // ECMA 262 - 15.9.5.34
 function DateSetUTCMinutes(min, sec, ms) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   min = $toNumber(min);
   var argc = %_ArgumentsLength();
@@ -538,6 +575,7 @@ function DateSetUTCMinutes(min, sec, ms) {
 
 // ECMA 262 - 15.9.5.35
 function DateSetHours(hour, min, sec, ms) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   hour = $toNumber(hour);
   var argc = %_ArgumentsLength();
@@ -551,6 +589,7 @@ function DateSetHours(hour, min, sec, ms) {
 
 // ECMA 262 - 15.9.5.34
 function DateSetUTCHours(hour, min, sec, ms) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   hour = $toNumber(hour);
   var argc = %_ArgumentsLength();
@@ -564,6 +603,7 @@ function DateSetUTCHours(hour, min, sec, ms) {
 
 // ECMA 262 - 15.9.5.36
 function DateSetDate(date) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   date = $toNumber(date);
   var day = MakeDay(LOCAL_YEAR(this), LOCAL_MONTH(this), date);
@@ -573,6 +613,7 @@ function DateSetDate(date) {
 
 // ECMA 262 - 15.9.5.37
 function DateSetUTCDate(date) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   date = $toNumber(date);
   var day = MakeDay(UTC_YEAR(this), UTC_MONTH(this), date);
@@ -582,6 +623,7 @@ function DateSetUTCDate(date) {
 
 // ECMA 262 - 15.9.5.38
 function DateSetMonth(month, date) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   month = $toNumber(month);
   date = %_ArgumentsLength() < 2 ? LOCAL_DAY(this) : $toNumber(date);
@@ -592,6 +634,7 @@ function DateSetMonth(month, date) {
 
 // ECMA 262 - 15.9.5.39
 function DateSetUTCMonth(month, date) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   month = $toNumber(month);
   date = %_ArgumentsLength() < 2 ? UTC_DAY(this) : $toNumber(date);
@@ -602,6 +645,7 @@ function DateSetUTCMonth(month, date) {
 
 // ECMA 262 - 15.9.5.40
 function DateSetFullYear(year, month, date) {
+  CHECK_DATE(this);
   var t = LOCAL_DATE_VALUE(this);
   year = $toNumber(year);
   var argc = %_ArgumentsLength();
@@ -622,6 +666,7 @@ function DateSetFullYear(year, month, date) {
 
 // ECMA 262 - 15.9.5.41
 function DateSetUTCFullYear(year, month, date) {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   year = $toNumber(year);
   var argc = %_ArgumentsLength();
@@ -642,6 +687,7 @@ function DateSetUTCFullYear(year, month, date) {
 
 // ECMA 262 - 15.9.5.42
 function DateToUTCString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) return kInvalidDate;
   // Return UTC string of the form: Sat, 31 Jan 1970 23:00:00 GMT
@@ -655,6 +701,7 @@ function DateToUTCString() {
 
 // ECMA 262 - B.2.4
 function DateGetYear() {
+  CHECK_DATE(this);
   return LOCAL_YEAR(this) - 1900;
 }
 
@@ -702,6 +749,7 @@ function PadInt(n, digits) {
 
 // ECMA 262 - 15.9.5.43
 function DateToISOString() {
+  CHECK_DATE(this);
   var t = UTC_DATE_VALUE(this);
   if (NUMBER_IS_NAN(t)) throw MakeRangeError(kInvalidTimeValue);
   var year = this.getUTCFullYear();
index d16e055..2414bf1 100644 (file)
@@ -126,7 +126,6 @@ class OptimizedFunctionVisitor BASE_EMBEDDED {
   V(kNoCache, "no cache")                                                      \
   V(kNonStrictElementsInKeyedLoadGenericStub,                                  \
     "non-strict elements in KeyedLoadGenericStub")                             \
-  V(kNotADateObject, "not a date object")                                      \
   V(kNotAHeapNumber, "not a heap number")                                      \
   V(kNotAHeapNumberUndefinedBoolean, "not a heap number/undefined/true/false") \
   V(kNotAHeapNumberUndefined, "not a heap number/undefined")                   \
index a7a91d0..ef4bf1f 100644 (file)
@@ -529,6 +529,7 @@ class FullCodeGenerator: public AstVisitor {
   F(Arguments)                            \
   F(ValueOf)                              \
   F(SetValueOf)                           \
+  F(ThrowIfNotADate)                      \
   F(DateField)                            \
   F(StringCharFromCode)                   \
   F(StringCharAt)                         \
index 5c8e89a..00855a8 100644 (file)
@@ -1626,6 +1626,9 @@ void HCheckInstanceType::GetCheckInterval(InstanceType* first,
     case IS_JS_ARRAY:
       *first = *last = JS_ARRAY_TYPE;
       return;
+    case IS_JS_DATE:
+      *first = *last = JS_DATE_TYPE;
+      return;
     default:
       UNREACHABLE();
   }
@@ -1695,6 +1698,8 @@ const char* HCheckInstanceType::GetCheckName() const {
   switch (check_) {
     case IS_SPEC_OBJECT: return "object";
     case IS_JS_ARRAY: return "array";
+    case IS_JS_DATE:
+      return "date";
     case IS_STRING: return "string";
     case IS_INTERNALIZED_STRING: return "internalized_string";
   }
index 8beee14..7e6181e 100644 (file)
@@ -2875,9 +2875,10 @@ class HCheckInstanceType final : public HUnaryOperation {
   enum Check {
     IS_SPEC_OBJECT,
     IS_JS_ARRAY,
+    IS_JS_DATE,
     IS_STRING,
     IS_INTERNALIZED_STRING,
-    LAST_INTERVAL_CHECK = IS_JS_ARRAY
+    LAST_INTERVAL_CHECK = IS_JS_DATE
   };
 
   DECLARE_INSTRUCTION_FACTORY_P2(HCheckInstanceType, HValue*, Check);
@@ -2892,6 +2893,8 @@ class HCheckInstanceType final : public HUnaryOperation {
     switch (check_) {
       case IS_SPEC_OBJECT: return HType::JSObject();
       case IS_JS_ARRAY: return HType::JSArray();
+      case IS_JS_DATE:
+        return HType::JSObject();
       case IS_STRING: return HType::String();
       case IS_INTERNALIZED_STRING: return HType::String();
     }
index 225875a..40022a1 100644 (file)
@@ -11935,6 +11935,17 @@ void HOptimizedGraphBuilder::GenerateJSValueGetValue(CallRuntime* call) {
 }
 
 
+void HOptimizedGraphBuilder::GenerateThrowIfNotADate(CallRuntime* call) {
+  DCHECK_EQ(1, call->arguments()->length());
+  CHECK_ALIVE(VisitForValue(call->arguments()->at(0)));
+  HValue* obj = Pop();
+  BuildCheckHeapObject(obj);
+  HCheckInstanceType* check =
+      New<HCheckInstanceType>(obj, HCheckInstanceType::IS_JS_DATE);
+  return ast_context()->ReturnInstruction(check, call->id());
+}
+
+
 void HOptimizedGraphBuilder::GenerateDateField(CallRuntime* call) {
   DCHECK(call->arguments()->length() == 2);
   DCHECK_NOT_NULL(call->arguments()->at(1)->AsLiteral());
index 4c6e389..125ec58 100644 (file)
@@ -2183,6 +2183,7 @@ class HOptimizedGraphBuilder : public HGraphBuilder, public AstVisitor {
   F(Arguments)                         \
   F(ValueOf)                           \
   F(SetValueOf)                        \
+  F(ThrowIfNotADate)                   \
   F(DateField)                         \
   F(StringCharFromCode)                \
   F(StringCharAt)                      \
index 6427013..ffc83df 100644 (file)
@@ -3801,6 +3801,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done, not_date_object;
+  Register object = eax;
+  Register result = eax;
+  Register scratch = ecx;
+
+  __ JumpIfSmi(object, &not_date_object, Label::kNear);
+  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
+  __ j(equal, &done, Label::kNear);
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3809,19 +3831,14 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = eax;
   Register result = eax;
   Register scratch = ecx;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  __ j(not_equal, &not_date_object);
-
   if (index->value() == 0) {
     __ mov(result, FieldOperand(object, JSDate::kValueOffset));
-    __ jmp(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ mov(scratch, Operand::StaticVariable(stamp));
@@ -3829,19 +3846,16 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
       __ j(not_equal, &runtime, Label::kNear);
       __ mov(result, FieldOperand(object, JSDate::kValueOffset +
                                           kPointerSize * index->value()));
-      __ jmp(&done);
+      __ jmp(&done, Label::kNear);
     }
     __ bind(&runtime);
     __ PrepareCallCFunction(2, scratch);
     __ mov(Operand(esp, 0), object);
     __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ jmp(&done);
+    __ bind(&done);
   }
 
-  __ bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ bind(&done);
   context()->Plug(result);
 }
 
index 30c35b1..ee0ec27 100644 (file)
@@ -1790,18 +1790,13 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register result = ToRegister(instr->result());
   Register scratch = ToRegister(instr->temp());
   Smi* index = instr->index();
-  Label runtime, done;
   DCHECK(object.is(result));
   DCHECK(object.is(eax));
 
-  __ test(object, Immediate(kSmiTagMask));
-  DeoptimizeIf(zero, instr, Deoptimizer::kSmi);
-  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
-
   if (index->value() == 0) {
     __ mov(result, FieldOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ mov(scratch, Operand::StaticVariable(stamp));
index cecfadd..e245ba7 100644 (file)
@@ -1816,7 +1816,7 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* date = UseFixed(instr->value(), eax);
   LDateField* result =
       new(zone()) LDateField(date, FixedTemp(ecx), instr->index());
-  return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, eax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
 
index c68101a..94f94c3 100644 (file)
@@ -193,7 +193,7 @@ define MAX_TIME_BEFORE_UTC = 8640002592000000;
 
 # Gets the value of a Date object. If arg is not a Date object
 # a type error is thrown.
-macro CHECK_DATE(arg) = if (%_ClassOf(arg) !== 'Date') throw MakeTypeError(kDateType);
+macro CHECK_DATE(arg) = %_ThrowIfNotADate(arg);
 macro LOCAL_DATE_VALUE(arg) = (%_DateField(arg, 0) + %_DateField(arg, 21));
 macro UTC_DATE_VALUE(arg)    = (%_DateField(arg, 0));
 
index ef8f981..47975c1 100644 (file)
@@ -3894,6 +3894,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done, not_date_object;
+  Register object = v0;
+  Register result = v0;
+  Register scratch1 = a1;
+
+  __ JumpIfSmi(object, &not_date_object);
+  __ GetObjectType(object, scratch1, scratch1);
+  __ Branch(&done, eq, scratch1, Operand(JS_DATE_TYPE));
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3902,20 +3924,15 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = v0;
   Register result = v0;
   Register scratch0 = t5;
   Register scratch1 = a1;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ GetObjectType(object, scratch1, scratch1);
-  __ Branch(&not_date_object, ne, scratch1, Operand(JS_DATE_TYPE));
-
   if (index->value() == 0) {
     __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
-    __ jmp(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ li(scratch1, Operand(stamp));
@@ -3931,13 +3948,10 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ li(a1, Operand(index));
     __ Move(a0, object);
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ jmp(&done);
+    __ bind(&done);
   }
 
-  __ bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ bind(&done);
-  context()->Plug(v0);
+  context()->Plug(result);
 }
 
 
index 910c83a..8940eb0 100644 (file)
@@ -1794,21 +1794,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register result = ToRegister(instr->result());
   Register scratch = ToRegister(instr->temp());
   Smi* index = instr->index();
-  Label runtime, done;
   DCHECK(object.is(a0));
   DCHECK(result.is(v0));
   DCHECK(!scratch.is(scratch0()));
   DCHECK(!scratch.is(object));
 
-  __ SmiTst(object, at);
-  DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
-  __ GetObjectType(object, scratch, scratch);
-  DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject, scratch,
-               Operand(JS_DATE_TYPE));
-
   if (index->value() == 0) {
     __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ li(scratch, Operand(stamp));
index eebab79..77c5836 100644 (file)
@@ -1802,7 +1802,7 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* object = UseFixed(instr->value(), a0);
   LDateField* result =
       new(zone()) LDateField(object, FixedTemp(a1), instr->index());
-  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
 
index ef05900..ac56219 100644 (file)
@@ -3897,6 +3897,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Label done, not_date_object;
+  Register object = v0;
+  Register result = v0;
+  Register scratch1 = a1;
+
+  __ JumpIfSmi(object, &not_date_object);
+  __ GetObjectType(object, scratch1, scratch1);
+  __ Branch(&done, eq, scratch1, Operand(JS_DATE_TYPE));
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3905,20 +3927,15 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = v0;
   Register result = v0;
   Register scratch0 = t1;
   Register scratch1 = a1;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ GetObjectType(object, scratch1, scratch1);
-  __ Branch(&not_date_object, ne, scratch1, Operand(JS_DATE_TYPE));
-
   if (index->value() == 0) {
     __ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
-    __ jmp(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ li(scratch1, Operand(stamp));
@@ -3934,13 +3951,10 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ li(a1, Operand(index));
     __ Move(a0, object);
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ jmp(&done);
+    __ bind(&done);
   }
 
-  __ bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ bind(&done);
-  context()->Plug(v0);
+  context()->Plug(result);
 }
 
 
index 89ba285..fb201c0 100644 (file)
@@ -1783,21 +1783,15 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register result = ToRegister(instr->result());
   Register scratch = ToRegister(instr->temp());
   Smi* index = instr->index();
-  Label runtime, done;
   DCHECK(object.is(a0));
   DCHECK(result.is(v0));
   DCHECK(!scratch.is(scratch0()));
   DCHECK(!scratch.is(object));
 
-  __ SmiTst(object, at);
-  DeoptimizeIf(eq, instr, Deoptimizer::kSmi, at, Operand(zero_reg));
-  __ GetObjectType(object, scratch, scratch);
-  DeoptimizeIf(ne, instr, Deoptimizer::kNotADateObject, scratch,
-               Operand(JS_DATE_TYPE));
-
   if (index->value() == 0) {
     __ ld(result, FieldMemOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       __ li(scratch, Operand(stamp));
index c0671e1..67921a9 100644 (file)
@@ -1803,7 +1803,7 @@ LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* object = UseFixed(instr->value(), a0);
   LDateField* result =
       new(zone()) LDateField(object, FixedTemp(a1), instr->index());
-  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, v0), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }
 
 
index d2b93f0..47342f9 100644 (file)
@@ -60,6 +60,19 @@ RUNTIME_FUNCTION(Runtime_DateSetValue) {
 }
 
 
+RUNTIME_FUNCTION(Runtime_ThrowIfNotADate) {
+  SealHandleScope shs(isolate);
+  DCHECK_EQ(1, args.length());
+  CONVERT_ARG_CHECKED(Object, obj, 0);
+  if (!obj->IsJSDate()) {
+    HandleScope scope(isolate);
+    THROW_NEW_ERROR_RETURN_FAILURE(
+        isolate, NewTypeError(MessageTemplate::kNotDateObject));
+  }
+  return obj;
+}
+
+
 RUNTIME_FUNCTION(Runtime_ThrowNotDateError) {
   HandleScope scope(isolate);
   DCHECK(args.length() == 0);
@@ -174,17 +187,13 @@ RUNTIME_FUNCTION(Runtime_DateCacheVersion) {
 
 RUNTIME_FUNCTION(Runtime_DateField) {
   SealHandleScope shs(isolate);
-  DCHECK(args.length() == 2);
-  CONVERT_ARG_CHECKED(Object, obj, 0);
+  DCHECK_EQ(2, args.length());
+  CONVERT_ARG_CHECKED(JSDate, date, 0);
   CONVERT_SMI_ARG_CHECKED(index, 1);
-  if (!obj->IsJSDate()) {
-    HandleScope scope(isolate);
-    THROW_NEW_ERROR_RETURN_FAILURE(
-        isolate, NewTypeError(MessageTemplate::kNotDateObject));
-  }
-  JSDate* date = JSDate::cast(obj);
+  DCHECK_LE(0, index);
   if (index == 0) return date->value();
   return JSDate::GetField(date, Smi::FromInt(index));
 }
+
 }  // namespace internal
 }  // namespace v8
index 6905b74..0868bc6 100644 (file)
@@ -120,6 +120,7 @@ namespace internal {
 #define FOR_EACH_INTRINSIC_DATE(F) \
   F(DateMakeDay, 2, 1)             \
   F(DateSetValue, 3, 1)            \
+  F(ThrowIfNotADate, 1, 1)         \
   F(ThrowNotDateError, 0, 1)       \
   F(DateCurrentTime, 0, 1)         \
   F(DateParseString, 2, 1)         \
index e1f747a..0596265 100644 (file)
@@ -3793,6 +3793,28 @@ void FullCodeGenerator::EmitValueOf(CallRuntime* expr) {
 }
 
 
+void FullCodeGenerator::EmitThrowIfNotADate(CallRuntime* expr) {
+  ZoneList<Expression*>* args = expr->arguments();
+  DCHECK_EQ(1, args->length());
+
+  VisitForAccumulatorValue(args->at(0));  // Load the object.
+
+  Register object = rax;
+  Register result = rax;
+  Register scratch = rcx;
+
+  Label done, not_date_object;
+  __ JumpIfSmi(object, &not_date_object, Label::kNear);
+  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
+  __ j(equal, &done, Label::kNear);
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+
+  __ bind(&done);
+  context()->Plug(result);
+}
+
+
 void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
   ZoneList<Expression*>* args = expr->arguments();
   DCHECK(args->length() == 2);
@@ -3801,19 +3823,20 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done, not_date_object;
   Register object = rax;
   Register result = rax;
   Register scratch = rcx;
 
-  __ JumpIfSmi(object, &not_date_object);
-  __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  __ j(not_equal, &not_date_object);
+  if (FLAG_debug_code) {
+    __ AssertNotSmi(object);
+    __ CmpObjectType(object, JS_DATE_TYPE, scratch);
+    __ Check(equal, kOperandIsNotADate);
+  }
 
   if (index->value() == 0) {
     __ movp(result, FieldOperand(object, JSDate::kValueOffset));
-    __ jmp(&done);
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       Operand stamp_operand = __ ExternalOperand(stamp);
@@ -3822,7 +3845,7 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
       __ j(not_equal, &runtime, Label::kNear);
       __ movp(result, FieldOperand(object, JSDate::kValueOffset +
                                            kPointerSize * index->value()));
-      __ jmp(&done);
+      __ jmp(&done, Label::kNear);
     }
     __ bind(&runtime);
     __ PrepareCallCFunction(2);
@@ -3830,12 +3853,9 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ Move(arg_reg_2, index, Assembler::RelocInfoNone());
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
     __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-    __ jmp(&done);
+    __ bind(&done);
   }
 
-  __ bind(&not_date_object);
-  __ CallRuntime(Runtime::kThrowNotDateError, 0);
-  __ bind(&done);
   context()->Plug(rax);
 }
 
index 14909b1..08cb5e5 100644 (file)
@@ -1776,18 +1776,19 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register object = ToRegister(instr->date());
   Register result = ToRegister(instr->result());
   Smi* index = instr->index();
-  Label runtime, done, not_date_object;
   DCHECK(object.is(result));
   DCHECK(object.is(rax));
 
-  Condition cc = masm()->CheckSmi(object);
-  DeoptimizeIf(cc, instr, Deoptimizer::kSmi);
-  __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
-  DeoptimizeIf(not_equal, instr, Deoptimizer::kNotADateObject);
+  if (FLAG_debug_code) {
+    __ AssertNotSmi(object);
+    __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
+    __ Check(equal, kOperandIsNotADate);
+  }
 
   if (index->value() == 0) {
     __ movp(result, FieldOperand(object, JSDate::kValueOffset));
   } else {
+    Label runtime, done;
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
       Operand stamp_operand = __ ExternalOperand(stamp);
index 69bf82e..9456f2f 100644 (file)
@@ -1793,7 +1793,7 @@ LInstruction* LChunkBuilder::DoMapEnumLength(HMapEnumLength* instr) {
 LInstruction* LChunkBuilder::DoDateField(HDateField* instr) {
   LOperand* object = UseFixed(instr->value(), rax);
   LDateField* result = new(zone()) LDateField(object, instr->index());
-  return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
+  return MarkAsCall(DefineFixed(result, rax), instr, CANNOT_DEOPTIMIZE_EAGERLY);
 }