• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
MakeDate(double day,double 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)
MakeDay(double year,double month,double 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)
MakeTime(double hour,double min,double sec,double 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)
TimeClip(double 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
ParseDateTimeString(Handle<String> str)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)
ToDateString(double time_val,Vector<char> str,DateCache * date_cache,ToDateStringMode mode=kDateAndTime)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 
SetLocalDateValue(Handle<JSDate> date,double time_val)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.
BUILTIN(DateConstructor)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.
BUILTIN(DateConstructor_ConstructStub)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 ( )
BUILTIN(DateNow)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 )
BUILTIN(DateParse)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)
BUILTIN(DateUTC)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 )
BUILTIN(DatePrototypeSetDate)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)
BUILTIN(DatePrototypeSetFullYear)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)
BUILTIN(DatePrototypeSetHours)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)
BUILTIN(DatePrototypeSetMilliseconds)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 )
BUILTIN(DatePrototypeSetMinutes)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 )
BUILTIN(DatePrototypeSetMonth)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 )
BUILTIN(DatePrototypeSetSeconds)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 )
BUILTIN(DatePrototypeSetTime)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 )
BUILTIN(DatePrototypeSetUTCDate)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)
BUILTIN(DatePrototypeSetUTCFullYear)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)
BUILTIN(DatePrototypeSetUTCHours)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)
BUILTIN(DatePrototypeSetUTCMilliseconds)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 )
BUILTIN(DatePrototypeSetUTCMinutes)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 )
BUILTIN(DatePrototypeSetUTCMonth)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 )
BUILTIN(DatePrototypeSetUTCSeconds)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 ( )
BUILTIN(DatePrototypeToDateString)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 ( )
BUILTIN(DatePrototypeToISOString)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 ( )
BUILTIN(DatePrototypeToString)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 ( )
BUILTIN(DatePrototypeToTimeString)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 ( )
BUILTIN(DatePrototypeToUTCString)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 ( )
BUILTIN(DatePrototypeGetYear)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 )
BUILTIN(DatePrototypeSetYear)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 )
BUILTIN(DatePrototypeToJson)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 
Generate_DatePrototype_GetField(CodeStubAssembler * assembler,int field_index)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
Generate_DatePrototypeGetDate(compiler::CodeAssemblerState * state)959 void Builtins::Generate_DatePrototypeGetDate(
960     compiler::CodeAssemblerState* state) {
961   CodeStubAssembler assembler(state);
962   Generate_DatePrototype_GetField(&assembler, JSDate::kDay);
963 }
964 
965 // static
Generate_DatePrototypeGetDay(compiler::CodeAssemblerState * state)966 void Builtins::Generate_DatePrototypeGetDay(
967     compiler::CodeAssemblerState* state) {
968   CodeStubAssembler assembler(state);
969   Generate_DatePrototype_GetField(&assembler, JSDate::kWeekday);
970 }
971 
972 // static
Generate_DatePrototypeGetFullYear(compiler::CodeAssemblerState * state)973 void Builtins::Generate_DatePrototypeGetFullYear(
974     compiler::CodeAssemblerState* state) {
975   CodeStubAssembler assembler(state);
976   Generate_DatePrototype_GetField(&assembler, JSDate::kYear);
977 }
978 
979 // static
Generate_DatePrototypeGetHours(compiler::CodeAssemblerState * state)980 void Builtins::Generate_DatePrototypeGetHours(
981     compiler::CodeAssemblerState* state) {
982   CodeStubAssembler assembler(state);
983   Generate_DatePrototype_GetField(&assembler, JSDate::kHour);
984 }
985 
986 // static
Generate_DatePrototypeGetMilliseconds(compiler::CodeAssemblerState * state)987 void Builtins::Generate_DatePrototypeGetMilliseconds(
988     compiler::CodeAssemblerState* state) {
989   CodeStubAssembler assembler(state);
990   Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecond);
991 }
992 
993 // static
Generate_DatePrototypeGetMinutes(compiler::CodeAssemblerState * state)994 void Builtins::Generate_DatePrototypeGetMinutes(
995     compiler::CodeAssemblerState* state) {
996   CodeStubAssembler assembler(state);
997   Generate_DatePrototype_GetField(&assembler, JSDate::kMinute);
998 }
999 
1000 // static
Generate_DatePrototypeGetMonth(compiler::CodeAssemblerState * state)1001 void Builtins::Generate_DatePrototypeGetMonth(
1002     compiler::CodeAssemblerState* state) {
1003   CodeStubAssembler assembler(state);
1004   Generate_DatePrototype_GetField(&assembler, JSDate::kMonth);
1005 }
1006 
1007 // static
Generate_DatePrototypeGetSeconds(compiler::CodeAssemblerState * state)1008 void Builtins::Generate_DatePrototypeGetSeconds(
1009     compiler::CodeAssemblerState* state) {
1010   CodeStubAssembler assembler(state);
1011   Generate_DatePrototype_GetField(&assembler, JSDate::kSecond);
1012 }
1013 
1014 // static
Generate_DatePrototypeGetTime(compiler::CodeAssemblerState * state)1015 void Builtins::Generate_DatePrototypeGetTime(
1016     compiler::CodeAssemblerState* state) {
1017   CodeStubAssembler assembler(state);
1018   Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue);
1019 }
1020 
1021 // static
Generate_DatePrototypeGetTimezoneOffset(compiler::CodeAssemblerState * state)1022 void Builtins::Generate_DatePrototypeGetTimezoneOffset(
1023     compiler::CodeAssemblerState* state) {
1024   CodeStubAssembler assembler(state);
1025   Generate_DatePrototype_GetField(&assembler, JSDate::kTimezoneOffset);
1026 }
1027 
1028 // static
Generate_DatePrototypeGetUTCDate(compiler::CodeAssemblerState * state)1029 void Builtins::Generate_DatePrototypeGetUTCDate(
1030     compiler::CodeAssemblerState* state) {
1031   CodeStubAssembler assembler(state);
1032   Generate_DatePrototype_GetField(&assembler, JSDate::kDayUTC);
1033 }
1034 
1035 // static
Generate_DatePrototypeGetUTCDay(compiler::CodeAssemblerState * state)1036 void Builtins::Generate_DatePrototypeGetUTCDay(
1037     compiler::CodeAssemblerState* state) {
1038   CodeStubAssembler assembler(state);
1039   Generate_DatePrototype_GetField(&assembler, JSDate::kWeekdayUTC);
1040 }
1041 
1042 // static
Generate_DatePrototypeGetUTCFullYear(compiler::CodeAssemblerState * state)1043 void Builtins::Generate_DatePrototypeGetUTCFullYear(
1044     compiler::CodeAssemblerState* state) {
1045   CodeStubAssembler assembler(state);
1046   Generate_DatePrototype_GetField(&assembler, JSDate::kYearUTC);
1047 }
1048 
1049 // static
Generate_DatePrototypeGetUTCHours(compiler::CodeAssemblerState * state)1050 void Builtins::Generate_DatePrototypeGetUTCHours(
1051     compiler::CodeAssemblerState* state) {
1052   CodeStubAssembler assembler(state);
1053   Generate_DatePrototype_GetField(&assembler, JSDate::kHourUTC);
1054 }
1055 
1056 // static
Generate_DatePrototypeGetUTCMilliseconds(compiler::CodeAssemblerState * state)1057 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(
1058     compiler::CodeAssemblerState* state) {
1059   CodeStubAssembler assembler(state);
1060   Generate_DatePrototype_GetField(&assembler, JSDate::kMillisecondUTC);
1061 }
1062 
1063 // static
Generate_DatePrototypeGetUTCMinutes(compiler::CodeAssemblerState * state)1064 void Builtins::Generate_DatePrototypeGetUTCMinutes(
1065     compiler::CodeAssemblerState* state) {
1066   CodeStubAssembler assembler(state);
1067   Generate_DatePrototype_GetField(&assembler, JSDate::kMinuteUTC);
1068 }
1069 
1070 // static
Generate_DatePrototypeGetUTCMonth(compiler::CodeAssemblerState * state)1071 void Builtins::Generate_DatePrototypeGetUTCMonth(
1072     compiler::CodeAssemblerState* state) {
1073   CodeStubAssembler assembler(state);
1074   Generate_DatePrototype_GetField(&assembler, JSDate::kMonthUTC);
1075 }
1076 
1077 // static
Generate_DatePrototypeGetUTCSeconds(compiler::CodeAssemblerState * state)1078 void Builtins::Generate_DatePrototypeGetUTCSeconds(
1079     compiler::CodeAssemblerState* state) {
1080   CodeStubAssembler assembler(state);
1081   Generate_DatePrototype_GetField(&assembler, JSDate::kSecondUTC);
1082 }
1083 
1084 // static
Generate_DatePrototypeValueOf(compiler::CodeAssemblerState * state)1085 void Builtins::Generate_DatePrototypeValueOf(
1086     compiler::CodeAssemblerState* state) {
1087   CodeStubAssembler assembler(state);
1088   Generate_DatePrototype_GetField(&assembler, JSDate::kDateValue);
1089 }
1090 
1091 // static
Generate_DatePrototypeToPrimitive(compiler::CodeAssemblerState * state)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