1 // Copyright 2012 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.h"
6 
7 #include "src/api.h"
8 #include "src/api-natives.h"
9 #include "src/arguments.h"
10 #include "src/base/once.h"
11 #include "src/bootstrapper.h"
12 #include "src/dateparser-inl.h"
13 #include "src/elements.h"
14 #include "src/frames-inl.h"
15 #include "src/gdb-jit.h"
16 #include "src/ic/handler-compiler.h"
17 #include "src/ic/ic.h"
18 #include "src/isolate-inl.h"
19 #include "src/messages.h"
20 #include "src/profiler/cpu-profiler.h"
21 #include "src/property-descriptor.h"
22 #include "src/prototype.h"
23 #include "src/string-builder.h"
24 #include "src/vm-state-inl.h"
25 
26 namespace v8 {
27 namespace internal {
28 
29 namespace {
30 
31 // Arguments object passed to C++ builtins.
32 template <BuiltinExtraArguments extra_args>
33 class BuiltinArguments : public Arguments {
34  public:
BuiltinArguments(int length,Object ** arguments)35   BuiltinArguments(int length, Object** arguments)
36       : Arguments(length, arguments) {
37     // Check we have at least the receiver.
38     DCHECK_LE(1, this->length());
39   }
40 
operator [](int index)41   Object*& operator[] (int index) {
42     DCHECK(index < length());
43     return Arguments::operator[](index);
44   }
45 
at(int index)46   template <class S> Handle<S> at(int index) {
47     DCHECK(index < length());
48     return Arguments::at<S>(index);
49   }
50 
atOrUndefined(Isolate * isolate,int index)51   Handle<Object> atOrUndefined(Isolate* isolate, int index) {
52     if (index >= length()) {
53       return isolate->factory()->undefined_value();
54     }
55     return at<Object>(index);
56   }
57 
receiver()58   Handle<Object> receiver() {
59     return Arguments::at<Object>(0);
60   }
61 
62   Handle<JSFunction> target();
63   Handle<HeapObject> new_target();
64 
65   // Gets the total number of arguments including the receiver (but
66   // excluding extra arguments).
67   int length() const;
68 };
69 
70 
71 // Specialize BuiltinArguments for the extra arguments.
72 
73 template <>
length() const74 int BuiltinArguments<BuiltinExtraArguments::kNone>::length() const {
75   return Arguments::length();
76 }
77 
78 template <>
length() const79 int BuiltinArguments<BuiltinExtraArguments::kTarget>::length() const {
80   return Arguments::length() - 1;
81 }
82 
83 template <>
target()84 Handle<JSFunction> BuiltinArguments<BuiltinExtraArguments::kTarget>::target() {
85   return Arguments::at<JSFunction>(Arguments::length() - 1);
86 }
87 
88 template <>
length() const89 int BuiltinArguments<BuiltinExtraArguments::kNewTarget>::length() const {
90   return Arguments::length() - 1;
91 }
92 
93 template <>
94 Handle<HeapObject>
new_target()95 BuiltinArguments<BuiltinExtraArguments::kNewTarget>::new_target() {
96   return Arguments::at<HeapObject>(Arguments::length() - 1);
97 }
98 
99 template <>
length() const100 int BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::length()
101     const {
102   return Arguments::length() - 2;
103 }
104 
105 template <>
106 Handle<JSFunction>
target()107 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::target() {
108   return Arguments::at<JSFunction>(Arguments::length() - 2);
109 }
110 
111 template <>
112 Handle<HeapObject>
new_target()113 BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget>::new_target() {
114   return Arguments::at<HeapObject>(Arguments::length() - 1);
115 }
116 
117 
118 #define DEF_ARG_TYPE(name, spec) \
119   typedef BuiltinArguments<BuiltinExtraArguments::spec> name##ArgumentsType;
BUILTIN_LIST_C(DEF_ARG_TYPE)120 BUILTIN_LIST_C(DEF_ARG_TYPE)
121 #undef DEF_ARG_TYPE
122 
123 
124 // ----------------------------------------------------------------------------
125 // Support macro for defining builtins in C++.
126 // ----------------------------------------------------------------------------
127 //
128 // A builtin function is defined by writing:
129 //
130 //   BUILTIN(name) {
131 //     ...
132 //   }
133 //
134 // In the body of the builtin function the arguments can be accessed
135 // through the BuiltinArguments object args.
136 
137 #define BUILTIN(name)                                            \
138   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
139       name##ArgumentsType args, Isolate* isolate);               \
140   MUST_USE_RESULT static Object* Builtin_##name(                 \
141       int args_length, Object** args_object, Isolate* isolate) { \
142     name##ArgumentsType args(args_length, args_object);          \
143     return Builtin_Impl_##name(args, isolate);                   \
144   }                                                              \
145   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
146       name##ArgumentsType args, Isolate* isolate)
147 
148 
149 // ----------------------------------------------------------------------------
150 
151 
152 #define CHECK_RECEIVER(Type, name, method)                                  \
153   if (!args.receiver()->Is##Type()) {                                       \
154     THROW_NEW_ERROR_RETURN_FAILURE(                                         \
155         isolate,                                                            \
156         NewTypeError(MessageTemplate::kIncompatibleMethodReceiver,          \
157                      isolate->factory()->NewStringFromAsciiChecked(method), \
158                      args.receiver()));                                     \
159   }                                                                         \
160   Handle<Type> name = Handle<Type>::cast(args.receiver())
161 
162 
163 inline bool ClampedToInteger(Object* object, int* out) {
164   // This is an extended version of ECMA-262 7.1.11 handling signed values
165   // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
166   if (object->IsSmi()) {
167     *out = Smi::cast(object)->value();
168     return true;
169   } else if (object->IsHeapNumber()) {
170     double value = HeapNumber::cast(object)->value();
171     if (std::isnan(value)) {
172       *out = 0;
173     } else if (value > kMaxInt) {
174       *out = kMaxInt;
175     } else if (value < kMinInt) {
176       *out = kMinInt;
177     } else {
178       *out = static_cast<int>(value);
179     }
180     return true;
181   } else if (object->IsUndefined() || object->IsNull()) {
182     *out = 0;
183     return true;
184   } else if (object->IsBoolean()) {
185     *out = object->IsTrue();
186     return true;
187   }
188   return false;
189 }
190 
191 
GetSloppyArgumentsLength(Isolate * isolate,Handle<JSObject> object,int * out)192 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
193                                      int* out) {
194   Map* arguments_map = isolate->native_context()->sloppy_arguments_map();
195   if (object->map() != arguments_map) return false;
196   DCHECK(object->HasFastElements());
197   Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
198   if (!len_obj->IsSmi()) return false;
199   *out = Max(0, Smi::cast(len_obj)->value());
200   return *out <= object->elements()->length();
201 }
202 
203 
PrototypeHasNoElements(PrototypeIterator * iter)204 inline bool PrototypeHasNoElements(PrototypeIterator* iter) {
205   DisallowHeapAllocation no_gc;
206   for (; !iter->IsAtEnd(); iter->Advance()) {
207     if (iter->GetCurrent()->IsJSProxy()) return false;
208     JSObject* current = iter->GetCurrent<JSObject>();
209     if (current->IsAccessCheckNeeded()) return false;
210     if (current->HasIndexedInterceptor()) return false;
211     if (current->elements()->length() != 0) return false;
212   }
213   return true;
214 }
215 
216 
IsJSArrayFastElementMovingAllowed(Isolate * isolate,JSArray * receiver)217 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
218                                               JSArray* receiver) {
219   DisallowHeapAllocation no_gc;
220   // If the array prototype chain is intact (and free of elements), and if the
221   // receiver's prototype is the array prototype, then we are done.
222   Object* prototype = receiver->map()->prototype();
223   if (prototype->IsJSArray() &&
224       isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
225       isolate->IsFastArrayConstructorPrototypeChainIntact()) {
226     return true;
227   }
228 
229   // Slow case.
230   PrototypeIterator iter(isolate, receiver);
231   return PrototypeHasNoElements(&iter);
232 }
233 
234 
235 // Returns empty handle if not applicable.
236 MUST_USE_RESULT
EnsureJSArrayWithWritableFastElements(Isolate * isolate,Handle<Object> receiver,Arguments * args,int first_added_arg)237 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
238     Isolate* isolate, Handle<Object> receiver, Arguments* args,
239     int first_added_arg) {
240   if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
241   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
242   // If there may be elements accessors in the prototype chain, the fast path
243   // cannot be used if there arguments to add to the array.
244   Heap* heap = isolate->heap();
245   if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
246     return MaybeHandle<FixedArrayBase>();
247   }
248   if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
249   if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
250   Handle<FixedArrayBase> elms(array->elements(), isolate);
251   Map* map = elms->map();
252   if (map == heap->fixed_array_map()) {
253     if (args == NULL || array->HasFastObjectElements()) return elms;
254   } else if (map == heap->fixed_cow_array_map()) {
255     elms = JSObject::EnsureWritableFastElements(array);
256     if (args == NULL || array->HasFastObjectElements()) return elms;
257   } else if (map == heap->fixed_double_array_map()) {
258     if (args == NULL) return elms;
259   } else {
260     return MaybeHandle<FixedArrayBase>();
261   }
262 
263   // Adding elements to the array prototype would break code that makes sure
264   // it has no elements. Handle that elsewhere.
265   if (isolate->IsAnyInitialArrayPrototype(array)) {
266     return MaybeHandle<FixedArrayBase>();
267   }
268 
269   // Need to ensure that the arguments passed in args can be contained in
270   // the array.
271   int args_length = args->length();
272   if (first_added_arg >= args_length) return handle(array->elements(), isolate);
273 
274   ElementsKind origin_kind = array->map()->elements_kind();
275   DCHECK(!IsFastObjectElementsKind(origin_kind));
276   ElementsKind target_kind = origin_kind;
277   {
278     DisallowHeapAllocation no_gc;
279     int arg_count = args_length - first_added_arg;
280     Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
281     for (int i = 0; i < arg_count; i++) {
282       Object* arg = arguments[i];
283       if (arg->IsHeapObject()) {
284         if (arg->IsHeapNumber()) {
285           target_kind = FAST_DOUBLE_ELEMENTS;
286         } else {
287           target_kind = FAST_ELEMENTS;
288           break;
289         }
290       }
291     }
292   }
293   if (target_kind != origin_kind) {
294     JSObject::TransitionElementsKind(array, target_kind);
295     return handle(array->elements(), isolate);
296   }
297   return elms;
298 }
299 
300 
CallJsIntrinsic(Isolate * isolate,Handle<JSFunction> function,BuiltinArguments<BuiltinExtraArguments::kNone> args)301 MUST_USE_RESULT static Object* CallJsIntrinsic(
302     Isolate* isolate, Handle<JSFunction> function,
303     BuiltinArguments<BuiltinExtraArguments::kNone> args) {
304   HandleScope handleScope(isolate);
305   int argc = args.length() - 1;
306   ScopedVector<Handle<Object> > argv(argc);
307   for (int i = 0; i < argc; ++i) {
308     argv[i] = args.at<Object>(i + 1);
309   }
310   Handle<Object> result;
311   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
312       isolate, result,
313       Execution::Call(isolate,
314                       function,
315                       args.receiver(),
316                       argc,
317                       argv.start()));
318   return *result;
319 }
320 
321 
322 }  // namespace
323 
324 
BUILTIN(Illegal)325 BUILTIN(Illegal) {
326   UNREACHABLE();
327   return isolate->heap()->undefined_value();  // Make compiler happy.
328 }
329 
330 
BUILTIN(EmptyFunction)331 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
332 
333 
BUILTIN(ArrayPush)334 BUILTIN(ArrayPush) {
335   HandleScope scope(isolate);
336   Handle<Object> receiver = args.receiver();
337   MaybeHandle<FixedArrayBase> maybe_elms_obj =
338       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
339   Handle<FixedArrayBase> elms_obj;
340   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
341     return CallJsIntrinsic(isolate, isolate->array_push(), args);
342   }
343   // Fast Elements Path
344   int push_size = args.length() - 1;
345   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
346   int len = Smi::cast(array->length())->value();
347   if (push_size == 0) {
348     return Smi::FromInt(len);
349   }
350   if (push_size > 0 &&
351       JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
352     return CallJsIntrinsic(isolate, isolate->array_push(), args);
353   }
354   DCHECK(!array->map()->is_observed());
355   ElementsAccessor* accessor = array->GetElementsAccessor();
356   int new_length = accessor->Push(array, elms_obj, &args, push_size);
357   return Smi::FromInt(new_length);
358 }
359 
360 
BUILTIN(ArrayPop)361 BUILTIN(ArrayPop) {
362   HandleScope scope(isolate);
363   Handle<Object> receiver = args.receiver();
364   MaybeHandle<FixedArrayBase> maybe_elms_obj =
365       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
366   Handle<FixedArrayBase> elms_obj;
367   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
368     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
369   }
370 
371   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
372   DCHECK(!array->map()->is_observed());
373 
374   uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
375   if (len == 0) return isolate->heap()->undefined_value();
376 
377   if (JSArray::HasReadOnlyLength(array)) {
378     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
379   }
380 
381   Handle<Object> result;
382   if (IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
383     // Fast Elements Path
384     result = array->GetElementsAccessor()->Pop(array, elms_obj);
385   } else {
386     // Use Slow Lookup otherwise
387     uint32_t new_length = len - 1;
388     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
389         isolate, result, Object::GetElement(isolate, array, new_length));
390     JSArray::SetLength(array, new_length);
391   }
392   return *result;
393 }
394 
395 
BUILTIN(ArrayShift)396 BUILTIN(ArrayShift) {
397   HandleScope scope(isolate);
398   Heap* heap = isolate->heap();
399   Handle<Object> receiver = args.receiver();
400   MaybeHandle<FixedArrayBase> maybe_elms_obj =
401       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
402   Handle<FixedArrayBase> elms_obj;
403   if (!maybe_elms_obj.ToHandle(&elms_obj) ||
404       !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
405     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
406   }
407   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
408   DCHECK(!array->map()->is_observed());
409 
410   int len = Smi::cast(array->length())->value();
411   if (len == 0) return heap->undefined_value();
412 
413   if (JSArray::HasReadOnlyLength(array)) {
414     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
415   }
416 
417   Handle<Object> first = array->GetElementsAccessor()->Shift(array, elms_obj);
418   return *first;
419 }
420 
421 
BUILTIN(ArrayUnshift)422 BUILTIN(ArrayUnshift) {
423   HandleScope scope(isolate);
424   Handle<Object> receiver = args.receiver();
425   MaybeHandle<FixedArrayBase> maybe_elms_obj =
426       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
427   Handle<FixedArrayBase> elms_obj;
428   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
429     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
430   }
431   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
432   DCHECK(!array->map()->is_observed());
433   int to_add = args.length() - 1;
434   if (to_add == 0) {
435     return array->length();
436   }
437   // Currently fixed arrays cannot grow too big, so
438   // we should never hit this case.
439   DCHECK(to_add <= (Smi::kMaxValue - Smi::cast(array->length())->value()));
440 
441   if (to_add > 0 && JSArray::HasReadOnlyLength(array)) {
442     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
443   }
444 
445   ElementsAccessor* accessor = array->GetElementsAccessor();
446   int new_length = accessor->Unshift(array, elms_obj, &args, to_add);
447   return Smi::FromInt(new_length);
448 }
449 
450 
BUILTIN(ArraySlice)451 BUILTIN(ArraySlice) {
452   HandleScope scope(isolate);
453   Handle<Object> receiver = args.receiver();
454   Handle<JSObject> object;
455   Handle<FixedArrayBase> elms_obj;
456   int len = -1;
457   int relative_start = 0;
458   int relative_end = 0;
459   bool is_sloppy_arguments = false;
460 
461   // TODO(littledan): Look up @@species only once, not once here and
462   // again in the JS builtin. Pass the species out?
463   Handle<Object> species;
464   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
465       isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
466   if (*species != isolate->context()->native_context()->array_function()) {
467     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
468   }
469   if (receiver->IsJSArray()) {
470     DisallowHeapAllocation no_gc;
471     JSArray* array = JSArray::cast(*receiver);
472     if (!array->HasFastElements() ||
473         !IsJSArrayFastElementMovingAllowed(isolate, array)) {
474       AllowHeapAllocation allow_allocation;
475       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
476     }
477     len = Smi::cast(array->length())->value();
478     object = Handle<JSObject>::cast(receiver);
479     elms_obj = handle(array->elements(), isolate);
480   } else if (receiver->IsJSObject() &&
481              GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
482                                       &len)) {
483     // Array.prototype.slice(arguments, ...) is quite a common idiom
484     // (notably more than 50% of invocations in Web apps).
485     // Treat it in C++ as well.
486     is_sloppy_arguments = true;
487     object = Handle<JSObject>::cast(receiver);
488     elms_obj = handle(object->elements(), isolate);
489   } else {
490     AllowHeapAllocation allow_allocation;
491     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
492   }
493   DCHECK(len >= 0);
494   int argument_count = args.length() - 1;
495   // Note carefully chosen defaults---if argument is missing,
496   // it's undefined which gets converted to 0 for relative_start
497   // and to len for relative_end.
498   relative_start = 0;
499   relative_end = len;
500   if (argument_count > 0) {
501     DisallowHeapAllocation no_gc;
502     if (!ClampedToInteger(args[1], &relative_start)) {
503       AllowHeapAllocation allow_allocation;
504       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
505     }
506     if (argument_count > 1) {
507       Object* end_arg = args[2];
508       // slice handles the end_arg specially
509       if (end_arg->IsUndefined()) {
510         relative_end = len;
511       } else if (!ClampedToInteger(end_arg, &relative_end)) {
512         AllowHeapAllocation allow_allocation;
513         return CallJsIntrinsic(isolate, isolate->array_slice(), args);
514       }
515     }
516   }
517 
518   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
519   uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
520                                                : Min(relative_start, len);
521 
522   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
523   uint32_t actual_end =
524       (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
525 
526   if (actual_end <= actual_start) {
527     Handle<JSArray> result_array = isolate->factory()->NewJSArray(
528         GetPackedElementsKind(object->GetElementsKind()), 0, 0);
529     return *result_array;
530   }
531 
532   ElementsAccessor* accessor = object->GetElementsAccessor();
533   if (is_sloppy_arguments &&
534       !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) {
535     // Don't deal with arguments with holes in C++
536     AllowHeapAllocation allow_allocation;
537     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
538   }
539   Handle<JSArray> result_array =
540       accessor->Slice(object, elms_obj, actual_start, actual_end);
541   return *result_array;
542 }
543 
544 
BUILTIN(ArraySplice)545 BUILTIN(ArraySplice) {
546   HandleScope scope(isolate);
547   Handle<Object> receiver = args.receiver();
548   MaybeHandle<FixedArrayBase> maybe_elms_obj =
549       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
550   Handle<FixedArrayBase> elms_obj;
551   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
552     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
553   }
554   // TODO(littledan): Look up @@species only once, not once here and
555   // again in the JS builtin. Pass the species out?
556   Handle<Object> species;
557   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
558       isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
559   if (*species != isolate->context()->native_context()->array_function()) {
560     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
561   }
562   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
563   DCHECK(!array->map()->is_observed());
564 
565   int argument_count = args.length() - 1;
566   int relative_start = 0;
567   if (argument_count > 0) {
568     DisallowHeapAllocation no_gc;
569     if (!ClampedToInteger(args[1], &relative_start)) {
570       AllowHeapAllocation allow_allocation;
571       return CallJsIntrinsic(isolate, isolate->array_splice(), args);
572     }
573   }
574   int len = Smi::cast(array->length())->value();
575   // clip relative start to [0, len]
576   int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
577                                           : Min(relative_start, len);
578 
579   int actual_delete_count;
580   if (argument_count == 1) {
581     // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
582     // given as a request to delete all the elements from the start.
583     // And it differs from the case of undefined delete count.
584     // This does not follow ECMA-262, but we do the same for compatibility.
585     DCHECK(len - actual_start >= 0);
586     actual_delete_count = len - actual_start;
587   } else {
588     int delete_count = 0;
589     DisallowHeapAllocation no_gc;
590     if (argument_count > 1) {
591       if (!ClampedToInteger(args[2], &delete_count)) {
592         AllowHeapAllocation allow_allocation;
593         return CallJsIntrinsic(isolate, isolate->array_splice(), args);
594       }
595     }
596     actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
597   }
598 
599   int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
600   int new_length = len - actual_delete_count + add_count;
601 
602   if (new_length != len && JSArray::HasReadOnlyLength(array)) {
603     AllowHeapAllocation allow_allocation;
604     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
605   }
606   ElementsAccessor* accessor = array->GetElementsAccessor();
607   Handle<JSArray> result_array = accessor->Splice(
608       array, elms_obj, actual_start, actual_delete_count, &args, add_count);
609   return *result_array;
610 }
611 
612 
613 // Array Concat -------------------------------------------------------------
614 
615 namespace {
616 
617 /**
618  * A simple visitor visits every element of Array's.
619  * The backend storage can be a fixed array for fast elements case,
620  * or a dictionary for sparse array. Since Dictionary is a subtype
621  * of FixedArray, the class can be used by both fast and slow cases.
622  * The second parameter of the constructor, fast_elements, specifies
623  * whether the storage is a FixedArray or Dictionary.
624  *
625  * An index limit is used to deal with the situation that a result array
626  * length overflows 32-bit non-negative integer.
627  */
628 class ArrayConcatVisitor {
629  public:
ArrayConcatVisitor(Isolate * isolate,Handle<FixedArray> storage,bool fast_elements)630   ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage,
631                      bool fast_elements)
632       : isolate_(isolate),
633         storage_(Handle<FixedArray>::cast(
634             isolate->global_handles()->Create(*storage))),
635         index_offset_(0u),
636         bit_field_(FastElementsField::encode(fast_elements) |
637                    ExceedsLimitField::encode(false)) {}
638 
~ArrayConcatVisitor()639   ~ArrayConcatVisitor() { clear_storage(); }
640 
visit(uint32_t i,Handle<Object> elm)641   void visit(uint32_t i, Handle<Object> elm) {
642     if (i >= JSObject::kMaxElementCount - index_offset_) {
643       set_exceeds_array_limit(true);
644       return;
645     }
646     uint32_t index = index_offset_ + i;
647 
648     if (fast_elements()) {
649       if (index < static_cast<uint32_t>(storage_->length())) {
650         storage_->set(index, *elm);
651         return;
652       }
653       // Our initial estimate of length was foiled, possibly by
654       // getters on the arrays increasing the length of later arrays
655       // during iteration.
656       // This shouldn't happen in anything but pathological cases.
657       SetDictionaryMode();
658       // Fall-through to dictionary mode.
659     }
660     DCHECK(!fast_elements());
661     Handle<SeededNumberDictionary> dict(
662         SeededNumberDictionary::cast(*storage_));
663     // The object holding this backing store has just been allocated, so
664     // it cannot yet be used as a prototype.
665     Handle<SeededNumberDictionary> result =
666         SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
667     if (!result.is_identical_to(dict)) {
668       // Dictionary needed to grow.
669       clear_storage();
670       set_storage(*result);
671     }
672   }
673 
increase_index_offset(uint32_t delta)674   void increase_index_offset(uint32_t delta) {
675     if (JSObject::kMaxElementCount - index_offset_ < delta) {
676       index_offset_ = JSObject::kMaxElementCount;
677     } else {
678       index_offset_ += delta;
679     }
680     // If the initial length estimate was off (see special case in visit()),
681     // but the array blowing the limit didn't contain elements beyond the
682     // provided-for index range, go to dictionary mode now.
683     if (fast_elements() &&
684         index_offset_ >
685             static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
686       SetDictionaryMode();
687     }
688   }
689 
exceeds_array_limit() const690   bool exceeds_array_limit() const {
691     return ExceedsLimitField::decode(bit_field_);
692   }
693 
ToArray()694   Handle<JSArray> ToArray() {
695     Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
696     Handle<Object> length =
697         isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
698     Handle<Map> map = JSObject::GetElementsTransitionMap(
699         array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
700     array->set_map(*map);
701     array->set_length(*length);
702     array->set_elements(*storage_);
703     return array;
704   }
705 
706  private:
707   // Convert storage to dictionary mode.
SetDictionaryMode()708   void SetDictionaryMode() {
709     DCHECK(fast_elements());
710     Handle<FixedArray> current_storage(*storage_);
711     Handle<SeededNumberDictionary> slow_storage(
712         SeededNumberDictionary::New(isolate_, current_storage->length()));
713     uint32_t current_length = static_cast<uint32_t>(current_storage->length());
714     for (uint32_t i = 0; i < current_length; i++) {
715       HandleScope loop_scope(isolate_);
716       Handle<Object> element(current_storage->get(i), isolate_);
717       if (!element->IsTheHole()) {
718         // The object holding this backing store has just been allocated, so
719         // it cannot yet be used as a prototype.
720         Handle<SeededNumberDictionary> new_storage =
721             SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
722                                                 false);
723         if (!new_storage.is_identical_to(slow_storage)) {
724           slow_storage = loop_scope.CloseAndEscape(new_storage);
725         }
726       }
727     }
728     clear_storage();
729     set_storage(*slow_storage);
730     set_fast_elements(false);
731   }
732 
clear_storage()733   inline void clear_storage() {
734     GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
735   }
736 
set_storage(FixedArray * storage)737   inline void set_storage(FixedArray* storage) {
738     storage_ =
739         Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage));
740   }
741 
742   class FastElementsField : public BitField<bool, 0, 1> {};
743   class ExceedsLimitField : public BitField<bool, 1, 1> {};
744 
fast_elements() const745   bool fast_elements() const { return FastElementsField::decode(bit_field_); }
set_fast_elements(bool fast)746   void set_fast_elements(bool fast) {
747     bit_field_ = FastElementsField::update(bit_field_, fast);
748   }
set_exceeds_array_limit(bool exceeds)749   void set_exceeds_array_limit(bool exceeds) {
750     bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
751   }
752 
753   Isolate* isolate_;
754   Handle<FixedArray> storage_;  // Always a global handle.
755   // Index after last seen index. Always less than or equal to
756   // JSObject::kMaxElementCount.
757   uint32_t index_offset_;
758   uint32_t bit_field_;
759 };
760 
761 
EstimateElementCount(Handle<JSArray> array)762 uint32_t EstimateElementCount(Handle<JSArray> array) {
763   uint32_t length = static_cast<uint32_t>(array->length()->Number());
764   int element_count = 0;
765   switch (array->GetElementsKind()) {
766     case FAST_SMI_ELEMENTS:
767     case FAST_HOLEY_SMI_ELEMENTS:
768     case FAST_ELEMENTS:
769     case FAST_HOLEY_ELEMENTS: {
770       // Fast elements can't have lengths that are not representable by
771       // a 32-bit signed integer.
772       DCHECK(static_cast<int32_t>(FixedArray::kMaxLength) >= 0);
773       int fast_length = static_cast<int>(length);
774       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
775       for (int i = 0; i < fast_length; i++) {
776         if (!elements->get(i)->IsTheHole()) element_count++;
777       }
778       break;
779     }
780     case FAST_DOUBLE_ELEMENTS:
781     case FAST_HOLEY_DOUBLE_ELEMENTS: {
782       // Fast elements can't have lengths that are not representable by
783       // a 32-bit signed integer.
784       DCHECK(static_cast<int32_t>(FixedDoubleArray::kMaxLength) >= 0);
785       int fast_length = static_cast<int>(length);
786       if (array->elements()->IsFixedArray()) {
787         DCHECK(FixedArray::cast(array->elements())->length() == 0);
788         break;
789       }
790       Handle<FixedDoubleArray> elements(
791           FixedDoubleArray::cast(array->elements()));
792       for (int i = 0; i < fast_length; i++) {
793         if (!elements->is_the_hole(i)) element_count++;
794       }
795       break;
796     }
797     case DICTIONARY_ELEMENTS: {
798       Handle<SeededNumberDictionary> dictionary(
799           SeededNumberDictionary::cast(array->elements()));
800       int capacity = dictionary->Capacity();
801       for (int i = 0; i < capacity; i++) {
802         Handle<Object> key(dictionary->KeyAt(i), array->GetIsolate());
803         if (dictionary->IsKey(*key)) {
804           element_count++;
805         }
806       }
807       break;
808     }
809     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
810     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
811 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
812 
813       TYPED_ARRAYS(TYPED_ARRAY_CASE)
814 #undef TYPED_ARRAY_CASE
815       // External arrays are always dense.
816       return length;
817   }
818   // As an estimate, we assume that the prototype doesn't contain any
819   // inherited elements.
820   return element_count;
821 }
822 
823 
824 template <class ExternalArrayClass, class ElementType>
IterateTypedArrayElements(Isolate * isolate,Handle<JSObject> receiver,bool elements_are_ints,bool elements_are_guaranteed_smis,ArrayConcatVisitor * visitor)825 void IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver,
826                                bool elements_are_ints,
827                                bool elements_are_guaranteed_smis,
828                                ArrayConcatVisitor* visitor) {
829   Handle<ExternalArrayClass> array(
830       ExternalArrayClass::cast(receiver->elements()));
831   uint32_t len = static_cast<uint32_t>(array->length());
832 
833   DCHECK(visitor != NULL);
834   if (elements_are_ints) {
835     if (elements_are_guaranteed_smis) {
836       for (uint32_t j = 0; j < len; j++) {
837         HandleScope loop_scope(isolate);
838         Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
839                       isolate);
840         visitor->visit(j, e);
841       }
842     } else {
843       for (uint32_t j = 0; j < len; j++) {
844         HandleScope loop_scope(isolate);
845         int64_t val = static_cast<int64_t>(array->get_scalar(j));
846         if (Smi::IsValid(static_cast<intptr_t>(val))) {
847           Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
848           visitor->visit(j, e);
849         } else {
850           Handle<Object> e =
851               isolate->factory()->NewNumber(static_cast<ElementType>(val));
852           visitor->visit(j, e);
853         }
854       }
855     }
856   } else {
857     for (uint32_t j = 0; j < len; j++) {
858       HandleScope loop_scope(isolate);
859       Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
860       visitor->visit(j, e);
861     }
862   }
863 }
864 
865 
866 // Used for sorting indices in a List<uint32_t>.
compareUInt32(const uint32_t * ap,const uint32_t * bp)867 int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
868   uint32_t a = *ap;
869   uint32_t b = *bp;
870   return (a == b) ? 0 : (a < b) ? -1 : 1;
871 }
872 
873 
CollectElementIndices(Handle<JSObject> object,uint32_t range,List<uint32_t> * indices)874 void CollectElementIndices(Handle<JSObject> object, uint32_t range,
875                            List<uint32_t>* indices) {
876   Isolate* isolate = object->GetIsolate();
877   ElementsKind kind = object->GetElementsKind();
878   switch (kind) {
879     case FAST_SMI_ELEMENTS:
880     case FAST_ELEMENTS:
881     case FAST_HOLEY_SMI_ELEMENTS:
882     case FAST_HOLEY_ELEMENTS: {
883       Handle<FixedArray> elements(FixedArray::cast(object->elements()));
884       uint32_t length = static_cast<uint32_t>(elements->length());
885       if (range < length) length = range;
886       for (uint32_t i = 0; i < length; i++) {
887         if (!elements->get(i)->IsTheHole()) {
888           indices->Add(i);
889         }
890       }
891       break;
892     }
893     case FAST_HOLEY_DOUBLE_ELEMENTS:
894     case FAST_DOUBLE_ELEMENTS: {
895       if (object->elements()->IsFixedArray()) {
896         DCHECK(object->elements()->length() == 0);
897         break;
898       }
899       Handle<FixedDoubleArray> elements(
900           FixedDoubleArray::cast(object->elements()));
901       uint32_t length = static_cast<uint32_t>(elements->length());
902       if (range < length) length = range;
903       for (uint32_t i = 0; i < length; i++) {
904         if (!elements->is_the_hole(i)) {
905           indices->Add(i);
906         }
907       }
908       break;
909     }
910     case DICTIONARY_ELEMENTS: {
911       Handle<SeededNumberDictionary> dict(
912           SeededNumberDictionary::cast(object->elements()));
913       uint32_t capacity = dict->Capacity();
914       for (uint32_t j = 0; j < capacity; j++) {
915         HandleScope loop_scope(isolate);
916         Handle<Object> k(dict->KeyAt(j), isolate);
917         if (dict->IsKey(*k)) {
918           DCHECK(k->IsNumber());
919           uint32_t index = static_cast<uint32_t>(k->Number());
920           if (index < range) {
921             indices->Add(index);
922           }
923         }
924       }
925       break;
926     }
927 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
928 
929       TYPED_ARRAYS(TYPED_ARRAY_CASE)
930 #undef TYPED_ARRAY_CASE
931       {
932         uint32_t length = static_cast<uint32_t>(
933             FixedArrayBase::cast(object->elements())->length());
934         if (range <= length) {
935           length = range;
936           // We will add all indices, so we might as well clear it first
937           // and avoid duplicates.
938           indices->Clear();
939         }
940         for (uint32_t i = 0; i < length; i++) {
941           indices->Add(i);
942         }
943         if (length == range) return;  // All indices accounted for already.
944         break;
945       }
946     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
947     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
948       ElementsAccessor* accessor = object->GetElementsAccessor();
949       for (uint32_t i = 0; i < range; i++) {
950         if (accessor->HasElement(object, i)) {
951           indices->Add(i);
952         }
953       }
954       break;
955     }
956   }
957 
958   PrototypeIterator iter(isolate, object);
959   if (!iter.IsAtEnd()) {
960     // The prototype will usually have no inherited element indices,
961     // but we have to check.
962     CollectElementIndices(PrototypeIterator::GetCurrent<JSObject>(iter), range,
963                           indices);
964   }
965 }
966 
967 
IterateElementsSlow(Isolate * isolate,Handle<JSReceiver> receiver,uint32_t length,ArrayConcatVisitor * visitor)968 bool IterateElementsSlow(Isolate* isolate, Handle<JSReceiver> receiver,
969                          uint32_t length, ArrayConcatVisitor* visitor) {
970   for (uint32_t i = 0; i < length; ++i) {
971     HandleScope loop_scope(isolate);
972     Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
973     if (!maybe.IsJust()) return false;
974     if (maybe.FromJust()) {
975       Handle<Object> element_value;
976       ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value,
977                                        Object::GetElement(isolate, receiver, i),
978                                        false);
979       visitor->visit(i, element_value);
980     }
981   }
982   visitor->increase_index_offset(length);
983   return true;
984 }
985 
986 
987 /**
988  * A helper function that visits "array" elements of a JSReceiver in numerical
989  * order.
990  *
991  * The visitor argument called for each existing element in the array
992  * with the element index and the element's value.
993  * Afterwards it increments the base-index of the visitor by the array
994  * length.
995  * Returns false if any access threw an exception, otherwise true.
996  */
IterateElements(Isolate * isolate,Handle<JSReceiver> receiver,ArrayConcatVisitor * visitor)997 bool IterateElements(Isolate* isolate, Handle<JSReceiver> receiver,
998                      ArrayConcatVisitor* visitor) {
999   uint32_t length = 0;
1000 
1001   if (receiver->IsJSArray()) {
1002     Handle<JSArray> array = Handle<JSArray>::cast(receiver);
1003     length = static_cast<uint32_t>(array->length()->Number());
1004   } else {
1005     Handle<Object> val;
1006     Handle<Object> key = isolate->factory()->length_string();
1007     ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1008         isolate, val, Runtime::GetObjectProperty(isolate, receiver, key),
1009         false);
1010     ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, val,
1011                                      Object::ToLength(isolate, val), false);
1012     // TODO(caitp): Support larger element indexes (up to 2^53-1).
1013     if (!val->ToUint32(&length)) {
1014       length = 0;
1015     }
1016   }
1017 
1018   if (!(receiver->IsJSArray() || receiver->IsJSTypedArray())) {
1019     // For classes which are not known to be safe to access via elements alone,
1020     // use the slow case.
1021     return IterateElementsSlow(isolate, receiver, length, visitor);
1022   }
1023   Handle<JSObject> array = Handle<JSObject>::cast(receiver);
1024 
1025   switch (array->GetElementsKind()) {
1026     case FAST_SMI_ELEMENTS:
1027     case FAST_ELEMENTS:
1028     case FAST_HOLEY_SMI_ELEMENTS:
1029     case FAST_HOLEY_ELEMENTS: {
1030       // Run through the elements FixedArray and use HasElement and GetElement
1031       // to check the prototype for missing elements.
1032       Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1033       int fast_length = static_cast<int>(length);
1034       DCHECK(fast_length <= elements->length());
1035       for (int j = 0; j < fast_length; j++) {
1036         HandleScope loop_scope(isolate);
1037         Handle<Object> element_value(elements->get(j), isolate);
1038         if (!element_value->IsTheHole()) {
1039           visitor->visit(j, element_value);
1040         } else {
1041           Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1042           if (!maybe.IsJust()) return false;
1043           if (maybe.FromJust()) {
1044             // Call GetElement on array, not its prototype, or getters won't
1045             // have the correct receiver.
1046             ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1047                 isolate, element_value, Object::GetElement(isolate, array, j),
1048                 false);
1049             visitor->visit(j, element_value);
1050           }
1051         }
1052       }
1053       break;
1054     }
1055     case FAST_HOLEY_DOUBLE_ELEMENTS:
1056     case FAST_DOUBLE_ELEMENTS: {
1057       // Empty array is FixedArray but not FixedDoubleArray.
1058       if (length == 0) break;
1059       // Run through the elements FixedArray and use HasElement and GetElement
1060       // to check the prototype for missing elements.
1061       if (array->elements()->IsFixedArray()) {
1062         DCHECK(array->elements()->length() == 0);
1063         break;
1064       }
1065       Handle<FixedDoubleArray> elements(
1066           FixedDoubleArray::cast(array->elements()));
1067       int fast_length = static_cast<int>(length);
1068       DCHECK(fast_length <= elements->length());
1069       for (int j = 0; j < fast_length; j++) {
1070         HandleScope loop_scope(isolate);
1071         if (!elements->is_the_hole(j)) {
1072           double double_value = elements->get_scalar(j);
1073           Handle<Object> element_value =
1074               isolate->factory()->NewNumber(double_value);
1075           visitor->visit(j, element_value);
1076         } else {
1077           Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1078           if (!maybe.IsJust()) return false;
1079           if (maybe.FromJust()) {
1080             // Call GetElement on array, not its prototype, or getters won't
1081             // have the correct receiver.
1082             Handle<Object> element_value;
1083             ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1084                 isolate, element_value, Object::GetElement(isolate, array, j),
1085                 false);
1086             visitor->visit(j, element_value);
1087           }
1088         }
1089       }
1090       break;
1091     }
1092     case DICTIONARY_ELEMENTS: {
1093       // CollectElementIndices() can't be called when there's a JSProxy
1094       // on the prototype chain.
1095       for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
1096            iter.Advance()) {
1097         if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1098           return IterateElementsSlow(isolate, array, length, visitor);
1099         }
1100       }
1101       Handle<SeededNumberDictionary> dict(array->element_dictionary());
1102       List<uint32_t> indices(dict->Capacity() / 2);
1103       // Collect all indices in the object and the prototypes less
1104       // than length. This might introduce duplicates in the indices list.
1105       CollectElementIndices(array, length, &indices);
1106       indices.Sort(&compareUInt32);
1107       int j = 0;
1108       int n = indices.length();
1109       while (j < n) {
1110         HandleScope loop_scope(isolate);
1111         uint32_t index = indices[j];
1112         Handle<Object> element;
1113         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1114             isolate, element, Object::GetElement(isolate, array, index), false);
1115         visitor->visit(index, element);
1116         // Skip to next different index (i.e., omit duplicates).
1117         do {
1118           j++;
1119         } while (j < n && indices[j] == index);
1120       }
1121       break;
1122     }
1123     case UINT8_CLAMPED_ELEMENTS: {
1124       Handle<FixedUint8ClampedArray> pixels(
1125           FixedUint8ClampedArray::cast(array->elements()));
1126       for (uint32_t j = 0; j < length; j++) {
1127         Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
1128         visitor->visit(j, e);
1129       }
1130       break;
1131     }
1132     case INT8_ELEMENTS: {
1133       IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true,
1134                                                         true, visitor);
1135       break;
1136     }
1137     case UINT8_ELEMENTS: {
1138       IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true,
1139                                                           true, visitor);
1140       break;
1141     }
1142     case INT16_ELEMENTS: {
1143       IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true,
1144                                                           true, visitor);
1145       break;
1146     }
1147     case UINT16_ELEMENTS: {
1148       IterateTypedArrayElements<FixedUint16Array, uint16_t>(
1149           isolate, array, true, true, visitor);
1150       break;
1151     }
1152     case INT32_ELEMENTS: {
1153       IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true,
1154                                                           false, visitor);
1155       break;
1156     }
1157     case UINT32_ELEMENTS: {
1158       IterateTypedArrayElements<FixedUint32Array, uint32_t>(
1159           isolate, array, true, false, visitor);
1160       break;
1161     }
1162     case FLOAT32_ELEMENTS: {
1163       IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false,
1164                                                           false, visitor);
1165       break;
1166     }
1167     case FLOAT64_ELEMENTS: {
1168       IterateTypedArrayElements<FixedFloat64Array, double>(
1169           isolate, array, false, false, visitor);
1170       break;
1171     }
1172     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1173     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1174       for (uint32_t index = 0; index < length; index++) {
1175         HandleScope loop_scope(isolate);
1176         Handle<Object> element;
1177         ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1178             isolate, element, Object::GetElement(isolate, array, index), false);
1179         visitor->visit(index, element);
1180       }
1181       break;
1182     }
1183   }
1184   visitor->increase_index_offset(length);
1185   return true;
1186 }
1187 
1188 
HasConcatSpreadableModifier(Isolate * isolate,Handle<JSArray> obj)1189 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
1190   DCHECK(isolate->IsFastArrayConstructorPrototypeChainIntact());
1191   if (!FLAG_harmony_concat_spreadable) return false;
1192   Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1193   Maybe<bool> maybe = JSReceiver::HasProperty(obj, key);
1194   return maybe.FromMaybe(false);
1195 }
1196 
1197 
IsConcatSpreadable(Isolate * isolate,Handle<Object> obj)1198 static Maybe<bool> IsConcatSpreadable(Isolate* isolate, Handle<Object> obj) {
1199   HandleScope handle_scope(isolate);
1200   if (!obj->IsJSReceiver()) return Just(false);
1201   if (FLAG_harmony_concat_spreadable) {
1202     Handle<Symbol> key(isolate->factory()->is_concat_spreadable_symbol());
1203     Handle<Object> value;
1204     MaybeHandle<Object> maybeValue =
1205         i::Runtime::GetObjectProperty(isolate, obj, key);
1206     if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1207     if (!value->IsUndefined()) return Just(value->BooleanValue());
1208   }
1209   return Object::IsArray(obj);
1210 }
1211 
1212 
Slow_ArrayConcat(Arguments * args,Isolate * isolate)1213 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) {
1214   int argument_count = args->length();
1215 
1216   // Pass 1: estimate the length and number of elements of the result.
1217   // The actual length can be larger if any of the arguments have getters
1218   // that mutate other arguments (but will otherwise be precise).
1219   // The number of elements is precise if there are no inherited elements.
1220 
1221   ElementsKind kind = FAST_SMI_ELEMENTS;
1222 
1223   uint32_t estimate_result_length = 0;
1224   uint32_t estimate_nof_elements = 0;
1225   for (int i = 0; i < argument_count; i++) {
1226     HandleScope loop_scope(isolate);
1227     Handle<Object> obj((*args)[i], isolate);
1228     uint32_t length_estimate;
1229     uint32_t element_estimate;
1230     if (obj->IsJSArray()) {
1231       Handle<JSArray> array(Handle<JSArray>::cast(obj));
1232       length_estimate = static_cast<uint32_t>(array->length()->Number());
1233       if (length_estimate != 0) {
1234         ElementsKind array_kind =
1235             GetPackedElementsKind(array->map()->elements_kind());
1236         kind = GetMoreGeneralElementsKind(kind, array_kind);
1237       }
1238       element_estimate = EstimateElementCount(array);
1239     } else {
1240       if (obj->IsHeapObject()) {
1241         if (obj->IsNumber()) {
1242           kind = GetMoreGeneralElementsKind(kind, FAST_DOUBLE_ELEMENTS);
1243         } else {
1244           kind = GetMoreGeneralElementsKind(kind, FAST_ELEMENTS);
1245         }
1246       }
1247       length_estimate = 1;
1248       element_estimate = 1;
1249     }
1250     // Avoid overflows by capping at kMaxElementCount.
1251     if (JSObject::kMaxElementCount - estimate_result_length < length_estimate) {
1252       estimate_result_length = JSObject::kMaxElementCount;
1253     } else {
1254       estimate_result_length += length_estimate;
1255     }
1256     if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1257       estimate_nof_elements = JSObject::kMaxElementCount;
1258     } else {
1259       estimate_nof_elements += element_estimate;
1260     }
1261   }
1262 
1263   // If estimated number of elements is more than half of length, a
1264   // fixed array (fast case) is more time and space-efficient than a
1265   // dictionary.
1266   bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length;
1267 
1268   if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1269     Handle<FixedArrayBase> storage =
1270         isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1271     int j = 0;
1272     bool failure = false;
1273     if (estimate_result_length > 0) {
1274       Handle<FixedDoubleArray> double_storage =
1275           Handle<FixedDoubleArray>::cast(storage);
1276       for (int i = 0; i < argument_count; i++) {
1277         Handle<Object> obj((*args)[i], isolate);
1278         if (obj->IsSmi()) {
1279           double_storage->set(j, Smi::cast(*obj)->value());
1280           j++;
1281         } else if (obj->IsNumber()) {
1282           double_storage->set(j, obj->Number());
1283           j++;
1284         } else {
1285           JSArray* array = JSArray::cast(*obj);
1286           uint32_t length = static_cast<uint32_t>(array->length()->Number());
1287           switch (array->map()->elements_kind()) {
1288             case FAST_HOLEY_DOUBLE_ELEMENTS:
1289             case FAST_DOUBLE_ELEMENTS: {
1290               // Empty array is FixedArray but not FixedDoubleArray.
1291               if (length == 0) break;
1292               FixedDoubleArray* elements =
1293                   FixedDoubleArray::cast(array->elements());
1294               for (uint32_t i = 0; i < length; i++) {
1295                 if (elements->is_the_hole(i)) {
1296                   // TODO(jkummerow/verwaest): We could be a bit more clever
1297                   // here: Check if there are no elements/getters on the
1298                   // prototype chain, and if so, allow creation of a holey
1299                   // result array.
1300                   // Same thing below (holey smi case).
1301                   failure = true;
1302                   break;
1303                 }
1304                 double double_value = elements->get_scalar(i);
1305                 double_storage->set(j, double_value);
1306                 j++;
1307               }
1308               break;
1309             }
1310             case FAST_HOLEY_SMI_ELEMENTS:
1311             case FAST_SMI_ELEMENTS: {
1312               FixedArray* elements(FixedArray::cast(array->elements()));
1313               for (uint32_t i = 0; i < length; i++) {
1314                 Object* element = elements->get(i);
1315                 if (element->IsTheHole()) {
1316                   failure = true;
1317                   break;
1318                 }
1319                 int32_t int_value = Smi::cast(element)->value();
1320                 double_storage->set(j, int_value);
1321                 j++;
1322               }
1323               break;
1324             }
1325             case FAST_HOLEY_ELEMENTS:
1326             case FAST_ELEMENTS:
1327             case DICTIONARY_ELEMENTS:
1328               DCHECK_EQ(0u, length);
1329               break;
1330             default:
1331               UNREACHABLE();
1332           }
1333         }
1334         if (failure) break;
1335       }
1336     }
1337     if (!failure) {
1338       Handle<JSArray> array = isolate->factory()->NewJSArray(0);
1339       Smi* length = Smi::FromInt(j);
1340       Handle<Map> map;
1341       map = JSObject::GetElementsTransitionMap(array, kind);
1342       array->set_map(*map);
1343       array->set_length(length);
1344       array->set_elements(*storage);
1345       return *array;
1346     }
1347     // In case of failure, fall through.
1348   }
1349 
1350   Handle<FixedArray> storage;
1351   if (fast_case) {
1352     // The backing storage array must have non-existing elements to preserve
1353     // holes across concat operations.
1354     storage =
1355         isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
1356   } else {
1357     // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1358     uint32_t at_least_space_for =
1359         estimate_nof_elements + (estimate_nof_elements >> 2);
1360     storage = Handle<FixedArray>::cast(
1361         SeededNumberDictionary::New(isolate, at_least_space_for));
1362   }
1363 
1364   ArrayConcatVisitor visitor(isolate, storage, fast_case);
1365 
1366   for (int i = 0; i < argument_count; i++) {
1367     Handle<Object> obj((*args)[i], isolate);
1368     Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1369     MAYBE_RETURN(spreadable, isolate->heap()->exception());
1370     if (spreadable.FromJust()) {
1371       Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1372       if (!IterateElements(isolate, object, &visitor)) {
1373         return isolate->heap()->exception();
1374       }
1375     } else {
1376       visitor.visit(0, obj);
1377       visitor.increase_index_offset(1);
1378     }
1379   }
1380 
1381   if (visitor.exceeds_array_limit()) {
1382     THROW_NEW_ERROR_RETURN_FAILURE(
1383         isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1384   }
1385   return *visitor.ToArray();
1386 }
1387 
1388 
Fast_ArrayConcat(Isolate * isolate,Arguments * args)1389 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1390   if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
1391     return MaybeHandle<JSArray>();
1392   }
1393   int n_arguments = args->length();
1394   int result_len = 0;
1395   {
1396     DisallowHeapAllocation no_gc;
1397     Object* array_proto = isolate->array_function()->prototype();
1398     // Iterate through all the arguments performing checks
1399     // and calculating total length.
1400     for (int i = 0; i < n_arguments; i++) {
1401       Object* arg = (*args)[i];
1402       if (!arg->IsJSArray()) return MaybeHandle<JSArray>();
1403       Handle<JSArray> array(JSArray::cast(arg), isolate);
1404       if (!array->HasFastElements()) return MaybeHandle<JSArray>();
1405       PrototypeIterator iter(isolate, arg);
1406       if (iter.GetCurrent() != array_proto) return MaybeHandle<JSArray>();
1407       if (HasConcatSpreadableModifier(isolate, array)) {
1408         return MaybeHandle<JSArray>();
1409       }
1410       int len = Smi::cast(array->length())->value();
1411 
1412       // We shouldn't overflow when adding another len.
1413       const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1414       STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1415       USE(kHalfOfMaxInt);
1416       result_len += len;
1417       DCHECK(result_len >= 0);
1418       // Throw an Error if we overflow the FixedArray limits
1419       if (FixedArray::kMaxLength < result_len) {
1420         THROW_NEW_ERROR(isolate,
1421                         NewRangeError(MessageTemplate::kInvalidArrayLength),
1422                         JSArray);
1423       }
1424     }
1425   }
1426   return ElementsAccessor::Concat(isolate, args, n_arguments);
1427 }
1428 
1429 }  // namespace
1430 
1431 // ES6 22.1.3.1 Array.prototype.concat
BUILTIN(ArrayConcat)1432 BUILTIN(ArrayConcat) {
1433   HandleScope scope(isolate);
1434 
1435   Handle<Object> receiver;
1436   if (!Object::ToObject(isolate, handle(args[0], isolate))
1437            .ToHandle(&receiver)) {
1438     THROW_NEW_ERROR_RETURN_FAILURE(
1439         isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1440                               isolate->factory()->NewStringFromAsciiChecked(
1441                                   "Array.prototype.concat")));
1442   }
1443   args[0] = *receiver;
1444 
1445   Handle<JSArray> result_array;
1446   if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1447     return *result_array;
1448   }
1449   if (isolate->has_pending_exception()) return isolate->heap()->exception();
1450   return Slow_ArrayConcat(&args, isolate);
1451 }
1452 
1453 
1454 // ES6 22.1.2.2 Array.isArray
BUILTIN(ArrayIsArray)1455 BUILTIN(ArrayIsArray) {
1456   HandleScope scope(isolate);
1457   DCHECK_EQ(2, args.length());
1458   Handle<Object> object = args.at<Object>(1);
1459   Maybe<bool> result = Object::IsArray(object);
1460   MAYBE_RETURN(result, isolate->heap()->exception());
1461   return *isolate->factory()->ToBoolean(result.FromJust());
1462 }
1463 
1464 
1465 // ES6 19.1.2.1 Object.assign
BUILTIN(ObjectAssign)1466 BUILTIN(ObjectAssign) {
1467   HandleScope scope(isolate);
1468   Handle<Object> target = args.atOrUndefined(isolate, 1);
1469 
1470   // 1. Let to be ? ToObject(target).
1471   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, target,
1472                                      Execution::ToObject(isolate, target));
1473   Handle<JSReceiver> to = Handle<JSReceiver>::cast(target);
1474   // 2. If only one argument was passed, return to.
1475   if (args.length() == 2) return *to;
1476   // 3. Let sources be the List of argument values starting with the
1477   //    second argument.
1478   // 4. For each element nextSource of sources, in ascending index order,
1479   for (int i = 2; i < args.length(); ++i) {
1480     Handle<Object> next_source = args.at<Object>(i);
1481     // 4a. If nextSource is undefined or null, let keys be an empty List.
1482     if (next_source->IsUndefined() || next_source->IsNull()) continue;
1483     // 4b. Else,
1484     // 4b i. Let from be ToObject(nextSource).
1485     Handle<JSReceiver> from =
1486         Object::ToObject(isolate, next_source).ToHandleChecked();
1487     // 4b ii. Let keys be ? from.[[OwnPropertyKeys]]().
1488     Handle<FixedArray> keys;
1489     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1490         isolate, keys, JSReceiver::GetKeys(from, JSReceiver::OWN_ONLY,
1491                                            ALL_PROPERTIES, KEEP_NUMBERS));
1492     // 4c. Repeat for each element nextKey of keys in List order,
1493     for (int j = 0; j < keys->length(); ++j) {
1494       Handle<Object> next_key(keys->get(j), isolate);
1495       // 4c i. Let desc be ? from.[[GetOwnProperty]](nextKey).
1496       PropertyDescriptor desc;
1497       Maybe<bool> found =
1498           JSReceiver::GetOwnPropertyDescriptor(isolate, from, next_key, &desc);
1499       if (found.IsNothing()) return isolate->heap()->exception();
1500       // 4c ii. If desc is not undefined and desc.[[Enumerable]] is true, then
1501       if (found.FromJust() && desc.enumerable()) {
1502         // 4c ii 1. Let propValue be ? Get(from, nextKey).
1503         Handle<Object> prop_value;
1504         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1505             isolate, prop_value,
1506             Runtime::GetObjectProperty(isolate, from, next_key, STRICT));
1507         // 4c ii 2. Let status be ? Set(to, nextKey, propValue, true).
1508         Handle<Object> status;
1509         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1510             isolate, status, Runtime::SetObjectProperty(isolate, to, next_key,
1511                                                         prop_value, STRICT));
1512       }
1513     }
1514   }
1515   // 5. Return to.
1516   return *to;
1517 }
1518 
1519 
1520 // ES6 section 19.1.2.2 Object.create ( O [ , Properties ] )
BUILTIN(ObjectCreate)1521 BUILTIN(ObjectCreate) {
1522   HandleScope scope(isolate);
1523   Handle<Object> prototype = args.atOrUndefined(isolate, 1);
1524   if (!prototype->IsNull() && !prototype->IsJSReceiver()) {
1525     THROW_NEW_ERROR_RETURN_FAILURE(
1526         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, prototype));
1527   }
1528 
1529   // Generate the map with the specified {prototype} based on the Object
1530   // function's initial map from the current native context.
1531   // TODO(bmeurer): Use a dedicated cache for Object.create; think about
1532   // slack tracking for Object.create.
1533   Handle<Map> map(isolate->native_context()->object_function()->initial_map(),
1534                   isolate);
1535   if (map->prototype() != *prototype) {
1536     map = Map::TransitionToPrototype(map, prototype, FAST_PROTOTYPE);
1537   }
1538 
1539   // Actually allocate the object.
1540   Handle<JSObject> object = isolate->factory()->NewJSObjectFromMap(map);
1541 
1542   // Define the properties if properties was specified and is not undefined.
1543   Handle<Object> properties = args.atOrUndefined(isolate, 2);
1544   if (!properties->IsUndefined()) {
1545     RETURN_FAILURE_ON_EXCEPTION(
1546         isolate, JSReceiver::DefineProperties(isolate, object, properties));
1547   }
1548 
1549   return *object;
1550 }
1551 
1552 
1553 // ES6 section 19.1.2.5 Object.freeze ( O )
BUILTIN(ObjectFreeze)1554 BUILTIN(ObjectFreeze) {
1555   HandleScope scope(isolate);
1556   Handle<Object> object = args.atOrUndefined(isolate, 1);
1557   if (object->IsJSReceiver()) {
1558     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1559                                                FROZEN, Object::THROW_ON_ERROR),
1560                  isolate->heap()->exception());
1561   }
1562   return *object;
1563 }
1564 
1565 
1566 // ES6 section 19.1.2.11 Object.isExtensible ( O )
BUILTIN(ObjectIsExtensible)1567 BUILTIN(ObjectIsExtensible) {
1568   HandleScope scope(isolate);
1569   Handle<Object> object = args.atOrUndefined(isolate, 1);
1570   Maybe<bool> result =
1571       object->IsJSReceiver()
1572           ? JSReceiver::IsExtensible(Handle<JSReceiver>::cast(object))
1573           : Just(false);
1574   MAYBE_RETURN(result, isolate->heap()->exception());
1575   return isolate->heap()->ToBoolean(result.FromJust());
1576 }
1577 
1578 
1579 // ES6 section 19.1.2.12 Object.isFrozen ( O )
BUILTIN(ObjectIsFrozen)1580 BUILTIN(ObjectIsFrozen) {
1581   HandleScope scope(isolate);
1582   Handle<Object> object = args.atOrUndefined(isolate, 1);
1583   Maybe<bool> result = object->IsJSReceiver()
1584                            ? JSReceiver::TestIntegrityLevel(
1585                                  Handle<JSReceiver>::cast(object), FROZEN)
1586                            : Just(true);
1587   MAYBE_RETURN(result, isolate->heap()->exception());
1588   return isolate->heap()->ToBoolean(result.FromJust());
1589 }
1590 
1591 
1592 // ES6 section 19.1.2.13 Object.isSealed ( O )
BUILTIN(ObjectIsSealed)1593 BUILTIN(ObjectIsSealed) {
1594   HandleScope scope(isolate);
1595   Handle<Object> object = args.atOrUndefined(isolate, 1);
1596   Maybe<bool> result = object->IsJSReceiver()
1597                            ? JSReceiver::TestIntegrityLevel(
1598                                  Handle<JSReceiver>::cast(object), SEALED)
1599                            : Just(true);
1600   MAYBE_RETURN(result, isolate->heap()->exception());
1601   return isolate->heap()->ToBoolean(result.FromJust());
1602 }
1603 
1604 
1605 // ES6 section 19.1.2.14 Object.keys ( O )
BUILTIN(ObjectKeys)1606 BUILTIN(ObjectKeys) {
1607   HandleScope scope(isolate);
1608   Handle<Object> object = args.atOrUndefined(isolate, 1);
1609   Handle<JSReceiver> receiver;
1610   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, receiver,
1611                                      Execution::ToObject(isolate, object));
1612   Handle<FixedArray> keys;
1613 
1614   int enum_length = receiver->map()->EnumLength();
1615   if (enum_length != kInvalidEnumCacheSentinel &&
1616       JSObject::cast(*receiver)->elements() ==
1617           isolate->heap()->empty_fixed_array()) {
1618     DCHECK(receiver->IsJSObject());
1619     DCHECK(!JSObject::cast(*receiver)->HasNamedInterceptor());
1620     DCHECK(!JSObject::cast(*receiver)->IsAccessCheckNeeded());
1621     DCHECK(!HeapObject::cast(receiver->map()->prototype())
1622                 ->map()
1623                 ->is_hidden_prototype());
1624     DCHECK(JSObject::cast(*receiver)->HasFastProperties());
1625     if (enum_length == 0) {
1626       keys = isolate->factory()->empty_fixed_array();
1627     } else {
1628       Handle<FixedArray> cache(
1629           receiver->map()->instance_descriptors()->GetEnumCache());
1630       keys = isolate->factory()->NewFixedArray(enum_length);
1631       for (int i = 0; i < enum_length; i++) {
1632         keys->set(i, cache->get(i));
1633       }
1634     }
1635   } else {
1636     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1637         isolate, keys,
1638         JSReceiver::GetKeys(receiver, JSReceiver::OWN_ONLY, ENUMERABLE_STRINGS,
1639                             CONVERT_TO_STRING));
1640   }
1641   return *isolate->factory()->NewJSArrayWithElements(keys, FAST_ELEMENTS);
1642 }
1643 
1644 
1645 // ES6 section 19.1.2.15 Object.preventExtensions ( O )
BUILTIN(ObjectPreventExtensions)1646 BUILTIN(ObjectPreventExtensions) {
1647   HandleScope scope(isolate);
1648   Handle<Object> object = args.atOrUndefined(isolate, 1);
1649   if (object->IsJSReceiver()) {
1650     MAYBE_RETURN(JSReceiver::PreventExtensions(Handle<JSReceiver>::cast(object),
1651                                                Object::THROW_ON_ERROR),
1652                  isolate->heap()->exception());
1653   }
1654   return *object;
1655 }
1656 
1657 
1658 // ES6 section 19.1.2.17 Object.seal ( O )
BUILTIN(ObjectSeal)1659 BUILTIN(ObjectSeal) {
1660   HandleScope scope(isolate);
1661   Handle<Object> object = args.atOrUndefined(isolate, 1);
1662   if (object->IsJSReceiver()) {
1663     MAYBE_RETURN(JSReceiver::SetIntegrityLevel(Handle<JSReceiver>::cast(object),
1664                                                SEALED, Object::THROW_ON_ERROR),
1665                  isolate->heap()->exception());
1666   }
1667   return *object;
1668 }
1669 
1670 
1671 namespace {
1672 
CodeGenerationFromStringsAllowed(Isolate * isolate,Handle<Context> context)1673 bool CodeGenerationFromStringsAllowed(Isolate* isolate,
1674                                       Handle<Context> context) {
1675   DCHECK(context->allow_code_gen_from_strings()->IsFalse());
1676   // Check with callback if set.
1677   AllowCodeGenerationFromStringsCallback callback =
1678       isolate->allow_code_gen_callback();
1679   if (callback == NULL) {
1680     // No callback set and code generation disallowed.
1681     return false;
1682   } else {
1683     // Callback set. Let it decide if code generation is allowed.
1684     VMState<EXTERNAL> state(isolate);
1685     return callback(v8::Utils::ToLocal(context));
1686   }
1687 }
1688 
1689 
CompileString(Handle<Context> context,Handle<String> source,ParseRestriction restriction)1690 MaybeHandle<JSFunction> CompileString(Handle<Context> context,
1691                                       Handle<String> source,
1692                                       ParseRestriction restriction) {
1693   Isolate* const isolate = context->GetIsolate();
1694   Handle<Context> native_context(context->native_context(), isolate);
1695 
1696   // Check if native context allows code generation from
1697   // strings. Throw an exception if it doesn't.
1698   if (native_context->allow_code_gen_from_strings()->IsFalse() &&
1699       !CodeGenerationFromStringsAllowed(isolate, native_context)) {
1700     Handle<Object> error_message =
1701         native_context->ErrorMessageForCodeGenerationFromStrings();
1702     THROW_NEW_ERROR(isolate, NewEvalError(MessageTemplate::kCodeGenFromStrings,
1703                                           error_message),
1704                     JSFunction);
1705   }
1706 
1707   // Compile source string in the native context.
1708   Handle<SharedFunctionInfo> outer_info(native_context->closure()->shared(),
1709                                         isolate);
1710   return Compiler::GetFunctionFromEval(source, outer_info, native_context,
1711                                        SLOPPY, restriction,
1712                                        RelocInfo::kNoPosition);
1713 }
1714 
1715 }  // namespace
1716 
1717 
1718 // ES6 section 18.2.1 eval (x)
BUILTIN(GlobalEval)1719 BUILTIN(GlobalEval) {
1720   HandleScope scope(isolate);
1721   Handle<Object> x = args.atOrUndefined(isolate, 1);
1722   Handle<JSFunction> target = args.target();
1723   Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
1724   if (!x->IsString()) return *x;
1725   Handle<JSFunction> function;
1726   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1727       isolate, function,
1728       CompileString(handle(target->native_context(), isolate),
1729                     Handle<String>::cast(x), NO_PARSE_RESTRICTION));
1730   Handle<Object> result;
1731   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1732       isolate, result,
1733       Execution::Call(isolate, function, target_global_proxy, 0, nullptr));
1734   return *result;
1735 }
1736 
1737 
1738 // ES6 section 26.1.3 Reflect.defineProperty
BUILTIN(ReflectDefineProperty)1739 BUILTIN(ReflectDefineProperty) {
1740   HandleScope scope(isolate);
1741   DCHECK_EQ(4, args.length());
1742   Handle<Object> target = args.at<Object>(1);
1743   Handle<Object> key = args.at<Object>(2);
1744   Handle<Object> attributes = args.at<Object>(3);
1745 
1746   if (!target->IsJSReceiver()) {
1747     THROW_NEW_ERROR_RETURN_FAILURE(
1748         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1749                               isolate->factory()->NewStringFromAsciiChecked(
1750                                   "Reflect.defineProperty")));
1751   }
1752 
1753   Handle<Name> name;
1754   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1755                                      Object::ToName(isolate, key));
1756 
1757   PropertyDescriptor desc;
1758   if (!PropertyDescriptor::ToPropertyDescriptor(isolate, attributes, &desc)) {
1759     return isolate->heap()->exception();
1760   }
1761 
1762   Maybe<bool> result =
1763       JSReceiver::DefineOwnProperty(isolate, Handle<JSReceiver>::cast(target),
1764                                     name, &desc, Object::DONT_THROW);
1765   MAYBE_RETURN(result, isolate->heap()->exception());
1766   return *isolate->factory()->ToBoolean(result.FromJust());
1767 }
1768 
1769 
1770 // ES6 section 26.1.4 Reflect.deleteProperty
BUILTIN(ReflectDeleteProperty)1771 BUILTIN(ReflectDeleteProperty) {
1772   HandleScope scope(isolate);
1773   DCHECK_EQ(3, args.length());
1774   Handle<Object> target = args.at<Object>(1);
1775   Handle<Object> key = args.at<Object>(2);
1776 
1777   if (!target->IsJSReceiver()) {
1778     THROW_NEW_ERROR_RETURN_FAILURE(
1779         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1780                               isolate->factory()->NewStringFromAsciiChecked(
1781                                   "Reflect.deleteProperty")));
1782   }
1783 
1784   Handle<Name> name;
1785   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1786                                      Object::ToName(isolate, key));
1787 
1788   Maybe<bool> result = JSReceiver::DeletePropertyOrElement(
1789       Handle<JSReceiver>::cast(target), name, SLOPPY);
1790   MAYBE_RETURN(result, isolate->heap()->exception());
1791   return *isolate->factory()->ToBoolean(result.FromJust());
1792 }
1793 
1794 
1795 // ES6 section 26.1.6 Reflect.get
BUILTIN(ReflectGet)1796 BUILTIN(ReflectGet) {
1797   HandleScope scope(isolate);
1798   Handle<Object> target = args.atOrUndefined(isolate, 1);
1799   Handle<Object> key = args.atOrUndefined(isolate, 2);
1800   Handle<Object> receiver = args.length() > 3 ? args.at<Object>(3) : target;
1801 
1802   if (!target->IsJSReceiver()) {
1803     THROW_NEW_ERROR_RETURN_FAILURE(
1804         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1805                               isolate->factory()->NewStringFromAsciiChecked(
1806                                   "Reflect.get")));
1807   }
1808 
1809   Handle<Name> name;
1810   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1811                                      Object::ToName(isolate, key));
1812 
1813   Handle<Object> result;
1814   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1815       isolate, result, Object::GetPropertyOrElement(
1816           Handle<JSReceiver>::cast(target), name, receiver));
1817 
1818   return *result;
1819 }
1820 
1821 
1822 // ES6 section 26.1.7 Reflect.getOwnPropertyDescriptor
BUILTIN(ReflectGetOwnPropertyDescriptor)1823 BUILTIN(ReflectGetOwnPropertyDescriptor) {
1824   HandleScope scope(isolate);
1825   DCHECK_EQ(3, args.length());
1826   Handle<Object> target = args.at<Object>(1);
1827   Handle<Object> key = args.at<Object>(2);
1828 
1829   if (!target->IsJSReceiver()) {
1830     THROW_NEW_ERROR_RETURN_FAILURE(
1831         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1832                               isolate->factory()->NewStringFromAsciiChecked(
1833                                   "Reflect.getOwnPropertyDescriptor")));
1834   }
1835 
1836   Handle<Name> name;
1837   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1838                                      Object::ToName(isolate, key));
1839 
1840   PropertyDescriptor desc;
1841   Maybe<bool> found = JSReceiver::GetOwnPropertyDescriptor(
1842       isolate, Handle<JSReceiver>::cast(target), name, &desc);
1843   MAYBE_RETURN(found, isolate->heap()->exception());
1844   if (!found.FromJust()) return isolate->heap()->undefined_value();
1845   return *desc.ToObject(isolate);
1846 }
1847 
1848 
1849 // ES6 section 26.1.8 Reflect.getPrototypeOf
BUILTIN(ReflectGetPrototypeOf)1850 BUILTIN(ReflectGetPrototypeOf) {
1851   HandleScope scope(isolate);
1852   DCHECK_EQ(2, args.length());
1853   Handle<Object> target = args.at<Object>(1);
1854 
1855   if (!target->IsJSReceiver()) {
1856     THROW_NEW_ERROR_RETURN_FAILURE(
1857         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1858                               isolate->factory()->NewStringFromAsciiChecked(
1859                                   "Reflect.getPrototypeOf")));
1860   }
1861   Handle<Object> prototype;
1862   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, prototype,
1863                                      Object::GetPrototype(isolate, target));
1864   return *prototype;
1865 }
1866 
1867 
1868 // ES6 section 26.1.9 Reflect.has
BUILTIN(ReflectHas)1869 BUILTIN(ReflectHas) {
1870   HandleScope scope(isolate);
1871   DCHECK_EQ(3, args.length());
1872   Handle<Object> target = args.at<Object>(1);
1873   Handle<Object> key = args.at<Object>(2);
1874 
1875   if (!target->IsJSReceiver()) {
1876     THROW_NEW_ERROR_RETURN_FAILURE(
1877         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1878                               isolate->factory()->NewStringFromAsciiChecked(
1879                                   "Reflect.has")));
1880   }
1881 
1882   Handle<Name> name;
1883   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1884                                      Object::ToName(isolate, key));
1885 
1886   Maybe<bool> result =
1887       JSReceiver::HasProperty(Handle<JSReceiver>::cast(target), name);
1888   return result.IsJust() ? *isolate->factory()->ToBoolean(result.FromJust())
1889                          : isolate->heap()->exception();
1890 }
1891 
1892 
1893 // ES6 section 26.1.10 Reflect.isExtensible
BUILTIN(ReflectIsExtensible)1894 BUILTIN(ReflectIsExtensible) {
1895   HandleScope scope(isolate);
1896   DCHECK_EQ(2, args.length());
1897   Handle<Object> target = args.at<Object>(1);
1898 
1899   if (!target->IsJSReceiver()) {
1900     THROW_NEW_ERROR_RETURN_FAILURE(
1901         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1902                               isolate->factory()->NewStringFromAsciiChecked(
1903                                   "Reflect.isExtensible")));
1904   }
1905 
1906   Maybe<bool> result =
1907       JSReceiver::IsExtensible(Handle<JSReceiver>::cast(target));
1908   MAYBE_RETURN(result, isolate->heap()->exception());
1909   return *isolate->factory()->ToBoolean(result.FromJust());
1910 }
1911 
1912 
1913 // ES6 section 26.1.11 Reflect.ownKeys
BUILTIN(ReflectOwnKeys)1914 BUILTIN(ReflectOwnKeys) {
1915   HandleScope scope(isolate);
1916   DCHECK_EQ(2, args.length());
1917   Handle<Object> target = args.at<Object>(1);
1918 
1919   if (!target->IsJSReceiver()) {
1920     THROW_NEW_ERROR_RETURN_FAILURE(
1921         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1922                               isolate->factory()->NewStringFromAsciiChecked(
1923                                   "Reflect.ownKeys")));
1924   }
1925 
1926   Handle<FixedArray> keys;
1927   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1928       isolate, keys, JSReceiver::GetKeys(Handle<JSReceiver>::cast(target),
1929                                          JSReceiver::OWN_ONLY, ALL_PROPERTIES,
1930                                          CONVERT_TO_STRING));
1931   return *isolate->factory()->NewJSArrayWithElements(keys);
1932 }
1933 
1934 
1935 // ES6 section 26.1.12 Reflect.preventExtensions
BUILTIN(ReflectPreventExtensions)1936 BUILTIN(ReflectPreventExtensions) {
1937   HandleScope scope(isolate);
1938   DCHECK_EQ(2, args.length());
1939   Handle<Object> target = args.at<Object>(1);
1940 
1941   if (!target->IsJSReceiver()) {
1942     THROW_NEW_ERROR_RETURN_FAILURE(
1943         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1944                               isolate->factory()->NewStringFromAsciiChecked(
1945                                   "Reflect.preventExtensions")));
1946   }
1947 
1948   Maybe<bool> result = JSReceiver::PreventExtensions(
1949       Handle<JSReceiver>::cast(target), Object::DONT_THROW);
1950   MAYBE_RETURN(result, isolate->heap()->exception());
1951   return *isolate->factory()->ToBoolean(result.FromJust());
1952 }
1953 
1954 
1955 // ES6 section 26.1.13 Reflect.set
BUILTIN(ReflectSet)1956 BUILTIN(ReflectSet) {
1957   HandleScope scope(isolate);
1958   Handle<Object> target = args.atOrUndefined(isolate, 1);
1959   Handle<Object> key = args.atOrUndefined(isolate, 2);
1960   Handle<Object> value = args.atOrUndefined(isolate, 3);
1961   Handle<Object> receiver = args.length() > 4 ? args.at<Object>(4) : target;
1962 
1963   if (!target->IsJSReceiver()) {
1964     THROW_NEW_ERROR_RETURN_FAILURE(
1965         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1966                               isolate->factory()->NewStringFromAsciiChecked(
1967                                   "Reflect.set")));
1968   }
1969 
1970   Handle<Name> name;
1971   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, name,
1972                                      Object::ToName(isolate, key));
1973 
1974   LookupIterator it = LookupIterator::PropertyOrElement(
1975       isolate, receiver, name, Handle<JSReceiver>::cast(target));
1976   Maybe<bool> result = Object::SetSuperProperty(
1977       &it, value, SLOPPY, Object::MAY_BE_STORE_FROM_KEYED);
1978   MAYBE_RETURN(result, isolate->heap()->exception());
1979   return *isolate->factory()->ToBoolean(result.FromJust());
1980 }
1981 
1982 
1983 // ES6 section 26.1.14 Reflect.setPrototypeOf
BUILTIN(ReflectSetPrototypeOf)1984 BUILTIN(ReflectSetPrototypeOf) {
1985   HandleScope scope(isolate);
1986   DCHECK_EQ(3, args.length());
1987   Handle<Object> target = args.at<Object>(1);
1988   Handle<Object> proto = args.at<Object>(2);
1989 
1990   if (!target->IsJSReceiver()) {
1991     THROW_NEW_ERROR_RETURN_FAILURE(
1992         isolate, NewTypeError(MessageTemplate::kCalledOnNonObject,
1993                               isolate->factory()->NewStringFromAsciiChecked(
1994                                   "Reflect.setPrototypeOf")));
1995   }
1996 
1997   if (!proto->IsJSReceiver() && !proto->IsNull()) {
1998     THROW_NEW_ERROR_RETURN_FAILURE(
1999         isolate, NewTypeError(MessageTemplate::kProtoObjectOrNull, proto));
2000   }
2001 
2002   Maybe<bool> result = JSReceiver::SetPrototype(
2003       Handle<JSReceiver>::cast(target), proto, true, Object::DONT_THROW);
2004   MAYBE_RETURN(result, isolate->heap()->exception());
2005   return *isolate->factory()->ToBoolean(result.FromJust());
2006 }
2007 
2008 
2009 // -----------------------------------------------------------------------------
2010 // ES6 section 20.3 Date Objects
2011 
2012 
2013 namespace {
2014 
2015 // ES6 section 20.3.1.1 Time Values and Time Range
2016 const double kMinYear = -1000000.0;
2017 const double kMaxYear = -kMinYear;
2018 const double kMinMonth = -10000000.0;
2019 const double kMaxMonth = -kMinMonth;
2020 
2021 
2022 // 20.3.1.2 Day Number and Time within Day
2023 const double kMsPerDay = 86400000.0;
2024 
2025 
2026 // ES6 section 20.3.1.11 Hours, Minutes, Second, and Milliseconds
2027 const double kMsPerSecond = 1000.0;
2028 const double kMsPerMinute = 60000.0;
2029 const double kMsPerHour = 3600000.0;
2030 
2031 
2032 // ES6 section 20.3.1.14 MakeDate (day, time)
MakeDate(double day,double time)2033 double MakeDate(double day, double time) {
2034   if (std::isfinite(day) && std::isfinite(time)) {
2035     return time + day * kMsPerDay;
2036   }
2037   return std::numeric_limits<double>::quiet_NaN();
2038 }
2039 
2040 
2041 // ES6 section 20.3.1.13 MakeDay (year, month, date)
MakeDay(double year,double month,double date)2042 double MakeDay(double year, double month, double date) {
2043   if ((kMinYear <= year && year <= kMaxYear) &&
2044       (kMinMonth <= month && month <= kMaxMonth) && std::isfinite(date)) {
2045     int y = FastD2I(year);
2046     int m = FastD2I(month);
2047     y += m / 12;
2048     m %= 12;
2049     if (m < 0) {
2050       m += 12;
2051       y -= 1;
2052     }
2053     DCHECK_LE(0, m);
2054     DCHECK_LT(m, 12);
2055 
2056     // kYearDelta is an arbitrary number such that:
2057     // a) kYearDelta = -1 (mod 400)
2058     // b) year + kYearDelta > 0 for years in the range defined by
2059     //    ECMA 262 - 15.9.1.1, i.e. upto 100,000,000 days on either side of
2060     //    Jan 1 1970. This is required so that we don't run into integer
2061     //    division of negative numbers.
2062     // c) there shouldn't be an overflow for 32-bit integers in the following
2063     //    operations.
2064     static const int kYearDelta = 399999;
2065     static const int kBaseDay =
2066         365 * (1970 + kYearDelta) + (1970 + kYearDelta) / 4 -
2067         (1970 + kYearDelta) / 100 + (1970 + kYearDelta) / 400;
2068     int day_from_year = 365 * (y + kYearDelta) + (y + kYearDelta) / 4 -
2069                         (y + kYearDelta) / 100 + (y + kYearDelta) / 400 -
2070                         kBaseDay;
2071     if ((y % 4 != 0) || (y % 100 == 0 && y % 400 != 0)) {
2072       static const int kDayFromMonth[] = {0,   31,  59,  90,  120, 151,
2073                                           181, 212, 243, 273, 304, 334};
2074       day_from_year += kDayFromMonth[m];
2075     } else {
2076       static const int kDayFromMonth[] = {0,   31,  60,  91,  121, 152,
2077                                           182, 213, 244, 274, 305, 335};
2078       day_from_year += kDayFromMonth[m];
2079     }
2080     return static_cast<double>(day_from_year - 1) + date;
2081   }
2082   return std::numeric_limits<double>::quiet_NaN();
2083 }
2084 
2085 
2086 // ES6 section 20.3.1.12 MakeTime (hour, min, sec, ms)
MakeTime(double hour,double min,double sec,double ms)2087 double MakeTime(double hour, double min, double sec, double ms) {
2088   if (std::isfinite(hour) && std::isfinite(min) && std::isfinite(sec) &&
2089       std::isfinite(ms)) {
2090     double const h = DoubleToInteger(hour);
2091     double const m = DoubleToInteger(min);
2092     double const s = DoubleToInteger(sec);
2093     double const milli = DoubleToInteger(ms);
2094     return h * kMsPerHour + m * kMsPerMinute + s * kMsPerSecond + milli;
2095   }
2096   return std::numeric_limits<double>::quiet_NaN();
2097 }
2098 
2099 
2100 // ES6 section 20.3.1.15 TimeClip (time)
TimeClip(double time)2101 double TimeClip(double time) {
2102   if (-DateCache::kMaxTimeInMs <= time && time <= DateCache::kMaxTimeInMs) {
2103     return DoubleToInteger(time) + 0.0;
2104   }
2105   return std::numeric_limits<double>::quiet_NaN();
2106 }
2107 
2108 
2109 const char* kShortWeekDays[] = {"Sun", "Mon", "Tue", "Wed",
2110                                 "Thu", "Fri", "Sat"};
2111 const char* kShortMonths[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
2112                               "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
2113 
2114 
2115 // ES6 section 20.3.1.16 Date Time String Format
ParseDateTimeString(Handle<String> str)2116 double ParseDateTimeString(Handle<String> str) {
2117   Isolate* const isolate = str->GetIsolate();
2118   str = String::Flatten(str);
2119   // TODO(bmeurer): Change DateParser to not use the FixedArray.
2120   Handle<FixedArray> tmp =
2121       isolate->factory()->NewFixedArray(DateParser::OUTPUT_SIZE);
2122   DisallowHeapAllocation no_gc;
2123   String::FlatContent str_content = str->GetFlatContent();
2124   bool result;
2125   if (str_content.IsOneByte()) {
2126     result = DateParser::Parse(str_content.ToOneByteVector(), *tmp,
2127                                isolate->unicode_cache());
2128   } else {
2129     result = DateParser::Parse(str_content.ToUC16Vector(), *tmp,
2130                                isolate->unicode_cache());
2131   }
2132   if (!result) return std::numeric_limits<double>::quiet_NaN();
2133   double const day = MakeDay(tmp->get(0)->Number(), tmp->get(1)->Number(),
2134                              tmp->get(2)->Number());
2135   double const time = MakeTime(tmp->get(3)->Number(), tmp->get(4)->Number(),
2136                                tmp->get(5)->Number(), tmp->get(6)->Number());
2137   double date = MakeDate(day, time);
2138   if (tmp->get(7)->IsNull()) {
2139     if (!std::isnan(date)) {
2140       date = isolate->date_cache()->ToUTC(static_cast<int64_t>(date));
2141     }
2142   } else {
2143     date -= tmp->get(7)->Number() * 1000.0;
2144   }
2145   return date;
2146 }
2147 
2148 
2149 enum ToDateStringMode { kDateOnly, kTimeOnly, kDateAndTime };
2150 
2151 
2152 // ES6 section 20.3.4.41.1 ToDateString(tv)
ToDateString(double time_val,Vector<char> str,DateCache * date_cache,ToDateStringMode mode=kDateAndTime)2153 void ToDateString(double time_val, Vector<char> str, DateCache* date_cache,
2154                   ToDateStringMode mode = kDateAndTime) {
2155   if (std::isnan(time_val)) {
2156     SNPrintF(str, "Invalid Date");
2157     return;
2158   }
2159   int64_t time_ms = static_cast<int64_t>(time_val);
2160   int64_t local_time_ms = date_cache->ToLocal(time_ms);
2161   int year, month, day, weekday, hour, min, sec, ms;
2162   date_cache->BreakDownTime(local_time_ms, &year, &month, &day, &weekday, &hour,
2163                             &min, &sec, &ms);
2164   int timezone_offset = -date_cache->TimezoneOffset(time_ms);
2165   int timezone_hour = std::abs(timezone_offset) / 60;
2166   int timezone_min = std::abs(timezone_offset) % 60;
2167   const char* local_timezone = date_cache->LocalTimezone(time_ms);
2168   switch (mode) {
2169     case kDateOnly:
2170       SNPrintF(str, "%s %s %02d %4d", kShortWeekDays[weekday],
2171                kShortMonths[month], day, year);
2172       return;
2173     case kTimeOnly:
2174       SNPrintF(str, "%02d:%02d:%02d GMT%c%02d%02d (%s)", hour, min, sec,
2175                (timezone_offset < 0) ? '-' : '+', timezone_hour, timezone_min,
2176                local_timezone);
2177       return;
2178     case kDateAndTime:
2179       SNPrintF(str, "%s %s %02d %4d %02d:%02d:%02d GMT%c%02d%02d (%s)",
2180                kShortWeekDays[weekday], kShortMonths[month], day, year, hour,
2181                min, sec, (timezone_offset < 0) ? '-' : '+', timezone_hour,
2182                timezone_min, local_timezone);
2183       return;
2184   }
2185   UNREACHABLE();
2186 }
2187 
2188 
SetLocalDateValue(Handle<JSDate> date,double time_val)2189 Object* SetLocalDateValue(Handle<JSDate> date, double time_val) {
2190   if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2191       time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2192     Isolate* const isolate = date->GetIsolate();
2193     time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2194   } else {
2195     time_val = std::numeric_limits<double>::quiet_NaN();
2196   }
2197   return *JSDate::SetValue(date, TimeClip(time_val));
2198 }
2199 
2200 }  // namespace
2201 
2202 
2203 // ES6 section 20.3.2 The Date Constructor for the [[Call]] case.
BUILTIN(DateConstructor)2204 BUILTIN(DateConstructor) {
2205   HandleScope scope(isolate);
2206   double const time_val = JSDate::CurrentTimeValue(isolate);
2207   char buffer[128];
2208   Vector<char> str(buffer, arraysize(buffer));
2209   ToDateString(time_val, str, isolate->date_cache());
2210   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2211 }
2212 
2213 
2214 // ES6 section 20.3.2 The Date Constructor for the [[Construct]] case.
BUILTIN(DateConstructor_ConstructStub)2215 BUILTIN(DateConstructor_ConstructStub) {
2216   HandleScope scope(isolate);
2217   int const argc = args.length() - 1;
2218   Handle<JSFunction> target = args.target();
2219   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
2220   double time_val;
2221   if (argc == 0) {
2222     time_val = JSDate::CurrentTimeValue(isolate);
2223   } else if (argc == 1) {
2224     Handle<Object> value = args.at<Object>(1);
2225     if (value->IsJSDate()) {
2226       time_val = Handle<JSDate>::cast(value)->value()->Number();
2227     } else {
2228       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2229                                          Object::ToPrimitive(value));
2230       if (value->IsString()) {
2231         time_val = ParseDateTimeString(Handle<String>::cast(value));
2232       } else {
2233         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value,
2234                                            Object::ToNumber(value));
2235         time_val = value->Number();
2236       }
2237     }
2238   } else {
2239     Handle<Object> year_object;
2240     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2241                                        Object::ToNumber(args.at<Object>(1)));
2242     Handle<Object> month_object;
2243     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2244                                        Object::ToNumber(args.at<Object>(2)));
2245     double year = year_object->Number();
2246     double month = month_object->Number();
2247     double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2248     if (argc >= 3) {
2249       Handle<Object> date_object;
2250       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date_object,
2251                                          Object::ToNumber(args.at<Object>(3)));
2252       date = date_object->Number();
2253       if (argc >= 4) {
2254         Handle<Object> hours_object;
2255         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2256             isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2257         hours = hours_object->Number();
2258         if (argc >= 5) {
2259           Handle<Object> minutes_object;
2260           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2261               isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2262           minutes = minutes_object->Number();
2263           if (argc >= 6) {
2264             Handle<Object> seconds_object;
2265             ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2266                 isolate, seconds_object, Object::ToNumber(args.at<Object>(6)));
2267             seconds = seconds_object->Number();
2268             if (argc >= 7) {
2269               Handle<Object> ms_object;
2270               ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2271                   isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2272               ms = ms_object->Number();
2273             }
2274           }
2275         }
2276       }
2277     }
2278     if (!std::isnan(year)) {
2279       double const y = DoubleToInteger(year);
2280       if (0.0 <= y && y <= 99) year = 1900 + y;
2281     }
2282     double const day = MakeDay(year, month, date);
2283     double const time = MakeTime(hours, minutes, seconds, ms);
2284     time_val = MakeDate(day, time);
2285     if (time_val >= -DateCache::kMaxTimeBeforeUTCInMs &&
2286         time_val <= DateCache::kMaxTimeBeforeUTCInMs) {
2287       time_val = isolate->date_cache()->ToUTC(static_cast<int64_t>(time_val));
2288     } else {
2289       time_val = std::numeric_limits<double>::quiet_NaN();
2290     }
2291   }
2292   Handle<JSDate> result;
2293   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2294                                      JSDate::New(target, new_target, time_val));
2295   return *result;
2296 }
2297 
2298 
2299 // ES6 section 20.3.3.1 Date.now ( )
BUILTIN(DateNow)2300 BUILTIN(DateNow) {
2301   HandleScope scope(isolate);
2302   return *isolate->factory()->NewNumber(JSDate::CurrentTimeValue(isolate));
2303 }
2304 
2305 
2306 // ES6 section 20.3.3.2 Date.parse ( string )
BUILTIN(DateParse)2307 BUILTIN(DateParse) {
2308   HandleScope scope(isolate);
2309   Handle<String> string;
2310   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2311       isolate, string,
2312       Object::ToString(isolate, args.atOrUndefined(isolate, 1)));
2313   return *isolate->factory()->NewNumber(ParseDateTimeString(string));
2314 }
2315 
2316 
2317 // ES6 section 20.3.3.4 Date.UTC (year,month,date,hours,minutes,seconds,ms)
BUILTIN(DateUTC)2318 BUILTIN(DateUTC) {
2319   HandleScope scope(isolate);
2320   int const argc = args.length() - 1;
2321   double year = std::numeric_limits<double>::quiet_NaN();
2322   double month = std::numeric_limits<double>::quiet_NaN();
2323   double date = 1.0, hours = 0.0, minutes = 0.0, seconds = 0.0, ms = 0.0;
2324   if (argc >= 1) {
2325     Handle<Object> year_object;
2326     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year_object,
2327                                        Object::ToNumber(args.at<Object>(1)));
2328     year = year_object->Number();
2329     if (argc >= 2) {
2330       Handle<Object> month_object;
2331       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month_object,
2332                                          Object::ToNumber(args.at<Object>(2)));
2333       month = month_object->Number();
2334       if (argc >= 3) {
2335         Handle<Object> date_object;
2336         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2337             isolate, date_object, Object::ToNumber(args.at<Object>(3)));
2338         date = date_object->Number();
2339         if (argc >= 4) {
2340           Handle<Object> hours_object;
2341           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2342               isolate, hours_object, Object::ToNumber(args.at<Object>(4)));
2343           hours = hours_object->Number();
2344           if (argc >= 5) {
2345             Handle<Object> minutes_object;
2346             ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2347                 isolate, minutes_object, Object::ToNumber(args.at<Object>(5)));
2348             minutes = minutes_object->Number();
2349             if (argc >= 6) {
2350               Handle<Object> seconds_object;
2351               ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2352                   isolate, seconds_object,
2353                   Object::ToNumber(args.at<Object>(6)));
2354               seconds = seconds_object->Number();
2355               if (argc >= 7) {
2356                 Handle<Object> ms_object;
2357                 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
2358                     isolate, ms_object, Object::ToNumber(args.at<Object>(7)));
2359                 ms = ms_object->Number();
2360               }
2361             }
2362           }
2363         }
2364       }
2365     }
2366   }
2367   if (!std::isnan(year)) {
2368     double const y = DoubleToInteger(year);
2369     if (0.0 <= y && y <= 99) year = 1900 + y;
2370   }
2371   double const day = MakeDay(year, month, date);
2372   double const time = MakeTime(hours, minutes, seconds, ms);
2373   return *isolate->factory()->NewNumber(TimeClip(MakeDate(day, time)));
2374 }
2375 
2376 
2377 // ES6 section 20.3.4.20 Date.prototype.setDate ( date )
BUILTIN(DatePrototypeSetDate)2378 BUILTIN(DatePrototypeSetDate) {
2379   HandleScope scope(isolate);
2380   CHECK_RECEIVER(JSDate, date, "Date.prototype.setDate");
2381   Handle<Object> value = args.atOrUndefined(isolate, 1);
2382   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2383   double time_val = date->value()->Number();
2384   if (!std::isnan(time_val)) {
2385     int64_t const time_ms = static_cast<int64_t>(time_val);
2386     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2387     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2388     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2389     int year, month, day;
2390     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2391     time_val = MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2392   }
2393   return SetLocalDateValue(date, time_val);
2394 }
2395 
2396 
2397 // ES6 section 20.3.4.21 Date.prototype.setFullYear (year, month, date)
BUILTIN(DatePrototypeSetFullYear)2398 BUILTIN(DatePrototypeSetFullYear) {
2399   HandleScope scope(isolate);
2400   CHECK_RECEIVER(JSDate, date, "Date.prototype.setFullYear");
2401   int const argc = args.length() - 1;
2402   Handle<Object> year = args.atOrUndefined(isolate, 1);
2403   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2404   double y = year->Number(), m = 0.0, dt = 1.0;
2405   int time_within_day = 0;
2406   if (!std::isnan(date->value()->Number())) {
2407     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2408     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2409     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2410     time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2411     int year, month, day;
2412     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2413     m = month;
2414     dt = day;
2415   }
2416   if (argc >= 2) {
2417     Handle<Object> month = args.at<Object>(2);
2418     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2419     m = month->Number();
2420     if (argc >= 3) {
2421       Handle<Object> date = args.at<Object>(3);
2422       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2423       dt = date->Number();
2424     }
2425   }
2426   double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2427   return SetLocalDateValue(date, time_val);
2428 }
2429 
2430 
2431 // ES6 section 20.3.4.22 Date.prototype.setHours(hour, min, sec, ms)
BUILTIN(DatePrototypeSetHours)2432 BUILTIN(DatePrototypeSetHours) {
2433   HandleScope scope(isolate);
2434   CHECK_RECEIVER(JSDate, date, "Date.prototype.setHours");
2435   int const argc = args.length() - 1;
2436   Handle<Object> hour = args.atOrUndefined(isolate, 1);
2437   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2438   double h = hour->Number();
2439   double time_val = date->value()->Number();
2440   if (!std::isnan(time_val)) {
2441     int64_t const time_ms = static_cast<int64_t>(time_val);
2442     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2443     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2444     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2445     double m = (time_within_day / (60 * 1000)) % 60;
2446     double s = (time_within_day / 1000) % 60;
2447     double milli = time_within_day % 1000;
2448     if (argc >= 2) {
2449       Handle<Object> min = args.at<Object>(2);
2450       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2451       m = min->Number();
2452       if (argc >= 3) {
2453         Handle<Object> sec = args.at<Object>(3);
2454         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2455         s = sec->Number();
2456         if (argc >= 4) {
2457           Handle<Object> ms = args.at<Object>(4);
2458           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2459           milli = ms->Number();
2460         }
2461       }
2462     }
2463     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2464   }
2465   return SetLocalDateValue(date, time_val);
2466 }
2467 
2468 
2469 // ES6 section 20.3.4.23 Date.prototype.setMilliseconds(ms)
BUILTIN(DatePrototypeSetMilliseconds)2470 BUILTIN(DatePrototypeSetMilliseconds) {
2471   HandleScope scope(isolate);
2472   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMilliseconds");
2473   Handle<Object> ms = args.atOrUndefined(isolate, 1);
2474   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2475   double time_val = date->value()->Number();
2476   if (!std::isnan(time_val)) {
2477     int64_t const time_ms = static_cast<int64_t>(time_val);
2478     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2479     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2480     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2481     int h = time_within_day / (60 * 60 * 1000);
2482     int m = (time_within_day / (60 * 1000)) % 60;
2483     int s = (time_within_day / 1000) % 60;
2484     time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2485   }
2486   return SetLocalDateValue(date, time_val);
2487 }
2488 
2489 
2490 // ES6 section 20.3.4.24 Date.prototype.setMinutes ( min, sec, ms )
BUILTIN(DatePrototypeSetMinutes)2491 BUILTIN(DatePrototypeSetMinutes) {
2492   HandleScope scope(isolate);
2493   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMinutes");
2494   int const argc = args.length() - 1;
2495   Handle<Object> min = args.atOrUndefined(isolate, 1);
2496   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2497   double time_val = date->value()->Number();
2498   if (!std::isnan(time_val)) {
2499     int64_t const time_ms = static_cast<int64_t>(time_val);
2500     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2501     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2502     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2503     int h = time_within_day / (60 * 60 * 1000);
2504     double m = min->Number();
2505     double s = (time_within_day / 1000) % 60;
2506     double milli = time_within_day % 1000;
2507     if (argc >= 2) {
2508       Handle<Object> sec = args.at<Object>(2);
2509       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2510       s = sec->Number();
2511       if (argc >= 3) {
2512         Handle<Object> ms = args.at<Object>(3);
2513         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2514         milli = ms->Number();
2515       }
2516     }
2517     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2518   }
2519   return SetLocalDateValue(date, time_val);
2520 }
2521 
2522 
2523 // ES6 section 20.3.4.25 Date.prototype.setMonth ( month, date )
BUILTIN(DatePrototypeSetMonth)2524 BUILTIN(DatePrototypeSetMonth) {
2525   HandleScope scope(isolate);
2526   CHECK_RECEIVER(JSDate, date, "Date.prototype.setMonth");
2527   int const argc = args.length() - 1;
2528   Handle<Object> month = args.atOrUndefined(isolate, 1);
2529   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2530   double time_val = date->value()->Number();
2531   if (!std::isnan(time_val)) {
2532     int64_t const time_ms = static_cast<int64_t>(time_val);
2533     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2534     int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2535     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2536     int year, unused, day;
2537     isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2538     double m = month->Number();
2539     double dt = day;
2540     if (argc >= 2) {
2541       Handle<Object> date = args.at<Object>(2);
2542       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2543       dt = date->Number();
2544     }
2545     time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
2546   }
2547   return SetLocalDateValue(date, time_val);
2548 }
2549 
2550 
2551 // ES6 section 20.3.4.26 Date.prototype.setSeconds ( sec, ms )
BUILTIN(DatePrototypeSetSeconds)2552 BUILTIN(DatePrototypeSetSeconds) {
2553   HandleScope scope(isolate);
2554   CHECK_RECEIVER(JSDate, date, "Date.prototype.setSeconds");
2555   int const argc = args.length() - 1;
2556   Handle<Object> sec = args.atOrUndefined(isolate, 1);
2557   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2558   double time_val = date->value()->Number();
2559   if (!std::isnan(time_val)) {
2560     int64_t const time_ms = static_cast<int64_t>(time_val);
2561     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2562     int day = isolate->date_cache()->DaysFromTime(local_time_ms);
2563     int time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, day);
2564     int h = time_within_day / (60 * 60 * 1000);
2565     double m = (time_within_day / (60 * 1000)) % 60;
2566     double s = sec->Number();
2567     double milli = time_within_day % 1000;
2568     if (argc >= 2) {
2569       Handle<Object> ms = args.at<Object>(2);
2570       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2571       milli = ms->Number();
2572     }
2573     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2574   }
2575   return SetLocalDateValue(date, time_val);
2576 }
2577 
2578 
2579 // ES6 section 20.3.4.27 Date.prototype.setTime ( time )
BUILTIN(DatePrototypeSetTime)2580 BUILTIN(DatePrototypeSetTime) {
2581   HandleScope scope(isolate);
2582   CHECK_RECEIVER(JSDate, date, "Date.prototype.setTime");
2583   Handle<Object> value = args.atOrUndefined(isolate, 1);
2584   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2585   return *JSDate::SetValue(date, TimeClip(value->Number()));
2586 }
2587 
2588 
2589 // ES6 section 20.3.4.28 Date.prototype.setUTCDate ( date )
BUILTIN(DatePrototypeSetUTCDate)2590 BUILTIN(DatePrototypeSetUTCDate) {
2591   HandleScope scope(isolate);
2592   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCDate");
2593   Handle<Object> value = args.atOrUndefined(isolate, 1);
2594   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, value, Object::ToNumber(value));
2595   if (std::isnan(date->value()->Number())) return date->value();
2596   int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2597   int const days = isolate->date_cache()->DaysFromTime(time_ms);
2598   int const time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2599   int year, month, day;
2600   isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2601   double const time_val =
2602       MakeDate(MakeDay(year, month, value->Number()), time_within_day);
2603   return *JSDate::SetValue(date, TimeClip(time_val));
2604 }
2605 
2606 
2607 // ES6 section 20.3.4.29 Date.prototype.setUTCFullYear (year, month, date)
BUILTIN(DatePrototypeSetUTCFullYear)2608 BUILTIN(DatePrototypeSetUTCFullYear) {
2609   HandleScope scope(isolate);
2610   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCFullYear");
2611   int const argc = args.length() - 1;
2612   Handle<Object> year = args.atOrUndefined(isolate, 1);
2613   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2614   double y = year->Number(), m = 0.0, dt = 1.0;
2615   int time_within_day = 0;
2616   if (!std::isnan(date->value()->Number())) {
2617     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2618     int const days = isolate->date_cache()->DaysFromTime(time_ms);
2619     time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2620     int year, month, day;
2621     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2622     m = month;
2623     dt = day;
2624   }
2625   if (argc >= 2) {
2626     Handle<Object> month = args.at<Object>(2);
2627     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2628     m = month->Number();
2629     if (argc >= 3) {
2630       Handle<Object> date = args.at<Object>(3);
2631       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2632       dt = date->Number();
2633     }
2634   }
2635   double const time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2636   return *JSDate::SetValue(date, TimeClip(time_val));
2637 }
2638 
2639 
2640 // ES6 section 20.3.4.30 Date.prototype.setUTCHours(hour, min, sec, ms)
BUILTIN(DatePrototypeSetUTCHours)2641 BUILTIN(DatePrototypeSetUTCHours) {
2642   HandleScope scope(isolate);
2643   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCHours");
2644   int const argc = args.length() - 1;
2645   Handle<Object> hour = args.atOrUndefined(isolate, 1);
2646   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, hour, Object::ToNumber(hour));
2647   double h = hour->Number();
2648   double time_val = date->value()->Number();
2649   if (!std::isnan(time_val)) {
2650     int64_t const time_ms = static_cast<int64_t>(time_val);
2651     int day = isolate->date_cache()->DaysFromTime(time_ms);
2652     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2653     double m = (time_within_day / (60 * 1000)) % 60;
2654     double s = (time_within_day / 1000) % 60;
2655     double milli = time_within_day % 1000;
2656     if (argc >= 2) {
2657       Handle<Object> min = args.at<Object>(2);
2658       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2659       m = min->Number();
2660       if (argc >= 3) {
2661         Handle<Object> sec = args.at<Object>(3);
2662         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2663         s = sec->Number();
2664         if (argc >= 4) {
2665           Handle<Object> ms = args.at<Object>(4);
2666           ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2667           milli = ms->Number();
2668         }
2669       }
2670     }
2671     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2672   }
2673   return *JSDate::SetValue(date, TimeClip(time_val));
2674 }
2675 
2676 
2677 // ES6 section 20.3.4.31 Date.prototype.setUTCMilliseconds(ms)
BUILTIN(DatePrototypeSetUTCMilliseconds)2678 BUILTIN(DatePrototypeSetUTCMilliseconds) {
2679   HandleScope scope(isolate);
2680   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMilliseconds");
2681   Handle<Object> ms = args.atOrUndefined(isolate, 1);
2682   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2683   double time_val = date->value()->Number();
2684   if (!std::isnan(time_val)) {
2685     int64_t const time_ms = static_cast<int64_t>(time_val);
2686     int day = isolate->date_cache()->DaysFromTime(time_ms);
2687     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2688     int h = time_within_day / (60 * 60 * 1000);
2689     int m = (time_within_day / (60 * 1000)) % 60;
2690     int s = (time_within_day / 1000) % 60;
2691     time_val = MakeDate(day, MakeTime(h, m, s, ms->Number()));
2692   }
2693   return *JSDate::SetValue(date, TimeClip(time_val));
2694 }
2695 
2696 
2697 // ES6 section 20.3.4.32 Date.prototype.setUTCMinutes ( min, sec, ms )
BUILTIN(DatePrototypeSetUTCMinutes)2698 BUILTIN(DatePrototypeSetUTCMinutes) {
2699   HandleScope scope(isolate);
2700   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMinutes");
2701   int const argc = args.length() - 1;
2702   Handle<Object> min = args.atOrUndefined(isolate, 1);
2703   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, min, Object::ToNumber(min));
2704   double time_val = date->value()->Number();
2705   if (!std::isnan(time_val)) {
2706     int64_t const time_ms = static_cast<int64_t>(time_val);
2707     int day = isolate->date_cache()->DaysFromTime(time_ms);
2708     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2709     int h = time_within_day / (60 * 60 * 1000);
2710     double m = min->Number();
2711     double s = (time_within_day / 1000) % 60;
2712     double milli = time_within_day % 1000;
2713     if (argc >= 2) {
2714       Handle<Object> sec = args.at<Object>(2);
2715       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2716       s = sec->Number();
2717       if (argc >= 3) {
2718         Handle<Object> ms = args.at<Object>(3);
2719         ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2720         milli = ms->Number();
2721       }
2722     }
2723     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2724   }
2725   return *JSDate::SetValue(date, TimeClip(time_val));
2726 }
2727 
2728 
2729 // ES6 section 20.3.4.31 Date.prototype.setUTCMonth ( month, date )
BUILTIN(DatePrototypeSetUTCMonth)2730 BUILTIN(DatePrototypeSetUTCMonth) {
2731   HandleScope scope(isolate);
2732   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCMonth");
2733   int const argc = args.length() - 1;
2734   Handle<Object> month = args.atOrUndefined(isolate, 1);
2735   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, month, Object::ToNumber(month));
2736   double time_val = date->value()->Number();
2737   if (!std::isnan(time_val)) {
2738     int64_t const time_ms = static_cast<int64_t>(time_val);
2739     int days = isolate->date_cache()->DaysFromTime(time_ms);
2740     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, days);
2741     int year, unused, day;
2742     isolate->date_cache()->YearMonthDayFromDays(days, &year, &unused, &day);
2743     double m = month->Number();
2744     double dt = day;
2745     if (argc >= 2) {
2746       Handle<Object> date = args.at<Object>(2);
2747       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, date, Object::ToNumber(date));
2748       dt = date->Number();
2749     }
2750     time_val = MakeDate(MakeDay(year, m, dt), time_within_day);
2751   }
2752   return *JSDate::SetValue(date, TimeClip(time_val));
2753 }
2754 
2755 
2756 // ES6 section 20.3.4.34 Date.prototype.setUTCSeconds ( sec, ms )
BUILTIN(DatePrototypeSetUTCSeconds)2757 BUILTIN(DatePrototypeSetUTCSeconds) {
2758   HandleScope scope(isolate);
2759   CHECK_RECEIVER(JSDate, date, "Date.prototype.setUTCSeconds");
2760   int const argc = args.length() - 1;
2761   Handle<Object> sec = args.atOrUndefined(isolate, 1);
2762   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, sec, Object::ToNumber(sec));
2763   double time_val = date->value()->Number();
2764   if (!std::isnan(time_val)) {
2765     int64_t const time_ms = static_cast<int64_t>(time_val);
2766     int day = isolate->date_cache()->DaysFromTime(time_ms);
2767     int time_within_day = isolate->date_cache()->TimeInDay(time_ms, day);
2768     int h = time_within_day / (60 * 60 * 1000);
2769     double m = (time_within_day / (60 * 1000)) % 60;
2770     double s = sec->Number();
2771     double milli = time_within_day % 1000;
2772     if (argc >= 2) {
2773       Handle<Object> ms = args.at<Object>(2);
2774       ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, ms, Object::ToNumber(ms));
2775       milli = ms->Number();
2776     }
2777     time_val = MakeDate(day, MakeTime(h, m, s, milli));
2778   }
2779   return *JSDate::SetValue(date, TimeClip(time_val));
2780 }
2781 
2782 
2783 // ES6 section 20.3.4.35 Date.prototype.toDateString ( )
BUILTIN(DatePrototypeToDateString)2784 BUILTIN(DatePrototypeToDateString) {
2785   HandleScope scope(isolate);
2786   CHECK_RECEIVER(JSDate, date, "Date.prototype.toDateString");
2787   char buffer[128];
2788   Vector<char> str(buffer, arraysize(buffer));
2789   ToDateString(date->value()->Number(), str, isolate->date_cache(), kDateOnly);
2790   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2791 }
2792 
2793 
2794 // ES6 section 20.3.4.36 Date.prototype.toISOString ( )
BUILTIN(DatePrototypeToISOString)2795 BUILTIN(DatePrototypeToISOString) {
2796   HandleScope scope(isolate);
2797   CHECK_RECEIVER(JSDate, date, "Date.prototype.toISOString");
2798   double const time_val = date->value()->Number();
2799   if (std::isnan(time_val)) {
2800     THROW_NEW_ERROR_RETURN_FAILURE(
2801         isolate, NewRangeError(MessageTemplate::kInvalidTimeValue));
2802   }
2803   int64_t const time_ms = static_cast<int64_t>(time_val);
2804   int year, month, day, weekday, hour, min, sec, ms;
2805   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
2806                                        &hour, &min, &sec, &ms);
2807   char buffer[128];
2808   Vector<char> str(buffer, arraysize(buffer));
2809   if (year >= 0 && year <= 9999) {
2810     SNPrintF(str, "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
2811              hour, min, sec, ms);
2812   } else if (year < 0) {
2813     SNPrintF(str, "-%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", -year, month + 1, day,
2814              hour, min, sec, ms);
2815   } else {
2816     SNPrintF(str, "+%06d-%02d-%02dT%02d:%02d:%02d.%03dZ", year, month + 1, day,
2817              hour, min, sec, ms);
2818   }
2819   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2820 }
2821 
2822 
2823 // ES6 section 20.3.4.41 Date.prototype.toString ( )
BUILTIN(DatePrototypeToString)2824 BUILTIN(DatePrototypeToString) {
2825   HandleScope scope(isolate);
2826   CHECK_RECEIVER(JSDate, date, "Date.prototype.toString");
2827   char buffer[128];
2828   Vector<char> str(buffer, arraysize(buffer));
2829   ToDateString(date->value()->Number(), str, isolate->date_cache());
2830   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2831 }
2832 
2833 
2834 // ES6 section 20.3.4.42 Date.prototype.toTimeString ( )
BUILTIN(DatePrototypeToTimeString)2835 BUILTIN(DatePrototypeToTimeString) {
2836   HandleScope scope(isolate);
2837   CHECK_RECEIVER(JSDate, date, "Date.prototype.toTimeString");
2838   char buffer[128];
2839   Vector<char> str(buffer, arraysize(buffer));
2840   ToDateString(date->value()->Number(), str, isolate->date_cache(), kTimeOnly);
2841   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2842 }
2843 
2844 
2845 // ES6 section 20.3.4.43 Date.prototype.toUTCString ( )
BUILTIN(DatePrototypeToUTCString)2846 BUILTIN(DatePrototypeToUTCString) {
2847   HandleScope scope(isolate);
2848   CHECK_RECEIVER(JSDate, date, "Date.prototype.toUTCString");
2849   double const time_val = date->value()->Number();
2850   if (std::isnan(time_val)) {
2851     return *isolate->factory()->NewStringFromAsciiChecked("Invalid Date");
2852   }
2853   char buffer[128];
2854   Vector<char> str(buffer, arraysize(buffer));
2855   int64_t time_ms = static_cast<int64_t>(time_val);
2856   int year, month, day, weekday, hour, min, sec, ms;
2857   isolate->date_cache()->BreakDownTime(time_ms, &year, &month, &day, &weekday,
2858                                        &hour, &min, &sec, &ms);
2859   SNPrintF(str, "%s, %02d %s %4d %02d:%02d:%02d GMT", kShortWeekDays[weekday],
2860            day, kShortMonths[month], year, hour, min, sec);
2861   return *isolate->factory()->NewStringFromAsciiChecked(str.start());
2862 }
2863 
2864 
2865 // ES6 section 20.3.4.44 Date.prototype.valueOf ( )
BUILTIN(DatePrototypeValueOf)2866 BUILTIN(DatePrototypeValueOf) {
2867   HandleScope scope(isolate);
2868   CHECK_RECEIVER(JSDate, date, "Date.prototype.valueOf");
2869   return date->value();
2870 }
2871 
2872 
2873 // ES6 section 20.3.4.45 Date.prototype [ @@toPrimitive ] ( hint )
BUILTIN(DatePrototypeToPrimitive)2874 BUILTIN(DatePrototypeToPrimitive) {
2875   HandleScope scope(isolate);
2876   DCHECK_EQ(2, args.length());
2877   CHECK_RECEIVER(JSReceiver, receiver, "Date.prototype [ @@toPrimitive ]");
2878   Handle<Object> hint = args.at<Object>(1);
2879   Handle<Object> result;
2880   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
2881                                      JSDate::ToPrimitive(receiver, hint));
2882   return *result;
2883 }
2884 
2885 
2886 // ES6 section B.2.4.1 Date.prototype.getYear ( )
BUILTIN(DatePrototypeGetYear)2887 BUILTIN(DatePrototypeGetYear) {
2888   HandleScope scope(isolate);
2889   CHECK_RECEIVER(JSDate, date, "Date.prototype.getYear");
2890   double time_val = date->value()->Number();
2891   if (std::isnan(time_val)) return date->value();
2892   int64_t time_ms = static_cast<int64_t>(time_val);
2893   int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2894   int days = isolate->date_cache()->DaysFromTime(local_time_ms);
2895   int year, month, day;
2896   isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2897   return Smi::FromInt(year - 1900);
2898 }
2899 
2900 
2901 // ES6 section B.2.4.2 Date.prototype.setYear ( year )
BUILTIN(DatePrototypeSetYear)2902 BUILTIN(DatePrototypeSetYear) {
2903   HandleScope scope(isolate);
2904   CHECK_RECEIVER(JSDate, date, "Date.prototype.setYear");
2905   Handle<Object> year = args.atOrUndefined(isolate, 1);
2906   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, year, Object::ToNumber(year));
2907   double m = 0.0, dt = 1.0, y = year->Number();
2908   if (0.0 <= y && y <= 99.0) {
2909     y = 1900.0 + DoubleToInteger(y);
2910   }
2911   int time_within_day = 0;
2912   if (!std::isnan(date->value()->Number())) {
2913     int64_t const time_ms = static_cast<int64_t>(date->value()->Number());
2914     int64_t local_time_ms = isolate->date_cache()->ToLocal(time_ms);
2915     int const days = isolate->date_cache()->DaysFromTime(local_time_ms);
2916     time_within_day = isolate->date_cache()->TimeInDay(local_time_ms, days);
2917     int year, month, day;
2918     isolate->date_cache()->YearMonthDayFromDays(days, &year, &month, &day);
2919     m = month;
2920     dt = day;
2921   }
2922   double time_val = MakeDate(MakeDay(y, m, dt), time_within_day);
2923   return SetLocalDateValue(date, time_val);
2924 }
2925 
2926 
2927 // static
Generate_DatePrototypeGetDate(MacroAssembler * masm)2928 void Builtins::Generate_DatePrototypeGetDate(MacroAssembler* masm) {
2929   Generate_DatePrototype_GetField(masm, JSDate::kDay);
2930 }
2931 
2932 
2933 // static
Generate_DatePrototypeGetDay(MacroAssembler * masm)2934 void Builtins::Generate_DatePrototypeGetDay(MacroAssembler* masm) {
2935   Generate_DatePrototype_GetField(masm, JSDate::kWeekday);
2936 }
2937 
2938 
2939 // static
Generate_DatePrototypeGetFullYear(MacroAssembler * masm)2940 void Builtins::Generate_DatePrototypeGetFullYear(MacroAssembler* masm) {
2941   Generate_DatePrototype_GetField(masm, JSDate::kYear);
2942 }
2943 
2944 
2945 // static
Generate_DatePrototypeGetHours(MacroAssembler * masm)2946 void Builtins::Generate_DatePrototypeGetHours(MacroAssembler* masm) {
2947   Generate_DatePrototype_GetField(masm, JSDate::kHour);
2948 }
2949 
2950 
2951 // static
Generate_DatePrototypeGetMilliseconds(MacroAssembler * masm)2952 void Builtins::Generate_DatePrototypeGetMilliseconds(MacroAssembler* masm) {
2953   Generate_DatePrototype_GetField(masm, JSDate::kMillisecond);
2954 }
2955 
2956 
2957 // static
Generate_DatePrototypeGetMinutes(MacroAssembler * masm)2958 void Builtins::Generate_DatePrototypeGetMinutes(MacroAssembler* masm) {
2959   Generate_DatePrototype_GetField(masm, JSDate::kMinute);
2960 }
2961 
2962 
2963 // static
Generate_DatePrototypeGetMonth(MacroAssembler * masm)2964 void Builtins::Generate_DatePrototypeGetMonth(MacroAssembler* masm) {
2965   Generate_DatePrototype_GetField(masm, JSDate::kMonth);
2966 }
2967 
2968 
2969 // static
Generate_DatePrototypeGetSeconds(MacroAssembler * masm)2970 void Builtins::Generate_DatePrototypeGetSeconds(MacroAssembler* masm) {
2971   Generate_DatePrototype_GetField(masm, JSDate::kSecond);
2972 }
2973 
2974 
2975 // static
Generate_DatePrototypeGetTime(MacroAssembler * masm)2976 void Builtins::Generate_DatePrototypeGetTime(MacroAssembler* masm) {
2977   Generate_DatePrototype_GetField(masm, JSDate::kDateValue);
2978 }
2979 
2980 
2981 // static
Generate_DatePrototypeGetTimezoneOffset(MacroAssembler * masm)2982 void Builtins::Generate_DatePrototypeGetTimezoneOffset(MacroAssembler* masm) {
2983   Generate_DatePrototype_GetField(masm, JSDate::kTimezoneOffset);
2984 }
2985 
2986 
2987 // static
Generate_DatePrototypeGetUTCDate(MacroAssembler * masm)2988 void Builtins::Generate_DatePrototypeGetUTCDate(MacroAssembler* masm) {
2989   Generate_DatePrototype_GetField(masm, JSDate::kDayUTC);
2990 }
2991 
2992 
2993 // static
Generate_DatePrototypeGetUTCDay(MacroAssembler * masm)2994 void Builtins::Generate_DatePrototypeGetUTCDay(MacroAssembler* masm) {
2995   Generate_DatePrototype_GetField(masm, JSDate::kWeekdayUTC);
2996 }
2997 
2998 
2999 // static
Generate_DatePrototypeGetUTCFullYear(MacroAssembler * masm)3000 void Builtins::Generate_DatePrototypeGetUTCFullYear(MacroAssembler* masm) {
3001   Generate_DatePrototype_GetField(masm, JSDate::kYearUTC);
3002 }
3003 
3004 
3005 // static
Generate_DatePrototypeGetUTCHours(MacroAssembler * masm)3006 void Builtins::Generate_DatePrototypeGetUTCHours(MacroAssembler* masm) {
3007   Generate_DatePrototype_GetField(masm, JSDate::kHourUTC);
3008 }
3009 
3010 
3011 // static
Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler * masm)3012 void Builtins::Generate_DatePrototypeGetUTCMilliseconds(MacroAssembler* masm) {
3013   Generate_DatePrototype_GetField(masm, JSDate::kMillisecondUTC);
3014 }
3015 
3016 
3017 // static
Generate_DatePrototypeGetUTCMinutes(MacroAssembler * masm)3018 void Builtins::Generate_DatePrototypeGetUTCMinutes(MacroAssembler* masm) {
3019   Generate_DatePrototype_GetField(masm, JSDate::kMinuteUTC);
3020 }
3021 
3022 
3023 // static
Generate_DatePrototypeGetUTCMonth(MacroAssembler * masm)3024 void Builtins::Generate_DatePrototypeGetUTCMonth(MacroAssembler* masm) {
3025   Generate_DatePrototype_GetField(masm, JSDate::kMonthUTC);
3026 }
3027 
3028 
3029 // static
Generate_DatePrototypeGetUTCSeconds(MacroAssembler * masm)3030 void Builtins::Generate_DatePrototypeGetUTCSeconds(MacroAssembler* masm) {
3031   Generate_DatePrototype_GetField(masm, JSDate::kSecondUTC);
3032 }
3033 
3034 
3035 namespace {
3036 
3037 // ES6 section 19.2.1.1.1 CreateDynamicFunction
CreateDynamicFunction(Isolate * isolate,BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,const char * token)3038 MaybeHandle<JSFunction> CreateDynamicFunction(
3039     Isolate* isolate,
3040     BuiltinArguments<BuiltinExtraArguments::kTargetAndNewTarget> args,
3041     const char* token) {
3042   // Compute number of arguments, ignoring the receiver.
3043   DCHECK_LE(1, args.length());
3044   int const argc = args.length() - 1;
3045 
3046   // Build the source string.
3047   Handle<String> source;
3048   {
3049     IncrementalStringBuilder builder(isolate);
3050     builder.AppendCharacter('(');
3051     builder.AppendCString(token);
3052     builder.AppendCharacter('(');
3053     bool parenthesis_in_arg_string = false;
3054     if (argc > 1) {
3055       for (int i = 1; i < argc; ++i) {
3056         if (i > 1) builder.AppendCharacter(',');
3057         Handle<String> param;
3058         ASSIGN_RETURN_ON_EXCEPTION(
3059             isolate, param, Object::ToString(isolate, args.at<Object>(i)),
3060             JSFunction);
3061         param = String::Flatten(param);
3062         builder.AppendString(param);
3063         // If the formal parameters string include ) - an illegal
3064         // character - it may make the combined function expression
3065         // compile. We avoid this problem by checking for this early on.
3066         DisallowHeapAllocation no_gc;  // Ensure vectors stay valid.
3067         String::FlatContent param_content = param->GetFlatContent();
3068         for (int i = 0, length = param->length(); i < length; ++i) {
3069           if (param_content.Get(i) == ')') {
3070             parenthesis_in_arg_string = true;
3071             break;
3072           }
3073         }
3074       }
3075       // If the formal parameters include an unbalanced block comment, the
3076       // function must be rejected. Since JavaScript does not allow nested
3077       // comments we can include a trailing block comment to catch this.
3078       builder.AppendCString("\n/**/");
3079     }
3080     builder.AppendCString(") {\n");
3081     if (argc > 0) {
3082       Handle<String> body;
3083       ASSIGN_RETURN_ON_EXCEPTION(
3084           isolate, body, Object::ToString(isolate, args.at<Object>(argc)),
3085           JSFunction);
3086       builder.AppendString(body);
3087     }
3088     builder.AppendCString("\n})");
3089     ASSIGN_RETURN_ON_EXCEPTION(isolate, source, builder.Finish(), JSFunction);
3090 
3091     // The SyntaxError must be thrown after all the (observable) ToString
3092     // conversions are done.
3093     if (parenthesis_in_arg_string) {
3094       THROW_NEW_ERROR(isolate,
3095                       NewSyntaxError(MessageTemplate::kParenthesisInArgString),
3096                       JSFunction);
3097     }
3098   }
3099 
3100   // Compile the string in the constructor and not a helper so that errors to
3101   // come from here.
3102   Handle<JSFunction> target = args.target();
3103   Handle<JSObject> target_global_proxy(target->global_proxy(), isolate);
3104   Handle<JSFunction> function;
3105   {
3106     ASSIGN_RETURN_ON_EXCEPTION(
3107         isolate, function,
3108         CompileString(handle(target->native_context(), isolate), source,
3109                       ONLY_SINGLE_FUNCTION_LITERAL),
3110         JSFunction);
3111     Handle<Object> result;
3112     ASSIGN_RETURN_ON_EXCEPTION(
3113         isolate, result,
3114         Execution::Call(isolate, function, target_global_proxy, 0, nullptr),
3115         JSFunction);
3116     function = Handle<JSFunction>::cast(result);
3117     function->shared()->set_name_should_print_as_anonymous(true);
3118   }
3119 
3120   // If new.target is equal to target then the function created
3121   // is already correctly setup and nothing else should be done
3122   // here. But if new.target is not equal to target then we are
3123   // have a Function builtin subclassing case and therefore the
3124   // function has wrong initial map. To fix that we create a new
3125   // function object with correct initial map.
3126   Handle<Object> unchecked_new_target = args.new_target();
3127   if (!unchecked_new_target->IsUndefined() &&
3128       !unchecked_new_target.is_identical_to(target)) {
3129     Handle<JSReceiver> new_target =
3130         Handle<JSReceiver>::cast(unchecked_new_target);
3131     Handle<Map> initial_map;
3132     ASSIGN_RETURN_ON_EXCEPTION(
3133         isolate, initial_map,
3134         JSFunction::GetDerivedMap(isolate, target, new_target), JSFunction);
3135 
3136     Handle<SharedFunctionInfo> shared_info(function->shared(), isolate);
3137     Handle<Map> map = Map::AsLanguageMode(
3138         initial_map, shared_info->language_mode(), shared_info->kind());
3139 
3140     Handle<Context> context(function->context(), isolate);
3141     function = isolate->factory()->NewFunctionFromSharedFunctionInfo(
3142         map, shared_info, context, NOT_TENURED);
3143   }
3144   return function;
3145 }
3146 
3147 }  // namespace
3148 
3149 
3150 // ES6 section 19.2.1.1 Function ( p1, p2, ... , pn, body )
BUILTIN(FunctionConstructor)3151 BUILTIN(FunctionConstructor) {
3152   HandleScope scope(isolate);
3153   Handle<JSFunction> result;
3154   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3155       isolate, result, CreateDynamicFunction(isolate, args, "function"));
3156   return *result;
3157 }
3158 
3159 
3160 // ES6 section 19.2.3.2 Function.prototype.bind ( thisArg, ...args )
BUILTIN(FunctionPrototypeBind)3161 BUILTIN(FunctionPrototypeBind) {
3162   HandleScope scope(isolate);
3163   DCHECK_LE(1, args.length());
3164   if (!args.receiver()->IsCallable()) {
3165     THROW_NEW_ERROR_RETURN_FAILURE(
3166         isolate, NewTypeError(MessageTemplate::kFunctionBind));
3167   }
3168 
3169   // Allocate the bound function with the given {this_arg} and {args}.
3170   Handle<JSReceiver> target = args.at<JSReceiver>(0);
3171   Handle<Object> this_arg = isolate->factory()->undefined_value();
3172   ScopedVector<Handle<Object>> argv(std::max(0, args.length() - 2));
3173   if (args.length() > 1) {
3174     this_arg = args.at<Object>(1);
3175     for (int i = 2; i < args.length(); ++i) {
3176       argv[i - 2] = args.at<Object>(i);
3177     }
3178   }
3179   Handle<JSBoundFunction> function;
3180   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3181       isolate, function,
3182       isolate->factory()->NewJSBoundFunction(target, this_arg, argv));
3183 
3184   // TODO(bmeurer): Optimize the rest for the common cases where {target} is
3185   // a function with some initial map or even a bound function.
3186   // Setup the "length" property based on the "length" of the {target}.
3187   Handle<Object> length(Smi::FromInt(0), isolate);
3188   Maybe<bool> target_has_length =
3189       JSReceiver::HasOwnProperty(target, isolate->factory()->length_string());
3190   if (!target_has_length.IsJust()) {
3191     return isolate->heap()->exception();
3192   } else if (target_has_length.FromJust()) {
3193     Handle<Object> target_length;
3194     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3195         isolate, target_length,
3196         JSReceiver::GetProperty(target, isolate->factory()->length_string()));
3197     if (target_length->IsNumber()) {
3198       length = isolate->factory()->NewNumber(std::max(
3199           0.0, DoubleToInteger(target_length->Number()) - argv.length()));
3200     }
3201   }
3202   function->set_length(*length);
3203 
3204   // Setup the "name" property based on the "name" of the {target}.
3205   Handle<Object> target_name;
3206   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3207       isolate, target_name,
3208       JSReceiver::GetProperty(target, isolate->factory()->name_string()));
3209   Handle<String> name;
3210   if (!target_name->IsString()) {
3211     name = isolate->factory()->bound__string();
3212   } else {
3213     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3214         isolate, name, Name::ToFunctionName(Handle<String>::cast(target_name)));
3215     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3216         isolate, name, isolate->factory()->NewConsString(
3217                            isolate->factory()->bound__string(), name));
3218   }
3219   function->set_name(*name);
3220   return *function;
3221 }
3222 
3223 
3224 // ES6 section 19.2.3.5 Function.prototype.toString ( )
BUILTIN(FunctionPrototypeToString)3225 BUILTIN(FunctionPrototypeToString) {
3226   HandleScope scope(isolate);
3227   Handle<Object> receiver = args.receiver();
3228   if (receiver->IsJSBoundFunction()) {
3229     return *JSBoundFunction::ToString(Handle<JSBoundFunction>::cast(receiver));
3230   } else if (receiver->IsJSFunction()) {
3231     return *JSFunction::ToString(Handle<JSFunction>::cast(receiver));
3232   }
3233   THROW_NEW_ERROR_RETURN_FAILURE(
3234       isolate, NewTypeError(MessageTemplate::kNotGeneric,
3235                             isolate->factory()->NewStringFromAsciiChecked(
3236                                 "Function.prototype.toString")));
3237 }
3238 
3239 
3240 // ES6 section 25.2.1.1 GeneratorFunction (p1, p2, ... , pn, body)
BUILTIN(GeneratorFunctionConstructor)3241 BUILTIN(GeneratorFunctionConstructor) {
3242   HandleScope scope(isolate);
3243   Handle<JSFunction> result;
3244   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3245       isolate, result, CreateDynamicFunction(isolate, args, "function*"));
3246   return *result;
3247 }
3248 
3249 
3250 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Call]] case.
BUILTIN(SymbolConstructor)3251 BUILTIN(SymbolConstructor) {
3252   HandleScope scope(isolate);
3253   Handle<Symbol> result = isolate->factory()->NewSymbol();
3254   Handle<Object> description = args.atOrUndefined(isolate, 1);
3255   if (!description->IsUndefined()) {
3256     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, description,
3257                                        Object::ToString(isolate, description));
3258     result->set_name(*description);
3259   }
3260   return *result;
3261 }
3262 
3263 
3264 // ES6 section 19.4.1.1 Symbol ( [ description ] ) for the [[Construct]] case.
BUILTIN(SymbolConstructor_ConstructStub)3265 BUILTIN(SymbolConstructor_ConstructStub) {
3266   HandleScope scope(isolate);
3267   THROW_NEW_ERROR_RETURN_FAILURE(
3268       isolate, NewTypeError(MessageTemplate::kNotConstructor,
3269                             isolate->factory()->Symbol_string()));
3270 }
3271 
3272 
3273 // ES6 19.1.3.6 Object.prototype.toString
BUILTIN(ObjectProtoToString)3274 BUILTIN(ObjectProtoToString) {
3275   HandleScope scope(isolate);
3276   Handle<Object> object = args.at<Object>(0);
3277   Handle<String> result;
3278   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3279       isolate, result, JSObject::ObjectProtoToString(isolate, object));
3280   return *result;
3281 }
3282 
3283 
3284 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Call]] case.
BUILTIN(ArrayBufferConstructor)3285 BUILTIN(ArrayBufferConstructor) {
3286   HandleScope scope(isolate);
3287   Handle<JSFunction> target = args.target();
3288   DCHECK(*target == target->native_context()->array_buffer_fun() ||
3289          *target == target->native_context()->shared_array_buffer_fun());
3290   THROW_NEW_ERROR_RETURN_FAILURE(
3291       isolate, NewTypeError(MessageTemplate::kConstructorNotFunction,
3292                             handle(target->shared()->name(), isolate)));
3293 }
3294 
3295 
3296 // ES6 section 24.1.2.1 ArrayBuffer ( length ) for the [[Construct]] case.
BUILTIN(ArrayBufferConstructor_ConstructStub)3297 BUILTIN(ArrayBufferConstructor_ConstructStub) {
3298   HandleScope scope(isolate);
3299   Handle<JSFunction> target = args.target();
3300   Handle<JSReceiver> new_target = Handle<JSReceiver>::cast(args.new_target());
3301   Handle<Object> length = args.atOrUndefined(isolate, 1);
3302   DCHECK(*target == target->native_context()->array_buffer_fun() ||
3303          *target == target->native_context()->shared_array_buffer_fun());
3304   Handle<Object> number_length;
3305   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, number_length,
3306                                      Object::ToInteger(isolate, length));
3307   if (number_length->Number() < 0.0) {
3308     THROW_NEW_ERROR_RETURN_FAILURE(
3309         isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3310   }
3311   Handle<Map> initial_map;
3312   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
3313       isolate, initial_map,
3314       JSFunction::GetDerivedMap(isolate, target, new_target));
3315   size_t byte_length;
3316   if (!TryNumberToSize(isolate, *number_length, &byte_length)) {
3317     THROW_NEW_ERROR_RETURN_FAILURE(
3318         isolate, NewRangeError(MessageTemplate::kInvalidArrayBufferLength));
3319   }
3320   Handle<JSArrayBuffer> result = Handle<JSArrayBuffer>::cast(
3321       isolate->factory()->NewJSObjectFromMap(initial_map));
3322   SharedFlag shared_flag =
3323       (*target == target->native_context()->array_buffer_fun())
3324           ? SharedFlag::kNotShared
3325           : SharedFlag::kShared;
3326   if (!JSArrayBuffer::SetupAllocatingData(result, isolate, byte_length, true,
3327                                           shared_flag)) {
3328     THROW_NEW_ERROR_RETURN_FAILURE(
3329         isolate, NewRangeError(MessageTemplate::kArrayBufferAllocationFailed));
3330   }
3331   return *result;
3332 }
3333 
3334 
3335 // ES6 section 24.1.3.1 ArrayBuffer.isView ( arg )
BUILTIN(ArrayBufferIsView)3336 BUILTIN(ArrayBufferIsView) {
3337   SealHandleScope shs(isolate);
3338   DCHECK_EQ(2, args.length());
3339   Object* arg = args[1];
3340   return isolate->heap()->ToBoolean(arg->IsJSArrayBufferView());
3341 }
3342 
3343 
3344 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Call]] case.
BUILTIN(ProxyConstructor)3345 BUILTIN(ProxyConstructor) {
3346   HandleScope scope(isolate);
3347   THROW_NEW_ERROR_RETURN_FAILURE(
3348       isolate,
3349       NewTypeError(MessageTemplate::kConstructorNotFunction,
3350                    isolate->factory()->NewStringFromAsciiChecked("Proxy")));
3351 }
3352 
3353 
3354 // ES6 section 26.2.1.1 Proxy ( target, handler ) for the [[Construct]] case.
BUILTIN(ProxyConstructor_ConstructStub)3355 BUILTIN(ProxyConstructor_ConstructStub) {
3356   HandleScope scope(isolate);
3357   DCHECK(isolate->proxy_function()->IsConstructor());
3358   Handle<Object> target = args.atOrUndefined(isolate, 1);
3359   Handle<Object> handler = args.atOrUndefined(isolate, 2);
3360   Handle<JSProxy> result;
3361   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3362                                      JSProxy::New(isolate, target, handler));
3363   return *result;
3364 }
3365 
3366 
3367 // -----------------------------------------------------------------------------
3368 // Throwers for restricted function properties and strict arguments object
3369 // properties
3370 
3371 
BUILTIN(RestrictedFunctionPropertiesThrower)3372 BUILTIN(RestrictedFunctionPropertiesThrower) {
3373   HandleScope scope(isolate);
3374   THROW_NEW_ERROR_RETURN_FAILURE(
3375       isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
3376 }
3377 
3378 
BUILTIN(RestrictedStrictArgumentsPropertiesThrower)3379 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
3380   HandleScope scope(isolate);
3381   THROW_NEW_ERROR_RETURN_FAILURE(
3382       isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
3383 }
3384 
3385 
3386 // -----------------------------------------------------------------------------
3387 //
3388 
3389 
3390 namespace {
3391 
3392 template <bool is_construct>
HandleApiCallHelper(Isolate * isolate,BuiltinArguments<BuiltinExtraArguments::kTarget> args)3393 MUST_USE_RESULT MaybeHandle<Object> HandleApiCallHelper(
3394     Isolate* isolate, BuiltinArguments<BuiltinExtraArguments::kTarget> args) {
3395   HandleScope scope(isolate);
3396   Handle<JSFunction> function = args.target();
3397   DCHECK(args.receiver()->IsJSReceiver());
3398   // TODO(ishell): turn this back to a DCHECK.
3399   CHECK(function->shared()->IsApiFunction());
3400 
3401   Handle<FunctionTemplateInfo> fun_data(
3402       function->shared()->get_api_func_data(), isolate);
3403   if (is_construct) {
3404     ASSIGN_RETURN_ON_EXCEPTION(
3405         isolate, fun_data,
3406         ApiNatives::ConfigureInstance(isolate, fun_data,
3407                                       Handle<JSObject>::cast(args.receiver())),
3408         Object);
3409   }
3410 
3411   if (!is_construct && !fun_data->accept_any_receiver()) {
3412     Handle<JSReceiver> receiver = args.at<JSReceiver>(0);
3413     if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
3414       Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
3415       if (!isolate->MayAccess(handle(isolate->context()), js_receiver)) {
3416         isolate->ReportFailedAccessCheck(js_receiver);
3417         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3418       }
3419     }
3420   }
3421 
3422   Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]);
3423 
3424   if (raw_holder->IsNull()) {
3425     // This function cannot be called with the given receiver.  Abort!
3426     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
3427                     Object);
3428   }
3429 
3430   Object* raw_call_data = fun_data->call_code();
3431   if (!raw_call_data->IsUndefined()) {
3432     // TODO(ishell): remove this debugging code.
3433     CHECK(raw_call_data->IsCallHandlerInfo());
3434     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
3435     Object* callback_obj = call_data->callback();
3436     v8::FunctionCallback callback =
3437         v8::ToCData<v8::FunctionCallback>(callback_obj);
3438     Object* data_obj = call_data->data();
3439 
3440     LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
3441     DCHECK(raw_holder->IsJSObject());
3442 
3443     FunctionCallbackArguments custom(isolate,
3444                                      data_obj,
3445                                      *function,
3446                                      raw_holder,
3447                                      &args[0] - 1,
3448                                      args.length() - 1,
3449                                      is_construct);
3450 
3451     v8::Local<v8::Value> value = custom.Call(callback);
3452     Handle<Object> result;
3453     if (value.IsEmpty()) {
3454       result = isolate->factory()->undefined_value();
3455     } else {
3456       result = v8::Utils::OpenHandle(*value);
3457       result->VerifyApiCallResultType();
3458     }
3459 
3460     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
3461     if (!is_construct || result->IsJSObject()) {
3462       return scope.CloseAndEscape(result);
3463     }
3464   }
3465 
3466   return scope.CloseAndEscape(args.receiver());
3467 }
3468 
3469 }  // namespace
3470 
3471 
BUILTIN(HandleApiCall)3472 BUILTIN(HandleApiCall) {
3473   HandleScope scope(isolate);
3474   Handle<Object> result;
3475   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3476                                      HandleApiCallHelper<false>(isolate, args));
3477   return *result;
3478 }
3479 
3480 
BUILTIN(HandleApiCallConstruct)3481 BUILTIN(HandleApiCallConstruct) {
3482   HandleScope scope(isolate);
3483   Handle<Object> result;
3484   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
3485                                      HandleApiCallHelper<true>(isolate, args));
3486   return *result;
3487 }
3488 
3489 
CallFunction(ConvertReceiverMode mode)3490 Handle<Code> Builtins::CallFunction(ConvertReceiverMode mode) {
3491   switch (mode) {
3492     case ConvertReceiverMode::kNullOrUndefined:
3493       return CallFunction_ReceiverIsNullOrUndefined();
3494     case ConvertReceiverMode::kNotNullOrUndefined:
3495       return CallFunction_ReceiverIsNotNullOrUndefined();
3496     case ConvertReceiverMode::kAny:
3497       return CallFunction_ReceiverIsAny();
3498   }
3499   UNREACHABLE();
3500   return Handle<Code>::null();
3501 }
3502 
3503 
Call(ConvertReceiverMode mode)3504 Handle<Code> Builtins::Call(ConvertReceiverMode mode) {
3505   switch (mode) {
3506     case ConvertReceiverMode::kNullOrUndefined:
3507       return Call_ReceiverIsNullOrUndefined();
3508     case ConvertReceiverMode::kNotNullOrUndefined:
3509       return Call_ReceiverIsNotNullOrUndefined();
3510     case ConvertReceiverMode::kAny:
3511       return Call_ReceiverIsAny();
3512   }
3513   UNREACHABLE();
3514   return Handle<Code>::null();
3515 }
3516 
3517 
3518 namespace {
3519 
3520 class RelocatableArguments
3521     : public BuiltinArguments<BuiltinExtraArguments::kTarget>,
3522       public Relocatable {
3523  public:
RelocatableArguments(Isolate * isolate,int length,Object ** arguments)3524   RelocatableArguments(Isolate* isolate, int length, Object** arguments)
3525       : BuiltinArguments<BuiltinExtraArguments::kTarget>(length, arguments),
3526         Relocatable(isolate) {}
3527 
IterateInstance(ObjectVisitor * v)3528   virtual inline void IterateInstance(ObjectVisitor* v) {
3529     if (length() == 0) return;
3530     v->VisitPointers(lowest_address(), highest_address() + 1);
3531   }
3532 
3533  private:
3534   DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
3535 };
3536 
3537 }  // namespace
3538 
3539 
InvokeApiFunction(Handle<JSFunction> function,Handle<Object> receiver,int argc,Handle<Object> args[])3540 MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function,
3541                                                 Handle<Object> receiver,
3542                                                 int argc,
3543                                                 Handle<Object> args[]) {
3544   // Construct BuiltinArguments object: function, arguments reversed, receiver.
3545   const int kBufferSize = 32;
3546   Object* small_argv[kBufferSize];
3547   Object** argv;
3548   if (argc + 2 <= kBufferSize) {
3549     argv = small_argv;
3550   } else {
3551     argv = new Object* [argc + 2];
3552   }
3553   argv[argc + 1] = *receiver;
3554   for (int i = 0; i < argc; ++i) {
3555     argv[argc - i] = *args[i];
3556   }
3557   argv[0] = *function;
3558   MaybeHandle<Object> result;
3559   {
3560     auto isolate = function->GetIsolate();
3561     RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
3562     result = HandleApiCallHelper<false>(isolate, arguments);
3563   }
3564   if (argv != small_argv) {
3565     delete[] argv;
3566   }
3567   return result;
3568 }
3569 
3570 
3571 // Helper function to handle calls to non-function objects created through the
3572 // API. The object can be called as either a constructor (using new) or just as
3573 // a function (without new).
HandleApiCallAsFunctionOrConstructor(Isolate * isolate,bool is_construct_call,BuiltinArguments<BuiltinExtraArguments::kNone> args)3574 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
3575     Isolate* isolate, bool is_construct_call,
3576     BuiltinArguments<BuiltinExtraArguments::kNone> args) {
3577   Heap* heap = isolate->heap();
3578 
3579   Handle<Object> receiver = args.receiver();
3580 
3581   // Get the object called.
3582   JSObject* obj = JSObject::cast(*receiver);
3583 
3584   // Get the invocation callback from the function descriptor that was
3585   // used to create the called object.
3586   DCHECK(obj->map()->is_callable());
3587   JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
3588   // TODO(ishell): turn this back to a DCHECK.
3589   CHECK(constructor->shared()->IsApiFunction());
3590   Object* handler =
3591       constructor->shared()->get_api_func_data()->instance_call_handler();
3592   DCHECK(!handler->IsUndefined());
3593   // TODO(ishell): remove this debugging code.
3594   CHECK(handler->IsCallHandlerInfo());
3595   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
3596   Object* callback_obj = call_data->callback();
3597   v8::FunctionCallback callback =
3598       v8::ToCData<v8::FunctionCallback>(callback_obj);
3599 
3600   // Get the data for the call and perform the callback.
3601   Object* result;
3602   {
3603     HandleScope scope(isolate);
3604     LOG(isolate, ApiObjectAccess("call non-function", obj));
3605 
3606     FunctionCallbackArguments custom(isolate,
3607                                      call_data->data(),
3608                                      constructor,
3609                                      obj,
3610                                      &args[0] - 1,
3611                                      args.length() - 1,
3612                                      is_construct_call);
3613     v8::Local<v8::Value> value = custom.Call(callback);
3614     if (value.IsEmpty()) {
3615       result = heap->undefined_value();
3616     } else {
3617       result = *reinterpret_cast<Object**>(*value);
3618       result->VerifyApiCallResultType();
3619     }
3620   }
3621   // Check for exceptions and return result.
3622   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
3623   return result;
3624 }
3625 
3626 
3627 // Handle calls to non-function objects created through the API. This delegate
3628 // function is used when the call is a normal function call.
BUILTIN(HandleApiCallAsFunction)3629 BUILTIN(HandleApiCallAsFunction) {
3630   return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
3631 }
3632 
3633 
3634 // Handle calls to non-function objects created through the API. This delegate
3635 // function is used when the call is a construct call.
BUILTIN(HandleApiCallAsConstructor)3636 BUILTIN(HandleApiCallAsConstructor) {
3637   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
3638 }
3639 
3640 
Generate_LoadIC_Miss(MacroAssembler * masm)3641 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
3642   LoadIC::GenerateMiss(masm);
3643 }
3644 
3645 
Generate_LoadIC_Normal(MacroAssembler * masm)3646 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
3647   LoadIC::GenerateNormal(masm, SLOPPY);
3648 }
3649 
3650 
Generate_LoadIC_Normal_Strong(MacroAssembler * masm)3651 static void Generate_LoadIC_Normal_Strong(MacroAssembler* masm) {
3652   LoadIC::GenerateNormal(masm, STRONG);
3653 }
3654 
3655 
Generate_LoadIC_Getter_ForDeopt(MacroAssembler * masm)3656 static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
3657   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
3658 }
3659 
3660 
Generate_LoadIC_Slow(MacroAssembler * masm)3661 static void Generate_LoadIC_Slow(MacroAssembler* masm) {
3662   LoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
3663 }
3664 
3665 
Generate_LoadIC_Slow_Strong(MacroAssembler * masm)3666 static void Generate_LoadIC_Slow_Strong(MacroAssembler* masm) {
3667   LoadIC::GenerateRuntimeGetProperty(masm, STRONG);
3668 }
3669 
3670 
Generate_KeyedLoadIC_Slow(MacroAssembler * masm)3671 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
3672   KeyedLoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
3673 }
3674 
3675 
Generate_KeyedLoadIC_Slow_Strong(MacroAssembler * masm)3676 static void Generate_KeyedLoadIC_Slow_Strong(MacroAssembler* masm) {
3677   KeyedLoadIC::GenerateRuntimeGetProperty(masm, STRONG);
3678 }
3679 
3680 
Generate_KeyedLoadIC_Miss(MacroAssembler * masm)3681 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
3682   KeyedLoadIC::GenerateMiss(masm);
3683 }
3684 
3685 
Generate_KeyedLoadIC_Megamorphic(MacroAssembler * masm)3686 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
3687   KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
3688 }
3689 
3690 
Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler * masm)3691 static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
3692   KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
3693 }
3694 
3695 
Generate_StoreIC_Miss(MacroAssembler * masm)3696 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
3697   StoreIC::GenerateMiss(masm);
3698 }
3699 
3700 
Generate_StoreIC_Normal(MacroAssembler * masm)3701 static void Generate_StoreIC_Normal(MacroAssembler* masm) {
3702   StoreIC::GenerateNormal(masm);
3703 }
3704 
3705 
Generate_StoreIC_Slow(MacroAssembler * masm)3706 static void Generate_StoreIC_Slow(MacroAssembler* masm) {
3707   NamedStoreHandlerCompiler::GenerateSlow(masm);
3708 }
3709 
3710 
Generate_KeyedStoreIC_Slow(MacroAssembler * masm)3711 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
3712   ElementHandlerCompiler::GenerateStoreSlow(masm);
3713 }
3714 
3715 
Generate_StoreIC_Setter_ForDeopt(MacroAssembler * masm)3716 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
3717   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
3718 }
3719 
3720 
Generate_KeyedStoreIC_Megamorphic(MacroAssembler * masm)3721 static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
3722   KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
3723 }
3724 
3725 
Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler * masm)3726 static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
3727   KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
3728 }
3729 
3730 
Generate_KeyedStoreIC_Miss(MacroAssembler * masm)3731 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
3732   KeyedStoreIC::GenerateMiss(masm);
3733 }
3734 
3735 
Generate_KeyedStoreIC_Initialize(MacroAssembler * masm)3736 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
3737   KeyedStoreIC::GenerateInitialize(masm);
3738 }
3739 
3740 
Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler * masm)3741 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
3742   KeyedStoreIC::GenerateInitialize(masm);
3743 }
3744 
3745 
Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler * masm)3746 static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
3747   KeyedStoreIC::GeneratePreMonomorphic(masm);
3748 }
3749 
3750 
Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler * masm)3751 static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
3752   KeyedStoreIC::GeneratePreMonomorphic(masm);
3753 }
3754 
3755 
Generate_Return_DebugBreak(MacroAssembler * masm)3756 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
3757   DebugCodegen::GenerateDebugBreakStub(masm,
3758                                        DebugCodegen::SAVE_RESULT_REGISTER);
3759 }
3760 
3761 
Generate_Slot_DebugBreak(MacroAssembler * masm)3762 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
3763   DebugCodegen::GenerateDebugBreakStub(masm,
3764                                        DebugCodegen::IGNORE_RESULT_REGISTER);
3765 }
3766 
3767 
Generate_FrameDropper_LiveEdit(MacroAssembler * masm)3768 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
3769   DebugCodegen::GenerateFrameDropperLiveEdit(masm);
3770 }
3771 
3772 
Builtins()3773 Builtins::Builtins() : initialized_(false) {
3774   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
3775   memset(names_, 0, sizeof(names_[0]) * builtin_count);
3776 }
3777 
3778 
~Builtins()3779 Builtins::~Builtins() {
3780 }
3781 
3782 
3783 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
3784 Address const Builtins::c_functions_[cfunction_count] = {
3785   BUILTIN_LIST_C(DEF_ENUM_C)
3786 };
3787 #undef DEF_ENUM_C
3788 
3789 
3790 struct BuiltinDesc {
3791   byte* generator;
3792   byte* c_code;
3793   const char* s_name;  // name is only used for generating log information.
3794   int name;
3795   Code::Flags flags;
3796   BuiltinExtraArguments extra_args;
3797 };
3798 
3799 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
3800 
3801 class BuiltinFunctionTable {
3802  public:
functions()3803   BuiltinDesc* functions() {
3804     base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
3805     return functions_;
3806   }
3807 
3808   base::OnceType once_;
3809   BuiltinDesc functions_[Builtins::builtin_count + 1];
3810 
3811   friend class Builtins;
3812 };
3813 
3814 static BuiltinFunctionTable builtin_function_table =
3815     BUILTIN_FUNCTION_TABLE_INIT;
3816 
3817 // Define array of pointers to generators and C builtin functions.
3818 // We do this in a sort of roundabout way so that we can do the initialization
3819 // within the lexical scope of Builtins:: and within a context where
3820 // Code::Flags names a non-abstract type.
InitBuiltinFunctionTable()3821 void Builtins::InitBuiltinFunctionTable() {
3822   BuiltinDesc* functions = builtin_function_table.functions_;
3823   functions[builtin_count].generator = NULL;
3824   functions[builtin_count].c_code = NULL;
3825   functions[builtin_count].s_name = NULL;
3826   functions[builtin_count].name = builtin_count;
3827   functions[builtin_count].flags = static_cast<Code::Flags>(0);
3828   functions[builtin_count].extra_args = BuiltinExtraArguments::kNone;
3829 
3830 #define DEF_FUNCTION_PTR_C(aname, aextra_args)                \
3831   functions->generator = FUNCTION_ADDR(Generate_Adaptor);     \
3832   functions->c_code = FUNCTION_ADDR(Builtin_##aname);         \
3833   functions->s_name = #aname;                                 \
3834   functions->name = c_##aname;                                \
3835   functions->flags = Code::ComputeFlags(Code::BUILTIN);       \
3836   functions->extra_args = BuiltinExtraArguments::aextra_args; \
3837   ++functions;
3838 
3839 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra)              \
3840   functions->generator = FUNCTION_ADDR(Generate_##aname);          \
3841   functions->c_code = NULL;                                        \
3842   functions->s_name = #aname;                                      \
3843   functions->name = k##aname;                                      \
3844   functions->flags = Code::ComputeFlags(Code::kind, state, extra); \
3845   functions->extra_args = BuiltinExtraArguments::kNone;            \
3846   ++functions;
3847 
3848 #define DEF_FUNCTION_PTR_H(aname, kind)                     \
3849   functions->generator = FUNCTION_ADDR(Generate_##aname);   \
3850   functions->c_code = NULL;                                 \
3851   functions->s_name = #aname;                               \
3852   functions->name = k##aname;                               \
3853   functions->flags = Code::ComputeHandlerFlags(Code::kind); \
3854   functions->extra_args = BuiltinExtraArguments::kNone;     \
3855   ++functions;
3856 
3857   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
3858   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
3859   BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
3860   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
3861 
3862 #undef DEF_FUNCTION_PTR_C
3863 #undef DEF_FUNCTION_PTR_A
3864 }
3865 
3866 
SetUp(Isolate * isolate,bool create_heap_objects)3867 void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
3868   DCHECK(!initialized_);
3869 
3870   // Create a scope for the handles in the builtins.
3871   HandleScope scope(isolate);
3872 
3873   const BuiltinDesc* functions = builtin_function_table.functions();
3874 
3875   // For now we generate builtin adaptor code into a stack-allocated
3876   // buffer, before copying it into individual code objects. Be careful
3877   // with alignment, some platforms don't like unaligned code.
3878 #ifdef DEBUG
3879   // We can generate a lot of debug code on Arm64.
3880   const size_t buffer_size = 32*KB;
3881 #elif V8_TARGET_ARCH_PPC64
3882   // 8 KB is insufficient on PPC64 when FLAG_debug_code is on.
3883   const size_t buffer_size = 10 * KB;
3884 #else
3885   const size_t buffer_size = 8*KB;
3886 #endif
3887   union { int force_alignment; byte buffer[buffer_size]; } u;
3888 
3889   // Traverse the list of builtins and generate an adaptor in a
3890   // separate code object for each one.
3891   for (int i = 0; i < builtin_count; i++) {
3892     if (create_heap_objects) {
3893       MacroAssembler masm(isolate, u.buffer, sizeof u.buffer,
3894                           CodeObjectRequired::kYes);
3895       // Generate the code/adaptor.
3896       typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
3897       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
3898       // We pass all arguments to the generator, but it may not use all of
3899       // them.  This works because the first arguments are on top of the
3900       // stack.
3901       DCHECK(!masm.has_frame());
3902       g(&masm, functions[i].name, functions[i].extra_args);
3903       // Move the code into the object heap.
3904       CodeDesc desc;
3905       masm.GetCode(&desc);
3906       Code::Flags flags = functions[i].flags;
3907       Handle<Code> code =
3908           isolate->factory()->NewCode(desc, flags, masm.CodeObject());
3909       // Log the event and add the code to the builtins array.
3910       PROFILE(isolate,
3911               CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
3912       builtins_[i] = *code;
3913       code->set_builtin_index(i);
3914 #ifdef ENABLE_DISASSEMBLER
3915       if (FLAG_print_builtin_code) {
3916         CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
3917         OFStream os(trace_scope.file());
3918         os << "Builtin: " << functions[i].s_name << "\n";
3919         code->Disassemble(functions[i].s_name, os);
3920         os << "\n";
3921       }
3922 #endif
3923     } else {
3924       // Deserializing. The values will be filled in during IterateBuiltins.
3925       builtins_[i] = NULL;
3926     }
3927     names_[i] = functions[i].s_name;
3928   }
3929 
3930   // Mark as initialized.
3931   initialized_ = true;
3932 }
3933 
3934 
TearDown()3935 void Builtins::TearDown() {
3936   initialized_ = false;
3937 }
3938 
3939 
IterateBuiltins(ObjectVisitor * v)3940 void Builtins::IterateBuiltins(ObjectVisitor* v) {
3941   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
3942 }
3943 
3944 
Lookup(byte * pc)3945 const char* Builtins::Lookup(byte* pc) {
3946   // may be called during initialization (disassembler!)
3947   if (initialized_) {
3948     for (int i = 0; i < builtin_count; i++) {
3949       Code* entry = Code::cast(builtins_[i]);
3950       if (entry->contains(pc)) {
3951         return names_[i];
3952       }
3953     }
3954   }
3955   return NULL;
3956 }
3957 
3958 
Generate_InterruptCheck(MacroAssembler * masm)3959 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
3960   masm->TailCallRuntime(Runtime::kInterrupt);
3961 }
3962 
3963 
Generate_StackCheck(MacroAssembler * masm)3964 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
3965   masm->TailCallRuntime(Runtime::kStackGuard);
3966 }
3967 
3968 
3969 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
3970 Handle<Code> Builtins::name() {                               \
3971   Code** code_address =                                       \
3972       reinterpret_cast<Code**>(builtin_address(k##name));     \
3973   return Handle<Code>(code_address);                          \
3974 }
3975 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
3976 Handle<Code> Builtins::name() {                             \
3977   Code** code_address =                                     \
3978       reinterpret_cast<Code**>(builtin_address(k##name));   \
3979   return Handle<Code>(code_address);                        \
3980 }
3981 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind)               \
3982 Handle<Code> Builtins::name() {                             \
3983   Code** code_address =                                     \
3984       reinterpret_cast<Code**>(builtin_address(k##name));   \
3985   return Handle<Code>(code_address);                        \
3986 }
3987 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
3988 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
3989 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
3990 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
3991 #undef DEFINE_BUILTIN_ACCESSOR_C
3992 #undef DEFINE_BUILTIN_ACCESSOR_A
3993 
3994 
3995 }  // namespace internal
3996 }  // namespace v8
3997