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