7ac60da66a8c579b5c620accbe9981bda99d961d
[platform/upstream/v8.git] / src / builtins.cc
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/v8.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/builtins.h"
13 #include "src/cpu-profiler.h"
14 #include "src/gdb-jit.h"
15 #include "src/heap/mark-compact.h"
16 #include "src/heap-profiler.h"
17 #include "src/ic/handler-compiler.h"
18 #include "src/ic/ic.h"
19 #include "src/messages.h"
20 #include "src/prototype.h"
21 #include "src/vm-state-inl.h"
22
23 namespace v8 {
24 namespace internal {
25
26 namespace {
27
28 // Arguments object passed to C++ builtins.
29 template <BuiltinExtraArguments extra_args>
30 class BuiltinArguments : public Arguments {
31  public:
32   BuiltinArguments(int length, Object** arguments)
33       : Arguments(length, arguments) { }
34
35   Object*& operator[] (int index) {
36     DCHECK(index < length());
37     return Arguments::operator[](index);
38   }
39
40   template <class S> Handle<S> at(int index) {
41     DCHECK(index < length());
42     return Arguments::at<S>(index);
43   }
44
45   Handle<Object> receiver() {
46     return Arguments::at<Object>(0);
47   }
48
49   Handle<JSFunction> called_function() {
50     STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
51     return Arguments::at<JSFunction>(Arguments::length() - 1);
52   }
53
54   // Gets the total number of arguments including the receiver (but
55   // excluding extra arguments).
56   int length() const {
57     STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
58     return Arguments::length();
59   }
60
61 #ifdef DEBUG
62   void Verify() {
63     // Check we have at least the receiver.
64     DCHECK(Arguments::length() >= 1);
65   }
66 #endif
67 };
68
69
70 // Specialize BuiltinArguments for the called function extra argument.
71
72 template <>
73 int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
74   return Arguments::length() - 1;
75 }
76
77 #ifdef DEBUG
78 template <>
79 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
80   // Check we have at least the receiver and the called function.
81   DCHECK(Arguments::length() >= 2);
82   // Make sure cast to JSFunction succeeds.
83   called_function();
84 }
85 #endif
86
87
88 #define DEF_ARG_TYPE(name, spec)                      \
89   typedef BuiltinArguments<spec> name##ArgumentsType;
90 BUILTIN_LIST_C(DEF_ARG_TYPE)
91 #undef DEF_ARG_TYPE
92
93 }  // namespace
94
95 // ----------------------------------------------------------------------------
96 // Support macro for defining builtins in C++.
97 // ----------------------------------------------------------------------------
98 //
99 // A builtin function is defined by writing:
100 //
101 //   BUILTIN(name) {
102 //     ...
103 //   }
104 //
105 // In the body of the builtin function the arguments can be accessed
106 // through the BuiltinArguments object args.
107
108 #ifdef DEBUG
109
110 #define BUILTIN(name)                                            \
111   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
112       name##ArgumentsType args, Isolate* isolate);               \
113   MUST_USE_RESULT static Object* Builtin_##name(                 \
114       int args_length, Object** args_object, Isolate* isolate) { \
115     name##ArgumentsType args(args_length, args_object);          \
116     args.Verify();                                               \
117     return Builtin_Impl_##name(args, isolate);                   \
118   }                                                              \
119   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
120       name##ArgumentsType args, Isolate* isolate)
121
122 #else  // For release mode.
123
124 #define BUILTIN(name)                                            \
125   static Object* Builtin_impl##name(                             \
126       name##ArgumentsType args, Isolate* isolate);               \
127   static Object* Builtin_##name(                                 \
128       int args_length, Object** args_object, Isolate* isolate) { \
129     name##ArgumentsType args(args_length, args_object);          \
130     return Builtin_impl##name(args, isolate);                    \
131   }                                                              \
132   static Object* Builtin_impl##name(                             \
133       name##ArgumentsType args, Isolate* isolate)
134 #endif
135
136
137 #ifdef DEBUG
138 static inline bool CalledAsConstructor(Isolate* isolate) {
139   // Calculate the result using a full stack frame iterator and check
140   // that the state of the stack is as we assume it to be in the
141   // code below.
142   StackFrameIterator it(isolate);
143   DCHECK(it.frame()->is_exit());
144   it.Advance();
145   StackFrame* frame = it.frame();
146   bool reference_result = frame->is_construct();
147   Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
148   // Because we know fp points to an exit frame we can use the relevant
149   // part of ExitFrame::ComputeCallerState directly.
150   const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
151   Address caller_fp = Memory::Address_at(fp + kCallerOffset);
152   // This inlines the part of StackFrame::ComputeType that grabs the
153   // type of the current frame.  Note that StackFrame::ComputeType
154   // has been specialized for each architecture so if any one of them
155   // changes this code has to be changed as well.
156   const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
157   const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
158   Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
159   bool result = (marker == kConstructMarker);
160   DCHECK_EQ(result, reference_result);
161   return result;
162 }
163 #endif
164
165
166 // ----------------------------------------------------------------------------
167
168 BUILTIN(Illegal) {
169   UNREACHABLE();
170   return isolate->heap()->undefined_value();  // Make compiler happy.
171 }
172
173
174 BUILTIN(EmptyFunction) {
175   return isolate->heap()->undefined_value();
176 }
177
178
179 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index,
180                                FixedDoubleArray* src, int src_index, int len) {
181   if (len == 0) return;
182   MemMove(dst->data_start() + dst_index, src->data_start() + src_index,
183           len * kDoubleSize);
184 }
185
186
187 static bool ArrayPrototypeHasNoElements(Heap* heap, PrototypeIterator* iter) {
188   DisallowHeapAllocation no_gc;
189   for (; !iter->IsAtEnd(); iter->Advance()) {
190     if (iter->GetCurrent()->IsJSProxy()) return false;
191     if (JSObject::cast(iter->GetCurrent())->elements() !=
192         heap->empty_fixed_array()) {
193       return false;
194     }
195   }
196   return true;
197 }
198
199
200 static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
201                                                      JSArray* receiver) {
202   DisallowHeapAllocation no_gc;
203   Isolate* isolate = heap->isolate();
204   if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
205     return false;
206   }
207
208   // If the array prototype chain is intact (and free of elements), and if the
209   // receiver's prototype is the array prototype, then we are done.
210   Object* prototype = receiver->map()->prototype();
211   if (prototype->IsJSArray() &&
212       isolate->is_initial_array_prototype(JSArray::cast(prototype))) {
213     return true;
214   }
215
216   // Slow case.
217   PrototypeIterator iter(isolate, receiver);
218   return ArrayPrototypeHasNoElements(heap, &iter);
219 }
220
221
222 // Returns empty handle if not applicable.
223 MUST_USE_RESULT
224 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
225     Isolate* isolate,
226     Handle<Object> receiver,
227     Arguments* args,
228     int first_added_arg) {
229   if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
230   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
231   // If there may be elements accessors in the prototype chain, the fast path
232   // cannot be used if there arguments to add to the array.
233   Heap* heap = isolate->heap();
234   if (args != NULL && !IsJSArrayFastElementMovingAllowed(heap, *array)) {
235     return MaybeHandle<FixedArrayBase>();
236   }
237   if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
238   if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
239   Handle<FixedArrayBase> elms(array->elements(), isolate);
240   Map* map = elms->map();
241   if (map == heap->fixed_array_map()) {
242     if (args == NULL || array->HasFastObjectElements()) return elms;
243   } else if (map == heap->fixed_cow_array_map()) {
244     elms = JSObject::EnsureWritableFastElements(array);
245     if (args == NULL || array->HasFastObjectElements()) return elms;
246   } else if (map == heap->fixed_double_array_map()) {
247     if (args == NULL) return elms;
248   } else {
249     return MaybeHandle<FixedArrayBase>();
250   }
251
252   // Adding elements to the array prototype would break code that makes sure
253   // it has no elements. Handle that elsewhere.
254   if (isolate->IsAnyInitialArrayPrototype(array)) {
255     return MaybeHandle<FixedArrayBase>();
256   }
257
258   // Need to ensure that the arguments passed in args can be contained in
259   // the array.
260   int args_length = args->length();
261   if (first_added_arg >= args_length) return handle(array->elements(), isolate);
262
263   ElementsKind origin_kind = array->map()->elements_kind();
264   DCHECK(!IsFastObjectElementsKind(origin_kind));
265   ElementsKind target_kind = origin_kind;
266   {
267     DisallowHeapAllocation no_gc;
268     int arg_count = args->length() - first_added_arg;
269     Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
270     for (int i = 0; i < arg_count; i++) {
271       Object* arg = arguments[i];
272       if (arg->IsHeapObject()) {
273         if (arg->IsHeapNumber()) {
274           target_kind = FAST_DOUBLE_ELEMENTS;
275         } else {
276           target_kind = FAST_ELEMENTS;
277           break;
278         }
279       }
280     }
281   }
282   if (target_kind != origin_kind) {
283     JSObject::TransitionElementsKind(array, target_kind);
284     return handle(array->elements(), isolate);
285   }
286   return elms;
287 }
288
289
290 MUST_USE_RESULT static Object* CallJsBuiltin(
291     Isolate* isolate,
292     const char* name,
293     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
294   HandleScope handleScope(isolate);
295
296   Handle<Object> js_builtin = Object::GetProperty(
297       isolate,
298       handle(isolate->native_context()->builtins(), isolate),
299       name).ToHandleChecked();
300   Handle<JSFunction> function = Handle<JSFunction>::cast(js_builtin);
301   int argc = args.length() - 1;
302   ScopedVector<Handle<Object> > argv(argc);
303   for (int i = 0; i < argc; ++i) {
304     argv[i] = args.at<Object>(i + 1);
305   }
306   Handle<Object> result;
307   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
308       isolate, result,
309       Execution::Call(isolate,
310                       function,
311                       args.receiver(),
312                       argc,
313                       argv.start()));
314   return *result;
315 }
316
317
318 BUILTIN(ArrayPush) {
319   HandleScope scope(isolate);
320   Handle<Object> receiver = args.receiver();
321   MaybeHandle<FixedArrayBase> maybe_elms_obj =
322       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
323   Handle<FixedArrayBase> elms_obj;
324   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
325     return CallJsBuiltin(isolate, "$arrayPush", args);
326   }
327
328   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
329   int len = Smi::cast(array->length())->value();
330   int to_add = args.length() - 1;
331   if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
332     return CallJsBuiltin(isolate, "$arrayPush", args);
333   }
334   DCHECK(!array->map()->is_observed());
335
336   ElementsKind kind = array->GetElementsKind();
337
338   if (IsFastSmiOrObjectElementsKind(kind)) {
339     Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
340     if (to_add == 0) {
341       return Smi::FromInt(len);
342     }
343     // Currently fixed arrays cannot grow too big, so
344     // we should never hit this case.
345     DCHECK(to_add <= (Smi::kMaxValue - len));
346
347     int new_length = len + to_add;
348
349     if (new_length > elms->length()) {
350       // New backing storage is needed.
351       int capacity = new_length + (new_length >> 1) + 16;
352       Handle<FixedArray> new_elms =
353           isolate->factory()->NewUninitializedFixedArray(capacity);
354
355       ElementsAccessor* accessor = array->GetElementsAccessor();
356       accessor->CopyElements(
357           elms_obj, 0, kind, new_elms, 0,
358           ElementsAccessor::kCopyToEndAndInitializeToHole);
359
360       elms = new_elms;
361     }
362
363     // Add the provided values.
364     DisallowHeapAllocation no_gc;
365     WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
366     for (int index = 0; index < to_add; index++) {
367       elms->set(index + len, args[index + 1], mode);
368     }
369
370     if (*elms != array->elements()) {
371       array->set_elements(*elms);
372     }
373
374     // Set the length.
375     array->set_length(Smi::FromInt(new_length));
376     return Smi::FromInt(new_length);
377   } else {
378     int elms_len = elms_obj->length();
379     if (to_add == 0) {
380       return Smi::FromInt(len);
381     }
382     // Currently fixed arrays cannot grow too big, so
383     // we should never hit this case.
384     DCHECK(to_add <= (Smi::kMaxValue - len));
385
386     int new_length = len + to_add;
387
388     Handle<FixedDoubleArray> new_elms;
389
390     if (new_length > elms_len) {
391       // New backing storage is needed.
392       int capacity = new_length + (new_length >> 1) + 16;
393       // Create new backing store; since capacity > 0, we can
394       // safely cast to FixedDoubleArray.
395       new_elms = Handle<FixedDoubleArray>::cast(
396           isolate->factory()->NewFixedDoubleArray(capacity));
397
398       ElementsAccessor* accessor = array->GetElementsAccessor();
399       accessor->CopyElements(
400           elms_obj, 0, kind, new_elms, 0,
401           ElementsAccessor::kCopyToEndAndInitializeToHole);
402
403     } else {
404       // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the
405       // empty_fixed_array.
406       new_elms = Handle<FixedDoubleArray>::cast(elms_obj);
407     }
408
409     // Add the provided values.
410     DisallowHeapAllocation no_gc;
411     int index;
412     for (index = 0; index < to_add; index++) {
413       Object* arg = args[index + 1];
414       new_elms->set(index + len, arg->Number());
415     }
416
417     if (*new_elms != array->elements()) {
418       array->set_elements(*new_elms);
419     }
420
421     // Set the length.
422     array->set_length(Smi::FromInt(new_length));
423     return Smi::FromInt(new_length);
424   }
425 }
426
427
428 BUILTIN(ArrayPop) {
429   HandleScope scope(isolate);
430   Handle<Object> receiver = args.receiver();
431   MaybeHandle<FixedArrayBase> maybe_elms_obj =
432       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
433   Handle<FixedArrayBase> elms_obj;
434   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
435     return CallJsBuiltin(isolate, "$arrayPop", args);
436   }
437
438   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
439   DCHECK(!array->map()->is_observed());
440
441   uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
442   if (len == 0) return isolate->heap()->undefined_value();
443
444   if (JSArray::HasReadOnlyLength(array)) {
445     return CallJsBuiltin(isolate, "$arrayPop", args);
446   }
447
448   ElementsAccessor* accessor = array->GetElementsAccessor();
449   uint32_t new_length = len - 1;
450   Handle<Object> element;
451   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
452       isolate, element, Object::GetElement(isolate, array, new_length));
453
454   RETURN_FAILURE_ON_EXCEPTION(
455       isolate,
456       accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
457   return *element;
458 }
459
460
461 BUILTIN(ArrayShift) {
462   HandleScope scope(isolate);
463   Heap* heap = isolate->heap();
464   Handle<Object> receiver = args.receiver();
465   MaybeHandle<FixedArrayBase> maybe_elms_obj =
466       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
467   Handle<FixedArrayBase> elms_obj;
468   if (!maybe_elms_obj.ToHandle(&elms_obj) ||
469       !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) {
470     return CallJsBuiltin(isolate, "$arrayShift", args);
471   }
472   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
473   DCHECK(!array->map()->is_observed());
474
475   int len = Smi::cast(array->length())->value();
476   if (len == 0) return heap->undefined_value();
477
478   if (JSArray::HasReadOnlyLength(array)) {
479     return CallJsBuiltin(isolate, "$arrayShift", args);
480   }
481
482   // Get first element
483   Handle<Object> first;
484   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first,
485                                      Object::GetElement(isolate, array, 0));
486
487   if (heap->CanMoveObjectStart(*elms_obj)) {
488     array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
489   } else {
490     // Shift the elements.
491     if (elms_obj->IsFixedArray()) {
492       Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
493       DisallowHeapAllocation no_gc;
494       heap->MoveElements(*elms, 0, 1, len - 1);
495       elms->set(len - 1, heap->the_hole_value());
496     } else {
497       Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
498       MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
499       elms->set_the_hole(len - 1);
500     }
501   }
502
503   // Set the length.
504   array->set_length(Smi::FromInt(len - 1));
505
506   return *first;
507 }
508
509
510 BUILTIN(ArrayUnshift) {
511   HandleScope scope(isolate);
512   Heap* heap = isolate->heap();
513   Handle<Object> receiver = args.receiver();
514   MaybeHandle<FixedArrayBase> maybe_elms_obj =
515       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
516   Handle<FixedArrayBase> elms_obj;
517   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
518     return CallJsBuiltin(isolate, "$arrayUnshift", args);
519   }
520   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
521   DCHECK(!array->map()->is_observed());
522   if (!array->HasFastSmiOrObjectElements()) {
523     return CallJsBuiltin(isolate, "$arrayUnshift", args);
524   }
525   int len = Smi::cast(array->length())->value();
526   int to_add = args.length() - 1;
527   int new_length = len + to_add;
528   // Currently fixed arrays cannot grow too big, so
529   // we should never hit this case.
530   DCHECK(to_add <= (Smi::kMaxValue - len));
531
532   if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
533     return CallJsBuiltin(isolate, "$arrayUnshift", args);
534   }
535
536   Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
537
538   if (new_length > elms->length()) {
539     // New backing storage is needed.
540     int capacity = new_length + (new_length >> 1) + 16;
541     Handle<FixedArray> new_elms =
542         isolate->factory()->NewUninitializedFixedArray(capacity);
543
544     ElementsKind kind = array->GetElementsKind();
545     ElementsAccessor* accessor = array->GetElementsAccessor();
546     accessor->CopyElements(
547         elms, 0, kind, new_elms, to_add,
548         ElementsAccessor::kCopyToEndAndInitializeToHole);
549
550     elms = new_elms;
551     array->set_elements(*elms);
552   } else {
553     DisallowHeapAllocation no_gc;
554     heap->MoveElements(*elms, to_add, 0, len);
555   }
556
557   // Add the provided values.
558   DisallowHeapAllocation no_gc;
559   WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
560   for (int i = 0; i < to_add; i++) {
561     elms->set(i, args[i + 1], mode);
562   }
563
564   // Set the length.
565   array->set_length(Smi::FromInt(new_length));
566   return Smi::FromInt(new_length);
567 }
568
569
570 BUILTIN(ArraySlice) {
571   HandleScope scope(isolate);
572   Heap* heap = isolate->heap();
573   Handle<Object> receiver = args.receiver();
574   int len = -1;
575   int relative_start = 0;
576   int relative_end = 0;
577   {
578     DisallowHeapAllocation no_gc;
579     if (receiver->IsJSArray()) {
580       JSArray* array = JSArray::cast(*receiver);
581       if (!IsJSArrayFastElementMovingAllowed(heap, array)) {
582         AllowHeapAllocation allow_allocation;
583         return CallJsBuiltin(isolate, "$arraySlice", args);
584       }
585
586       if (!array->HasFastElements()) {
587         AllowHeapAllocation allow_allocation;
588         return CallJsBuiltin(isolate, "$arraySlice", args);
589       }
590
591       len = Smi::cast(array->length())->value();
592     } else {
593       // Array.slice(arguments, ...) is quite a common idiom (notably more
594       // than 50% of invocations in Web apps).  Treat it in C++ as well.
595       Map* arguments_map =
596           isolate->context()->native_context()->sloppy_arguments_map();
597
598       bool is_arguments_object_with_fast_elements =
599           receiver->IsJSObject() &&
600           JSObject::cast(*receiver)->map() == arguments_map;
601       if (!is_arguments_object_with_fast_elements) {
602         AllowHeapAllocation allow_allocation;
603         return CallJsBuiltin(isolate, "$arraySlice", args);
604       }
605       JSObject* object = JSObject::cast(*receiver);
606
607       if (!object->HasFastElements()) {
608         AllowHeapAllocation allow_allocation;
609         return CallJsBuiltin(isolate, "$arraySlice", args);
610       }
611
612       Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
613       if (!len_obj->IsSmi()) {
614         AllowHeapAllocation allow_allocation;
615         return CallJsBuiltin(isolate, "$arraySlice", args);
616       }
617       len = Smi::cast(len_obj)->value();
618       if (len > object->elements()->length()) {
619         AllowHeapAllocation allow_allocation;
620         return CallJsBuiltin(isolate, "$arraySlice", args);
621       }
622     }
623
624     DCHECK(len >= 0);
625     int n_arguments = args.length() - 1;
626
627     // Note carefully choosen defaults---if argument is missing,
628     // it's undefined which gets converted to 0 for relative_start
629     // and to len for relative_end.
630     relative_start = 0;
631     relative_end = len;
632     if (n_arguments > 0) {
633       Object* arg1 = args[1];
634       if (arg1->IsSmi()) {
635         relative_start = Smi::cast(arg1)->value();
636       } else if (arg1->IsHeapNumber()) {
637         double start = HeapNumber::cast(arg1)->value();
638         if (start < kMinInt || start > kMaxInt) {
639           AllowHeapAllocation allow_allocation;
640           return CallJsBuiltin(isolate, "$arraySlice", args);
641         }
642         relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
643       } else if (!arg1->IsUndefined()) {
644         AllowHeapAllocation allow_allocation;
645         return CallJsBuiltin(isolate, "$arraySlice", args);
646       }
647       if (n_arguments > 1) {
648         Object* arg2 = args[2];
649         if (arg2->IsSmi()) {
650           relative_end = Smi::cast(arg2)->value();
651         } else if (arg2->IsHeapNumber()) {
652           double end = HeapNumber::cast(arg2)->value();
653           if (end < kMinInt || end > kMaxInt) {
654             AllowHeapAllocation allow_allocation;
655             return CallJsBuiltin(isolate, "$arraySlice", args);
656           }
657           relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
658         } else if (!arg2->IsUndefined()) {
659           AllowHeapAllocation allow_allocation;
660           return CallJsBuiltin(isolate, "$arraySlice", args);
661         }
662       }
663     }
664   }
665
666   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
667   int k = (relative_start < 0) ? Max(len + relative_start, 0)
668                                : Min(relative_start, len);
669
670   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
671   int final = (relative_end < 0) ? Max(len + relative_end, 0)
672                                  : Min(relative_end, len);
673
674   // Calculate the length of result array.
675   int result_len = Max(final - k, 0);
676
677   Handle<JSObject> object = Handle<JSObject>::cast(receiver);
678   Handle<FixedArrayBase> elms(object->elements(), isolate);
679
680   ElementsKind kind = object->GetElementsKind();
681   if (IsHoleyElementsKind(kind)) {
682     DisallowHeapAllocation no_gc;
683     bool packed = true;
684     ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
685     for (int i = k; i < final; i++) {
686       if (!accessor->HasElement(object, i, elms)) {
687         packed = false;
688         break;
689       }
690     }
691     if (packed) {
692       kind = GetPackedElementsKind(kind);
693     } else if (!receiver->IsJSArray()) {
694       AllowHeapAllocation allow_allocation;
695       return CallJsBuiltin(isolate, "$arraySlice", args);
696     }
697   }
698
699   Handle<JSArray> result_array =
700       isolate->factory()->NewJSArray(kind, result_len, result_len);
701
702   DisallowHeapAllocation no_gc;
703   if (result_len == 0) return *result_array;
704
705   ElementsAccessor* accessor = object->GetElementsAccessor();
706   accessor->CopyElements(
707       elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
708   return *result_array;
709 }
710
711
712 BUILTIN(ArraySplice) {
713   HandleScope scope(isolate);
714   Heap* heap = isolate->heap();
715   Handle<Object> receiver = args.receiver();
716   MaybeHandle<FixedArrayBase> maybe_elms_obj =
717       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
718   Handle<FixedArrayBase> elms_obj;
719   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
720     return CallJsBuiltin(isolate, "$arraySplice", args);
721   }
722   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
723   DCHECK(!array->map()->is_observed());
724
725   int len = Smi::cast(array->length())->value();
726
727   int n_arguments = args.length() - 1;
728
729   int relative_start = 0;
730   if (n_arguments > 0) {
731     DisallowHeapAllocation no_gc;
732     Object* arg1 = args[1];
733     if (arg1->IsSmi()) {
734       relative_start = Smi::cast(arg1)->value();
735     } else if (arg1->IsHeapNumber()) {
736       double start = HeapNumber::cast(arg1)->value();
737       if (start < kMinInt || start > kMaxInt) {
738         AllowHeapAllocation allow_allocation;
739         return CallJsBuiltin(isolate, "$arraySplice", args);
740       }
741       relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
742     } else if (!arg1->IsUndefined()) {
743       AllowHeapAllocation allow_allocation;
744       return CallJsBuiltin(isolate, "$arraySplice", args);
745     }
746   }
747   int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
748                                           : Min(relative_start, len);
749
750   // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
751   // given as a request to delete all the elements from the start.
752   // And it differs from the case of undefined delete count.
753   // This does not follow ECMA-262, but we do the same for
754   // compatibility.
755   int actual_delete_count;
756   if (n_arguments == 1) {
757     DCHECK(len - actual_start >= 0);
758     actual_delete_count = len - actual_start;
759   } else {
760     int value = 0;  // ToInteger(undefined) == 0
761     if (n_arguments > 1) {
762       DisallowHeapAllocation no_gc;
763       Object* arg2 = args[2];
764       if (arg2->IsSmi()) {
765         value = Smi::cast(arg2)->value();
766       } else {
767         AllowHeapAllocation allow_allocation;
768         return CallJsBuiltin(isolate, "$arraySplice", args);
769       }
770     }
771     actual_delete_count = Min(Max(value, 0), len - actual_start);
772   }
773
774   ElementsKind elements_kind = array->GetElementsKind();
775
776   int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
777   int new_length = len - actual_delete_count + item_count;
778
779   // For double mode we do not support changing the length.
780   if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
781     return CallJsBuiltin(isolate, "$arraySplice", args);
782   }
783
784   if (new_length != len && JSArray::HasReadOnlyLength(array)) {
785     AllowHeapAllocation allow_allocation;
786     return CallJsBuiltin(isolate, "$arraySplice", args);
787   }
788
789   if (new_length == 0) {
790     Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
791         elms_obj, elements_kind, actual_delete_count);
792     array->set_elements(heap->empty_fixed_array());
793     array->set_length(Smi::FromInt(0));
794     return *result;
795   }
796
797   Handle<JSArray> result_array =
798       isolate->factory()->NewJSArray(elements_kind,
799                                      actual_delete_count,
800                                      actual_delete_count);
801
802   if (actual_delete_count > 0) {
803     DisallowHeapAllocation no_gc;
804     ElementsAccessor* accessor = array->GetElementsAccessor();
805     accessor->CopyElements(
806         elms_obj, actual_start, elements_kind,
807         handle(result_array->elements(), isolate), 0, actual_delete_count);
808   }
809
810   bool elms_changed = false;
811   if (item_count < actual_delete_count) {
812     // Shrink the array.
813     const bool trim_array = !heap->lo_space()->Contains(*elms_obj) &&
814       ((actual_start + item_count) <
815           (len - actual_delete_count - actual_start));
816     if (trim_array) {
817       const int delta = actual_delete_count - item_count;
818
819       if (elms_obj->IsFixedDoubleArray()) {
820         Handle<FixedDoubleArray> elms =
821             Handle<FixedDoubleArray>::cast(elms_obj);
822         MoveDoubleElements(*elms, delta, *elms, 0, actual_start);
823       } else {
824         Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
825         DisallowHeapAllocation no_gc;
826         heap->MoveElements(*elms, delta, 0, actual_start);
827       }
828
829       if (heap->CanMoveObjectStart(*elms_obj)) {
830         // On the fast path we move the start of the object in memory.
831         elms_obj = handle(heap->LeftTrimFixedArray(*elms_obj, delta));
832       } else {
833         // This is the slow path. We are going to move the elements to the left
834         // by copying them. For trimmed values we store the hole.
835         if (elms_obj->IsFixedDoubleArray()) {
836           Handle<FixedDoubleArray> elms =
837               Handle<FixedDoubleArray>::cast(elms_obj);
838           MoveDoubleElements(*elms, 0, *elms, delta, len - delta);
839           elms->FillWithHoles(len - delta, len);
840         } else {
841           Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
842           DisallowHeapAllocation no_gc;
843           heap->MoveElements(*elms, 0, delta, len - delta);
844           elms->FillWithHoles(len - delta, len);
845         }
846       }
847       elms_changed = true;
848     } else {
849       if (elms_obj->IsFixedDoubleArray()) {
850         Handle<FixedDoubleArray> elms =
851             Handle<FixedDoubleArray>::cast(elms_obj);
852         MoveDoubleElements(*elms, actual_start + item_count,
853                            *elms, actual_start + actual_delete_count,
854                            (len - actual_delete_count - actual_start));
855         elms->FillWithHoles(new_length, len);
856       } else {
857         Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
858         DisallowHeapAllocation no_gc;
859         heap->MoveElements(*elms, actual_start + item_count,
860                            actual_start + actual_delete_count,
861                            (len - actual_delete_count - actual_start));
862         elms->FillWithHoles(new_length, len);
863       }
864     }
865   } else if (item_count > actual_delete_count) {
866     Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
867     // Currently fixed arrays cannot grow too big, so
868     // we should never hit this case.
869     DCHECK((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
870
871     // Check if array need to grow.
872     if (new_length > elms->length()) {
873       // New backing storage is needed.
874       int capacity = new_length + (new_length >> 1) + 16;
875       Handle<FixedArray> new_elms =
876           isolate->factory()->NewUninitializedFixedArray(capacity);
877
878       DisallowHeapAllocation no_gc;
879
880       ElementsKind kind = array->GetElementsKind();
881       ElementsAccessor* accessor = array->GetElementsAccessor();
882       if (actual_start > 0) {
883         // Copy the part before actual_start as is.
884         accessor->CopyElements(
885             elms, 0, kind, new_elms, 0, actual_start);
886       }
887       accessor->CopyElements(
888           elms, actual_start + actual_delete_count, kind,
889           new_elms, actual_start + item_count,
890           ElementsAccessor::kCopyToEndAndInitializeToHole);
891
892       elms_obj = new_elms;
893       elms_changed = true;
894     } else {
895       DisallowHeapAllocation no_gc;
896       heap->MoveElements(*elms, actual_start + item_count,
897                          actual_start + actual_delete_count,
898                          (len - actual_delete_count - actual_start));
899     }
900   }
901
902   if (IsFastDoubleElementsKind(elements_kind)) {
903     Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
904     for (int k = actual_start; k < actual_start + item_count; k++) {
905       Object* arg = args[3 + k - actual_start];
906       if (arg->IsSmi()) {
907         elms->set(k, Smi::cast(arg)->value());
908       } else {
909         elms->set(k, HeapNumber::cast(arg)->value());
910       }
911     }
912   } else {
913     Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
914     DisallowHeapAllocation no_gc;
915     WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
916     for (int k = actual_start; k < actual_start + item_count; k++) {
917       elms->set(k, args[3 + k - actual_start], mode);
918     }
919   }
920
921   if (elms_changed) {
922     array->set_elements(*elms_obj);
923   }
924   // Set the length.
925   array->set_length(Smi::FromInt(new_length));
926
927   return *result_array;
928 }
929
930
931 BUILTIN(ArrayConcat) {
932   HandleScope scope(isolate);
933
934   int n_arguments = args.length();
935   int result_len = 0;
936   ElementsKind elements_kind = GetInitialFastElementsKind();
937   bool has_double = false;
938   {
939     DisallowHeapAllocation no_gc;
940     Heap* heap = isolate->heap();
941     Context* native_context = isolate->context()->native_context();
942     Object* array_proto = native_context->array_function()->prototype();
943     PrototypeIterator iter(isolate, array_proto,
944                            PrototypeIterator::START_AT_RECEIVER);
945     if (!ArrayPrototypeHasNoElements(heap, &iter)) {
946       AllowHeapAllocation allow_allocation;
947       return CallJsBuiltin(isolate, "$arrayConcat", args);
948     }
949
950     // Iterate through all the arguments performing checks
951     // and calculating total length.
952     bool is_holey = false;
953     for (int i = 0; i < n_arguments; i++) {
954       Object* arg = args[i];
955       PrototypeIterator iter(isolate, arg);
956       if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() ||
957           iter.GetCurrent() != array_proto) {
958         AllowHeapAllocation allow_allocation;
959         return CallJsBuiltin(isolate, "$arrayConcat", args);
960       }
961       int len = Smi::cast(JSArray::cast(arg)->length())->value();
962
963       // We shouldn't overflow when adding another len.
964       const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
965       STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
966       USE(kHalfOfMaxInt);
967       result_len += len;
968       DCHECK(result_len >= 0);
969
970       if (result_len > FixedDoubleArray::kMaxLength) {
971         AllowHeapAllocation allow_allocation;
972         return CallJsBuiltin(isolate, "$arrayConcat", args);
973       }
974
975       ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
976       has_double = has_double || IsFastDoubleElementsKind(arg_kind);
977       is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
978       if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
979         elements_kind = arg_kind;
980       }
981     }
982     if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
983   }
984
985   // If a double array is concatted into a fast elements array, the fast
986   // elements array needs to be initialized to contain proper holes, since
987   // boxing doubles may cause incremental marking.
988   ArrayStorageAllocationMode mode =
989       has_double && IsFastObjectElementsKind(elements_kind)
990       ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
991   Handle<JSArray> result_array = isolate->factory()->NewJSArray(
992       elements_kind, result_len, result_len, WEAK, mode);
993   if (result_len == 0) return *result_array;
994
995   int j = 0;
996   Handle<FixedArrayBase> storage(result_array->elements(), isolate);
997   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
998   for (int i = 0; i < n_arguments; i++) {
999     // It is crucial to keep |array| in a raw pointer form to avoid performance
1000     // degradation.
1001     JSArray* array = JSArray::cast(args[i]);
1002     int len = Smi::cast(array->length())->value();
1003     if (len > 0) {
1004       ElementsKind from_kind = array->GetElementsKind();
1005       accessor->CopyElements(array, 0, from_kind, storage, j, len);
1006       j += len;
1007     }
1008   }
1009
1010   DCHECK(j == result_len);
1011
1012   return *result_array;
1013 }
1014
1015
1016 // -----------------------------------------------------------------------------
1017 // Throwers for restricted function properties and strict arguments object
1018 // properties
1019
1020
1021 BUILTIN(RestrictedFunctionPropertiesThrower) {
1022   HandleScope scope(isolate);
1023   THROW_NEW_ERROR_RETURN_FAILURE(
1024       isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
1025 }
1026
1027
1028 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
1029   HandleScope scope(isolate);
1030   THROW_NEW_ERROR_RETURN_FAILURE(
1031       isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
1032 }
1033
1034
1035 // -----------------------------------------------------------------------------
1036 //
1037
1038
1039 template <bool is_construct>
1040 MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
1041     Isolate* isolate, BuiltinArguments<NEEDS_CALLED_FUNCTION>& args) {
1042   HandleScope scope(isolate);
1043   Handle<JSFunction> function = args.called_function();
1044   // TODO(ishell): turn this back to a DCHECK.
1045   CHECK(function->shared()->IsApiFunction());
1046
1047   Handle<FunctionTemplateInfo> fun_data(
1048       function->shared()->get_api_func_data(), isolate);
1049   if (is_construct) {
1050     ASSIGN_RETURN_ON_EXCEPTION(
1051         isolate, fun_data,
1052         ApiNatives::ConfigureInstance(isolate, fun_data,
1053                                       Handle<JSObject>::cast(args.receiver())),
1054         Object);
1055   }
1056
1057   DCHECK(!args[0]->IsNull());
1058   if (args[0]->IsUndefined()) args[0] = function->global_proxy();
1059
1060   if (!is_construct && !fun_data->accept_any_receiver()) {
1061     Handle<Object> receiver(&args[0]);
1062     if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
1063       Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
1064       if (!isolate->MayAccess(js_receiver)) {
1065         isolate->ReportFailedAccessCheck(js_receiver);
1066         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1067       }
1068     }
1069   }
1070
1071   Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]);
1072
1073   if (raw_holder->IsNull()) {
1074     // This function cannot be called with the given receiver.  Abort!
1075     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
1076                     Object);
1077   }
1078
1079   Object* raw_call_data = fun_data->call_code();
1080   if (!raw_call_data->IsUndefined()) {
1081     // TODO(ishell): remove this debugging code.
1082     CHECK(raw_call_data->IsCallHandlerInfo());
1083     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1084     Object* callback_obj = call_data->callback();
1085     v8::FunctionCallback callback =
1086         v8::ToCData<v8::FunctionCallback>(callback_obj);
1087     Object* data_obj = call_data->data();
1088
1089     LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
1090     DCHECK(raw_holder->IsJSObject());
1091
1092     FunctionCallbackArguments custom(isolate,
1093                                      data_obj,
1094                                      *function,
1095                                      raw_holder,
1096                                      &args[0] - 1,
1097                                      args.length() - 1,
1098                                      is_construct);
1099
1100     v8::Handle<v8::Value> value = custom.Call(callback);
1101     Handle<Object> result;
1102     if (value.IsEmpty()) {
1103       result = isolate->factory()->undefined_value();
1104     } else {
1105       result = v8::Utils::OpenHandle(*value);
1106       result->VerifyApiCallResultType();
1107     }
1108
1109     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
1110     if (!is_construct || result->IsJSObject()) {
1111       return scope.CloseAndEscape(result);
1112     }
1113   }
1114
1115   return scope.CloseAndEscape(args.receiver());
1116 }
1117
1118
1119 BUILTIN(HandleApiCall) {
1120   HandleScope scope(isolate);
1121   DCHECK(!CalledAsConstructor(isolate));
1122   Handle<Object> result;
1123   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1124                                      HandleApiCallHelper<false>(isolate, args));
1125   return *result;
1126 }
1127
1128
1129 BUILTIN(HandleApiCallConstruct) {
1130   HandleScope scope(isolate);
1131   DCHECK(CalledAsConstructor(isolate));
1132   Handle<Object> result;
1133   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
1134                                      HandleApiCallHelper<true>(isolate, args));
1135   return *result;
1136 }
1137
1138
1139 namespace {
1140
1141 class RelocatableArguments : public BuiltinArguments<NEEDS_CALLED_FUNCTION>,
1142                              public Relocatable {
1143  public:
1144   RelocatableArguments(Isolate* isolate, int length, Object** arguments)
1145       : BuiltinArguments<NEEDS_CALLED_FUNCTION>(length, arguments),
1146         Relocatable(isolate) {}
1147
1148   virtual inline void IterateInstance(ObjectVisitor* v) {
1149     if (length() == 0) return;
1150     v->VisitPointers(lowest_address(), highest_address() + 1);
1151   }
1152
1153  private:
1154   DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
1155 };
1156
1157 }  // namespace
1158
1159
1160 MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function,
1161                                                 Handle<Object> receiver,
1162                                                 int argc,
1163                                                 Handle<Object> args[]) {
1164   // Construct BuiltinArguments object: function, arguments reversed, receiver.
1165   const int kBufferSize = 32;
1166   Object* small_argv[kBufferSize];
1167   Object** argv;
1168   if (argc + 2 <= kBufferSize) {
1169     argv = small_argv;
1170   } else {
1171     argv = new Object* [argc + 2];
1172   }
1173   argv[argc + 1] = *receiver;
1174   for (int i = 0; i < argc; ++i) {
1175     argv[argc - i] = *args[i];
1176   }
1177   argv[0] = *function;
1178   MaybeHandle<Object> result;
1179   {
1180     auto isolate = function->GetIsolate();
1181     RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
1182     result = HandleApiCallHelper<false>(isolate, arguments);
1183   }
1184   if (argv != small_argv) {
1185     delete[] argv;
1186   }
1187   return result;
1188 }
1189
1190
1191 // Helper function to handle calls to non-function objects created through the
1192 // API. The object can be called as either a constructor (using new) or just as
1193 // a function (without new).
1194 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
1195     Isolate* isolate,
1196     bool is_construct_call,
1197     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
1198   // Non-functions are never called as constructors. Even if this is an object
1199   // called as a constructor the delegate call is not a construct call.
1200   DCHECK(!CalledAsConstructor(isolate));
1201   Heap* heap = isolate->heap();
1202
1203   Handle<Object> receiver = args.receiver();
1204
1205   // Get the object called.
1206   JSObject* obj = JSObject::cast(*receiver);
1207
1208   // Get the invocation callback from the function descriptor that was
1209   // used to create the called object.
1210   DCHECK(obj->map()->has_instance_call_handler());
1211   JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
1212   // TODO(ishell): turn this back to a DCHECK.
1213   CHECK(constructor->shared()->IsApiFunction());
1214   Object* handler =
1215       constructor->shared()->get_api_func_data()->instance_call_handler();
1216   DCHECK(!handler->IsUndefined());
1217   // TODO(ishell): remove this debugging code.
1218   CHECK(handler->IsCallHandlerInfo());
1219   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
1220   Object* callback_obj = call_data->callback();
1221   v8::FunctionCallback callback =
1222       v8::ToCData<v8::FunctionCallback>(callback_obj);
1223
1224   // Get the data for the call and perform the callback.
1225   Object* result;
1226   {
1227     HandleScope scope(isolate);
1228     LOG(isolate, ApiObjectAccess("call non-function", obj));
1229
1230     FunctionCallbackArguments custom(isolate,
1231                                      call_data->data(),
1232                                      constructor,
1233                                      obj,
1234                                      &args[0] - 1,
1235                                      args.length() - 1,
1236                                      is_construct_call);
1237     v8::Handle<v8::Value> value = custom.Call(callback);
1238     if (value.IsEmpty()) {
1239       result = heap->undefined_value();
1240     } else {
1241       result = *reinterpret_cast<Object**>(*value);
1242       result->VerifyApiCallResultType();
1243     }
1244   }
1245   // Check for exceptions and return result.
1246   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
1247   return result;
1248 }
1249
1250
1251 // Handle calls to non-function objects created through the API. This delegate
1252 // function is used when the call is a normal function call.
1253 BUILTIN(HandleApiCallAsFunction) {
1254   return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
1255 }
1256
1257
1258 // Handle calls to non-function objects created through the API. This delegate
1259 // function is used when the call is a construct call.
1260 BUILTIN(HandleApiCallAsConstructor) {
1261   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
1262 }
1263
1264
1265 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
1266   LoadIC::GenerateMiss(masm);
1267 }
1268
1269
1270 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
1271   LoadIC::GenerateNormal(masm);
1272 }
1273
1274
1275 static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
1276   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
1277 }
1278
1279
1280 static void Generate_LoadIC_Slow(MacroAssembler* masm) {
1281   LoadIC::GenerateRuntimeGetProperty(masm);
1282 }
1283
1284
1285 static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
1286   KeyedLoadIC::GenerateInitialize(masm);
1287 }
1288
1289
1290 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
1291   KeyedLoadIC::GenerateRuntimeGetProperty(masm);
1292 }
1293
1294
1295 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
1296   KeyedLoadIC::GenerateMiss(masm);
1297 }
1298
1299
1300 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
1301   KeyedLoadIC::GenerateMegamorphic(masm);
1302 }
1303
1304
1305 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
1306   StoreIC::GenerateMiss(masm);
1307 }
1308
1309
1310 static void Generate_StoreIC_Normal(MacroAssembler* masm) {
1311   StoreIC::GenerateNormal(masm);
1312 }
1313
1314
1315 static void Generate_StoreIC_Slow(MacroAssembler* masm) {
1316   NamedStoreHandlerCompiler::GenerateSlow(masm);
1317 }
1318
1319
1320 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
1321   ElementHandlerCompiler::GenerateStoreSlow(masm);
1322 }
1323
1324
1325 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
1326   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
1327 }
1328
1329
1330 static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
1331   KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
1332 }
1333
1334
1335 static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
1336   KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
1337 }
1338
1339
1340 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
1341   KeyedStoreIC::GenerateMiss(masm);
1342 }
1343
1344
1345 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
1346   KeyedStoreIC::GenerateInitialize(masm);
1347 }
1348
1349
1350 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
1351   KeyedStoreIC::GenerateInitialize(masm);
1352 }
1353
1354
1355 static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
1356   KeyedStoreIC::GeneratePreMonomorphic(masm);
1357 }
1358
1359
1360 static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
1361   KeyedStoreIC::GeneratePreMonomorphic(masm);
1362 }
1363
1364
1365 static void Generate_CallICStub_DebugBreak(MacroAssembler* masm) {
1366   DebugCodegen::GenerateCallICStubDebugBreak(masm);
1367 }
1368
1369
1370 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
1371   DebugCodegen::GenerateLoadICDebugBreak(masm);
1372 }
1373
1374
1375 static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
1376   DebugCodegen::GenerateStoreICDebugBreak(masm);
1377 }
1378
1379
1380 static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
1381   DebugCodegen::GenerateKeyedLoadICDebugBreak(masm);
1382 }
1383
1384
1385 static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
1386   DebugCodegen::GenerateKeyedStoreICDebugBreak(masm);
1387 }
1388
1389
1390 static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) {
1391   DebugCodegen::GenerateCompareNilICDebugBreak(masm);
1392 }
1393
1394
1395 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
1396   DebugCodegen::GenerateReturnDebugBreak(masm);
1397 }
1398
1399
1400 static void Generate_CallFunctionStub_DebugBreak(MacroAssembler* masm) {
1401   DebugCodegen::GenerateCallFunctionStubDebugBreak(masm);
1402 }
1403
1404
1405 static void Generate_CallConstructStub_DebugBreak(MacroAssembler* masm) {
1406   DebugCodegen::GenerateCallConstructStubDebugBreak(masm);
1407 }
1408
1409
1410 static void Generate_CallConstructStub_Recording_DebugBreak(
1411     MacroAssembler* masm) {
1412   DebugCodegen::GenerateCallConstructStubRecordDebugBreak(masm);
1413 }
1414
1415
1416 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
1417   DebugCodegen::GenerateSlotDebugBreak(masm);
1418 }
1419
1420
1421 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
1422   DebugCodegen::GeneratePlainReturnLiveEdit(masm);
1423 }
1424
1425
1426 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
1427   DebugCodegen::GenerateFrameDropperLiveEdit(masm);
1428 }
1429
1430
1431 Builtins::Builtins() : initialized_(false) {
1432   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
1433   memset(names_, 0, sizeof(names_[0]) * builtin_count);
1434 }
1435
1436
1437 Builtins::~Builtins() {
1438 }
1439
1440
1441 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
1442 Address const Builtins::c_functions_[cfunction_count] = {
1443   BUILTIN_LIST_C(DEF_ENUM_C)
1444 };
1445 #undef DEF_ENUM_C
1446
1447 #define DEF_JS_NAME(name, ignore) #name,
1448 #define DEF_JS_ARGC(ignore, argc) argc,
1449 const char* const Builtins::javascript_names_[id_count] = {
1450   BUILTINS_LIST_JS(DEF_JS_NAME)
1451 };
1452
1453 int const Builtins::javascript_argc_[id_count] = {
1454   BUILTINS_LIST_JS(DEF_JS_ARGC)
1455 };
1456 #undef DEF_JS_NAME
1457 #undef DEF_JS_ARGC
1458
1459 struct BuiltinDesc {
1460   byte* generator;
1461   byte* c_code;
1462   const char* s_name;  // name is only used for generating log information.
1463   int name;
1464   Code::Flags flags;
1465   BuiltinExtraArguments extra_args;
1466 };
1467
1468 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
1469
1470 class BuiltinFunctionTable {
1471  public:
1472   BuiltinDesc* functions() {
1473     base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
1474     return functions_;
1475   }
1476
1477   base::OnceType once_;
1478   BuiltinDesc functions_[Builtins::builtin_count + 1];
1479
1480   friend class Builtins;
1481 };
1482
1483 static BuiltinFunctionTable builtin_function_table =
1484     BUILTIN_FUNCTION_TABLE_INIT;
1485
1486 // Define array of pointers to generators and C builtin functions.
1487 // We do this in a sort of roundabout way so that we can do the initialization
1488 // within the lexical scope of Builtins:: and within a context where
1489 // Code::Flags names a non-abstract type.
1490 void Builtins::InitBuiltinFunctionTable() {
1491   BuiltinDesc* functions = builtin_function_table.functions_;
1492   functions[builtin_count].generator = NULL;
1493   functions[builtin_count].c_code = NULL;
1494   functions[builtin_count].s_name = NULL;
1495   functions[builtin_count].name = builtin_count;
1496   functions[builtin_count].flags = static_cast<Code::Flags>(0);
1497   functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
1498
1499 #define DEF_FUNCTION_PTR_C(aname, aextra_args)                         \
1500     functions->generator = FUNCTION_ADDR(Generate_Adaptor);            \
1501     functions->c_code = FUNCTION_ADDR(Builtin_##aname);                \
1502     functions->s_name = #aname;                                        \
1503     functions->name = c_##aname;                                       \
1504     functions->flags = Code::ComputeFlags(Code::BUILTIN);              \
1505     functions->extra_args = aextra_args;                               \
1506     ++functions;
1507
1508 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra)                       \
1509     functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
1510     functions->c_code = NULL;                                               \
1511     functions->s_name = #aname;                                             \
1512     functions->name = k##aname;                                             \
1513     functions->flags = Code::ComputeFlags(Code::kind,                       \
1514                                           state,                            \
1515                                           extra);                           \
1516     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
1517     ++functions;
1518
1519 #define DEF_FUNCTION_PTR_H(aname, kind)                                     \
1520     functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
1521     functions->c_code = NULL;                                               \
1522     functions->s_name = #aname;                                             \
1523     functions->name = k##aname;                                             \
1524     functions->flags = Code::ComputeHandlerFlags(Code::kind);               \
1525     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
1526     ++functions;
1527
1528   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1529   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
1530   BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
1531   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1532
1533 #undef DEF_FUNCTION_PTR_C
1534 #undef DEF_FUNCTION_PTR_A
1535 }
1536
1537
1538 void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
1539   DCHECK(!initialized_);
1540
1541   // Create a scope for the handles in the builtins.
1542   HandleScope scope(isolate);
1543
1544   const BuiltinDesc* functions = builtin_function_table.functions();
1545
1546   // For now we generate builtin adaptor code into a stack-allocated
1547   // buffer, before copying it into individual code objects. Be careful
1548   // with alignment, some platforms don't like unaligned code.
1549 #ifdef DEBUG
1550   // We can generate a lot of debug code on Arm64.
1551   const size_t buffer_size = 32*KB;
1552 #else
1553   const size_t buffer_size = 8*KB;
1554 #endif
1555   union { int force_alignment; byte buffer[buffer_size]; } u;
1556
1557   // Traverse the list of builtins and generate an adaptor in a
1558   // separate code object for each one.
1559   for (int i = 0; i < builtin_count; i++) {
1560     if (create_heap_objects) {
1561       MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
1562       // Generate the code/adaptor.
1563       typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
1564       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1565       // We pass all arguments to the generator, but it may not use all of
1566       // them.  This works because the first arguments are on top of the
1567       // stack.
1568       DCHECK(!masm.has_frame());
1569       g(&masm, functions[i].name, functions[i].extra_args);
1570       // Move the code into the object heap.
1571       CodeDesc desc;
1572       masm.GetCode(&desc);
1573       Code::Flags flags = functions[i].flags;
1574       Handle<Code> code =
1575           isolate->factory()->NewCode(desc, flags, masm.CodeObject());
1576       // Log the event and add the code to the builtins array.
1577       PROFILE(isolate,
1578               CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
1579       builtins_[i] = *code;
1580       code->set_builtin_index(i);
1581 #ifdef ENABLE_DISASSEMBLER
1582       if (FLAG_print_builtin_code) {
1583         CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
1584         OFStream os(trace_scope.file());
1585         os << "Builtin: " << functions[i].s_name << "\n";
1586         code->Disassemble(functions[i].s_name, os);
1587         os << "\n";
1588       }
1589 #endif
1590     } else {
1591       // Deserializing. The values will be filled in during IterateBuiltins.
1592       builtins_[i] = NULL;
1593     }
1594     names_[i] = functions[i].s_name;
1595   }
1596
1597   // Mark as initialized.
1598   initialized_ = true;
1599 }
1600
1601
1602 void Builtins::TearDown() {
1603   initialized_ = false;
1604 }
1605
1606
1607 void Builtins::IterateBuiltins(ObjectVisitor* v) {
1608   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
1609 }
1610
1611
1612 const char* Builtins::Lookup(byte* pc) {
1613   // may be called during initialization (disassembler!)
1614   if (initialized_) {
1615     for (int i = 0; i < builtin_count; i++) {
1616       Code* entry = Code::cast(builtins_[i]);
1617       if (entry->contains(pc)) {
1618         return names_[i];
1619       }
1620     }
1621   }
1622   return NULL;
1623 }
1624
1625
1626 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
1627   masm->TailCallRuntime(Runtime::kInterrupt, 0, 1);
1628 }
1629
1630
1631 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
1632   masm->TailCallRuntime(Runtime::kStackGuard, 0, 1);
1633 }
1634
1635
1636 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
1637 Handle<Code> Builtins::name() {                               \
1638   Code** code_address =                                       \
1639       reinterpret_cast<Code**>(builtin_address(k##name));     \
1640   return Handle<Code>(code_address);                          \
1641 }
1642 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
1643 Handle<Code> Builtins::name() {                             \
1644   Code** code_address =                                     \
1645       reinterpret_cast<Code**>(builtin_address(k##name));   \
1646   return Handle<Code>(code_address);                        \
1647 }
1648 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind)               \
1649 Handle<Code> Builtins::name() {                             \
1650   Code** code_address =                                     \
1651       reinterpret_cast<Code**>(builtin_address(k##name));   \
1652   return Handle<Code>(code_address);                        \
1653 }
1654 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1655 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1656 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1657 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1658 #undef DEFINE_BUILTIN_ACCESSOR_C
1659 #undef DEFINE_BUILTIN_ACCESSOR_A
1660
1661
1662 }  // namespace internal
1663 }  // namespace v8