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