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