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