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 "ic-inl.h"
     35 
     36 namespace v8 {
     37 namespace internal {
     38 
     39 namespace {
     40 
     41 // Arguments object passed to C++ builtins.
     42 template <BuiltinExtraArguments extra_args>
     43 class BuiltinArguments : public Arguments {
     44  public:
     45   BuiltinArguments(int length, Object** arguments)
     46       : Arguments(length, arguments) { }
     47 
     48   Object*& operator[] (int index) {
     49     ASSERT(index < length());
     50     return Arguments::operator[](index);
     51   }
     52 
     53   template <class S> Handle<S> at(int index) {
     54     ASSERT(index < length());
     55     return Arguments::at<S>(index);
     56   }
     57 
     58   Handle<Object> receiver() {
     59     return Arguments::at<Object>(0);
     60   }
     61 
     62   Handle<JSFunction> called_function() {
     63     STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
     64     return Arguments::at<JSFunction>(Arguments::length() - 1);
     65   }
     66 
     67   // Gets the total number of arguments including the receiver (but
     68   // excluding extra arguments).
     69   int length() const {
     70     STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
     71     return Arguments::length();
     72   }
     73 
     74 #ifdef DEBUG
     75   void Verify() {
     76     // Check we have at least the receiver.
     77     ASSERT(Arguments::length() >= 1);
     78   }
     79 #endif
     80 };
     81 
     82 
     83 // Specialize BuiltinArguments for the called function extra argument.
     84 
     85 template <>
     86 int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
     87   return Arguments::length() - 1;
     88 }
     89 
     90 #ifdef DEBUG
     91 template <>
     92 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
     93   // Check we have at least the receiver and the called function.
     94   ASSERT(Arguments::length() >= 2);
     95   // Make sure cast to JSFunction succeeds.
     96   called_function();
     97 }
     98 #endif
     99 
    100 
    101 #define DEF_ARG_TYPE(name, spec)                      \
    102   typedef BuiltinArguments<spec> name##ArgumentsType;
    103 BUILTIN_LIST_C(DEF_ARG_TYPE)
    104 #undef DEF_ARG_TYPE
    105 
    106 }  // namespace
    107 
    108 
    109 // ----------------------------------------------------------------------------
    110 // Support macro for defining builtins in C++.
    111 // ----------------------------------------------------------------------------
    112 //
    113 // A builtin function is defined by writing:
    114 //
    115 //   BUILTIN(name) {
    116 //     ...
    117 //   }
    118 //
    119 // In the body of the builtin function the arguments can be accessed
    120 // through the BuiltinArguments object args.
    121 
    122 #ifdef DEBUG
    123 
    124 #define BUILTIN(name)                                           \
    125   static Object* Builtin_Impl_##name(name##ArgumentsType args); \
    126   static Object* Builtin_##name(name##ArgumentsType args) {     \
    127     args.Verify();                                              \
    128     return Builtin_Impl_##name(args);                           \
    129   }                                                             \
    130   static Object* Builtin_Impl_##name(name##ArgumentsType args)
    131 
    132 #else  // For release mode.
    133 
    134 #define BUILTIN(name)                                           \
    135   static Object* Builtin_##name(name##ArgumentsType args)
    136 
    137 #endif
    138 
    139 
    140 static inline bool CalledAsConstructor() {
    141 #ifdef DEBUG
    142   // Calculate the result using a full stack frame iterator and check
    143   // that the state of the stack is as we assume it to be in the
    144   // code below.
    145   StackFrameIterator it;
    146   ASSERT(it.frame()->is_exit());
    147   it.Advance();
    148   StackFrame* frame = it.frame();
    149   bool reference_result = frame->is_construct();
    150 #endif
    151   Address fp = Top::c_entry_fp(Top::GetCurrentThread());
    152   // Because we know fp points to an exit frame we can use the relevant
    153   // part of ExitFrame::ComputeCallerState directly.
    154   const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
    155   Address caller_fp = Memory::Address_at(fp + kCallerOffset);
    156   // This inlines the part of StackFrame::ComputeType that grabs the
    157   // type of the current frame.  Note that StackFrame::ComputeType
    158   // has been specialized for each architecture so if any one of them
    159   // changes this code has to be changed as well.
    160   const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
    161   const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
    162   Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
    163   bool result = (marker == kConstructMarker);
    164   ASSERT_EQ(result, reference_result);
    165   return result;
    166 }
    167 
    168 // ----------------------------------------------------------------------------
    169 
    170 
    171 BUILTIN(Illegal) {
    172   UNREACHABLE();
    173   return Heap::undefined_value();  // Make compiler happy.
    174 }
    175 
    176 
    177 BUILTIN(EmptyFunction) {
    178   return Heap::undefined_value();
    179 }
    180 
    181 
    182 BUILTIN(ArrayCodeGeneric) {
    183   Counters::array_function_runtime.Increment();
    184 
    185   JSArray* array;
    186   if (CalledAsConstructor()) {
    187     array = JSArray::cast(*args.receiver());
    188   } else {
    189     // Allocate the JS Array
    190     JSFunction* constructor =
    191         Top::context()->global_context()->array_function();
    192     Object* obj = Heap::AllocateJSObject(constructor);
    193     if (obj->IsFailure()) return obj;
    194     array = JSArray::cast(obj);
    195   }
    196 
    197   // 'array' now contains the JSArray we should initialize.
    198 
    199   // Optimize the case where there is one argument and the argument is a
    200   // small smi.
    201   if (args.length() == 2) {
    202     Object* obj = args[1];
    203     if (obj->IsSmi()) {
    204       int len = Smi::cast(obj)->value();
    205       if (len >= 0 && len < JSObject::kInitialMaxFastElementArray) {
    206         Object* obj = Heap::AllocateFixedArrayWithHoles(len);
    207         if (obj->IsFailure()) return obj;
    208         array->SetContent(FixedArray::cast(obj));
    209         return array;
    210       }
    211     }
    212     // Take the argument as the length.
    213     obj = array->Initialize(0);
    214     if (obj->IsFailure()) return obj;
    215     return array->SetElementsLength(args[1]);
    216   }
    217 
    218   // Optimize the case where there are no parameters passed.
    219   if (args.length() == 1) {
    220     return array->Initialize(JSArray::kPreallocatedArrayElements);
    221   }
    222 
    223   // Take the arguments as elements.
    224   int number_of_elements = args.length() - 1;
    225   Smi* len = Smi::FromInt(number_of_elements);
    226   Object* obj = Heap::AllocateFixedArrayWithHoles(len->value());
    227   if (obj->IsFailure()) return obj;
    228 
    229   AssertNoAllocation no_gc;
    230   FixedArray* elms = FixedArray::cast(obj);
    231   WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
    232   // Fill in the content
    233   for (int index = 0; index < number_of_elements; index++) {
    234     elms->set(index, args[index+1], mode);
    235   }
    236 
    237   // Set length and elements on the array.
    238   array->set_elements(FixedArray::cast(obj));
    239   array->set_length(len);
    240 
    241   return array;
    242 }
    243 
    244 
    245 BUILTIN(ArrayPush) {
    246   JSArray* array = JSArray::cast(*args.receiver());
    247   ASSERT(array->HasFastElements());
    248 
    249   int len = Smi::cast(array->length())->value();
    250   int to_add = args.length() - 1;
    251   if (to_add == 0) {
    252     return Smi::FromInt(len);
    253   }
    254   // Currently fixed arrays cannot grow too big, so
    255   // we should never hit this case.
    256   ASSERT(to_add <= (Smi::kMaxValue - len));
    257 
    258   int new_length = len + to_add;
    259   FixedArray* elms = FixedArray::cast(array->elements());
    260 
    261   if (new_length > elms->length()) {
    262     // New backing storage is needed.
    263     int capacity = new_length + (new_length >> 1) + 16;
    264     Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
    265     if (obj->IsFailure()) return obj;
    266 
    267     AssertNoAllocation no_gc;
    268     FixedArray* new_elms = FixedArray::cast(obj);
    269     WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
    270     // Fill out the new array with old elements.
    271     for (int i = 0; i < len; i++) new_elms->set(i, elms->get(i), mode);
    272     elms = new_elms;
    273     array->set_elements(elms);
    274   }
    275 
    276   AssertNoAllocation no_gc;
    277   WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
    278 
    279   // Add the provided values.
    280   for (int index = 0; index < to_add; index++) {
    281     elms->set(index + len, args[index + 1], mode);
    282   }
    283 
    284   // Set the length.
    285   array->set_length(Smi::FromInt(new_length));
    286   return Smi::FromInt(new_length);
    287 }
    288 
    289 
    290 BUILTIN(ArrayPop) {
    291   JSArray* array = JSArray::cast(*args.receiver());
    292   ASSERT(array->HasFastElements());
    293   Object* undefined = Heap::undefined_value();
    294 
    295   int len = Smi::cast(array->length())->value();
    296   if (len == 0) return undefined;
    297 
    298   // Get top element
    299   FixedArray* elms = FixedArray::cast(array->elements());
    300   Object* top = elms->get(len - 1);
    301 
    302   // Set the length.
    303   array->set_length(Smi::FromInt(len - 1));
    304 
    305   if (!top->IsTheHole()) {
    306     // Delete the top element.
    307     elms->set_the_hole(len - 1);
    308     return top;
    309   }
    310 
    311   // Remember to check the prototype chain.
    312   JSFunction* array_function =
    313       Top::context()->global_context()->array_function();
    314   JSObject* prototype = JSObject::cast(array_function->prototype());
    315   top = prototype->GetElement(len - 1);
    316 
    317   return top;
    318 }
    319 
    320 
    321 static Object* GetElementToMove(uint32_t index,
    322                                 FixedArray* elms,
    323                                 JSObject* prototype) {
    324   Object* e = elms->get(index);
    325   if (e->IsTheHole() && prototype->HasElement(index)) {
    326     e = prototype->GetElement(index);
    327   }
    328   return e;
    329 }
    330 
    331 
    332 BUILTIN(ArrayShift) {
    333   JSArray* array = JSArray::cast(*args.receiver());
    334   ASSERT(array->HasFastElements());
    335 
    336   int len = Smi::cast(array->length())->value();
    337   if (len == 0) return Heap::undefined_value();
    338 
    339   // Fetch the prototype.
    340   JSFunction* array_function =
    341       Top::context()->global_context()->array_function();
    342   JSObject* prototype = JSObject::cast(array_function->prototype());
    343 
    344   FixedArray* elms = FixedArray::cast(array->elements());
    345 
    346   // Get first element
    347   Object* first = elms->get(0);
    348   if (first->IsTheHole()) {
    349     first = prototype->GetElement(0);
    350   }
    351 
    352   // Shift the elements.
    353   for (int i = 0; i < len - 1; i++) {
    354     elms->set(i, GetElementToMove(i + 1, elms, prototype));
    355   }
    356   elms->set(len - 1, Heap::the_hole_value());
    357 
    358   // Set the length.
    359   array->set_length(Smi::FromInt(len - 1));
    360 
    361   return first;
    362 }
    363 
    364 
    365 BUILTIN(ArrayUnshift) {
    366   JSArray* array = JSArray::cast(*args.receiver());
    367   ASSERT(array->HasFastElements());
    368 
    369   int len = Smi::cast(array->length())->value();
    370   int to_add = args.length() - 1;
    371   // Note that we cannot quit early if to_add == 0 as
    372   // values should be lifted from prototype into
    373   // the array.
    374 
    375   int new_length = len + to_add;
    376   // Currently fixed arrays cannot grow too big, so
    377   // we should never hit this case.
    378   ASSERT(to_add <= (Smi::kMaxValue - len));
    379 
    380   FixedArray* elms = FixedArray::cast(array->elements());
    381 
    382   // Fetch the prototype.
    383   JSFunction* array_function =
    384       Top::context()->global_context()->array_function();
    385   JSObject* prototype = JSObject::cast(array_function->prototype());
    386 
    387   if (new_length > elms->length()) {
    388     // New backing storage is needed.
    389     int capacity = new_length + (new_length >> 1) + 16;
    390     Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
    391     if (obj->IsFailure()) return obj;
    392 
    393     AssertNoAllocation no_gc;
    394     FixedArray* new_elms = FixedArray::cast(obj);
    395     WriteBarrierMode mode = new_elms->GetWriteBarrierMode(no_gc);
    396     // Fill out the new array with old elements.
    397     for (int i = 0; i < len; i++)
    398       new_elms->set(to_add + i,
    399                     GetElementToMove(i, elms, prototype),
    400                     mode);
    401 
    402     elms = new_elms;
    403     array->set_elements(elms);
    404   } else {
    405     AssertNoAllocation no_gc;
    406     WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
    407 
    408     // Move elements to the right
    409     for (int i = 0; i < len; i++) {
    410       elms->set(new_length - i - 1,
    411                 GetElementToMove(len - i - 1, elms, prototype),
    412                 mode);
    413     }
    414   }
    415 
    416   // Add the provided values.
    417   AssertNoAllocation no_gc;
    418   WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
    419   for (int i = 0; i < to_add; i++) {
    420     elms->set(i, args[i + 1], mode);
    421   }
    422 
    423   // Set the length.
    424   array->set_length(Smi::FromInt(new_length));
    425   return Smi::FromInt(new_length);
    426 }
    427 
    428 
    429 static Object* CallJsBuiltin(const char* name,
    430                              BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
    431   HandleScope handleScope;
    432 
    433   Handle<Object> js_builtin =
    434       GetProperty(Handle<JSObject>(Top::global_context()->builtins()),
    435                   name);
    436   ASSERT(js_builtin->IsJSFunction());
    437   Handle<JSFunction> function(Handle<JSFunction>::cast(js_builtin));
    438   Vector<Object**> argv(Vector<Object**>::New(args.length() - 1));
    439   int n_args = args.length() - 1;
    440   for (int i = 0; i < n_args; i++) {
    441     argv[i] = &args[i + 1];
    442   }
    443   bool pending_exception = false;
    444   Handle<Object> result = Execution::Call(function,
    445                                           args.receiver(),
    446                                           n_args,
    447                                           argv.start(),
    448                                           &pending_exception);
    449   if (pending_exception) return Failure::Exception();
    450   return *result;
    451 }
    452 
    453 
    454 BUILTIN(ArraySlice) {
    455   JSArray* array = JSArray::cast(*args.receiver());
    456   ASSERT(array->HasFastElements());
    457 
    458   int len = Smi::cast(array->length())->value();
    459 
    460   int n_arguments = args.length() - 1;
    461 
    462   // Note carefully choosen defaults---if argument is missing,
    463   // it's undefined which gets converted to 0 for relativeStart
    464   // and to len for relativeEnd.
    465   int relativeStart = 0;
    466   int relativeEnd = len;
    467   if (n_arguments > 0) {
    468     Object* arg1 = args[1];
    469     if (arg1->IsSmi()) {
    470       relativeStart = Smi::cast(arg1)->value();
    471     } else if (!arg1->IsUndefined()) {
    472       return CallJsBuiltin("ArraySlice", args);
    473     }
    474     if (n_arguments > 1) {
    475       Object* arg2 = args[2];
    476       if (arg2->IsSmi()) {
    477         relativeEnd = Smi::cast(arg2)->value();
    478       } else if (!arg2->IsUndefined()) {
    479         return CallJsBuiltin("ArraySlice", args);
    480       }
    481     }
    482   }
    483 
    484   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
    485   int k = (relativeStart < 0) ? Max(len + relativeStart, 0)
    486                               : Min(relativeStart, len);
    487 
    488   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
    489   int final = (relativeEnd < 0) ? Max(len + relativeEnd, 0)
    490                                 : Min(relativeEnd, len);
    491 
    492   // Calculate the length of result array.
    493   int result_len = final - k;
    494   if (result_len < 0) {
    495     result_len = 0;
    496   }
    497 
    498   JSFunction* array_function =
    499       Top::context()->global_context()->array_function();
    500   Object* result = Heap::AllocateJSObject(array_function);
    501   if (result->IsFailure()) return result;
    502   JSArray* result_array = JSArray::cast(result);
    503 
    504   result = Heap::AllocateFixedArrayWithHoles(result_len);
    505   if (result->IsFailure()) return result;
    506   FixedArray* result_elms = FixedArray::cast(result);
    507 
    508   FixedArray* elms = FixedArray::cast(array->elements());
    509 
    510   // Fetch the prototype.
    511   JSObject* prototype = JSObject::cast(array_function->prototype());
    512 
    513   AssertNoAllocation no_gc;
    514   WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc);
    515 
    516   // Fill newly created array.
    517   for (int i = 0; i < result_len; i++) {
    518     result_elms->set(i,
    519                      GetElementToMove(k + i, elms, prototype),
    520                      mode);
    521   }
    522 
    523   // Set elements.
    524   result_array->set_elements(result_elms);
    525 
    526   // Set the length.
    527   result_array->set_length(Smi::FromInt(result_len));
    528   return result_array;
    529 }
    530 
    531 
    532 BUILTIN(ArraySplice) {
    533   JSArray* array = JSArray::cast(*args.receiver());
    534   ASSERT(array->HasFastElements());
    535 
    536   int len = Smi::cast(array->length())->value();
    537 
    538   int n_arguments = args.length() - 1;
    539 
    540   // SpiderMonkey and JSC return undefined in the case where no
    541   // arguments are given instead of using the implicit undefined
    542   // arguments.  This does not follow ECMA-262, but we do the same for
    543   // compatibility.
    544   // TraceMonkey follows ECMA-262 though.
    545   if (n_arguments == 0) {
    546     return Heap::undefined_value();
    547   }
    548 
    549   int relativeStart = 0;
    550   Object* arg1 = args[1];
    551   if (arg1->IsSmi()) {
    552     relativeStart = Smi::cast(arg1)->value();
    553   } else if (!arg1->IsUndefined()) {
    554     return CallJsBuiltin("ArraySplice", args);
    555   }
    556   int actualStart = (relativeStart < 0) ? Max(len + relativeStart, 0)
    557                                         : Min(relativeStart, len);
    558 
    559   // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
    560   // given differently from when an undefined delete count is given.
    561   // This does not follow ECMA-262, but we do the same for
    562   // compatibility.
    563   int deleteCount = len;
    564   if (n_arguments > 1) {
    565     Object* arg2 = args[2];
    566     if (arg2->IsSmi()) {
    567       deleteCount = Smi::cast(arg2)->value();
    568     } else {
    569       return CallJsBuiltin("ArraySplice", args);
    570     }
    571   }
    572   int actualDeleteCount = Min(Max(deleteCount, 0), len - actualStart);
    573 
    574   JSFunction* array_function =
    575       Top::context()->global_context()->array_function();
    576 
    577   // Allocate result array.
    578   Object* result = Heap::AllocateJSObject(array_function);
    579   if (result->IsFailure()) return result;
    580   JSArray* result_array = JSArray::cast(result);
    581 
    582   result = Heap::AllocateFixedArrayWithHoles(actualDeleteCount);
    583   if (result->IsFailure()) return result;
    584   FixedArray* result_elms = FixedArray::cast(result);
    585 
    586   FixedArray* elms = FixedArray::cast(array->elements());
    587 
    588   // Fetch the prototype.
    589   JSObject* prototype = JSObject::cast(array_function->prototype());
    590 
    591   AssertNoAllocation no_gc;
    592   WriteBarrierMode mode = result_elms->GetWriteBarrierMode(no_gc);
    593 
    594   // Fill newly created array.
    595   for (int k = 0; k < actualDeleteCount; k++) {
    596     result_elms->set(k,
    597                      GetElementToMove(actualStart + k, elms, prototype),
    598                      mode);
    599   }
    600 
    601   // Set elements.
    602   result_array->set_elements(result_elms);
    603 
    604   // Set the length.
    605   result_array->set_length(Smi::FromInt(actualDeleteCount));
    606 
    607   int itemCount = (n_arguments > 1) ? (n_arguments - 2) : 0;
    608 
    609   int new_length = len - actualDeleteCount + itemCount;
    610 
    611   mode = elms->GetWriteBarrierMode(no_gc);
    612   if (itemCount < actualDeleteCount) {
    613     // Shrink the array.
    614     for (int k = actualStart; k < (len - actualDeleteCount); k++) {
    615       elms->set(k + itemCount,
    616                 GetElementToMove(k + actualDeleteCount, elms, prototype),
    617                 mode);
    618     }
    619 
    620     for (int k = len; k > new_length; k--) {
    621       elms->set(k - 1, Heap::the_hole_value());
    622     }
    623   } else if (itemCount > actualDeleteCount) {
    624     // Currently fixed arrays cannot grow too big, so
    625     // we should never hit this case.
    626     ASSERT((itemCount - actualDeleteCount) <= (Smi::kMaxValue - len));
    627 
    628     FixedArray* source_elms = elms;
    629 
    630     // Check if array need to grow.
    631     if (new_length > elms->length()) {
    632       // New backing storage is needed.
    633       int capacity = new_length + (new_length >> 1) + 16;
    634       Object* obj = Heap::AllocateFixedArrayWithHoles(capacity);
    635       if (obj->IsFailure()) return obj;
    636 
    637       FixedArray* new_elms = FixedArray::cast(obj);
    638       mode = new_elms->GetWriteBarrierMode(no_gc);
    639 
    640       // Copy the part before actualStart as is.
    641       for (int k = 0; k < actualStart; k++) {
    642         new_elms->set(k, elms->get(k), mode);
    643       }
    644 
    645       source_elms = elms;
    646       elms = new_elms;
    647       array->set_elements(elms);
    648     }
    649 
    650     for (int k = len - actualDeleteCount; k > actualStart; k--) {
    651       elms->set(k + itemCount - 1,
    652                 GetElementToMove(k + actualDeleteCount - 1,
    653                                  source_elms,
    654                                  prototype),
    655                 mode);
    656     }
    657   }
    658 
    659   for (int k = actualStart; k < actualStart + itemCount; k++) {
    660     elms->set(k, args[3 + k - actualStart], mode);
    661   }
    662 
    663   // Set the length.
    664   array->set_length(Smi::FromInt(new_length));
    665 
    666   return result_array;
    667 }
    668 
    669 
    670 // -----------------------------------------------------------------------------
    671 //
    672 
    673 
    674 // Returns the holder JSObject if the function can legally be called
    675 // with this receiver.  Returns Heap::null_value() if the call is
    676 // illegal.  Any arguments that don't fit the expected type is
    677 // overwritten with undefined.  Arguments that do fit the expected
    678 // type is overwritten with the object in the prototype chain that
    679 // actually has that type.
    680 static inline Object* TypeCheck(int argc,
    681                                 Object** argv,
    682                                 FunctionTemplateInfo* info) {
    683   Object* recv = argv[0];
    684   Object* sig_obj = info->signature();
    685   if (sig_obj->IsUndefined()) return recv;
    686   SignatureInfo* sig = SignatureInfo::cast(sig_obj);
    687   // If necessary, check the receiver
    688   Object* recv_type = sig->receiver();
    689 
    690   Object* holder = recv;
    691   if (!recv_type->IsUndefined()) {
    692     for (; holder != Heap::null_value(); holder = holder->GetPrototype()) {
    693       if (holder->IsInstanceOf(FunctionTemplateInfo::cast(recv_type))) {
    694         break;
    695       }
    696     }
    697     if (holder == Heap::null_value()) return holder;
    698   }
    699   Object* args_obj = sig->args();
    700   // If there is no argument signature we're done
    701   if (args_obj->IsUndefined()) return holder;
    702   FixedArray* args = FixedArray::cast(args_obj);
    703   int length = args->length();
    704   if (argc <= length) length = argc - 1;
    705   for (int i = 0; i < length; i++) {
    706     Object* argtype = args->get(i);
    707     if (argtype->IsUndefined()) continue;
    708     Object** arg = &argv[-1 - i];
    709     Object* current = *arg;
    710     for (; current != Heap::null_value(); current = current->GetPrototype()) {
    711       if (current->IsInstanceOf(FunctionTemplateInfo::cast(argtype))) {
    712         *arg = current;
    713         break;
    714       }
    715     }
    716     if (current == Heap::null_value()) *arg = Heap::undefined_value();
    717   }
    718   return holder;
    719 }
    720 
    721 
    722 template <bool is_construct>
    723 static Object* HandleApiCallHelper(
    724     BuiltinArguments<NEEDS_CALLED_FUNCTION> args) {
    725   ASSERT(is_construct == CalledAsConstructor());
    726 
    727   HandleScope scope;
    728   Handle<JSFunction> function = args.called_function();
    729 
    730   if (is_construct) {
    731     Handle<FunctionTemplateInfo> desc =
    732         Handle<FunctionTemplateInfo>(
    733             FunctionTemplateInfo::cast(function->shared()->function_data()));
    734     bool pending_exception = false;
    735     Factory::ConfigureInstance(desc, Handle<JSObject>::cast(args.receiver()),
    736                                &pending_exception);
    737     ASSERT(Top::has_pending_exception() == pending_exception);
    738     if (pending_exception) return Failure::Exception();
    739   }
    740 
    741   FunctionTemplateInfo* fun_data =
    742       FunctionTemplateInfo::cast(function->shared()->function_data());
    743   Object* raw_holder = TypeCheck(args.length(), &args[0], fun_data);
    744 
    745   if (raw_holder->IsNull()) {
    746     // This function cannot be called with the given receiver.  Abort!
    747     Handle<Object> obj =
    748         Factory::NewTypeError("illegal_invocation", HandleVector(&function, 1));
    749     return Top::Throw(*obj);
    750   }
    751 
    752   Object* raw_call_data = fun_data->call_code();
    753   if (!raw_call_data->IsUndefined()) {
    754     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
    755     Object* callback_obj = call_data->callback();
    756     v8::InvocationCallback callback =
    757         v8::ToCData<v8::InvocationCallback>(callback_obj);
    758     Object* data_obj = call_data->data();
    759     Object* result;
    760 
    761     Handle<Object> data_handle(data_obj);
    762     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
    763     ASSERT(raw_holder->IsJSObject());
    764     v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
    765     Handle<JSObject> holder_handle(JSObject::cast(raw_holder));
    766     v8::Local<v8::Object> holder = v8::Utils::ToLocal(holder_handle);
    767     LOG(ApiObjectAccess("call", JSObject::cast(*args.receiver())));
    768     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
    769         data,
    770         holder,
    771         callee,
    772         is_construct,
    773         reinterpret_cast<void**>(&args[0] - 1),
    774         args.length() - 1);
    775 
    776     v8::Handle<v8::Value> value;
    777     {
    778       // Leaving JavaScript.
    779       VMState state(EXTERNAL);
    780 #ifdef ENABLE_LOGGING_AND_PROFILING
    781       state.set_external_callback(v8::ToCData<Address>(callback_obj));
    782 #endif
    783       value = callback(new_args);
    784     }
    785     if (value.IsEmpty()) {
    786       result = Heap::undefined_value();
    787     } else {
    788       result = *reinterpret_cast<Object**>(*value);
    789     }
    790 
    791     RETURN_IF_SCHEDULED_EXCEPTION();
    792     if (!is_construct || result->IsJSObject()) return result;
    793   }
    794 
    795   return *args.receiver();
    796 }
    797 
    798 
    799 BUILTIN(HandleApiCall) {
    800   return HandleApiCallHelper<false>(args);
    801 }
    802 
    803 
    804 BUILTIN(HandleApiCallConstruct) {
    805   return HandleApiCallHelper<true>(args);
    806 }
    807 
    808 
    809 #ifdef DEBUG
    810 
    811 static void VerifyTypeCheck(Handle<JSObject> object,
    812                             Handle<JSFunction> function) {
    813   FunctionTemplateInfo* info =
    814       FunctionTemplateInfo::cast(function->shared()->function_data());
    815   if (info->signature()->IsUndefined()) return;
    816   SignatureInfo* signature = SignatureInfo::cast(info->signature());
    817   Object* receiver_type = signature->receiver();
    818   if (receiver_type->IsUndefined()) return;
    819   FunctionTemplateInfo* type = FunctionTemplateInfo::cast(receiver_type);
    820   ASSERT(object->IsInstanceOf(type));
    821 }
    822 
    823 #endif
    824 
    825 
    826 BUILTIN(FastHandleApiCall) {
    827   ASSERT(!CalledAsConstructor());
    828   const bool is_construct = false;
    829 
    830   // We expect four more arguments: function, callback, call data, and holder.
    831   const int args_length = args.length() - 4;
    832   ASSERT(args_length >= 0);
    833 
    834   Handle<JSFunction> function = args.at<JSFunction>(args_length);
    835   Object* callback_obj = args[args_length + 1];
    836   Handle<Object> data_handle = args.at<Object>(args_length + 2);
    837   Handle<JSObject> checked_holder = args.at<JSObject>(args_length + 3);
    838 
    839 #ifdef DEBUG
    840   VerifyTypeCheck(checked_holder, function);
    841 #endif
    842 
    843   v8::Local<v8::Object> holder = v8::Utils::ToLocal(checked_holder);
    844   v8::Local<v8::Function> callee = v8::Utils::ToLocal(function);
    845   v8::InvocationCallback callback =
    846       v8::ToCData<v8::InvocationCallback>(callback_obj);
    847   v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
    848 
    849   v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
    850       data,
    851       holder,
    852       callee,
    853       is_construct,
    854       reinterpret_cast<void**>(&args[0] - 1),
    855       args_length - 1);
    856 
    857   HandleScope scope;
    858   Object* result;
    859   v8::Handle<v8::Value> value;
    860   {
    861     // Leaving JavaScript.
    862     VMState state(EXTERNAL);
    863 #ifdef ENABLE_LOGGING_AND_PROFILING
    864     state.set_external_callback(v8::ToCData<Address>(callback_obj));
    865 #endif
    866     value = callback(new_args);
    867   }
    868   if (value.IsEmpty()) {
    869     result = Heap::undefined_value();
    870   } else {
    871     result = *reinterpret_cast<Object**>(*value);
    872   }
    873 
    874   RETURN_IF_SCHEDULED_EXCEPTION();
    875   return result;
    876 }
    877 
    878 
    879 // Helper function to handle calls to non-function objects created through the
    880 // API. The object can be called as either a constructor (using new) or just as
    881 // a function (without new).
    882 static Object* HandleApiCallAsFunctionOrConstructor(
    883     bool is_construct_call,
    884     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
    885   // Non-functions are never called as constructors. Even if this is an object
    886   // called as a constructor the delegate call is not a construct call.
    887   ASSERT(!CalledAsConstructor());
    888 
    889   Handle<Object> receiver = args.at<Object>(0);
    890 
    891   // Get the object called.
    892   JSObject* obj = JSObject::cast(*args.receiver());
    893 
    894   // Get the invocation callback from the function descriptor that was
    895   // used to create the called object.
    896   ASSERT(obj->map()->has_instance_call_handler());
    897   JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
    898   Object* template_info = constructor->shared()->function_data();
    899   Object* handler =
    900       FunctionTemplateInfo::cast(template_info)->instance_call_handler();
    901   ASSERT(!handler->IsUndefined());
    902   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
    903   Object* callback_obj = call_data->callback();
    904   v8::InvocationCallback callback =
    905       v8::ToCData<v8::InvocationCallback>(callback_obj);
    906 
    907   // Get the data for the call and perform the callback.
    908   Object* data_obj = call_data->data();
    909   Object* result;
    910   { HandleScope scope;
    911     v8::Local<v8::Object> self =
    912         v8::Utils::ToLocal(Handle<JSObject>::cast(args.receiver()));
    913     Handle<Object> data_handle(data_obj);
    914     v8::Local<v8::Value> data = v8::Utils::ToLocal(data_handle);
    915     Handle<JSFunction> callee_handle(constructor);
    916     v8::Local<v8::Function> callee = v8::Utils::ToLocal(callee_handle);
    917     LOG(ApiObjectAccess("call non-function", JSObject::cast(*args.receiver())));
    918     v8::Arguments new_args = v8::ImplementationUtilities::NewArguments(
    919         data,
    920         self,
    921         callee,
    922         is_construct_call,
    923         reinterpret_cast<void**>(&args[0] - 1),
    924         args.length() - 1);
    925     v8::Handle<v8::Value> value;
    926     {
    927       // Leaving JavaScript.
    928       VMState state(EXTERNAL);
    929 #ifdef ENABLE_LOGGING_AND_PROFILING
    930       state.set_external_callback(v8::ToCData<Address>(callback_obj));
    931 #endif
    932       value = callback(new_args);
    933     }
    934     if (value.IsEmpty()) {
    935       result = Heap::undefined_value();
    936     } else {
    937       result = *reinterpret_cast<Object**>(*value);
    938     }
    939   }
    940   // Check for exceptions and return result.
    941   RETURN_IF_SCHEDULED_EXCEPTION();
    942   return result;
    943 }
    944 
    945 
    946 // Handle calls to non-function objects created through the API. This delegate
    947 // function is used when the call is a normal function call.
    948 BUILTIN(HandleApiCallAsFunction) {
    949   return HandleApiCallAsFunctionOrConstructor(false, args);
    950 }
    951 
    952 
    953 // Handle calls to non-function objects created through the API. This delegate
    954 // function is used when the call is a construct call.
    955 BUILTIN(HandleApiCallAsConstructor) {
    956   return HandleApiCallAsFunctionOrConstructor(true, args);
    957 }
    958 
    959 
    960 static void Generate_LoadIC_ArrayLength(MacroAssembler* masm) {
    961   LoadIC::GenerateArrayLength(masm);
    962 }
    963 
    964 
    965 static void Generate_LoadIC_StringLength(MacroAssembler* masm) {
    966   LoadIC::GenerateStringLength(masm);
    967 }
    968 
    969 
    970 static void Generate_LoadIC_FunctionPrototype(MacroAssembler* masm) {
    971   LoadIC::GenerateFunctionPrototype(masm);
    972 }
    973 
    974 
    975 static void Generate_LoadIC_Initialize(MacroAssembler* masm) {
    976   LoadIC::GenerateInitialize(masm);
    977 }
    978 
    979 
    980 static void Generate_LoadIC_PreMonomorphic(MacroAssembler* masm) {
    981   LoadIC::GeneratePreMonomorphic(masm);
    982 }
    983 
    984 
    985 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
    986   LoadIC::GenerateMiss(masm);
    987 }
    988 
    989 
    990 static void Generate_LoadIC_Megamorphic(MacroAssembler* masm) {
    991   LoadIC::GenerateMegamorphic(masm);
    992 }
    993 
    994 
    995 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
    996   LoadIC::GenerateNormal(masm);
    997 }
    998 
    999 
   1000 static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
   1001   KeyedLoadIC::GenerateInitialize(masm);
   1002 }
   1003 
   1004 
   1005 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
   1006   KeyedLoadIC::GenerateMiss(masm);
   1007 }
   1008 
   1009 
   1010 static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
   1011   KeyedLoadIC::GenerateGeneric(masm);
   1012 }
   1013 
   1014 
   1015 static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
   1016   KeyedLoadIC::GenerateString(masm);
   1017 }
   1018 
   1019 
   1020 static void Generate_KeyedLoadIC_ExternalByteArray(MacroAssembler* masm) {
   1021   KeyedLoadIC::GenerateExternalArray(masm, kExternalByteArray);
   1022 }
   1023 
   1024 
   1025 static void Generate_KeyedLoadIC_ExternalUnsignedByteArray(
   1026     MacroAssembler* masm) {
   1027   KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
   1028 }
   1029 
   1030 
   1031 static void Generate_KeyedLoadIC_ExternalShortArray(MacroAssembler* masm) {
   1032   KeyedLoadIC::GenerateExternalArray(masm, kExternalShortArray);
   1033 }
   1034 
   1035 
   1036 static void Generate_KeyedLoadIC_ExternalUnsignedShortArray(
   1037     MacroAssembler* masm) {
   1038   KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
   1039 }
   1040 
   1041 
   1042 static void Generate_KeyedLoadIC_ExternalIntArray(MacroAssembler* masm) {
   1043   KeyedLoadIC::GenerateExternalArray(masm, kExternalIntArray);
   1044 }
   1045 
   1046 
   1047 static void Generate_KeyedLoadIC_ExternalUnsignedIntArray(
   1048     MacroAssembler* masm) {
   1049   KeyedLoadIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
   1050 }
   1051 
   1052 
   1053 static void Generate_KeyedLoadIC_ExternalFloatArray(MacroAssembler* masm) {
   1054   KeyedLoadIC::GenerateExternalArray(masm, kExternalFloatArray);
   1055 }
   1056 
   1057 
   1058 static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
   1059   KeyedLoadIC::GeneratePreMonomorphic(masm);
   1060 }
   1061 
   1062 static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
   1063   KeyedLoadIC::GenerateIndexedInterceptor(masm);
   1064 }
   1065 
   1066 
   1067 static void Generate_StoreIC_Initialize(MacroAssembler* masm) {
   1068   StoreIC::GenerateInitialize(masm);
   1069 }
   1070 
   1071 
   1072 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
   1073   StoreIC::GenerateMiss(masm);
   1074 }
   1075 
   1076 
   1077 static void Generate_StoreIC_Megamorphic(MacroAssembler* masm) {
   1078   StoreIC::GenerateMegamorphic(masm);
   1079 }
   1080 
   1081 
   1082 static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
   1083   KeyedStoreIC::GenerateGeneric(masm);
   1084 }
   1085 
   1086 
   1087 static void Generate_KeyedStoreIC_ExternalByteArray(MacroAssembler* masm) {
   1088   KeyedStoreIC::GenerateExternalArray(masm, kExternalByteArray);
   1089 }
   1090 
   1091 
   1092 static void Generate_KeyedStoreIC_ExternalUnsignedByteArray(
   1093     MacroAssembler* masm) {
   1094   KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedByteArray);
   1095 }
   1096 
   1097 
   1098 static void Generate_KeyedStoreIC_ExternalShortArray(MacroAssembler* masm) {
   1099   KeyedStoreIC::GenerateExternalArray(masm, kExternalShortArray);
   1100 }
   1101 
   1102 
   1103 static void Generate_KeyedStoreIC_ExternalUnsignedShortArray(
   1104     MacroAssembler* masm) {
   1105   KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedShortArray);
   1106 }
   1107 
   1108 
   1109 static void Generate_KeyedStoreIC_ExternalIntArray(MacroAssembler* masm) {
   1110   KeyedStoreIC::GenerateExternalArray(masm, kExternalIntArray);
   1111 }
   1112 
   1113 
   1114 static void Generate_KeyedStoreIC_ExternalUnsignedIntArray(
   1115     MacroAssembler* masm) {
   1116   KeyedStoreIC::GenerateExternalArray(masm, kExternalUnsignedIntArray);
   1117 }
   1118 
   1119 
   1120 static void Generate_KeyedStoreIC_ExternalFloatArray(MacroAssembler* masm) {
   1121   KeyedStoreIC::GenerateExternalArray(masm, kExternalFloatArray);
   1122 }
   1123 
   1124 
   1125 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
   1126   KeyedStoreIC::GenerateMiss(masm);
   1127 }
   1128 
   1129 
   1130 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
   1131   KeyedStoreIC::GenerateInitialize(masm);
   1132 }
   1133 
   1134 
   1135 #ifdef ENABLE_DEBUGGER_SUPPORT
   1136 static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
   1137   Debug::GenerateLoadICDebugBreak(masm);
   1138 }
   1139 
   1140 
   1141 static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
   1142   Debug::GenerateStoreICDebugBreak(masm);
   1143 }
   1144 
   1145 
   1146 static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
   1147   Debug::GenerateKeyedLoadICDebugBreak(masm);
   1148 }
   1149 
   1150 
   1151 static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
   1152   Debug::GenerateKeyedStoreICDebugBreak(masm);
   1153 }
   1154 
   1155 
   1156 static void Generate_ConstructCall_DebugBreak(MacroAssembler* masm) {
   1157   Debug::GenerateConstructCallDebugBreak(masm);
   1158 }
   1159 
   1160 
   1161 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
   1162   Debug::GenerateReturnDebugBreak(masm);
   1163 }
   1164 
   1165 
   1166 static void Generate_StubNoRegisters_DebugBreak(MacroAssembler* masm) {
   1167   Debug::GenerateStubNoRegistersDebugBreak(masm);
   1168 }
   1169 #endif
   1170 
   1171 Object* Builtins::builtins_[builtin_count] = { NULL, };
   1172 const char* Builtins::names_[builtin_count] = { NULL, };
   1173 
   1174 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
   1175   Address Builtins::c_functions_[cfunction_count] = {
   1176     BUILTIN_LIST_C(DEF_ENUM_C)
   1177   };
   1178 #undef DEF_ENUM_C
   1179 
   1180 #define DEF_JS_NAME(name, ignore) #name,
   1181 #define DEF_JS_ARGC(ignore, argc) argc,
   1182 const char* Builtins::javascript_names_[id_count] = {
   1183   BUILTINS_LIST_JS(DEF_JS_NAME)
   1184 };
   1185 
   1186 int Builtins::javascript_argc_[id_count] = {
   1187   BUILTINS_LIST_JS(DEF_JS_ARGC)
   1188 };
   1189 #undef DEF_JS_NAME
   1190 #undef DEF_JS_ARGC
   1191 
   1192 static bool is_initialized = false;
   1193 void Builtins::Setup(bool create_heap_objects) {
   1194   ASSERT(!is_initialized);
   1195 
   1196   // Create a scope for the handles in the builtins.
   1197   HandleScope scope;
   1198 
   1199   struct BuiltinDesc {
   1200     byte* generator;
   1201     byte* c_code;
   1202     const char* s_name;  // name is only used for generating log information.
   1203     int name;
   1204     Code::Flags flags;
   1205     BuiltinExtraArguments extra_args;
   1206   };
   1207 
   1208 #define DEF_FUNCTION_PTR_C(name, extra_args) \
   1209     { FUNCTION_ADDR(Generate_Adaptor),            \
   1210       FUNCTION_ADDR(Builtin_##name),              \
   1211       #name,                                      \
   1212       c_##name,                                   \
   1213       Code::ComputeFlags(Code::BUILTIN),          \
   1214       extra_args                                  \
   1215     },
   1216 
   1217 #define DEF_FUNCTION_PTR_A(name, kind, state)              \
   1218     { FUNCTION_ADDR(Generate_##name),                      \
   1219       NULL,                                                \
   1220       #name,                                               \
   1221       name,                                                \
   1222       Code::ComputeFlags(Code::kind, NOT_IN_LOOP, state),  \
   1223       NO_EXTRA_ARGUMENTS                                   \
   1224     },
   1225 
   1226   // Define array of pointers to generators and C builtin functions.
   1227   static BuiltinDesc functions[] = {
   1228       BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
   1229       BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
   1230       BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
   1231       // Terminator:
   1232       { NULL, NULL, NULL, builtin_count, static_cast<Code::Flags>(0),
   1233         NO_EXTRA_ARGUMENTS }
   1234   };
   1235 
   1236 #undef DEF_FUNCTION_PTR_C
   1237 #undef DEF_FUNCTION_PTR_A
   1238 
   1239   // For now we generate builtin adaptor code into a stack-allocated
   1240   // buffer, before copying it into individual code objects.
   1241   byte buffer[4*KB];
   1242 
   1243   // Traverse the list of builtins and generate an adaptor in a
   1244   // separate code object for each one.
   1245   for (int i = 0; i < builtin_count; i++) {
   1246     if (create_heap_objects) {
   1247       MacroAssembler masm(buffer, sizeof buffer);
   1248       // Generate the code/adaptor.
   1249       typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
   1250       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
   1251       // We pass all arguments to the generator, but it may not use all of
   1252       // them.  This works because the first arguments are on top of the
   1253       // stack.
   1254       g(&masm, functions[i].name, functions[i].extra_args);
   1255       // Move the code into the object heap.
   1256       CodeDesc desc;
   1257       masm.GetCode(&desc);
   1258       Code::Flags flags =  functions[i].flags;
   1259       Object* code;
   1260       {
   1261         // During startup it's OK to always allocate and defer GC to later.
   1262         // This simplifies things because we don't need to retry.
   1263         AlwaysAllocateScope __scope__;
   1264         code = Heap::CreateCode(desc, NULL, flags, masm.CodeObject());
   1265         if (code->IsFailure()) {
   1266           v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
   1267         }
   1268       }
   1269       // Log the event and add the code to the builtins array.
   1270       LOG(CodeCreateEvent(Logger::BUILTIN_TAG,
   1271                           Code::cast(code), functions[i].s_name));
   1272       builtins_[i] = code;
   1273 #ifdef ENABLE_DISASSEMBLER
   1274       if (FLAG_print_builtin_code) {
   1275         PrintF("Builtin: %s\n", functions[i].s_name);
   1276         Code::cast(code)->Disassemble(functions[i].s_name);
   1277         PrintF("\n");
   1278       }
   1279 #endif
   1280     } else {
   1281       // Deserializing. The values will be filled in during IterateBuiltins.
   1282       builtins_[i] = NULL;
   1283     }
   1284     names_[i] = functions[i].s_name;
   1285   }
   1286 
   1287   // Mark as initialized.
   1288   is_initialized = true;
   1289 }
   1290 
   1291 
   1292 void Builtins::TearDown() {
   1293   is_initialized = false;
   1294 }
   1295 
   1296 
   1297 void Builtins::IterateBuiltins(ObjectVisitor* v) {
   1298   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
   1299 }
   1300 
   1301 
   1302 const char* Builtins::Lookup(byte* pc) {
   1303   if (is_initialized) {  // may be called during initialization (disassembler!)
   1304     for (int i = 0; i < builtin_count; i++) {
   1305       Code* entry = Code::cast(builtins_[i]);
   1306       if (entry->contains(pc)) {
   1307         return names_[i];
   1308       }
   1309     }
   1310   }
   1311   return NULL;
   1312 }
   1313 
   1314 
   1315 } }  // namespace v8::internal
   1316