Home | History | Annotate | Download | only in src
      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         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 #ifdef DEBUG
   1147 
   1148 static void VerifyTypeCheck(Handle<JSObject> object,
   1149                             Handle<JSFunction> function) {
   1150   ASSERT(function->shared()->IsApiFunction());
   1151   FunctionTemplateInfo* info = function->shared()->get_api_func_data();
   1152   if (info->signature()->IsUndefined()) return;
   1153   SignatureInfo* signature = SignatureInfo::cast(info->signature());
   1154   Object* receiver_type = signature->receiver();
   1155   if (receiver_type->IsUndefined()) return;
   1156   FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type);
   1157   ASSERT(object->IsInstanceOf(type));
   1158 }
   1159 
   1160 #endif
   1161 
   1162 
   1163 BUILTIN(FastHandleApiCall) {
   1164   ASSERT(!CalledAsConstructor(isolate));
   1165   Heap* heap = isolate->heap();
   1166   const bool is_construct = false;
   1167 
   1168   // We expect four more arguments: callback, function, call data, and holder.
   1169   const int args_length = args.length() - 4;
   1170   ASSERT(args_length >= 0);
   1171 
   1172   Object* callback_obj = args[args_length];
   1173 
   1174   v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
   1175       &args[args_length + 1],
   1176       &args[0] - 1,
   1177       args_length - 1,
   1178       is_construct);
   1179 
   1180 #ifdef DEBUG
   1181   VerifyTypeCheck(Utils::OpenHandle(*new_args.Holder()),
   1182                   Utils::OpenHandle(*new_args.Callee()));
   1183 #endif
   1184   HandleScope scope(isolate);
   1185   Object* result;
   1186   v8::Handle<v8::Value> value;
   1187   {
   1188     // Leaving JavaScript.
   1189     VMState state(isolate, EXTERNAL);
   1190     ExternalCallbackScope call_scope(isolate,
   1191                                      v8::ToCData<Address>(callback_obj));
   1192     v8::InvocationCallback callback =
   1193         v8::ToCData<v8::InvocationCallback>(callback_obj);
   1194 
   1195     value = callback(new_args);
   1196   }
   1197   if (value.IsEmpty()) {
   1198     result = heap->undefined_value();
   1199   } else {
   1200     result = *reinterpret_cast<Object**>(*value);
   1201   }
   1202 
   1203   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1204   return result;
   1205 }
   1206 
   1207 
   1208 // Helper function to handle calls to non-function objects created through the
   1209 // API. The object can be called as either a constructor (using new) or just as
   1210 // a function (without new).
   1211 MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
   1212     Isolate* isolate,
   1213     bool is_construct_call,
   1214     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
   1215   // Non-functions are never called as constructors. Even if this is an object
   1216   // called as a constructor the delegate call is not a construct call.
   1217   ASSERT(!CalledAsConstructor(isolate));
   1218   Heap* heap = isolate->heap();
   1219 
   1220   Handle<Object> receiver = args.receiver();
   1221 
   1222   // Get the object called.
   1223   JSObject* obj = JSObject::cast(*receiver);
   1224 
   1225   // Get the invocation callback from the function descriptor that was
   1226   // used to create the called object.
   1227   ASSERT(obj->map()->has_instance_call_handler());
   1228   JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
   1229   ASSERT(constructor->shared()->IsApiFunction());
   1230   Object* handler =
   1231       constructor->shared()->get_api_func_data()->instance_call_handler();
   1232   ASSERT(!handler->IsUndefined());
   1233   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
   1234   Object* callback_obj = call_data->callback();
   1235   v8::InvocationCallback callback =
   1236       v8::ToCData<v8::InvocationCallback>(callback_obj);
   1237 
   1238   // Get the data for the call and perform the callback.
   1239   Object* result;
   1240   {
   1241     HandleScope scope(isolate);
   1242     LOG(isolate, ApiObjectAccess("call non-function", obj));
   1243 
   1244     CustomArguments custom(isolate);
   1245     v8::ImplementationUtilities::PrepareArgumentsData(custom.end(),
   1246         call_data->data(), constructor, obj);
   1247     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
   1248         custom.end(),
   1249         &args[0] - 1,
   1250         args.length() - 1,
   1251         is_construct_call);
   1252     v8::Handle<v8::Value> value;
   1253     {
   1254       // Leaving JavaScript.
   1255       VMState state(isolate, EXTERNAL);
   1256       ExternalCallbackScope call_scope(isolate,
   1257                                        v8::ToCData<Address>(callback_obj));
   1258       value = callback(new_args);
   1259     }
   1260     if (value.IsEmpty()) {
   1261       result = heap->undefined_value();
   1262     } else {
   1263       result = *reinterpret_cast<Object**>(*value);
   1264     }
   1265   }
   1266   // Check for exceptions and return result.
   1267   RETURN_IF_SCHEDULED_EXCEPTION(isolate);
   1268   return result;
   1269 }
   1270 
   1271 
   1272 // Handle calls to non-function objects created through the API. This delegate
   1273 // function is used when the call is a normal function call.
   1274 BUILTIN(HandleApiCallAsFunction) {
   1275   return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
   1276 }
   1277 
   1278 
   1279 // Handle calls to non-function objects created through the API. This delegate
   1280 // function is used when the call is a construct call.
   1281 BUILTIN(HandleApiCallAsConstructor) {
   1282   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
   1283 }
   1284 
   1285 
   1286 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
   1287   LoadIC::GenerateArrayLength(masm);
   1288 }
   1289 
   1290 
   1291 static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
   1292   LoadIC::GenerateStringLength(masm, false);
   1293 }
   1294 
   1295 
   1296 static void Generate_LoadIC_StringWrapperLength(MacroAssembler* masm) {
   1297   LoadIC::GenerateStringLength(masm, true);
   1298 }
   1299 
   1300 
   1301 static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
   1302   LoadIC::GenerateFunctionPrototype(masm);
   1303 }
   1304 
   1305 
   1306 static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
   1307   LoadIC::GenerateInitialize(masm);
   1308 }
   1309 
   1310 
   1311 static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
   1312   LoadIC::GeneratePreMonomorphic(masm);
   1313 }
   1314 
   1315 
   1316 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
   1317   LoadIC::GenerateMiss(masm);
   1318 }
   1319 
   1320 
   1321 static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
   1322   LoadIC::GenerateMegamorphic(masm);
   1323 }
   1324 
   1325 
   1326 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
   1327   LoadIC::GenerateNormal(masm);
   1328 }
   1329 
   1330 
   1331 static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
   1332   KeyedLoadIC::GenerateInitialize(masm);
   1333 }
   1334 
   1335 
   1336 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
   1337   KeyedLoadIC::GenerateRuntimeGetProperty(masm);
   1338 }
   1339 
   1340 
   1341 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
   1342   KeyedLoadIC::GenerateMiss(masm, false);
   1343 }
   1344 
   1345 
   1346 static void Generate_KeyedLoadIC_MissForceGeneric(MacroAssembler* masm) {
   1347   KeyedLoadIC::GenerateMiss(masm, true);
   1348 }
   1349 
   1350 
   1351 static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
   1352   KeyedLoadIC::GenerateGeneric(masm);
   1353 }
   1354 
   1355 
   1356 static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
   1357   KeyedLoadIC::GenerateString(masm);
   1358 }
   1359 
   1360 
   1361 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
   1362   KeyedLoadIC::GeneratePreMonomorphic(masm);
   1363 }
   1364 
   1365 static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
   1366   KeyedLoadIC::GenerateIndexedInterceptor(masm);
   1367 }
   1368 
   1369 static void Generate_KeyedLoadIC_NonStrictArguments(MacroAssembler* masm) {
   1370   KeyedLoadIC::GenerateNonStrictArguments(masm);
   1371 }
   1372 
   1373 static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
   1374   StoreIC::GenerateInitialize(masm);
   1375 }
   1376 
   1377 
   1378 static void Generate_StoreIC_Initialize_Strict(MacroAssembler* masm) {
   1379   StoreIC::GenerateInitialize(masm);
   1380 }
   1381 
   1382 
   1383 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
   1384   StoreIC::GenerateMiss(masm);
   1385 }
   1386 
   1387 
   1388 static void Generate_StoreIC_Normal(MacroAssembler* masm) {
   1389   StoreIC::GenerateNormal(masm);
   1390 }
   1391 
   1392 
   1393 static void Generate_StoreIC_Normal_Strict(MacroAssembler* masm) {
   1394   StoreIC::GenerateNormal(masm);
   1395 }
   1396 
   1397 
   1398 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
   1399   StoreIC::GenerateMegamorphic(masm, kNonStrictMode);
   1400 }
   1401 
   1402 
   1403 static void Generate_StoreIC_Megamorphic_Strict(MacroAssembler* masm) {
   1404   StoreIC::GenerateMegamorphic(masm, kStrictMode);
   1405 }
   1406 
   1407 
   1408 static void Generate_StoreIC_ArrayLength(MacroAssembler* masm) {
   1409   StoreIC::GenerateArrayLength(masm);
   1410 }
   1411 
   1412 
   1413 static void Generate_StoreIC_ArrayLength_Strict(MacroAssembler* masm) {
   1414   StoreIC::GenerateArrayLength(masm);
   1415 }
   1416 
   1417 
   1418 static void Generate_StoreIC_GlobalProxy(MacroAssembler* masm) {
   1419   StoreIC::GenerateGlobalProxy(masm, kNonStrictMode);
   1420 }
   1421 
   1422 
   1423 static void Generate_StoreIC_GlobalProxy_Strict(MacroAssembler* masm) {
   1424   StoreIC::GenerateGlobalProxy(masm, kStrictMode);
   1425 }
   1426 
   1427 
   1428 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
   1429   KeyedStoreIC::GenerateGeneric(masm, kNonStrictMode);
   1430 }
   1431 
   1432 
   1433 static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
   1434   KeyedStoreIC::GenerateGeneric(masm, kStrictMode);
   1435 }
   1436 
   1437 
   1438 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
   1439   KeyedStoreIC::GenerateMiss(masm, false);
   1440 }
   1441 
   1442 
   1443 static void Generate_KeyedStoreIC_MissForceGeneric(MacroAssembler* masm) {
   1444   KeyedStoreIC::GenerateMiss(masm, true);
   1445 }
   1446 
   1447 
   1448 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
   1449   KeyedStoreIC::GenerateSlow(masm);
   1450 }
   1451 
   1452 
   1453 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
   1454   KeyedStoreIC::GenerateInitialize(masm);
   1455 }
   1456 
   1457 
   1458 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
   1459   KeyedStoreIC::GenerateInitialize(masm);
   1460 }
   1461 
   1462 static void Generate_KeyedStoreIC_NonStrictArguments(MacroAssembler* masm) {
   1463   KeyedStoreIC::GenerateNonStrictArguments(masm);
   1464 }
   1465 
   1466 static void Generate_TransitionElementsSmiToDouble(MacroAssembler* masm) {
   1467   KeyedStoreIC::GenerateTransitionElementsSmiToDouble(masm);
   1468 }
   1469 
   1470 static void Generate_TransitionElementsDoubleToObject(MacroAssembler* masm) {
   1471   KeyedStoreIC::GenerateTransitionElementsDoubleToObject(masm);
   1472 }
   1473 
   1474 #ifdef ENABLE_DEBUGGER_SUPPORT
   1475 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
   1476   Debug::GenerateLoadICDebugBreak(masm);
   1477 }
   1478 
   1479 
   1480 static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
   1481   Debug::GenerateStoreICDebugBreak(masm);
   1482 }
   1483 
   1484 
   1485 static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
   1486   Debug::GenerateKeyedLoadICDebugBreak(masm);
   1487 }
   1488 
   1489 
   1490 static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
   1491   Debug::GenerateKeyedStoreICDebugBreak(masm);
   1492 }
   1493 
   1494 
   1495 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
   1496   Debug::GenerateReturnDebugBreak(masm);
   1497 }
   1498 
   1499 
   1500 static void Generate_CallFunctionStub_DebugBreak(MacroAssembler* masm) {
   1501   Debug::GenerateCallFunctionStubDebugBreak(masm);
   1502 }
   1503 
   1504 
   1505 static void Generate_CallFunctionStub_Recording_DebugBreak(
   1506     MacroAssembler* masm) {
   1507   Debug::GenerateCallFunctionStubRecordDebugBreak(masm);
   1508 }
   1509 
   1510 
   1511 static void Generate_CallConstructStub_DebugBreak(MacroAssembler* masm) {
   1512   Debug::GenerateCallConstructStubDebugBreak(masm);
   1513 }
   1514 
   1515 
   1516 static void Generate_CallConstructStub_Recording_DebugBreak(
   1517     MacroAssembler* masm) {
   1518   Debug::GenerateCallConstructStubRecordDebugBreak(masm);
   1519 }
   1520 
   1521 
   1522 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
   1523   Debug::GenerateSlotDebugBreak(masm);
   1524 }
   1525 
   1526 
   1527 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
   1528   Debug::GeneratePlainReturnLiveEdit(masm);
   1529 }
   1530 
   1531 
   1532 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
   1533   Debug::GenerateFrameDropperLiveEdit(masm);
   1534 }
   1535 #endif
   1536 
   1537 
   1538 Builtins::Builtins() : initialized_(false) {
   1539   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
   1540   memset(names_, 0, sizeof(names_[0]) * builtin_count);
   1541 }
   1542 
   1543 
   1544 Builtins::~Builtins() {
   1545 }
   1546 
   1547 
   1548 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
   1549 Address const Builtins::c_functions_[cfunction_count] = {
   1550   BUILTIN_LIST_C(DEF_ENUM_C)
   1551 };
   1552 #undef DEF_ENUM_C
   1553 
   1554 #define DEF_JS_NAME(name, ignore) #name,
   1555 #define DEF_JS_ARGC(ignore, argc) argc,
   1556 const char* const Builtins::javascript_names_[id_count] = {
   1557   BUILTINS_LIST_JS(DEF_JS_NAME)
   1558 };
   1559 
   1560 int const Builtins::javascript_argc_[id_count] = {
   1561   BUILTINS_LIST_JS(DEF_JS_ARGC)
   1562 };
   1563 #undef DEF_JS_NAME
   1564 #undef DEF_JS_ARGC
   1565 
   1566 struct BuiltinDesc {
   1567   byte* generator;
   1568   byte* c_code;
   1569   const char* s_name;  // name is only used for generating log information.
   1570   int name;
   1571   Code::Flags flags;
   1572   BuiltinExtraArguments extra_args;
   1573 };
   1574 
   1575 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
   1576 
   1577 class BuiltinFunctionTable {
   1578  public:
   1579   BuiltinDesc* functions() {
   1580     CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
   1581     return functions_;
   1582   }
   1583 
   1584   OnceType once_;
   1585   BuiltinDesc functions_[Builtins::builtin_count + 1];
   1586 
   1587   friend class Builtins;
   1588 };
   1589 
   1590 static BuiltinFunctionTable builtin_function_table =
   1591     BUILTIN_FUNCTION_TABLE_INIT;
   1592 
   1593 // Define array of pointers to generators and C builtin functions.
   1594 // We do this in a sort of roundabout way so that we can do the initialization
   1595 // within the lexical scope of Builtins:: and within a context where
   1596 // Code::Flags names a non-abstract type.
   1597 void Builtins::InitBuiltinFunctionTable() {
   1598   BuiltinDesc* functions = builtin_function_table.functions_;
   1599   functions[builtin_count].generator = NULL;
   1600   functions[builtin_count].c_code = NULL;
   1601   functions[builtin_count].s_name = NULL;
   1602   functions[builtin_count].name = builtin_count;
   1603   functions[builtin_count].flags = static_cast<Code::Flags>(0);
   1604   functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
   1605 
   1606 #define DEF_FUNCTION_PTR_C(aname, aextra_args)                         \
   1607     functions->generator = FUNCTION_ADDR(Generate_Adaptor);            \
   1608     functions->c_code = FUNCTION_ADDR(Builtin_##aname);                \
   1609     functions->s_name = #aname;                                        \
   1610     functions->name = c_##aname;                                       \
   1611     functions->flags = Code::ComputeFlags(Code::BUILTIN);              \
   1612     functions->extra_args = aextra_args;                               \
   1613     ++functions;
   1614 
   1615 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra)                       \
   1616     functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
   1617     functions->c_code = NULL;                                               \
   1618     functions->s_name = #aname;                                             \
   1619     functions->name = k##aname;                                             \
   1620     functions->flags = Code::ComputeFlags(Code::kind,                       \
   1621                                           state,                            \
   1622                                           extra);                           \
   1623     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
   1624     ++functions;
   1625 
   1626   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
   1627   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
   1628   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
   1629 
   1630 #undef DEF_FUNCTION_PTR_C
   1631 #undef DEF_FUNCTION_PTR_A
   1632 }
   1633 
   1634 void Builtins::SetUp(bool create_heap_objects) {
   1635   ASSERT(!initialized_);
   1636   Isolate* isolate = Isolate::Current();
   1637   Heap* heap = isolate->heap();
   1638 
   1639   // Create a scope for the handles in the builtins.
   1640   HandleScope scope(isolate);
   1641 
   1642   const BuiltinDesc* functions = builtin_function_table.functions();
   1643 
   1644   // For now we generate builtin adaptor code into a stack-allocated
   1645   // buffer, before copying it into individual code objects. Be careful
   1646   // with alignment, some platforms don't like unaligned code.
   1647   union { int force_alignment; byte buffer[4*KB]; } u;
   1648 
   1649   // Traverse the list of builtins and generate an adaptor in a
   1650   // separate code object for each one.
   1651   for (int i = 0; i < builtin_count; i++) {
   1652     if (create_heap_objects) {
   1653       MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
   1654       // Generate the code/adaptor.
   1655       typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
   1656       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
   1657       // We pass all arguments to the generator, but it may not use all of
   1658       // them.  This works because the first arguments are on top of the
   1659       // stack.
   1660       ASSERT(!masm.has_frame());
   1661       g(&masm, functions[i].name, functions[i].extra_args);
   1662       // Move the code into the object heap.
   1663       CodeDesc desc;
   1664       masm.GetCode(&desc);
   1665       Code::Flags flags =  functions[i].flags;
   1666       Object* code = NULL;
   1667       {
   1668         // During startup it's OK to always allocate and defer GC to later.
   1669         // This simplifies things because we don't need to retry.
   1670         AlwaysAllocateScope __scope__;
   1671         { MaybeObject* maybe_code =
   1672               heap->CreateCode(desc, flags, masm.CodeObject());
   1673           if (!maybe_code->ToObject(&code)) {
   1674             v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
   1675           }
   1676         }
   1677       }
   1678       // Log the event and add the code to the builtins array.
   1679       PROFILE(isolate,
   1680               CodeCreateEvent(Logger::BUILTIN_TAG,
   1681                               Code::cast(code),
   1682                               functions[i].s_name));
   1683       GDBJIT(AddCode(GDBJITInterface::BUILTIN,
   1684                      functions[i].s_name,
   1685                      Code::cast(code)));
   1686       builtins_[i] = code;
   1687 #ifdef ENABLE_DISASSEMBLER
   1688       if (FLAG_print_builtin_code) {
   1689         PrintF("Builtin: %s\n", functions[i].s_name);
   1690         Code::cast(code)->Disassemble(functions[i].s_name);
   1691         PrintF("\n");
   1692       }
   1693 #endif
   1694     } else {
   1695       // Deserializing. The values will be filled in during IterateBuiltins.
   1696       builtins_[i] = NULL;
   1697     }
   1698     names_[i] = functions[i].s_name;
   1699   }
   1700 
   1701   // Mark as initialized.
   1702   initialized_ = true;
   1703 }
   1704 
   1705 
   1706 void Builtins::TearDown() {
   1707   initialized_ = false;
   1708 }
   1709 
   1710 
   1711 void Builtins::IterateBuiltins(ObjectVisitor* v) {
   1712   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
   1713 }
   1714 
   1715 
   1716 const char* Builtins::Lookup(byte* pc) {
   1717   // may be called during initialization (disassembler!)
   1718   if (initialized_) {
   1719     for (int i = 0; i < builtin_count; i++) {
   1720       Code* entry = Code::cast(builtins_[i]);
   1721       if (entry->contains(pc)) {
   1722         return names_[i];
   1723       }
   1724     }
   1725   }
   1726   return NULL;
   1727 }
   1728 
   1729 
   1730 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
   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 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
   1737 Handle<Code> Builtins::name() {                             \
   1738   Code** code_address =                                     \
   1739       reinterpret_cast<Code**>(builtin_address(k##name));   \
   1740   return Handle<Code>(code_address);                        \
   1741 }
   1742 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
   1743 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
   1744 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
   1745 #undef DEFINE_BUILTIN_ACCESSOR_C
   1746 #undef DEFINE_BUILTIN_ACCESSOR_A
   1747 
   1748 
   1749 } }  // namespace v8::internal
   1750