1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins.h" 7 #include "src/code-factory.h" 8 #include "src/code-stub-assembler.h" 9 #include "src/conversions.h" 10 #include "src/counters.h" 11 #include "src/dateparser-inl.h" 12 #include "src/objects-inl.h" 13 14 namespace v8 { 15 namespace internal { 16 17 // ----------------------------------------------------------------------------- 18 // ES6 section 20.3 Date Objects 19 20 namespace { 21 22 // ES6 section 20.3.1.1 Time Values and Time Range 23 const double kMinYear = -1000000.0; 24 const double kMaxYear = -kMinYear; 25 const double kMinMonth = -10000000.0; 26 const double kMaxMonth = -kMinMonth; 27 28 // 20.3.1.2 Day Number and Time within Day 29 const double kMsPerDay = 86400000.0; 30 31 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds 32 const double kMsPerSecond = 1000.0; 33 const double kMsPerMinute = 60000.0; 34 const double kMsPerHour = 3600000.0; 35 36 // ES6 section 20.3.1.14 MakeDate (day, time) 37 double MakeDate(double day, double time) { 38 if (std::isfinite(day) && std::isfinite(time)) { 39 return time + day * kMsPerDay; 40 } 41 return std::numeric_limits<double>::quiet_NaN(); 42 } 43 44 // ES6 section 20.3.1.13 MakeDay (year, month, date) 45 double MakeDay(double year, double month, double date) { 46 if ((kMinYear <= year && year <= kMaxYear) && 47 (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) { 48 int y = FastD2I(year); 49 int m = FastD2I(month); 50 y += m / 12; 51 m %= 12; 52 if (m < 0) { 53 m += 12; 54 y -= 1; 55 } 56 DCHECK_LE(0, m); 57 DCHECK_LT(m, 12); 58 59 // kYearDelta is an arbitrary number such that: 60 // a) kYearDelta = -1 (mod 400) 61 // b) year + kYearDelta > 0 for years in the range defined by 62 // ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of 63 // Jan 1 1970. This is required so that we don't run into integer 64 // division of negative numbers. 65 // c) there shouldn't be an overflow for 32-bit integers in the following 66 // operations. 67 static const int kYearDelta = 399999; 68 static const int kBaseDay = 69 365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 - 70 (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400; 71 int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 - 72 (y + kYearDelta) / 100 + (y + kYearDelta) / 400 - 73 kBaseDay; 74 if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) { 75 static const int kDayFromMonth[] = {0, 31, 59, 90, 120, 151, 76 181, 212, 243, 273, 304, 334}; 77 day_from_year += kDayFromMonth[m]; 78 } else { 79 static const int kDayFromMonth[] = {0, 31, 60, 91, 121, 152, 80 182, 213, 244, 274, 305, 335}; 81 day_from_year += kDayFromMonth[m]; 82 } 83 return static_cast<double>(day_from_year - 1) + date; 84 } 85 return std::numeric_limits<double>::quiet_NaN(); 86 } 87 88 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms) 89 double MakeTime(double hour, double min, double sec, double ms) { 90 if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) && 91 std::isfinite(ms)) { 92 double const h = DoubleToInteger(hour); 93 double const m = DoubleToInteger(min); 94 double const s = DoubleToInteger(sec); 95 double const milli = DoubleToInteger(ms); 96 return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli; 97 } 98 return std::numeric_limits<double>::quiet_NaN(); 99 } 100 101 // ES6 section 20.3.1.15 TimeClip (time) 102 double TimeClip(double time) { 103 if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) { 104 return DoubleToInteger(time) + 0.0; 105 } 106 return std::numeric_limits<double>::quiet_NaN(); 107 } 108 109 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed", 110 "Thu", "Fri", "Sat"}; 111 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 112 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 113 114 // ES6 section 20.3.1.16 Date Time String Format 115 double ParseDateTimeString(Handle<String> str) { 116 Isolate* const isolate = str->GetIsolate(); 117 str = String::Flatten(str); 118 // TODO(bmeurer): Change DateParser to not use the FixedArray. 119 Handle<FixedArray> tmp = 120 isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE); 121 DisallowHeapAllocation no_gc; 122 String::FlatContent str_content = str->GetFlatContent(); 123 bool result; 124 if (str_content.IsOneByte()) { 125 result = DateParser::Parse(isolate, str_content.ToOneByteVector(), *tmp); 126 } else { 127 result = DateParser::Parse(isolate, str_content.ToUC16Vector(), *tmp); 128 } 129 if (!result) return std::numeric_limits<double>::quiet_NaN(); 130 double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(), 131 tmp->get(2)->Number()); 132 double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(), 133 tmp->get(5)->Number(), tmp->get(6)->Number()); 134 double date = MakeDate(day, time); 135 if (tmp->get(7)->IsNull(isolate)) { 136 if (!std::isnan(date)) { 137 date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date)); 138 } 139 } else { 140 date -= tmp->get(7)->Number() * 1000.0; 141 } 142 return date; 143 } 144 145 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime }; 146 147 // ES6 section 20.3.4.41.1 ToDateString(tv) 148 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache, 149 ToDateStringMode mode = kDateAndTime) { 150 if (std::isnan(time_val)) { 151 SNPrintF(str, "Invalid Date"); 152 return; 153 } 154 int64_t time_ms = static_cast<int64_t>(time_val); 155 int64_t local_time_ms = date_cache->ToLocal(time_ms); 156 int year, month, day, weekday, hour, min, sec, ms; 157 date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour, 158 &min, &sec, &ms); 159 int timezone_offset = -date_cache->TimezoneOffset(time_ms); 160 int timezone_hour = std::abs(timezone_offset) / 60; 161 int timezone_min = std::abs(timezone_offset) % 60; 162 const char* local_timezone = date_cache->LocalTimezone(time_ms); 163 switch (mode) { 164 case kDateOnly: 165 SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday], 166 kShortMonths[month], day, year); 167 return; 168 case kTimeOnly: 169 SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec, 170 (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min, 171 local_timezone); 172 return; 173 case kDateAndTime: 174 SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)", 175 kShortWeekDays[weekday], kShortMonths[month], day, year, hour, 176 min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour, 177 timezone_min, local_timezone); 178 return; 179 } 180 UNREACHABLE(); 181 } 182 183 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) { 184 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 185 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 186 Isolate* const isolate = date->GetIsolate(); 187 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 188 } else { 189 time_val = std::numeric_limits<double>::quiet_NaN(); 190 } 191 return *JSDate::SetValue(date, TimeClip(time_val)); 192 } 193 194 } // namespace 195 196 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case. 197 BUILTIN(DateConstructor) { 198 HandleScope scope(isolate); 199 double const time_val = JSDate::CurrentTimeValue(isolate); 200 char buffer[128]; 201 ToDateString(time_val, ArrayVector(buffer), isolate->date_cache()); 202 RETURN_RESULT_OR_FAILURE( 203 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); 204 } 205 206 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case. 207 BUILTIN(DateConstructor_ConstructStub) { 208 HandleScope scope(isolate); 209 int const argc = args.length() - 1; 210 Handle<JSFunction> target = args.target(); 211 Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target()); 212 double time_val; 213 if (argc == 0) { 214 time_val = JSDate::CurrentTimeValue(isolate); 215 } else if (argc == 1) { 216 Handle<Object> value = args.at(1); 217 if (value->IsJSDate()) { 218 time_val = Handle<JSDate>::cast(value)->value()->Number(); 219 } else { 220 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 221 Object::ToPrimitive(value)); 222 if (value->IsString()) { 223 time_val = ParseDateTimeString(Handle<String>::cast(value)); 224 } else { 225 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, 226 Object::ToNumber(value)); 227 time_val = value->Number(); 228 } 229 } 230 } else { 231 Handle<Object> year_object; 232 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 233 Object::ToNumber(args.at(1))); 234 Handle<Object> month_object; 235 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 236 Object::ToNumber(args.at(2))); 237 double year = year_object->Number(); 238 double month = month_object->Number(); 239 double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0; 240 if (argc >= 3) { 241 Handle<Object> date_object; 242 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, 243 Object::ToNumber(args.at(3))); 244 date = date_object->Number(); 245 if (argc >= 4) { 246 Handle<Object> hours_object; 247 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hours_object, 248 Object::ToNumber(args.at(4))); 249 hours = hours_object->Number(); 250 if (argc >= 5) { 251 Handle<Object> minutes_object; 252 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, minutes_object, 253 Object::ToNumber(args.at(5))); 254 minutes = minutes_object->Number(); 255 if (argc >= 6) { 256 Handle<Object> seconds_object; 257 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, seconds_object, 258 Object::ToNumber(args.at(6))); 259 seconds = seconds_object->Number(); 260 if (argc >= 7) { 261 Handle<Object> ms_object; 262 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms_object, 263 Object::ToNumber(args.at(7))); 264 ms = ms_object->Number(); 265 } 266 } 267 } 268 } 269 } 270 if (!std::isnan(year)) { 271 double const y = DoubleToInteger(year); 272 if (0.0 <= y && y <= 99) year = 1900 + y; 273 } 274 double const day = MakeDay(year, month, date); 275 double const time = MakeTime(hours, minutes, seconds, ms); 276 time_val = MakeDate(day, time); 277 if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs && 278 time_val <= DateCache::kMaxTimeBeforeUTCInMs) { 279 time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val)); 280 } else { 281 time_val = std::numeric_limits<double>::quiet_NaN(); 282 } 283 } 284 RETURN_RESULT_OR_FAILURE(isolate, JSDate::New(target, new_target, time_val)); 285 } 286 287 // ES6 section 20.3.3.1 Date.now ( ) 288 BUILTIN(DateNow) { 289 HandleScope scope(isolate); 290 return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate)); 291 } 292 293 // ES6 section 20.3.3.2 Date.parse ( string ) 294 BUILTIN(DateParse) { 295 HandleScope scope(isolate); 296 Handle<String> string; 297 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 298 isolate, string, 299 Object::ToString(isolate, args.atOrUndefined(isolate, 1))); 300 return *isolate->factory()->NewNumber(ParseDateTimeString(string)); 301 } 302 303 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms) 304 BUILTIN(DateUTC) { 305 HandleScope scope(isolate); 306 int const argc = args.length() - 1; 307 double year = std::numeric_limits<double>::quiet_NaN(); 308 double month = 0.0, date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, 309 ms = 0.0; 310 if (argc >= 1) { 311 Handle<Object> year_object; 312 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object, 313 Object::ToNumber(args.at(1))); 314 year = year_object->Number(); 315 if (argc >= 2) { 316 Handle<Object> month_object; 317 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object, 318 Object::ToNumber(args.at(2))); 319 month = month_object->Number(); 320 if (argc >= 3) { 321 Handle<Object> date_object; 322 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object, 323 Object::ToNumber(args.at(3))); 324 date = date_object->Number(); 325 if (argc >= 4) { 326 Handle<Object> hours_object; 327 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hours_object, 328 Object::ToNumber(args.at(4))); 329 hours = hours_object->Number(); 330 if (argc >= 5) { 331 Handle<Object> minutes_object; 332 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, minutes_object, 333 Object::ToNumber(args.at(5))); 334 minutes = minutes_object->Number(); 335 if (argc >= 6) { 336 Handle<Object> seconds_object; 337 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, seconds_object, 338 Object::ToNumber(args.at(6))); 339 seconds = seconds_object->Number(); 340 if (argc >= 7) { 341 Handle<Object> ms_object; 342 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 343 isolate, ms_object, Object::ToNumber(args.at(7))); 344 ms = ms_object->Number(); 345 } 346 } 347 } 348 } 349 } 350 } 351 } 352 if (!std::isnan(year)) { 353 double const y = DoubleToInteger(year); 354 if (0.0 <= y && y <= 99) year = 1900 + y; 355 } 356 double const day = MakeDay(year, month, date); 357 double const time = MakeTime(hours, minutes, seconds, ms); 358 return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time))); 359 } 360 361 // ES6 section 20.3.4.20 Date.prototype.setDate ( date ) 362 BUILTIN(DatePrototypeSetDate) { 363 HandleScope scope(isolate); 364 CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate"); 365 Handle<Object> value = args.atOrUndefined(isolate, 1); 366 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 367 double time_val = date->value()->Number(); 368 if (!std::isnan(time_val)) { 369 int64_t const time_ms = static_cast<int64_t>(time_val); 370 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 371 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 372 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 373 int year, month, day; 374 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 375 time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day); 376 } 377 return SetLocalDateValue(date, time_val); 378 } 379 380 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date) 381 BUILTIN(DatePrototypeSetFullYear) { 382 HandleScope scope(isolate); 383 CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear"); 384 int const argc = args.length() - 1; 385 Handle<Object> year = args.atOrUndefined(isolate, 1); 386 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 387 double y = year->Number(), m = 0.0, dt = 1.0; 388 int time_within_day = 0; 389 if (!std::isnan(date->value()->Number())) { 390 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 391 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 392 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 393 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 394 int year, month, day; 395 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 396 m = month; 397 dt = day; 398 } 399 if (argc >= 2) { 400 Handle<Object> month = args.at(2); 401 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 402 m = month->Number(); 403 if (argc >= 3) { 404 Handle<Object> date = args.at(3); 405 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 406 dt = date->Number(); 407 } 408 } 409 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 410 return SetLocalDateValue(date, time_val); 411 } 412 413 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms) 414 BUILTIN(DatePrototypeSetHours) { 415 HandleScope scope(isolate); 416 CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours"); 417 int const argc = args.length() - 1; 418 Handle<Object> hour = args.atOrUndefined(isolate, 1); 419 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); 420 double h = hour->Number(); 421 double time_val = date->value()->Number(); 422 if (!std::isnan(time_val)) { 423 int64_t const time_ms = static_cast<int64_t>(time_val); 424 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 425 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 426 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 427 double m = (time_within_day / (60 * 1000)) % 60; 428 double s = (time_within_day / 1000) % 60; 429 double milli = time_within_day % 1000; 430 if (argc >= 2) { 431 Handle<Object> min = args.at(2); 432 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 433 m = min->Number(); 434 if (argc >= 3) { 435 Handle<Object> sec = args.at(3); 436 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 437 s = sec->Number(); 438 if (argc >= 4) { 439 Handle<Object> ms = args.at(4); 440 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 441 milli = ms->Number(); 442 } 443 } 444 } 445 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 446 } 447 return SetLocalDateValue(date, time_val); 448 } 449 450 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms) 451 BUILTIN(DatePrototypeSetMilliseconds) { 452 HandleScope scope(isolate); 453 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds"); 454 Handle<Object> ms = args.atOrUndefined(isolate, 1); 455 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 456 double time_val = date->value()->Number(); 457 if (!std::isnan(time_val)) { 458 int64_t const time_ms = static_cast<int64_t>(time_val); 459 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 460 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 461 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 462 int h = time_within_day / (60 * 60 * 1000); 463 int m = (time_within_day / (60 * 1000)) % 60; 464 int s = (time_within_day / 1000) % 60; 465 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 466 } 467 return SetLocalDateValue(date, time_val); 468 } 469 470 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms ) 471 BUILTIN(DatePrototypeSetMinutes) { 472 HandleScope scope(isolate); 473 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes"); 474 int const argc = args.length() - 1; 475 Handle<Object> min = args.atOrUndefined(isolate, 1); 476 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 477 double time_val = date->value()->Number(); 478 if (!std::isnan(time_val)) { 479 int64_t const time_ms = static_cast<int64_t>(time_val); 480 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 481 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 482 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 483 int h = time_within_day / (60 * 60 * 1000); 484 double m = min->Number(); 485 double s = (time_within_day / 1000) % 60; 486 double milli = time_within_day % 1000; 487 if (argc >= 2) { 488 Handle<Object> sec = args.at(2); 489 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 490 s = sec->Number(); 491 if (argc >= 3) { 492 Handle<Object> ms = args.at(3); 493 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 494 milli = ms->Number(); 495 } 496 } 497 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 498 } 499 return SetLocalDateValue(date, time_val); 500 } 501 502 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date ) 503 BUILTIN(DatePrototypeSetMonth) { 504 HandleScope scope(isolate); 505 CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth"); 506 int const argc = args.length() - 1; 507 Handle<Object> month = args.atOrUndefined(isolate, 1); 508 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 509 double time_val = date->value()->Number(); 510 if (!std::isnan(time_val)) { 511 int64_t const time_ms = static_cast<int64_t>(time_val); 512 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 513 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 514 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 515 int year, unused, day; 516 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 517 double m = month->Number(); 518 double dt = day; 519 if (argc >= 2) { 520 Handle<Object> date = args.at(2); 521 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 522 dt = date->Number(); 523 } 524 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 525 } 526 return SetLocalDateValue(date, time_val); 527 } 528 529 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms ) 530 BUILTIN(DatePrototypeSetSeconds) { 531 HandleScope scope(isolate); 532 CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds"); 533 int const argc = args.length() - 1; 534 Handle<Object> sec = args.atOrUndefined(isolate, 1); 535 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 536 double time_val = date->value()->Number(); 537 if (!std::isnan(time_val)) { 538 int64_t const time_ms = static_cast<int64_t>(time_val); 539 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 540 int day = isolate->date_cache()->DaysFromTime(local_time_ms); 541 int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day); 542 int h = time_within_day / (60 * 60 * 1000); 543 double m = (time_within_day / (60 * 1000)) % 60; 544 double s = sec->Number(); 545 double milli = time_within_day % 1000; 546 if (argc >= 2) { 547 Handle<Object> ms = args.at(2); 548 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 549 milli = ms->Number(); 550 } 551 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 552 } 553 return SetLocalDateValue(date, time_val); 554 } 555 556 // ES6 section 20.3.4.27 Date.prototype.setTime ( time ) 557 BUILTIN(DatePrototypeSetTime) { 558 HandleScope scope(isolate); 559 CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime"); 560 Handle<Object> value = args.atOrUndefined(isolate, 1); 561 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 562 return *JSDate::SetValue(date, TimeClip(value->Number())); 563 } 564 565 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date ) 566 BUILTIN(DatePrototypeSetUTCDate) { 567 HandleScope scope(isolate); 568 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate"); 569 Handle<Object> value = args.atOrUndefined(isolate, 1); 570 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value)); 571 if (std::isnan(date->value()->Number())) return date->value(); 572 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 573 int const days = isolate->date_cache()->DaysFromTime(time_ms); 574 int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 575 int year, month, day; 576 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 577 double const time_val = 578 MakeDate(MakeDay(year, month, value->Number()), time_within_day); 579 return *JSDate::SetValue(date, TimeClip(time_val)); 580 } 581 582 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date) 583 BUILTIN(DatePrototypeSetUTCFullYear) { 584 HandleScope scope(isolate); 585 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear"); 586 int const argc = args.length() - 1; 587 Handle<Object> year = args.atOrUndefined(isolate, 1); 588 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 589 double y = year->Number(), m = 0.0, dt = 1.0; 590 int time_within_day = 0; 591 if (!std::isnan(date->value()->Number())) { 592 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 593 int const days = isolate->date_cache()->DaysFromTime(time_ms); 594 time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 595 int year, month, day; 596 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 597 m = month; 598 dt = day; 599 } 600 if (argc >= 2) { 601 Handle<Object> month = args.at(2); 602 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 603 m = month->Number(); 604 if (argc >= 3) { 605 Handle<Object> date = args.at(3); 606 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 607 dt = date->Number(); 608 } 609 } 610 double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 611 return *JSDate::SetValue(date, TimeClip(time_val)); 612 } 613 614 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms) 615 BUILTIN(DatePrototypeSetUTCHours) { 616 HandleScope scope(isolate); 617 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours"); 618 int const argc = args.length() - 1; 619 Handle<Object> hour = args.atOrUndefined(isolate, 1); 620 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour)); 621 double h = hour->Number(); 622 double time_val = date->value()->Number(); 623 if (!std::isnan(time_val)) { 624 int64_t const time_ms = static_cast<int64_t>(time_val); 625 int day = isolate->date_cache()->DaysFromTime(time_ms); 626 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 627 double m = (time_within_day / (60 * 1000)) % 60; 628 double s = (time_within_day / 1000) % 60; 629 double milli = time_within_day % 1000; 630 if (argc >= 2) { 631 Handle<Object> min = args.at(2); 632 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 633 m = min->Number(); 634 if (argc >= 3) { 635 Handle<Object> sec = args.at(3); 636 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 637 s = sec->Number(); 638 if (argc >= 4) { 639 Handle<Object> ms = args.at(4); 640 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 641 milli = ms->Number(); 642 } 643 } 644 } 645 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 646 } 647 return *JSDate::SetValue(date, TimeClip(time_val)); 648 } 649 650 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms) 651 BUILTIN(DatePrototypeSetUTCMilliseconds) { 652 HandleScope scope(isolate); 653 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds"); 654 Handle<Object> ms = args.atOrUndefined(isolate, 1); 655 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 656 double time_val = date->value()->Number(); 657 if (!std::isnan(time_val)) { 658 int64_t const time_ms = static_cast<int64_t>(time_val); 659 int day = isolate->date_cache()->DaysFromTime(time_ms); 660 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 661 int h = time_within_day / (60 * 60 * 1000); 662 int m = (time_within_day / (60 * 1000)) % 60; 663 int s = (time_within_day / 1000) % 60; 664 time_val = MakeDate(day, MakeTime(h, m, s, ms->Number())); 665 } 666 return *JSDate::SetValue(date, TimeClip(time_val)); 667 } 668 669 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms ) 670 BUILTIN(DatePrototypeSetUTCMinutes) { 671 HandleScope scope(isolate); 672 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes"); 673 int const argc = args.length() - 1; 674 Handle<Object> min = args.atOrUndefined(isolate, 1); 675 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min)); 676 double time_val = date->value()->Number(); 677 if (!std::isnan(time_val)) { 678 int64_t const time_ms = static_cast<int64_t>(time_val); 679 int day = isolate->date_cache()->DaysFromTime(time_ms); 680 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 681 int h = time_within_day / (60 * 60 * 1000); 682 double m = min->Number(); 683 double s = (time_within_day / 1000) % 60; 684 double milli = time_within_day % 1000; 685 if (argc >= 2) { 686 Handle<Object> sec = args.at(2); 687 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 688 s = sec->Number(); 689 if (argc >= 3) { 690 Handle<Object> ms = args.at(3); 691 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 692 milli = ms->Number(); 693 } 694 } 695 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 696 } 697 return *JSDate::SetValue(date, TimeClip(time_val)); 698 } 699 700 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date ) 701 BUILTIN(DatePrototypeSetUTCMonth) { 702 HandleScope scope(isolate); 703 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth"); 704 int const argc = args.length() - 1; 705 Handle<Object> month = args.atOrUndefined(isolate, 1); 706 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month)); 707 double time_val = date->value()->Number(); 708 if (!std::isnan(time_val)) { 709 int64_t const time_ms = static_cast<int64_t>(time_val); 710 int days = isolate->date_cache()->DaysFromTime(time_ms); 711 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days); 712 int year, unused, day; 713 isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day); 714 double m = month->Number(); 715 double dt = day; 716 if (argc >= 2) { 717 Handle<Object> date = args.at(2); 718 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date)); 719 dt = date->Number(); 720 } 721 time_val = MakeDate(MakeDay(year, m, dt), time_within_day); 722 } 723 return *JSDate::SetValue(date, TimeClip(time_val)); 724 } 725 726 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms ) 727 BUILTIN(DatePrototypeSetUTCSeconds) { 728 HandleScope scope(isolate); 729 CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds"); 730 int const argc = args.length() - 1; 731 Handle<Object> sec = args.atOrUndefined(isolate, 1); 732 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec)); 733 double time_val = date->value()->Number(); 734 if (!std::isnan(time_val)) { 735 int64_t const time_ms = static_cast<int64_t>(time_val); 736 int day = isolate->date_cache()->DaysFromTime(time_ms); 737 int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day); 738 int h = time_within_day / (60 * 60 * 1000); 739 double m = (time_within_day / (60 * 1000)) % 60; 740 double s = sec->Number(); 741 double milli = time_within_day % 1000; 742 if (argc >= 2) { 743 Handle<Object> ms = args.at(2); 744 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms)); 745 milli = ms->Number(); 746 } 747 time_val = MakeDate(day, MakeTime(h, m, s, milli)); 748 } 749 return *JSDate::SetValue(date, TimeClip(time_val)); 750 } 751 752 // ES6 section 20.3.4.35 Date.prototype.toDateString ( ) 753 BUILTIN(DatePrototypeToDateString) { 754 HandleScope scope(isolate); 755 CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString"); 756 char buffer[128]; 757 ToDateString(date->value()->Number(), ArrayVector(buffer), 758 isolate->date_cache(), kDateOnly); 759 RETURN_RESULT_OR_FAILURE( 760 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); 761 } 762 763 // ES6 section 20.3.4.36 Date.prototype.toISOString ( ) 764 BUILTIN(DatePrototypeToISOString) { 765 HandleScope scope(isolate); 766 CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString"); 767 double const time_val = date->value()->Number(); 768 if (std::isnan(time_val)) { 769 THROW_NEW_ERROR_RETURN_FAILURE( 770 isolate, NewRangeError(MessageTemplate::kInvalidTimeValue)); 771 } 772 int64_t const time_ms = static_cast<int64_t>(time_val); 773 int year, month, day, weekday, hour, min, sec, ms; 774 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, 775 &hour, &min, &sec, &ms); 776 char buffer[128]; 777 if (year >= 0 && year <= 9999) { 778 SNPrintF(ArrayVector(buffer), "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, 779 month + 1, day, hour, min, sec, ms); 780 } else if (year < 0) { 781 SNPrintF(ArrayVector(buffer), "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, 782 month + 1, day, hour, min, sec, ms); 783 } else { 784 SNPrintF(ArrayVector(buffer), "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, 785 month + 1, day, hour, min, sec, ms); 786 } 787 return *isolate->factory()->NewStringFromAsciiChecked(buffer); 788 } 789 790 // ES6 section 20.3.4.41 Date.prototype.toString ( ) 791 BUILTIN(DatePrototypeToString) { 792 HandleScope scope(isolate); 793 CHECK_RECEIVER(JSDate, date, "Date.prototype.toString"); 794 char buffer[128]; 795 ToDateString(date->value()->Number(), ArrayVector(buffer), 796 isolate->date_cache()); 797 RETURN_RESULT_OR_FAILURE( 798 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); 799 } 800 801 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( ) 802 BUILTIN(DatePrototypeToTimeString) { 803 HandleScope scope(isolate); 804 CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString"); 805 char buffer[128]; 806 ToDateString(date->value()->Number(), ArrayVector(buffer), 807 isolate->date_cache(), kTimeOnly); 808 RETURN_RESULT_OR_FAILURE( 809 isolate, isolate->factory()->NewStringFromUtf8(CStrVector(buffer))); 810 } 811 812 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( ) 813 BUILTIN(DatePrototypeToUTCString) { 814 HandleScope scope(isolate); 815 CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString"); 816 double const time_val = date->value()->Number(); 817 if (std::isnan(time_val)) { 818 return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date"); 819 } 820 char buffer[128]; 821 int64_t time_ms = static_cast<int64_t>(time_val); 822 int year, month, day, weekday, hour, min, sec, ms; 823 isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday, 824 &hour, &min, &sec, &ms); 825 SNPrintF(ArrayVector(buffer), "%s, %02d %s %4d %02d:%02d:%02d GMT", 826 kShortWeekDays[weekday], day, kShortMonths[month], year, hour, min, 827 sec); 828 return *isolate->factory()->NewStringFromAsciiChecked(buffer); 829 } 830 831 // ES6 section B.2.4.1 Date.prototype.getYear ( ) 832 BUILTIN(DatePrototypeGetYear) { 833 HandleScope scope(isolate); 834 CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear"); 835 double time_val = date->value()->Number(); 836 if (std::isnan(time_val)) return date->value(); 837 int64_t time_ms = static_cast<int64_t>(time_val); 838 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 839 int days = isolate->date_cache()->DaysFromTime(local_time_ms); 840 int year, month, day; 841 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 842 return Smi::FromInt(year - 1900); 843 } 844 845 // ES6 section B.2.4.2 Date.prototype.setYear ( year ) 846 BUILTIN(DatePrototypeSetYear) { 847 HandleScope scope(isolate); 848 CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear"); 849 Handle<Object> year = args.atOrUndefined(isolate, 1); 850 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year)); 851 double m = 0.0, dt = 1.0, y = year->Number(); 852 if (0.0 <= y && y <= 99.0) { 853 y = 1900.0 + DoubleToInteger(y); 854 } 855 int time_within_day = 0; 856 if (!std::isnan(date->value()->Number())) { 857 int64_t const time_ms = static_cast<int64_t>(date->value()->Number()); 858 int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms); 859 int const days = isolate->date_cache()->DaysFromTime(local_time_ms); 860 time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days); 861 int year, month, day; 862 isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day); 863 m = month; 864 dt = day; 865 } 866 double time_val = MakeDate(MakeDay(y, m, dt), time_within_day); 867 return SetLocalDateValue(date, time_val); 868 } 869 870 // ES6 section 20.3.4.37 Date.prototype.toJSON ( key ) 871 BUILTIN(DatePrototypeToJson) { 872 HandleScope scope(isolate); 873 Handle<Object> receiver = args.atOrUndefined(isolate, 0); 874 Handle<JSReceiver> receiver_obj; 875 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver_obj, 876 Object::ToObject(isolate, receiver)); 877 Handle<Object> primitive; 878 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( 879 isolate, primitive, 880 Object::ToPrimitive(receiver_obj, ToPrimitiveHint::kNumber)); 881 if (primitive->IsNumber() && !std::isfinite(primitive->Number())) { 882 return isolate->heap()->null_value(); 883 } else { 884 Handle<String> name = 885 isolate->factory()->NewStringFromAsciiChecked("toISOString"); 886 Handle<Object> function; 887 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, function, 888 Object::GetProperty(receiver_obj, name)); 889 if (!function->IsCallable()) { 890 THROW_NEW_ERROR_RETURN_FAILURE( 891 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, name)); 892 } 893 RETURN_RESULT_OR_FAILURE( 894 isolate, Execution::Call(isolate, function, receiver_obj, 0, NULL)); 895 } 896 } 897 898 namespace { 899 900 void Generate_DatePrototype_GetField(CodeStubAssembler* assembler, 901 int field_index) { 902 typedef CodeStubAssembler::Label Label; 903 typedef compiler::Node Node; 904 905 Node* receiver = assembler->Parameter(0); 906 Node* context = assembler->Parameter(3); 907 908 Label receiver_not_date(assembler, Label::kDeferred); 909 910 assembler->GotoIf(assembler->TaggedIsSmi(receiver), &receiver_not_date); 911 Node* receiver_instance_type = assembler->LoadInstanceType(receiver); 912 assembler->GotoIf( 913 assembler->Word32NotEqual(receiver_instance_type, 914 assembler->Int32Constant(JS_DATE_TYPE)), 915 &receiver_not_date); 916 917 // Load the specified date field, falling back to the runtime as necessary. 918 if (field_index == JSDate::kDateValue) { 919 assembler->Return( 920 assembler->LoadObjectField(receiver, JSDate::kValueOffset)); 921 } else { 922 if (field_index < JSDate::kFirstUncachedField) { 923 Label stamp_mismatch(assembler, Label::kDeferred); 924 Node* date_cache_stamp = assembler->Load( 925 MachineType::AnyTagged(), 926 assembler->ExternalConstant( 927 ExternalReference::date_cache_stamp(assembler->isolate()))); 928 929 Node* cache_stamp = 930 assembler->LoadObjectField(receiver, JSDate::kCacheStampOffset); 931 assembler->GotoIf(assembler->WordNotEqual(date_cache_stamp, cache_stamp), 932 &stamp_mismatch); 933 assembler->Return(assembler->LoadObjectField( 934 receiver, JSDate::kValueOffset + field_index * kPointerSize)); 935 936 assembler->Bind(&stamp_mismatch); 937 } 938 939 Node* field_index_smi = assembler->SmiConstant(Smi::FromInt(field_index)); 940 Node* function = assembler->ExternalConstant( 941 ExternalReference::get_date_field_function(assembler->isolate())); 942 Node* result = assembler->CallCFunction2( 943 MachineType::AnyTagged(), MachineType::AnyTagged(), 944 MachineType::AnyTagged(), function, receiver, field_index_smi); 945 assembler->Return(result); 946 } 947 948 // Raise a TypeError if the receiver is not a date. 949 assembler->Bind(&receiver_not_date); 950 { 951 assembler->CallRuntime(Runtime::kThrowNotDateError, context); 952 assembler->Unreachable(); 953 } 954 } 955 956 } // namespace 957 958 // static 959 void Builtins::Generate_DatePrototypeGetDate( 960 compiler::CodeAssemblerState* state) { 961 CodeStubAssembler assembler(state); 962 Generate_DatePrototype_GetField(&assembler, JSDate::kDay); 963 } 964 965 // static 966 void Builtins::Generate_DatePrototypeGetDay( 967 compiler::CodeAssemblerState* state) { 968 CodeStubAssembler assembler(state); 969 Generate_DatePrototype_GetField(&assembler, JSDate::kWeekday); 970 } 971 972 // static 973 void Builtins::Generate_DatePrototypeGetFullYear( 974 compiler::CodeAssemblerState* state) { 975 CodeStubAssembler assembler(state); 976 Generate_DatePrototype_GetField(&assembler, JSDate::kYear); 977 } 978 979 // static 980 void Builtins::Generate_DatePrototypeGetHours( 981 compiler::CodeAssemblerState* state) { 982 CodeStubAssembler assembler(state); 983 Generate_DatePrototype_GetField(&assembler, JSDate::kHour); 984 } 985 986 // static 987 void Builtins::Generate_DatePrototypeGetMilliseconds( 988 compiler::CodeAssemblerState* state) { 989 CodeStubAssembler assembler(state); 990 Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecond); 991 } 992 993 // static 994 void Builtins::Generate_DatePrototypeGetMinutes( 995 compiler::CodeAssemblerState* state) { 996 CodeStubAssembler assembler(state); 997 Generate_DatePrototype_GetField(&assembler, JSDate::kMinute); 998 } 999 1000 // static 1001 void Builtins::Generate_DatePrototypeGetMonth( 1002 compiler::CodeAssemblerState* state) { 1003 CodeStubAssembler assembler(state); 1004 Generate_DatePrototype_GetField(&assembler, JSDate::kMonth); 1005 } 1006 1007 // static 1008 void Builtins::Generate_DatePrototypeGetSeconds( 1009 compiler::CodeAssemblerState* state) { 1010 CodeStubAssembler assembler(state); 1011 Generate_DatePrototype_GetField(&assembler, JSDate::kSecond); 1012 } 1013 1014 // static 1015 void Builtins::Generate_DatePrototypeGetTime( 1016 compiler::CodeAssemblerState* state) { 1017 CodeStubAssembler assembler(state); 1018 Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue); 1019 } 1020 1021 // static 1022 void Builtins::Generate_DatePrototypeGetTimezoneOffset( 1023 compiler::CodeAssemblerState* state) { 1024 CodeStubAssembler assembler(state); 1025 Generate_DatePrototype_GetField(&assembler, JSDate::kTimezoneOffset); 1026 } 1027 1028 // static 1029 void Builtins::Generate_DatePrototypeGetUTCDate( 1030 compiler::CodeAssemblerState* state) { 1031 CodeStubAssembler assembler(state); 1032 Generate_DatePrototype_GetField(&assembler, JSDate::kDayUTC); 1033 } 1034 1035 // static 1036 void Builtins::Generate_DatePrototypeGetUTCDay( 1037 compiler::CodeAssemblerState* state) { 1038 CodeStubAssembler assembler(state); 1039 Generate_DatePrototype_GetField(&assembler, JSDate::kWeekdayUTC); 1040 } 1041 1042 // static 1043 void Builtins::Generate_DatePrototypeGetUTCFullYear( 1044 compiler::CodeAssemblerState* state) { 1045 CodeStubAssembler assembler(state); 1046 Generate_DatePrototype_GetField(&assembler, JSDate::kYearUTC); 1047 } 1048 1049 // static 1050 void Builtins::Generate_DatePrototypeGetUTCHours( 1051 compiler::CodeAssemblerState* state) { 1052 CodeStubAssembler assembler(state); 1053 Generate_DatePrototype_GetField(&assembler, JSDate::kHourUTC); 1054 } 1055 1056 // static 1057 void Builtins::Generate_DatePrototypeGetUTCMilliseconds( 1058 compiler::CodeAssemblerState* state) { 1059 CodeStubAssembler assembler(state); 1060 Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecondUTC); 1061 } 1062 1063 // static 1064 void Builtins::Generate_DatePrototypeGetUTCMinutes( 1065 compiler::CodeAssemblerState* state) { 1066 CodeStubAssembler assembler(state); 1067 Generate_DatePrototype_GetField(&assembler, JSDate::kMinuteUTC); 1068 } 1069 1070 // static 1071 void Builtins::Generate_DatePrototypeGetUTCMonth( 1072 compiler::CodeAssemblerState* state) { 1073 CodeStubAssembler assembler(state); 1074 Generate_DatePrototype_GetField(&assembler, JSDate::kMonthUTC); 1075 } 1076 1077 // static 1078 void Builtins::Generate_DatePrototypeGetUTCSeconds( 1079 compiler::CodeAssemblerState* state) { 1080 CodeStubAssembler assembler(state); 1081 Generate_DatePrototype_GetField(&assembler, JSDate::kSecondUTC); 1082 } 1083 1084 // static 1085 void Builtins::Generate_DatePrototypeValueOf( 1086 compiler::CodeAssemblerState* state) { 1087 CodeStubAssembler assembler(state); 1088 Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue); 1089 } 1090 1091 // static 1092 void Builtins::Generate_DatePrototypeToPrimitive( 1093 compiler::CodeAssemblerState* state) { 1094 CodeStubAssembler assembler(state); 1095 typedef CodeStubAssembler::Label Label; 1096 typedef compiler::Node Node; 1097 1098 Node* receiver = assembler.Parameter(0); 1099 Node* hint = assembler.Parameter(1); 1100 Node* context = assembler.Parameter(4); 1101 1102 // Check if the {receiver} is actually a JSReceiver. 1103 Label receiver_is_invalid(&assembler, Label::kDeferred); 1104 assembler.GotoIf(assembler.TaggedIsSmi(receiver), &receiver_is_invalid); 1105 assembler.GotoIfNot(assembler.IsJSReceiver(receiver), &receiver_is_invalid); 1106 1107 // Dispatch to the appropriate OrdinaryToPrimitive builtin. 1108 Label hint_is_number(&assembler), hint_is_string(&assembler), 1109 hint_is_invalid(&assembler, Label::kDeferred); 1110 1111 // Fast cases for internalized strings. 1112 Node* number_string = assembler.LoadRoot(Heap::knumber_stringRootIndex); 1113 assembler.GotoIf(assembler.WordEqual(hint, number_string), &hint_is_number); 1114 Node* default_string = assembler.LoadRoot(Heap::kdefault_stringRootIndex); 1115 assembler.GotoIf(assembler.WordEqual(hint, default_string), &hint_is_string); 1116 Node* string_string = assembler.LoadRoot(Heap::kstring_stringRootIndex); 1117 assembler.GotoIf(assembler.WordEqual(hint, string_string), &hint_is_string); 1118 1119 // Slow-case with actual string comparisons. 1120 Callable string_equal = CodeFactory::StringEqual(assembler.isolate()); 1121 assembler.GotoIf(assembler.TaggedIsSmi(hint), &hint_is_invalid); 1122 assembler.GotoIfNot(assembler.IsString(hint), &hint_is_invalid); 1123 assembler.GotoIf(assembler.WordEqual(assembler.CallStub(string_equal, context, 1124 hint, number_string), 1125 assembler.TrueConstant()), 1126 &hint_is_number); 1127 assembler.GotoIf(assembler.WordEqual(assembler.CallStub(string_equal, context, 1128 hint, default_string), 1129 assembler.TrueConstant()), 1130 &hint_is_string); 1131 assembler.GotoIf(assembler.WordEqual(assembler.CallStub(string_equal, context, 1132 hint, string_string), 1133 assembler.TrueConstant()), 1134 &hint_is_string); 1135 assembler.Goto(&hint_is_invalid); 1136 1137 // Use the OrdinaryToPrimitive builtin to convert to a Number. 1138 assembler.Bind(&hint_is_number); 1139 { 1140 Callable callable = CodeFactory::OrdinaryToPrimitive( 1141 assembler.isolate(), OrdinaryToPrimitiveHint::kNumber); 1142 Node* result = assembler.CallStub(callable, context, receiver); 1143 assembler.Return(result); 1144 } 1145 1146 // Use the OrdinaryToPrimitive builtin to convert to a String. 1147 assembler.Bind(&hint_is_string); 1148 { 1149 Callable callable = CodeFactory::OrdinaryToPrimitive( 1150 assembler.isolate(), OrdinaryToPrimitiveHint::kString); 1151 Node* result = assembler.CallStub(callable, context, receiver); 1152 assembler.Return(result); 1153 } 1154 1155 // Raise a TypeError if the {hint} is invalid. 1156 assembler.Bind(&hint_is_invalid); 1157 { 1158 assembler.CallRuntime(Runtime::kThrowInvalidHint, context, hint); 1159 assembler.Unreachable(); 1160 } 1161 1162 // Raise a TypeError if the {receiver} is not a JSReceiver instance. 1163 assembler.Bind(&receiver_is_invalid); 1164 { 1165 assembler.CallRuntime( 1166 Runtime::kThrowIncompatibleMethodReceiver, context, 1167 assembler.HeapConstant(assembler.factory()->NewStringFromAsciiChecked( 1168 "Date.prototype [ @@toPrimitive ]", TENURED)), 1169 receiver); 1170 assembler.Unreachable(); 1171 } 1172 } 1173 1174 } // namespace internal 1175 } // namespace v8 1176