Add checks to runtime functions.
authoryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 Sep 2012 08:35:26 +0000 (08:35 +0000)
committeryangguo@chromium.org <yangguo@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Mon, 10 Sep 2012 08:35:26 +0000 (08:35 +0000)
BUG=

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

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@12471 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

21 files changed:
src/arm/full-codegen-arm.cc
src/arm/lithium-arm.cc
src/arm/lithium-codegen-arm.cc
src/date.js
src/ia32/full-codegen-ia32.cc
src/ia32/lithium-codegen-ia32.cc
src/ia32/lithium-ia32.cc
src/liveedit.cc
src/messages.js
src/mips/full-codegen-mips.cc
src/mips/lithium-codegen-mips.cc
src/mips/lithium-mips.cc
src/objects.cc
src/objects.h
src/runtime.cc
src/runtime.h
src/x64/full-codegen-x64.cc
src/x64/lithium-codegen-x64.cc
src/x64/lithium-x64.cc
test/mjsunit/date.js
test/mjsunit/string-charcodeat.js

index 85e94f2..b2f629b 100644 (file)
@@ -3134,20 +3134,19 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done;
+  Label runtime, done, not_date_object;
   Register object = r0;
   Register result = r0;
   Register scratch0 = r9;
   Register scratch1 = r1;
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ JumpIfSmi(object, &not_date_object);
   __ CompareObjectType(object, scratch1, scratch1, JS_DATE_TYPE);
-  __ Assert(eq, "Trying to get date field from non-date.");
-#endif
+  __ b(ne, &not_date_object);
 
   if (index->value() == 0) {
     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
+    __ jmp(&done);
   } else {
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
@@ -3164,8 +3163,12 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ PrepareCallCFunction(2, scratch1);
     __ mov(r1, Operand(index));
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ bind(&done);
+    __ jmp(&done);
   }
+
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+  __ bind(&done);
   context()->Plug(r0);
 }
 
@@ -3580,9 +3583,8 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
   ASSERT(args->length() == 1);
   VisitForAccumulatorValue(args->at(0));
 
-  if (generate_debug_code_) {
-    __ AbortIfNotString(r0);
-  }
+  __ AbortIfNotString(r0);
+
 
   __ ldr(r0, FieldMemOperand(r0, String::kHashFieldOffset));
   __ IndexFromHash(r0, r0);
index aac7e8c..fc1d640 100644 (file)
@@ -1562,7 +1562,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);
+  return MarkAsCall(DefineFixed(result, r0), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
index f11044d..4be6d26 100644 (file)
@@ -1597,11 +1597,10 @@ void LCodeGen::DoDateField(LDateField* instr) {
   ASSERT(!scratch.is(scratch0()));
   ASSERT(!scratch.is(object));
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ tst(object, Operand(kSmiTagMask));
+  DeoptimizeIf(eq, instr->environment());
   __ CompareObjectType(object, scratch, scratch, JS_DATE_TYPE);
-  __ Assert(eq, "Trying to get date field from non-date.");
-#endif
+  DeoptimizeIf(ne, instr->environment());
 
   if (index->value() == 0) {
     __ ldr(result, FieldMemOperand(object, JSDate::kValueOffset));
@@ -2237,9 +2236,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
   Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
-  if (FLAG_debug_code) {
-    __ AbortIfNotString(input);
-  }
+  __ AbortIfNotString(input);
 
   __ ldr(result, FieldMemOperand(input, String::kHashFieldOffset));
   __ IndexFromHash(result, result);
index d0e24ab..a54cb23 100644 (file)
@@ -318,7 +318,6 @@ 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)
@@ -328,7 +327,6 @@ 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);
@@ -337,7 +335,6 @@ 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);
@@ -353,7 +350,6 @@ function DateToLocaleString() {
 
 // 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);
@@ -362,7 +358,6 @@ 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);
@@ -371,133 +366,114 @@ 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);
 }
 
@@ -512,7 +488,6 @@ 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);
@@ -522,7 +497,6 @@ 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),
@@ -535,7 +509,6 @@ 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);
@@ -546,7 +519,6 @@ 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);
@@ -557,7 +529,6 @@ 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();
@@ -570,7 +541,6 @@ 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();
@@ -583,7 +553,6 @@ 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();
@@ -597,7 +566,6 @@ 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();
@@ -611,7 +579,6 @@ 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);
@@ -621,7 +588,6 @@ 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);
@@ -631,7 +597,6 @@ 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);
@@ -642,7 +607,6 @@ 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);
@@ -653,7 +617,6 @@ 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();
@@ -674,7 +637,6 @@ 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();
@@ -695,7 +657,6 @@ 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
@@ -709,7 +670,6 @@ function DateToUTCString() {
 
 // ECMA 262 - B.2.4
 function DateGetYear() {
-  CHECK_DATE(this);
   return LOCAL_YEAR(this) - 1900;
 }
 
@@ -757,7 +717,6 @@ 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("invalid_time_value", []);
   var year = this.getUTCFullYear();
index de8e490..7fb7cc3 100644 (file)
@@ -3068,19 +3068,18 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done;
+  Label runtime, done, not_date_object;
   Register object = eax;
   Register result = eax;
   Register scratch = ecx;
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ JumpIfSmi(object, &not_date_object);
   __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  __ Assert(equal, "Trying to get date field from non-date.");
-#endif
+  __ j(not_equal, &not_date_object);
 
   if (index->value() == 0) {
     __ mov(result, FieldOperand(object, JSDate::kValueOffset));
+    __ jmp(&done);
   } else {
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
@@ -3096,8 +3095,12 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ mov(Operand(esp, 0), object);
     __ mov(Operand(esp, 1 * kPointerSize), Immediate(index));
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ bind(&done);
+    __ jmp(&done);
   }
+
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+  __ bind(&done);
   context()->Plug(result);
 }
 
@@ -3522,9 +3525,7 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
   ASSERT(args->length() == 1);
   VisitForAccumulatorValue(args->at(0));
 
-  if (generate_debug_code_) {
-    __ AbortIfNotString(eax);
-  }
+  __ AbortIfNotString(eax);
 
   __ mov(eax, FieldOperand(eax, String::kHashFieldOffset));
   __ IndexFromHash(eax, eax);
index b645fd9..33efdd8 100644 (file)
@@ -1449,11 +1449,10 @@ void LCodeGen::DoDateField(LDateField* instr) {
   ASSERT(object.is(result));
   ASSERT(object.is(eax));
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ test(object, Immediate(kSmiTagMask));
+  DeoptimizeIf(zero, instr->environment());
   __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  __ Assert(equal, "Trying to get date field from non-date.");
-#endif
+  DeoptimizeIf(not_equal, instr->environment());
 
   if (index->value() == 0) {
     __ mov(result, FieldOperand(object, JSDate::kValueOffset));
@@ -2075,9 +2074,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
   Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
-  if (FLAG_debug_code) {
-    __ AbortIfNotString(input);
-  }
+  __ AbortIfNotString(input);
 
   __ mov(result, FieldOperand(input, String::kHashFieldOffset));
   __ IndexFromHash(result, result);
index 66da00d..f576e37 100644 (file)
@@ -1610,7 +1610,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);
+  return MarkAsCall(DefineFixed(result, eax), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
index 5dc86f9..f353154 100644 (file)
@@ -670,6 +670,7 @@ class JSArrayBasedStruct {
   }
   int GetSmiValueField(int field_position) {
     Object* res = GetField(field_position);
+    CHECK(res->IsSmi());
     return Smi::cast(res)->value();
   }
 
@@ -714,14 +715,17 @@ class FunctionInfoWrapper : public JSArrayBasedStruct<FunctionInfoWrapper> {
     return this->GetSmiValueField(kParentIndexOffset_);
   }
   Handle<Code> GetFunctionCode() {
-    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
-        JSValue::cast(this->GetField(kCodeOffset_))));
+    Object* element = this->GetField(kCodeOffset_);
+    CHECK(element->IsJSValue());
+    Handle<JSValue> value_wrapper(JSValue::cast(element));
+    Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
+    CHECK(raw_result->IsCode());
     return Handle<Code>::cast(raw_result);
   }
   Handle<Object> GetCodeScopeInfo() {
-    Handle<Object> raw_result = UnwrapJSValue(Handle<JSValue>(
-        JSValue::cast(this->GetField(kCodeScopeInfoOffset_))));
-    return raw_result;
+    Object* element = this->GetField(kCodeScopeInfoOffset_);
+    CHECK(element->IsJSValue());
+    return UnwrapJSValue(Handle<JSValue>(JSValue::cast(element)));
   }
   int GetStartPosition() {
     return this->GetSmiValueField(kStartPositionOffset_);
@@ -771,8 +775,10 @@ class SharedInfoWrapper : public JSArrayBasedStruct<SharedInfoWrapper> {
   }
   Handle<SharedFunctionInfo> GetInfo() {
     Object* element = this->GetField(kSharedInfoOffset_);
+    CHECK(element->IsJSValue());
     Handle<JSValue> value_wrapper(JSValue::cast(element));
     Handle<Object> raw_result = UnwrapJSValue(value_wrapper);
+    CHECK(raw_result->IsSharedFunctionInfo());
     return Handle<SharedFunctionInfo>::cast(raw_result);
   }
 
@@ -1127,6 +1133,7 @@ void LiveEdit::SetFunctionScript(Handle<JSValue> function_wrapper,
                                  Handle<Object> script_handle) {
   Handle<SharedFunctionInfo> shared_info =
       Handle<SharedFunctionInfo>::cast(UnwrapJSValue(function_wrapper));
+  CHECK(script_handle->IsScript() || script_handle->IsUndefined());
   shared_info->set_script(*script_handle);
 
   Isolate::Current()->compilation_cache()->Remove(shared_info);
index e46750f..28cedba 100644 (file)
@@ -202,6 +202,7 @@ function FormatMessage(message) {
       "proxy_non_object_prop_names",  ["Trap '", "%1", "' returned non-object ", "%0"],
       "proxy_repeated_prop_name",     ["Trap '", "%1", "' returned repeated property name '", "%2", "'"],
       "invalid_weakmap_key",          ["Invalid value used as weak map key"],
+      "not_date_object",              ["Receiver is not a Date object."],
       // RangeError
       "invalid_array_length",         ["Invalid array length"],
       "stack_overflow",               ["Maximum call stack size exceeded"],
index 6a697bc..bfa2425 100644 (file)
@@ -3160,21 +3160,19 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done;
+  Label runtime, done, not_date_object;
   Register object = v0;
   Register result = v0;
   Register scratch0 = t5;
   Register scratch1 = a1;
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ JumpIfSmi(object, &not_date_object);
   __ GetObjectType(object, scratch1, scratch1);
-  __ Assert(eq, "Trying to get date field from non-date.",
-      scratch1, Operand(JS_DATE_TYPE));
-#endif
+  __ Branch(&not_date_object, ne, scratch1, Operand(JS_DATE_TYPE));
 
   if (index->value() == 0) {
     __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
+    __ jmp(&done);
   } else {
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
@@ -3191,9 +3189,12 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
     __ li(a1, Operand(index));
     __ Move(a0, object);
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
-    __ bind(&done);
+    __ jmp(&done);
   }
 
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+  __ bind(&done);
   context()->Plug(v0);
 }
 
@@ -3620,9 +3621,7 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
   ASSERT(args->length() == 1);
   VisitForAccumulatorValue(args->at(0));
 
-  if (generate_debug_code_) {
-    __ AbortIfNotString(v0);
-  }
+  __ AbortIfNotString(v0);
 
   __ lw(v0, FieldMemOperand(v0, String::kHashFieldOffset));
   __ IndexFromHash(v0, v0);
index a00a92d..db9748a 100644 (file)
@@ -1290,12 +1290,10 @@ void LCodeGen::DoDateField(LDateField* instr) {
   ASSERT(!scratch.is(scratch0()));
   ASSERT(!scratch.is(object));
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ And(at, object, Operand(kSmiTagMask));
+  DeoptimizeIf(eq, instr->environment(), at, Operand(zero_reg));
   __ GetObjectType(object, scratch, scratch);
-  __ Assert(eq, "Trying to get date field from non-date.",
-      scratch, Operand(JS_DATE_TYPE));
-#endif
+  DeoptimizeIf(ne, instr->environment(), scratch, Operand(JS_DATE_TYPE));
 
   if (index->value() == 0) {
     __ lw(result, FieldMemOperand(object, JSDate::kValueOffset));
@@ -1973,9 +1971,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
   Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
-  if (FLAG_debug_code) {
-    __ AbortIfNotString(input);
-  }
+  __ AbortIfNotString(input);
 
   __ lw(result, FieldMemOperand(input, String::kHashFieldOffset));
   __ IndexFromHash(result, result);
index 560ea53..958bbc4 100644 (file)
@@ -1501,7 +1501,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);
+  return MarkAsCall(DefineFixed(result, v0), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
index 74af575..158de14 100644 (file)
@@ -7533,16 +7533,13 @@ MaybeObject* JSFunction::SetPrototype(Object* value) {
 }
 
 
-Object* JSFunction::RemovePrototype() {
+void JSFunction::RemovePrototype() {
   Context* native_context = context()->native_context();
   Map* no_prototype_map = shared()->is_classic_mode()
       ? native_context->function_without_prototype_map()
       : native_context->strict_mode_function_without_prototype_map();
 
-  if (map() == no_prototype_map) {
-    // Be idempotent.
-    return this;
-  }
+  if (map() == no_prototype_map) return;
 
   ASSERT(map() == (shared()->is_classic_mode()
                    ? native_context->function_map()
@@ -7550,13 +7547,11 @@ Object* JSFunction::RemovePrototype() {
 
   set_map(no_prototype_map);
   set_prototype_or_initial_map(no_prototype_map->GetHeap()->the_hole_value());
-  return this;
 }
 
 
-Object* JSFunction::SetInstanceClassName(String* name) {
+void JSFunction::SetInstanceClassName(String* name) {
   shared()->set_instance_class_name(name);
-  return this;
 }
 
 
index 720d96e..02d3ec2 100644 (file)
@@ -6084,7 +6084,7 @@ class JSFunction: public JSObject {
 
   // After prototype is removed, it will not be created when accessed, and
   // [[Construct]] from this function will not be allowed.
-  Object* RemovePrototype();
+  void RemovePrototype();
   inline bool should_have_prototype();
 
   // Accessor for this function's initial map's [[class]]
@@ -6096,7 +6096,7 @@ class JSFunction: public JSObject {
   // Instances created afterwards will have a map whose [[class]] is
   // set to 'value', but there is no guarantees on instances created
   // before.
-  Object* SetInstanceClassName(String* name);
+  void SetInstanceClassName(String* name);
 
   // Returns if this function has been compiled to native code yet.
   inline bool is_compiled();
index 48022b0..0fbd9c2 100644 (file)
@@ -673,7 +673,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateArrayLiteralShallow) {
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
   ASSERT(args.length() == 2);
-  Object* handler = args[0];
+  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
   Object* prototype = args[1];
   Object* used_prototype =
       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
@@ -683,9 +683,10 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSProxy) {
 
 RUNTIME_FUNCTION(MaybeObject*, Runtime_CreateJSFunctionProxy) {
   ASSERT(args.length() == 4);
-  Object* handler = args[0];
+  CONVERT_ARG_CHECKED(JSReceiver, handler, 0);
   Object* call_trap = args[1];
-  Object* construct_trap = args[2];
+  RUNTIME_ASSERT(call_trap->IsJSFunction() || call_trap->IsJSFunctionProxy());
+  CONVERT_ARG_CHECKED(JSFunction, construct_trap, 2);
   Object* prototype = args[3];
   Object* used_prototype =
       prototype->IsJSReceiver() ? prototype : isolate->heap()->null_value();
@@ -2066,8 +2067,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_FunctionRemovePrototype) {
   ASSERT(args.length() == 1);
 
   CONVERT_ARG_CHECKED(JSFunction, f, 0);
-  Object* obj = f->RemovePrototype();
-  if (obj->IsFailure()) return obj;
+  f->RemovePrototype();
 
   return isolate->heap()->undefined_value();
 }
@@ -2307,19 +2307,7 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringCharCodeAt) {
   ASSERT(args.length() == 2);
 
   CONVERT_ARG_CHECKED(String, subject, 0);
-  Object* index = args[1];
-  RUNTIME_ASSERT(index->IsNumber());
-
-  uint32_t i = 0;
-  if (index->IsSmi()) {
-    int value = Smi::cast(index)->value();
-    if (value < 0) return isolate->heap()->nan_value();
-    i = value;
-  } else {
-    ASSERT(index->IsHeapNumber());
-    double value = HeapNumber::cast(index)->value();
-    i = static_cast<uint32_t>(DoubleToInteger(value));
-  }
+  CONVERT_NUMBER_CHECKED(uint32_t, i, Uint32, args[1]);
 
   // Flatten the string.  If someone wants to get a char at an index
   // in a cons string, it is likely that more indices will be
@@ -3289,12 +3277,12 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceRegExpWithString) {
 }
 
 
-Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
-                                                       Handle<String> subject,
-                                                       Handle<String> search,
-                                                       Handle<String> replace,
-                                                       bool* found,
-                                                       int recursion_limit) {
+Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
+                                              Handle<String> subject,
+                                              Handle<String> search,
+                                              Handle<String> replace,
+                                              bool* found,
+                                              int recursion_limit) {
   if (recursion_limit == 0) return Handle<String>::null();
   if (subject->IsConsString()) {
     ConsString* cons = ConsString::cast(*subject);
@@ -3322,7 +3310,7 @@ Handle<String> Runtime::StringReplaceOneCharWithString(Isolate* isolate,
 
     return subject;
   } else {
-    int index = StringMatch(isolate, subject, search, 0);
+    int index = Runtime::StringMatch(isolate, subject, search, 0);
     if (index == -1) return subject;
     *found = true;
     Handle<String> first = isolate->factory()->NewSubString(subject, 0, index);
@@ -3345,20 +3333,19 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_StringReplaceOneCharWithString) {
   // retry with a flattened subject string.
   const int kRecursionLimit = 0x1000;
   bool found = false;
-  Handle<String> result =
-      Runtime::StringReplaceOneCharWithString(isolate,
-                                              subject,
-                                              search,
-                                              replace,
-                                              &found,
-                                              kRecursionLimit);
+  Handle<String> result = StringReplaceOneCharWithString(isolate,
+                                                         subject,
+                                                         search,
+                                                         replace,
+                                                         &found,
+                                                         kRecursionLimit);
   if (!result.is_null()) return *result;
-  return *Runtime::StringReplaceOneCharWithString(isolate,
-                                                  FlattenGetString(subject),
-                                                  search,
-                                                  replace,
-                                                  &found,
-                                                  kRecursionLimit);
+  return *StringReplaceOneCharWithString(isolate,
+                                         FlattenGetString(subject),
+                                         search,
+                                         replace,
+                                         &found,
+                                         kRecursionLimit);
 }
 
 
@@ -8864,6 +8851,15 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowReferenceError) {
 }
 
 
+RUNTIME_FUNCTION(MaybeObject*, Runtime_ThrowNotDateError) {
+  HandleScope scope(isolate);
+  ASSERT(args.length() == 0);
+  return isolate->Throw(*isolate->factory()->NewTypeError(
+      "not_date_object", HandleVector<Object>(NULL, 0)));
+}
+
+
+
 RUNTIME_FUNCTION(MaybeObject*, Runtime_StackGuard) {
   ASSERT(args.length() == 0);
 
@@ -12260,7 +12256,7 @@ RUNTIME_FUNCTION(MaybeObject*,
   HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSValue, script_value, 0);
 
-
+  RUNTIME_ASSERT(script_value->value()->IsScript());
   Handle<Script> script = Handle<Script>(Script::cast(script_value->value()));
 
   const int kBufferSize = 32;
@@ -12306,6 +12302,8 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_LiveEditGatherCompileInfo) {
   HandleScope scope(isolate);
   CONVERT_ARG_CHECKED(JSValue, script, 0);
   CONVERT_ARG_HANDLE_CHECKED(String, source, 1);
+
+  RUNTIME_ASSERT(script->value()->IsScript());
   Handle<Script> script_handle = Handle<Script>(Script::cast(script->value()));
 
   JSArray* result =  LiveEdit::GatherCompileInfo(script_handle, source);
index 3fa5ea1..da60ee1 100644 (file)
@@ -325,6 +325,7 @@ namespace internal {
   F(Throw, 1, 1) \
   F(ReThrow, 1, 1) \
   F(ThrowReferenceError, 1, 1) \
+  F(ThrowNotDateError, 0, 1) \
   F(StackGuard, 0, 1) \
   F(Interrupt, 0, 1) \
   F(PromoteScheduledException, 0, 1) \
@@ -647,13 +648,6 @@ class Runtime : public AllStatic {
   // Get the intrinsic function with the given FunctionId.
   static const Function* FunctionForId(FunctionId id);
 
-  static Handle<String> StringReplaceOneCharWithString(Isolate* isolate,
-                                                       Handle<String> subject,
-                                                       Handle<String> search,
-                                                       Handle<String> replace,
-                                                       bool* found,
-                                                       int recursion_limit);
-
   // General-purpose helper functions for runtime system.
   static int StringMatch(Isolate* isolate,
                          Handle<String> sub,
index 5e306dd..78e1dec 100644 (file)
@@ -3036,19 +3036,18 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 
   VisitForAccumulatorValue(args->at(0));  // Load the object.
 
-  Label runtime, done;
+  Label runtime, done, not_date_object;
   Register object = rax;
   Register result = rax;
   Register scratch = rcx;
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  __ JumpIfSmi(object, &not_date_object);
   __ CmpObjectType(object, JS_DATE_TYPE, scratch);
-  __ Assert(equal, "Trying to get date field from non-date.");
-#endif
+  __ j(not_equal, &not_date_object);
 
   if (index->value() == 0) {
     __ movq(result, FieldOperand(object, JSDate::kValueOffset));
+    __ jmp(&done);
   } else {
     if (index->value() < JSDate::kFirstUncachedField) {
       ExternalReference stamp = ExternalReference::date_cache_stamp(isolate());
@@ -3070,8 +3069,12 @@ void FullCodeGenerator::EmitDateField(CallRuntime* expr) {
 #endif
     __ CallCFunction(ExternalReference::get_date_field_function(isolate()), 2);
     __ movq(rsi, Operand(rbp, StandardFrameConstants::kContextOffset));
-    __ bind(&done);
+    __ jmp(&done);
   }
+
+  __ bind(&not_date_object);
+  __ CallRuntime(Runtime::kThrowNotDateError, 0);
+  __ bind(&done);
   context()->Plug(rax);
 }
 
@@ -3495,9 +3498,7 @@ void FullCodeGenerator::EmitGetCachedArrayIndex(CallRuntime* expr) {
   ASSERT(args->length() == 1);
   VisitForAccumulatorValue(args->at(0));
 
-  if (generate_debug_code_) {
-    __ AbortIfNotString(rax);
-  }
+  __ AbortIfNotString(rax);
 
   __ movl(rax, FieldOperand(rax, String::kHashFieldOffset));
   ASSERT(String::kHashShift >= kSmiTagSize);
index fea7627..89e311e 100644 (file)
@@ -1332,15 +1332,14 @@ void LCodeGen::DoDateField(LDateField* instr) {
   Register object = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
   Smi* index = instr->index();
-  Label runtime, done;
+  Label runtime, done, not_date_object;
   ASSERT(object.is(result));
   ASSERT(object.is(rax));
 
-#ifdef DEBUG
-  __ AbortIfSmi(object);
+  Condition cc = masm()->CheckSmi(object);
+  DeoptimizeIf(cc, instr->environment());
   __ CmpObjectType(object, JS_DATE_TYPE, kScratchRegister);
-  __ Assert(equal, "Trying to get date field from non-date.");
-#endif
+  DeoptimizeIf(not_equal, instr->environment());
 
   if (index->value() == 0) {
     __ movq(result, FieldOperand(object, JSDate::kValueOffset));
@@ -1959,9 +1958,7 @@ void LCodeGen::DoGetCachedArrayIndex(LGetCachedArrayIndex* instr) {
   Register input = ToRegister(instr->InputAt(0));
   Register result = ToRegister(instr->result());
 
-  if (FLAG_debug_code) {
-    __ AbortIfNotString(input);
-  }
+  __ AbortIfNotString(input);
 
   __ movl(result, FieldOperand(input, String::kHashFieldOffset));
   ASSERT(String::kHashShift >= kSmiTagSize);
index af2dcc2..bee1854 100644 (file)
@@ -1550,7 +1550,7 @@ LInstruction* LChunkBuilder::DoValueOf(HValueOf* 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);
+  return MarkAsCall(DefineFixed(result, rax), instr, CAN_DEOPTIMIZE_EAGERLY);
 }
 
 
index 3e153ab..5aaa3bb 100644 (file)
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Flags: --allow-natives-syntax
+
 // Test date construction from other dates.
 var date0 = new Date(1111);
 var date1 = new Date(date0);
@@ -319,3 +321,23 @@ for (var i = 0; i < 24; i++) {
     assertEquals(70674603500 - ms, Date.parse(string), string);
   }
 }
+
+assertThrows('Date.prototype.setTime.call("", 1);', TypeError);
+assertThrows('Date.prototype.setYear.call("", 1);', TypeError);
+assertThrows('Date.prototype.setHours.call("", 1, 2, 3, 4);', TypeError);
+assertThrows('Date.prototype.getDate.call("");', TypeError);
+assertThrows('Date.prototype.getUTCDate.call("");', TypeError);
+
+var date = new Date();
+date.getTime();
+date.getTime();
+%OptimizeFunctionOnNextCall(Date.prototype.getTime);
+assertThrows(function() { Date.prototype.getTime.call(""); }, TypeError);
+assertTrue(%GetOptimizationStatus(Date.prototype.getTime) != 1);
+
+date.getYear();
+date.getYear();
+%OptimizeFunctionOnNextCall(Date.prototype.getYear);
+assertThrows(function() { Date.prototype.getYear.call(""); }, TypeError);
+opt_status = %GetOptimizationStatus(Date.prototype.getYear);
+assertTrue(%GetOptimizationStatus(Date.prototype.getTime) != 1);
\ No newline at end of file
index 8be6a09..72dc819 100644 (file)
@@ -231,3 +231,6 @@ for (var i = 0; i < 5; i++) {
 }
 %OptimizeFunctionOnNextCall(directlyOnPrototype);
 directlyOnPrototype();
+
+assertTrue(isNaN(%_StringCharCodeAt("ABC", -1)));
+assertTrue(isNaN(%_StringCharCodeAt("ABC", 4)));