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