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