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