8fe53d95761c9eb24bc5fe79af56865a9c3af8bb
[platform/upstream/v8.git] / src / builtins.cc
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/builtins.h"
6
7 #include "src/api.h"
8 #include "src/api-natives.h"
9 #include "src/arguments.h"
10 #include "src/base/once.h"
11 #include "src/bootstrapper.h"
12 #include "src/cpu-profiler.h"
13 #include "src/elements.h"
14 #include "src/frames-inl.h"
15 #include "src/gdb-jit.h"
16 #include "src/heap-profiler.h"
17 #include "src/ic/handler-compiler.h"
18 #include "src/ic/ic.h"
19 #include "src/messages.h"
20 #include "src/prototype.h"
21 #include "src/vm-state-inl.h"
22
23 namespace v8 {
24 namespace internal {
25
26 namespace {
27
28 // Arguments object passed to C++ builtins.
29 template <BuiltinExtraArguments extra_args>
30 class BuiltinArguments : public Arguments {
31  public:
32   BuiltinArguments(int length, Object** arguments)
33       : Arguments(length, arguments) { }
34
35   Object*& operator[] (int index) {
36     DCHECK(index < length());
37     return Arguments::operator[](index);
38   }
39
40   template <class S> Handle<S> at(int index) {
41     DCHECK(index < length());
42     return Arguments::at<S>(index);
43   }
44
45   Handle<Object> receiver() {
46     return Arguments::at<Object>(0);
47   }
48
49   Handle<JSFunction> called_function() {
50     STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
51     return Arguments::at<JSFunction>(Arguments::length() - 1);
52   }
53
54   // Gets the total number of arguments including the receiver (but
55   // excluding extra arguments).
56   int length() const {
57     STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
58     return Arguments::length();
59   }
60
61 #ifdef DEBUG
62   void Verify() {
63     // Check we have at least the receiver.
64     DCHECK(Arguments::length() >= 1);
65   }
66 #endif
67 };
68
69
70 // Specialize BuiltinArguments for the called function extra argument.
71
72 template <>
73 int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
74   return Arguments::length() - 1;
75 }
76
77 #ifdef DEBUG
78 template <>
79 void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
80   // Check we have at least the receiver and the called function.
81   DCHECK(Arguments::length() >= 2);
82   // Make sure cast to JSFunction succeeds.
83   called_function();
84 }
85 #endif
86
87
88 #define DEF_ARG_TYPE(name, spec)                      \
89   typedef BuiltinArguments<spec> name##ArgumentsType;
90 BUILTIN_LIST_C(DEF_ARG_TYPE)
91 #undef DEF_ARG_TYPE
92
93
94 // ----------------------------------------------------------------------------
95 // Support macro for defining builtins in C++.
96 // ----------------------------------------------------------------------------
97 //
98 // A builtin function is defined by writing:
99 //
100 //   BUILTIN(name) {
101 //     ...
102 //   }
103 //
104 // In the body of the builtin function the arguments can be accessed
105 // through the BuiltinArguments object args.
106
107 #ifdef DEBUG
108
109 #define BUILTIN(name)                                            \
110   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
111       name##ArgumentsType args, Isolate* isolate);               \
112   MUST_USE_RESULT static Object* Builtin_##name(                 \
113       int args_length, Object** args_object, Isolate* isolate) { \
114     name##ArgumentsType args(args_length, args_object);          \
115     args.Verify();                                               \
116     return Builtin_Impl_##name(args, isolate);                   \
117   }                                                              \
118   MUST_USE_RESULT static Object* Builtin_Impl_##name(            \
119       name##ArgumentsType args, Isolate* isolate)
120
121 #else  // For release mode.
122
123 #define BUILTIN(name)                                            \
124   static Object* Builtin_impl##name(                             \
125       name##ArgumentsType args, Isolate* isolate);               \
126   static Object* Builtin_##name(                                 \
127       int args_length, Object** args_object, Isolate* isolate) { \
128     name##ArgumentsType args(args_length, args_object);          \
129     return Builtin_impl##name(args, isolate);                    \
130   }                                                              \
131   static Object* Builtin_impl##name(                             \
132       name##ArgumentsType args, Isolate* isolate)
133 #endif
134
135
136 #ifdef DEBUG
137 inline bool CalledAsConstructor(Isolate* isolate) {
138   // Calculate the result using a full stack frame iterator and check
139   // that the state of the stack is as we assume it to be in the
140   // code below.
141   StackFrameIterator it(isolate);
142   DCHECK(it.frame()->is_exit());
143   it.Advance();
144   StackFrame* frame = it.frame();
145   bool reference_result = frame->is_construct();
146   Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
147   // Because we know fp points to an exit frame we can use the relevant
148   // part of ExitFrame::ComputeCallerState directly.
149   const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
150   Address caller_fp = Memory::Address_at(fp + kCallerOffset);
151   // This inlines the part of StackFrame::ComputeType that grabs the
152   // type of the current frame.  Note that StackFrame::ComputeType
153   // has been specialized for each architecture so if any one of them
154   // changes this code has to be changed as well.
155   const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
156   const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
157   Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
158   bool result = (marker == kConstructMarker);
159   DCHECK_EQ(result, reference_result);
160   return result;
161 }
162 #endif
163
164
165 // ----------------------------------------------------------------------------
166
167
168 inline bool ClampedToInteger(Object* object, int* out) {
169   // This is an extended version of ECMA-262 7.1.11 handling signed values
170   // Try to convert object to a number and clamp values to [kMinInt, kMaxInt]
171   if (object->IsSmi()) {
172     *out = Smi::cast(object)->value();
173     return true;
174   } else if (object->IsHeapNumber()) {
175     double value = HeapNumber::cast(object)->value();
176     if (std::isnan(value)) {
177       *out = 0;
178     } else if (value > kMaxInt) {
179       *out = kMaxInt;
180     } else if (value < kMinInt) {
181       *out = kMinInt;
182     } else {
183       *out = static_cast<int>(value);
184     }
185     return true;
186   } else if (object->IsUndefined() || object->IsNull()) {
187     *out = 0;
188     return true;
189   } else if (object->IsBoolean()) {
190     *out = object->IsTrue();
191     return true;
192   }
193   return false;
194 }
195
196
197 void MoveDoubleElements(FixedDoubleArray* dst, int dst_index,
198                         FixedDoubleArray* src, int src_index, int len) {
199   if (len == 0) return;
200   MemMove(dst->data_start() + dst_index, src->data_start() + src_index,
201           len * kDoubleSize);
202 }
203
204
205 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object,
206                                      int* out) {
207   Map* arguments_map =
208       isolate->context()->native_context()->sloppy_arguments_map();
209   if (object->map() != arguments_map || !object->HasFastElements()) {
210     return false;
211   }
212   Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
213   if (!len_obj->IsSmi()) {
214     return false;
215   }
216   *out = Smi::cast(len_obj)->value();
217   return *out <= object->elements()->length();
218 }
219
220
221 bool PrototypeHasNoElements(PrototypeIterator* iter) {
222   DisallowHeapAllocation no_gc;
223   for (; !iter->IsAtEnd(); iter->Advance()) {
224     if (iter->GetCurrent()->IsJSProxy()) return false;
225     JSObject* current = JSObject::cast(iter->GetCurrent());
226     if (current->IsAccessCheckNeeded()) return false;
227     if (current->HasIndexedInterceptor()) return false;
228     if (current->elements()->length() != 0) return false;
229   }
230   return true;
231 }
232
233
234 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate,
235                                               JSArray* receiver) {
236   DisallowHeapAllocation no_gc;
237   // If the array prototype chain is intact (and free of elements), and if the
238   // receiver's prototype is the array prototype, then we are done.
239   Object* prototype = receiver->map()->prototype();
240   if (prototype->IsJSArray() &&
241       isolate->is_initial_array_prototype(JSArray::cast(prototype)) &&
242       isolate->IsFastArrayConstructorPrototypeChainIntact()) {
243     return true;
244   }
245
246   // Slow case.
247   PrototypeIterator iter(isolate, receiver);
248   return PrototypeHasNoElements(&iter);
249 }
250
251
252 // Returns empty handle if not applicable.
253 MUST_USE_RESULT
254 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
255     Isolate* isolate, Handle<Object> receiver, Arguments* args,
256     int first_added_arg) {
257   if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
258   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
259   // If there may be elements accessors in the prototype chain, the fast path
260   // cannot be used if there arguments to add to the array.
261   Heap* heap = isolate->heap();
262   if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) {
263     return MaybeHandle<FixedArrayBase>();
264   }
265   if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
266   if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
267   Handle<FixedArrayBase> elms(array->elements(), isolate);
268   Map* map = elms->map();
269   if (map == heap->fixed_array_map()) {
270     if (args == NULL || array->HasFastObjectElements()) return elms;
271   } else if (map == heap->fixed_cow_array_map()) {
272     elms = JSObject::EnsureWritableFastElements(array);
273     if (args == NULL || array->HasFastObjectElements()) return elms;
274   } else if (map == heap->fixed_double_array_map()) {
275     if (args == NULL) return elms;
276   } else {
277     return MaybeHandle<FixedArrayBase>();
278   }
279
280   // Adding elements to the array prototype would break code that makes sure
281   // it has no elements. Handle that elsewhere.
282   if (isolate->IsAnyInitialArrayPrototype(array)) {
283     return MaybeHandle<FixedArrayBase>();
284   }
285
286   // Need to ensure that the arguments passed in args can be contained in
287   // the array.
288   int args_length = args->length();
289   if (first_added_arg >= args_length) return handle(array->elements(), isolate);
290
291   ElementsKind origin_kind = array->map()->elements_kind();
292   DCHECK(!IsFastObjectElementsKind(origin_kind));
293   ElementsKind target_kind = origin_kind;
294   {
295     DisallowHeapAllocation no_gc;
296     int arg_count = args_length - first_added_arg;
297     Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
298     for (int i = 0; i < arg_count; i++) {
299       Object* arg = arguments[i];
300       if (arg->IsHeapObject()) {
301         if (arg->IsHeapNumber()) {
302           target_kind = FAST_DOUBLE_ELEMENTS;
303         } else {
304           target_kind = FAST_ELEMENTS;
305           break;
306         }
307       }
308     }
309   }
310   if (target_kind != origin_kind) {
311     JSObject::TransitionElementsKind(array, target_kind);
312     return handle(array->elements(), isolate);
313   }
314   return elms;
315 }
316
317
318 MUST_USE_RESULT static Object* CallJsIntrinsic(
319     Isolate* isolate, Handle<JSFunction> function,
320     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
321   HandleScope handleScope(isolate);
322   int argc = args.length() - 1;
323   ScopedVector<Handle<Object> > argv(argc);
324   for (int i = 0; i < argc; ++i) {
325     argv[i] = args.at<Object>(i + 1);
326   }
327   Handle<Object> result;
328   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
329       isolate, result,
330       Execution::Call(isolate,
331                       function,
332                       args.receiver(),
333                       argc,
334                       argv.start()));
335   return *result;
336 }
337
338
339 }  // namespace
340
341
342 BUILTIN(Illegal) {
343   UNREACHABLE();
344   return isolate->heap()->undefined_value();  // Make compiler happy.
345 }
346
347
348 BUILTIN(EmptyFunction) { return isolate->heap()->undefined_value(); }
349
350
351 BUILTIN(ArrayPush) {
352   HandleScope scope(isolate);
353   Handle<Object> receiver = args.receiver();
354   MaybeHandle<FixedArrayBase> maybe_elms_obj =
355       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
356   Handle<FixedArrayBase> elms_obj;
357   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
358     return CallJsIntrinsic(isolate, isolate->array_push(), args);
359   }
360   // Fast Elements Path
361   int push_size = args.length() - 1;
362   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
363   int len = Smi::cast(array->length())->value();
364   if (push_size == 0) {
365     return Smi::FromInt(len);
366   }
367   if (push_size > 0 &&
368       JSArray::WouldChangeReadOnlyLength(array, len + push_size)) {
369     return CallJsIntrinsic(isolate, isolate->array_push(), args);
370   }
371   DCHECK(!array->map()->is_observed());
372   ElementsAccessor* accessor = array->GetElementsAccessor();
373   int new_length = accessor->Push(array, elms_obj, &args[1], push_size,
374                                   ElementsAccessor::kDirectionReverse);
375   return Smi::FromInt(new_length);
376 }
377
378
379 BUILTIN(ArrayPop) {
380   HandleScope scope(isolate);
381   Handle<Object> receiver = args.receiver();
382   MaybeHandle<FixedArrayBase> maybe_elms_obj =
383       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
384   Handle<FixedArrayBase> elms_obj;
385   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
386     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
387   }
388
389   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
390   DCHECK(!array->map()->is_observed());
391
392   uint32_t len = static_cast<uint32_t>(Smi::cast(array->length())->value());
393   if (len == 0) return isolate->heap()->undefined_value();
394
395   if (JSArray::HasReadOnlyLength(array)) {
396     return CallJsIntrinsic(isolate, isolate->array_pop(), args);
397   }
398
399   uint32_t new_length = len - 1;
400   Handle<Object> element;
401   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
402       isolate, element, Object::GetElement(isolate, array, new_length));
403
404   JSArray::SetLength(array, new_length);
405   return *element;
406 }
407
408
409 BUILTIN(ArrayShift) {
410   HandleScope scope(isolate);
411   Heap* heap = isolate->heap();
412   Handle<Object> receiver = args.receiver();
413   MaybeHandle<FixedArrayBase> maybe_elms_obj =
414       EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
415   Handle<FixedArrayBase> elms_obj;
416   if (!maybe_elms_obj.ToHandle(&elms_obj) ||
417       !IsJSArrayFastElementMovingAllowed(isolate, JSArray::cast(*receiver))) {
418     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
419   }
420   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
421   DCHECK(!array->map()->is_observed());
422
423   int len = Smi::cast(array->length())->value();
424   if (len == 0) return heap->undefined_value();
425
426   if (JSArray::HasReadOnlyLength(array)) {
427     return CallJsIntrinsic(isolate, isolate->array_shift(), args);
428   }
429
430   // Get first element
431   Handle<Object> first;
432   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, first,
433                                      Object::GetElement(isolate, array, 0));
434
435   if (heap->CanMoveObjectStart(*elms_obj)) {
436     array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
437   } else {
438     // Shift the elements.
439     if (elms_obj->IsFixedArray()) {
440       Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
441       DisallowHeapAllocation no_gc;
442       heap->MoveElements(*elms, 0, 1, len - 1);
443       elms->set(len - 1, heap->the_hole_value());
444     } else {
445       Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
446       MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
447       elms->set_the_hole(len - 1);
448     }
449   }
450
451   // Set the length.
452   array->set_length(Smi::FromInt(len - 1));
453
454   return *first;
455 }
456
457
458 BUILTIN(ArrayUnshift) {
459   HandleScope scope(isolate);
460   Handle<Object> receiver = args.receiver();
461   MaybeHandle<FixedArrayBase> maybe_elms_obj =
462       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
463   Handle<FixedArrayBase> elms_obj;
464   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
465     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
466   }
467   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
468   DCHECK(!array->map()->is_observed());
469   if (!array->HasFastSmiOrObjectElements()) {
470     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
471   }
472   int len = Smi::cast(array->length())->value();
473   int to_add = args.length() - 1;
474   int new_length = len + to_add;
475   // Currently fixed arrays cannot grow too big, so
476   // we should never hit this case.
477   DCHECK(to_add <= (Smi::kMaxValue - len));
478
479   if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
480     return CallJsIntrinsic(isolate, isolate->array_unshift(), args);
481   }
482
483   Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
484
485   if (new_length > elms->length()) {
486     // New backing storage is needed.
487     int capacity = new_length + (new_length >> 1) + 16;
488     Handle<FixedArray> new_elms =
489         isolate->factory()->NewUninitializedFixedArray(capacity);
490
491     ElementsKind kind = array->GetElementsKind();
492     ElementsAccessor* accessor = array->GetElementsAccessor();
493     accessor->CopyElements(
494         elms, 0, kind, new_elms, to_add,
495         ElementsAccessor::kCopyToEndAndInitializeToHole);
496
497     elms = new_elms;
498     array->set_elements(*elms);
499   } else {
500     DisallowHeapAllocation no_gc;
501     Heap* heap = isolate->heap();
502     heap->MoveElements(*elms, to_add, 0, len);
503   }
504
505   // Add the provided values.
506   DisallowHeapAllocation no_gc;
507   WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
508   for (int i = 0; i < to_add; i++) {
509     elms->set(i, args[i + 1], mode);
510   }
511
512   // Set the length.
513   array->set_length(Smi::FromInt(new_length));
514   return Smi::FromInt(new_length);
515 }
516
517
518 BUILTIN(ArraySlice) {
519   HandleScope scope(isolate);
520   Handle<Object> receiver = args.receiver();
521   Handle<JSObject> object;
522   Handle<FixedArrayBase> elms_obj;
523   int len = -1;
524   int relative_start = 0;
525   int relative_end = 0;
526   bool is_sloppy_arguments = false;
527
528   if (receiver->IsJSArray()) {
529     DisallowHeapAllocation no_gc;
530     JSArray* array = JSArray::cast(*receiver);
531     if (!array->HasFastElements() ||
532         !IsJSArrayFastElementMovingAllowed(isolate, array)) {
533       AllowHeapAllocation allow_allocation;
534       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
535     }
536     len = Smi::cast(array->length())->value();
537     object = Handle<JSObject>::cast(receiver);
538     elms_obj = handle(array->elements(), isolate);
539   } else if (receiver->IsJSObject() &&
540              GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver),
541                                       &len)) {
542     // Array.prototype.slice(arguments, ...) is quite a common idiom
543     // (notably more than 50% of invocations in Web apps).
544     // Treat it in C++ as well.
545     is_sloppy_arguments = true;
546     object = Handle<JSObject>::cast(receiver);
547     elms_obj = handle(object->elements(), isolate);
548   } else {
549     AllowHeapAllocation allow_allocation;
550     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
551   }
552   DCHECK(len >= 0);
553   int argument_count = args.length() - 1;
554   // Note carefully chosen defaults---if argument is missing,
555   // it's undefined which gets converted to 0 for relative_start
556   // and to len for relative_end.
557   relative_start = 0;
558   relative_end = len;
559   if (argument_count > 0) {
560     DisallowHeapAllocation no_gc;
561     if (!ClampedToInteger(args[1], &relative_start)) {
562       AllowHeapAllocation allow_allocation;
563       return CallJsIntrinsic(isolate, isolate->array_slice(), args);
564     }
565     if (argument_count > 1) {
566       Object* end_arg = args[2];
567       // slice handles the end_arg specially
568       if (end_arg->IsUndefined()) {
569         relative_end = len;
570       } else if (!ClampedToInteger(end_arg, &relative_end)) {
571         AllowHeapAllocation allow_allocation;
572         return CallJsIntrinsic(isolate, isolate->array_slice(), args);
573       }
574     }
575   }
576
577   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
578   uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
579                                                : Min(relative_start, len);
580
581   // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
582   uint32_t actual_end =
583       (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len);
584
585   ElementsAccessor* accessor = object->GetElementsAccessor();
586   if (is_sloppy_arguments &&
587       !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) {
588     // Don't deal with arguments with holes in C++
589     AllowHeapAllocation allow_allocation;
590     return CallJsIntrinsic(isolate, isolate->array_slice(), args);
591   }
592   Handle<JSArray> result_array =
593       accessor->Slice(object, elms_obj, actual_start, actual_end);
594   return *result_array;
595 }
596
597
598 BUILTIN(ArraySplice) {
599   HandleScope scope(isolate);
600   Handle<Object> receiver = args.receiver();
601   MaybeHandle<FixedArrayBase> maybe_elms_obj =
602       EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
603   Handle<FixedArrayBase> elms_obj;
604   if (!maybe_elms_obj.ToHandle(&elms_obj)) {
605     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
606   }
607   Handle<JSArray> array = Handle<JSArray>::cast(receiver);
608   DCHECK(!array->map()->is_observed());
609
610   int argument_count = args.length() - 1;
611   int relative_start = 0;
612   if (argument_count > 0) {
613     DisallowHeapAllocation no_gc;
614     if (!ClampedToInteger(args[1], &relative_start)) {
615       AllowHeapAllocation allow_allocation;
616       return CallJsIntrinsic(isolate, isolate->array_splice(), args);
617     }
618   }
619   int len = Smi::cast(array->length())->value();
620   // clip relative start to [0, len]
621   int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
622                                           : Min(relative_start, len);
623
624   int actual_delete_count;
625   if (argument_count == 1) {
626     // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
627     // given as a request to delete all the elements from the start.
628     // And it differs from the case of undefined delete count.
629     // This does not follow ECMA-262, but we do the same for compatibility.
630     DCHECK(len - actual_start >= 0);
631     actual_delete_count = len - actual_start;
632   } else {
633     int delete_count = 0;
634     DisallowHeapAllocation no_gc;
635     if (argument_count > 1) {
636       if (!ClampedToInteger(args[2], &delete_count)) {
637         AllowHeapAllocation allow_allocation;
638         return CallJsIntrinsic(isolate, isolate->array_splice(), args);
639       }
640     }
641     actual_delete_count = Min(Max(delete_count, 0), len - actual_start);
642   }
643
644   int add_count = (argument_count > 1) ? (argument_count - 2) : 0;
645   int new_length = len - actual_delete_count + add_count;
646
647   if (new_length != len && JSArray::HasReadOnlyLength(array)) {
648     AllowHeapAllocation allow_allocation;
649     return CallJsIntrinsic(isolate, isolate->array_splice(), args);
650   }
651   ElementsAccessor* accessor = array->GetElementsAccessor();
652   Handle<JSArray> result_array = accessor->Splice(
653       array, elms_obj, actual_start, actual_delete_count, args, add_count);
654   return *result_array;
655 }
656
657
658 BUILTIN(ArrayConcat) {
659   HandleScope scope(isolate);
660
661   int n_arguments = args.length();
662   int result_len = 0;
663   ElementsKind elements_kind = GetInitialFastElementsKind();
664   bool has_double = false;
665   {
666     DisallowHeapAllocation no_gc;
667     Context* native_context = isolate->context()->native_context();
668     Object* array_proto = native_context->array_function()->prototype();
669     PrototypeIterator iter(isolate, array_proto,
670                            PrototypeIterator::START_AT_RECEIVER);
671     if (!PrototypeHasNoElements(&iter)) {
672       AllowHeapAllocation allow_allocation;
673       return CallJsIntrinsic(isolate, isolate->array_concat(), args);
674     }
675
676     // Iterate through all the arguments performing checks
677     // and calculating total length.
678     bool is_holey = false;
679     for (int i = 0; i < n_arguments; i++) {
680       Object* arg = args[i];
681       PrototypeIterator iter(isolate, arg);
682       if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() ||
683           iter.GetCurrent() != array_proto) {
684         AllowHeapAllocation allow_allocation;
685         return CallJsIntrinsic(isolate, isolate->array_concat(), args);
686       }
687       int len = Smi::cast(JSArray::cast(arg)->length())->value();
688
689       // We shouldn't overflow when adding another len.
690       const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
691       STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
692       USE(kHalfOfMaxInt);
693       result_len += len;
694       DCHECK(result_len >= 0);
695
696       if (result_len > FixedDoubleArray::kMaxLength) {
697         AllowHeapAllocation allow_allocation;
698         return CallJsIntrinsic(isolate, isolate->array_concat(), args);
699       }
700
701       ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
702       has_double = has_double || IsFastDoubleElementsKind(arg_kind);
703       is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
704       if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
705         elements_kind = arg_kind;
706       }
707     }
708     if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
709   }
710
711   // If a double array is concatted into a fast elements array, the fast
712   // elements array needs to be initialized to contain proper holes, since
713   // boxing doubles may cause incremental marking.
714   ArrayStorageAllocationMode mode =
715       has_double && IsFastObjectElementsKind(elements_kind)
716       ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
717   Handle<JSArray> result_array = isolate->factory()->NewJSArray(
718       elements_kind, result_len, result_len, Strength::WEAK, mode);
719   if (result_len == 0) return *result_array;
720
721   int j = 0;
722   Handle<FixedArrayBase> storage(result_array->elements(), isolate);
723   ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
724   for (int i = 0; i < n_arguments; i++) {
725     // It is crucial to keep |array| in a raw pointer form to avoid performance
726     // degradation.
727     JSArray* array = JSArray::cast(args[i]);
728     int len = Smi::cast(array->length())->value();
729     if (len > 0) {
730       ElementsKind from_kind = array->GetElementsKind();
731       accessor->CopyElements(array, 0, from_kind, storage, j, len);
732       j += len;
733     }
734   }
735
736   DCHECK(j == result_len);
737
738   return *result_array;
739 }
740
741
742 // -----------------------------------------------------------------------------
743 // Throwers for restricted function properties and strict arguments object
744 // properties
745
746
747 BUILTIN(RestrictedFunctionPropertiesThrower) {
748   HandleScope scope(isolate);
749   THROW_NEW_ERROR_RETURN_FAILURE(
750       isolate, NewTypeError(MessageTemplate::kRestrictedFunctionProperties));
751 }
752
753
754 BUILTIN(RestrictedStrictArgumentsPropertiesThrower) {
755   HandleScope scope(isolate);
756   THROW_NEW_ERROR_RETURN_FAILURE(
757       isolate, NewTypeError(MessageTemplate::kStrictPoisonPill));
758 }
759
760
761 // -----------------------------------------------------------------------------
762 //
763
764
765 template <bool is_construct>
766 MUST_USE_RESULT static MaybeHandle<Object> HandleApiCallHelper(
767     Isolate* isolate, BuiltinArguments<NEEDS_CALLED_FUNCTION>& args) {
768   HandleScope scope(isolate);
769   Handle<JSFunction> function = args.called_function();
770   // TODO(ishell): turn this back to a DCHECK.
771   CHECK(function->shared()->IsApiFunction());
772
773   Handle<FunctionTemplateInfo> fun_data(
774       function->shared()->get_api_func_data(), isolate);
775   if (is_construct) {
776     ASSIGN_RETURN_ON_EXCEPTION(
777         isolate, fun_data,
778         ApiNatives::ConfigureInstance(isolate, fun_data,
779                                       Handle<JSObject>::cast(args.receiver())),
780         Object);
781   }
782
783   DCHECK(!args[0]->IsNull());
784   if (args[0]->IsUndefined()) args[0] = function->global_proxy();
785
786   if (!is_construct && !fun_data->accept_any_receiver()) {
787     Handle<Object> receiver(&args[0]);
788     if (receiver->IsJSObject() && receiver->IsAccessCheckNeeded()) {
789       Handle<JSObject> js_receiver = Handle<JSObject>::cast(receiver);
790       if (!isolate->MayAccess(js_receiver)) {
791         isolate->ReportFailedAccessCheck(js_receiver);
792         RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
793       }
794     }
795   }
796
797   Object* raw_holder = fun_data->GetCompatibleReceiver(isolate, args[0]);
798
799   if (raw_holder->IsNull()) {
800     // This function cannot be called with the given receiver.  Abort!
801     THROW_NEW_ERROR(isolate, NewTypeError(MessageTemplate::kIllegalInvocation),
802                     Object);
803   }
804
805   Object* raw_call_data = fun_data->call_code();
806   if (!raw_call_data->IsUndefined()) {
807     // TODO(ishell): remove this debugging code.
808     CHECK(raw_call_data->IsCallHandlerInfo());
809     CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
810     Object* callback_obj = call_data->callback();
811     v8::FunctionCallback callback =
812         v8::ToCData<v8::FunctionCallback>(callback_obj);
813     Object* data_obj = call_data->data();
814
815     LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
816     DCHECK(raw_holder->IsJSObject());
817
818     FunctionCallbackArguments custom(isolate,
819                                      data_obj,
820                                      *function,
821                                      raw_holder,
822                                      &args[0] - 1,
823                                      args.length() - 1,
824                                      is_construct);
825
826     v8::Local<v8::Value> value = custom.Call(callback);
827     Handle<Object> result;
828     if (value.IsEmpty()) {
829       result = isolate->factory()->undefined_value();
830     } else {
831       result = v8::Utils::OpenHandle(*value);
832       result->VerifyApiCallResultType();
833     }
834
835     RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, Object);
836     if (!is_construct || result->IsJSObject()) {
837       return scope.CloseAndEscape(result);
838     }
839   }
840
841   return scope.CloseAndEscape(args.receiver());
842 }
843
844
845 BUILTIN(HandleApiCall) {
846   HandleScope scope(isolate);
847   DCHECK(!CalledAsConstructor(isolate));
848   Handle<Object> result;
849   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
850                                      HandleApiCallHelper<false>(isolate, args));
851   return *result;
852 }
853
854
855 BUILTIN(HandleApiCallConstruct) {
856   HandleScope scope(isolate);
857   DCHECK(CalledAsConstructor(isolate));
858   Handle<Object> result;
859   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result,
860                                      HandleApiCallHelper<true>(isolate, args));
861   return *result;
862 }
863
864
865 namespace {
866
867 class RelocatableArguments : public BuiltinArguments<NEEDS_CALLED_FUNCTION>,
868                              public Relocatable {
869  public:
870   RelocatableArguments(Isolate* isolate, int length, Object** arguments)
871       : BuiltinArguments<NEEDS_CALLED_FUNCTION>(length, arguments),
872         Relocatable(isolate) {}
873
874   virtual inline void IterateInstance(ObjectVisitor* v) {
875     if (length() == 0) return;
876     v->VisitPointers(lowest_address(), highest_address() + 1);
877   }
878
879  private:
880   DISALLOW_COPY_AND_ASSIGN(RelocatableArguments);
881 };
882
883 }  // namespace
884
885
886 MaybeHandle<Object> Builtins::InvokeApiFunction(Handle<JSFunction> function,
887                                                 Handle<Object> receiver,
888                                                 int argc,
889                                                 Handle<Object> args[]) {
890   // Construct BuiltinArguments object: function, arguments reversed, receiver.
891   const int kBufferSize = 32;
892   Object* small_argv[kBufferSize];
893   Object** argv;
894   if (argc + 2 <= kBufferSize) {
895     argv = small_argv;
896   } else {
897     argv = new Object* [argc + 2];
898   }
899   argv[argc + 1] = *receiver;
900   for (int i = 0; i < argc; ++i) {
901     argv[argc - i] = *args[i];
902   }
903   argv[0] = *function;
904   MaybeHandle<Object> result;
905   {
906     auto isolate = function->GetIsolate();
907     RelocatableArguments arguments(isolate, argc + 2, &argv[argc + 1]);
908     result = HandleApiCallHelper<false>(isolate, arguments);
909   }
910   if (argv != small_argv) {
911     delete[] argv;
912   }
913   return result;
914 }
915
916
917 // Helper function to handle calls to non-function objects created through the
918 // API. The object can be called as either a constructor (using new) or just as
919 // a function (without new).
920 MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
921     Isolate* isolate,
922     bool is_construct_call,
923     BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
924   // Non-functions are never called as constructors. Even if this is an object
925   // called as a constructor the delegate call is not a construct call.
926   DCHECK(!CalledAsConstructor(isolate));
927   Heap* heap = isolate->heap();
928
929   Handle<Object> receiver = args.receiver();
930
931   // Get the object called.
932   JSObject* obj = JSObject::cast(*receiver);
933
934   // Get the invocation callback from the function descriptor that was
935   // used to create the called object.
936   DCHECK(obj->map()->has_instance_call_handler());
937   JSFunction* constructor = JSFunction::cast(obj->map()->GetConstructor());
938   // TODO(ishell): turn this back to a DCHECK.
939   CHECK(constructor->shared()->IsApiFunction());
940   Object* handler =
941       constructor->shared()->get_api_func_data()->instance_call_handler();
942   DCHECK(!handler->IsUndefined());
943   // TODO(ishell): remove this debugging code.
944   CHECK(handler->IsCallHandlerInfo());
945   CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
946   Object* callback_obj = call_data->callback();
947   v8::FunctionCallback callback =
948       v8::ToCData<v8::FunctionCallback>(callback_obj);
949
950   // Get the data for the call and perform the callback.
951   Object* result;
952   {
953     HandleScope scope(isolate);
954     LOG(isolate, ApiObjectAccess("call non-function", obj));
955
956     FunctionCallbackArguments custom(isolate,
957                                      call_data->data(),
958                                      constructor,
959                                      obj,
960                                      &args[0] - 1,
961                                      args.length() - 1,
962                                      is_construct_call);
963     v8::Local<v8::Value> value = custom.Call(callback);
964     if (value.IsEmpty()) {
965       result = heap->undefined_value();
966     } else {
967       result = *reinterpret_cast<Object**>(*value);
968       result->VerifyApiCallResultType();
969     }
970   }
971   // Check for exceptions and return result.
972   RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
973   return result;
974 }
975
976
977 // Handle calls to non-function objects created through the API. This delegate
978 // function is used when the call is a normal function call.
979 BUILTIN(HandleApiCallAsFunction) {
980   return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
981 }
982
983
984 // Handle calls to non-function objects created through the API. This delegate
985 // function is used when the call is a construct call.
986 BUILTIN(HandleApiCallAsConstructor) {
987   return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
988 }
989
990
991 static void Generate_LoadIC_Miss(MacroAssembler* masm) {
992   LoadIC::GenerateMiss(masm);
993 }
994
995
996 static void Generate_LoadIC_Normal(MacroAssembler* masm) {
997   LoadIC::GenerateNormal(masm, SLOPPY);
998 }
999
1000
1001 static void Generate_LoadIC_Normal_Strong(MacroAssembler* masm) {
1002   LoadIC::GenerateNormal(masm, STRONG);
1003 }
1004
1005
1006 static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
1007   NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
1008 }
1009
1010
1011 static void Generate_LoadIC_Slow(MacroAssembler* masm) {
1012   LoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
1013 }
1014
1015
1016 static void Generate_LoadIC_Slow_Strong(MacroAssembler* masm) {
1017   LoadIC::GenerateRuntimeGetProperty(masm, STRONG);
1018 }
1019
1020
1021 static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
1022   KeyedLoadIC::GenerateRuntimeGetProperty(masm, SLOPPY);
1023 }
1024
1025
1026 static void Generate_KeyedLoadIC_Slow_Strong(MacroAssembler* masm) {
1027   KeyedLoadIC::GenerateRuntimeGetProperty(masm, STRONG);
1028 }
1029
1030
1031 static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
1032   KeyedLoadIC::GenerateMiss(masm);
1033 }
1034
1035
1036 static void Generate_KeyedLoadIC_Megamorphic(MacroAssembler* masm) {
1037   KeyedLoadIC::GenerateMegamorphic(masm, SLOPPY);
1038 }
1039
1040
1041 static void Generate_KeyedLoadIC_Megamorphic_Strong(MacroAssembler* masm) {
1042   KeyedLoadIC::GenerateMegamorphic(masm, STRONG);
1043 }
1044
1045
1046 static void Generate_StoreIC_Miss(MacroAssembler* masm) {
1047   StoreIC::GenerateMiss(masm);
1048 }
1049
1050
1051 static void Generate_StoreIC_Normal(MacroAssembler* masm) {
1052   StoreIC::GenerateNormal(masm);
1053 }
1054
1055
1056 static void Generate_StoreIC_Slow(MacroAssembler* masm) {
1057   NamedStoreHandlerCompiler::GenerateSlow(masm);
1058 }
1059
1060
1061 static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
1062   ElementHandlerCompiler::GenerateStoreSlow(masm);
1063 }
1064
1065
1066 static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
1067   NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
1068 }
1069
1070
1071 static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
1072   KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
1073 }
1074
1075
1076 static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
1077   KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
1078 }
1079
1080
1081 static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
1082   KeyedStoreIC::GenerateMiss(masm);
1083 }
1084
1085
1086 static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
1087   KeyedStoreIC::GenerateInitialize(masm);
1088 }
1089
1090
1091 static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
1092   KeyedStoreIC::GenerateInitialize(masm);
1093 }
1094
1095
1096 static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
1097   KeyedStoreIC::GeneratePreMonomorphic(masm);
1098 }
1099
1100
1101 static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
1102   KeyedStoreIC::GeneratePreMonomorphic(masm);
1103 }
1104
1105
1106 static void Generate_Return_DebugBreak(MacroAssembler* masm) {
1107   DebugCodegen::GenerateDebugBreakStub(masm,
1108                                        DebugCodegen::SAVE_RESULT_REGISTER);
1109 }
1110
1111
1112 static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
1113   DebugCodegen::GenerateDebugBreakStub(masm,
1114                                        DebugCodegen::IGNORE_RESULT_REGISTER);
1115 }
1116
1117
1118 static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
1119   DebugCodegen::GeneratePlainReturnLiveEdit(masm);
1120 }
1121
1122
1123 static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
1124   DebugCodegen::GenerateFrameDropperLiveEdit(masm);
1125 }
1126
1127
1128 Builtins::Builtins() : initialized_(false) {
1129   memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
1130   memset(names_, 0, sizeof(names_[0]) * builtin_count);
1131 }
1132
1133
1134 Builtins::~Builtins() {
1135 }
1136
1137
1138 #define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
1139 Address const Builtins::c_functions_[cfunction_count] = {
1140   BUILTIN_LIST_C(DEF_ENUM_C)
1141 };
1142 #undef DEF_ENUM_C
1143
1144
1145 struct BuiltinDesc {
1146   byte* generator;
1147   byte* c_code;
1148   const char* s_name;  // name is only used for generating log information.
1149   int name;
1150   Code::Flags flags;
1151   BuiltinExtraArguments extra_args;
1152 };
1153
1154 #define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
1155
1156 class BuiltinFunctionTable {
1157  public:
1158   BuiltinDesc* functions() {
1159     base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
1160     return functions_;
1161   }
1162
1163   base::OnceType once_;
1164   BuiltinDesc functions_[Builtins::builtin_count + 1];
1165
1166   friend class Builtins;
1167 };
1168
1169 static BuiltinFunctionTable builtin_function_table =
1170     BUILTIN_FUNCTION_TABLE_INIT;
1171
1172 // Define array of pointers to generators and C builtin functions.
1173 // We do this in a sort of roundabout way so that we can do the initialization
1174 // within the lexical scope of Builtins:: and within a context where
1175 // Code::Flags names a non-abstract type.
1176 void Builtins::InitBuiltinFunctionTable() {
1177   BuiltinDesc* functions = builtin_function_table.functions_;
1178   functions[builtin_count].generator = NULL;
1179   functions[builtin_count].c_code = NULL;
1180   functions[builtin_count].s_name = NULL;
1181   functions[builtin_count].name = builtin_count;
1182   functions[builtin_count].flags = static_cast<Code::Flags>(0);
1183   functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
1184
1185 #define DEF_FUNCTION_PTR_C(aname, aextra_args)                         \
1186     functions->generator = FUNCTION_ADDR(Generate_Adaptor);            \
1187     functions->c_code = FUNCTION_ADDR(Builtin_##aname);                \
1188     functions->s_name = #aname;                                        \
1189     functions->name = c_##aname;                                       \
1190     functions->flags = Code::ComputeFlags(Code::BUILTIN);              \
1191     functions->extra_args = aextra_args;                               \
1192     ++functions;
1193
1194 #define DEF_FUNCTION_PTR_A(aname, kind, state, extra)                       \
1195     functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
1196     functions->c_code = NULL;                                               \
1197     functions->s_name = #aname;                                             \
1198     functions->name = k##aname;                                             \
1199     functions->flags = Code::ComputeFlags(Code::kind,                       \
1200                                           state,                            \
1201                                           extra);                           \
1202     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
1203     ++functions;
1204
1205 #define DEF_FUNCTION_PTR_H(aname, kind)                                     \
1206     functions->generator = FUNCTION_ADDR(Generate_##aname);                 \
1207     functions->c_code = NULL;                                               \
1208     functions->s_name = #aname;                                             \
1209     functions->name = k##aname;                                             \
1210     functions->flags = Code::ComputeHandlerFlags(Code::kind);               \
1211     functions->extra_args = NO_EXTRA_ARGUMENTS;                             \
1212     ++functions;
1213
1214   BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1215   BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
1216   BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
1217   BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1218
1219 #undef DEF_FUNCTION_PTR_C
1220 #undef DEF_FUNCTION_PTR_A
1221 }
1222
1223
1224 void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
1225   DCHECK(!initialized_);
1226
1227   // Create a scope for the handles in the builtins.
1228   HandleScope scope(isolate);
1229
1230   const BuiltinDesc* functions = builtin_function_table.functions();
1231
1232   // For now we generate builtin adaptor code into a stack-allocated
1233   // buffer, before copying it into individual code objects. Be careful
1234   // with alignment, some platforms don't like unaligned code.
1235 #ifdef DEBUG
1236   // We can generate a lot of debug code on Arm64.
1237   const size_t buffer_size = 32*KB;
1238 #else
1239   const size_t buffer_size = 8*KB;
1240 #endif
1241   union { int force_alignment; byte buffer[buffer_size]; } u;
1242
1243   // Traverse the list of builtins and generate an adaptor in a
1244   // separate code object for each one.
1245   for (int i = 0; i < builtin_count; i++) {
1246     if (create_heap_objects) {
1247       MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
1248       // Generate the code/adaptor.
1249       typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
1250       Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1251       // We pass all arguments to the generator, but it may not use all of
1252       // them.  This works because the first arguments are on top of the
1253       // stack.
1254       DCHECK(!masm.has_frame());
1255       g(&masm, functions[i].name, functions[i].extra_args);
1256       // Move the code into the object heap.
1257       CodeDesc desc;
1258       masm.GetCode(&desc);
1259       Code::Flags flags = functions[i].flags;
1260       Handle<Code> code =
1261           isolate->factory()->NewCode(desc, flags, masm.CodeObject());
1262       // Log the event and add the code to the builtins array.
1263       PROFILE(isolate,
1264               CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
1265       builtins_[i] = *code;
1266       code->set_builtin_index(i);
1267 #ifdef ENABLE_DISASSEMBLER
1268       if (FLAG_print_builtin_code) {
1269         CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
1270         OFStream os(trace_scope.file());
1271         os << "Builtin: " << functions[i].s_name << "\n";
1272         code->Disassemble(functions[i].s_name, os);
1273         os << "\n";
1274       }
1275 #endif
1276     } else {
1277       // Deserializing. The values will be filled in during IterateBuiltins.
1278       builtins_[i] = NULL;
1279     }
1280     names_[i] = functions[i].s_name;
1281   }
1282
1283   // Mark as initialized.
1284   initialized_ = true;
1285 }
1286
1287
1288 void Builtins::TearDown() {
1289   initialized_ = false;
1290 }
1291
1292
1293 void Builtins::IterateBuiltins(ObjectVisitor* v) {
1294   v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
1295 }
1296
1297
1298 const char* Builtins::Lookup(byte* pc) {
1299   // may be called during initialization (disassembler!)
1300   if (initialized_) {
1301     for (int i = 0; i < builtin_count; i++) {
1302       Code* entry = Code::cast(builtins_[i]);
1303       if (entry->contains(pc)) {
1304         return names_[i];
1305       }
1306     }
1307   }
1308   return NULL;
1309 }
1310
1311
1312 void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
1313   masm->TailCallRuntime(Runtime::kInterrupt, 0, 1);
1314 }
1315
1316
1317 void Builtins::Generate_StackCheck(MacroAssembler* masm) {
1318   masm->TailCallRuntime(Runtime::kStackGuard, 0, 1);
1319 }
1320
1321
1322 #define DEFINE_BUILTIN_ACCESSOR_C(name, ignore)               \
1323 Handle<Code> Builtins::name() {                               \
1324   Code** code_address =                                       \
1325       reinterpret_cast<Code**>(builtin_address(k##name));     \
1326   return Handle<Code>(code_address);                          \
1327 }
1328 #define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
1329 Handle<Code> Builtins::name() {                             \
1330   Code** code_address =                                     \
1331       reinterpret_cast<Code**>(builtin_address(k##name));   \
1332   return Handle<Code>(code_address);                        \
1333 }
1334 #define DEFINE_BUILTIN_ACCESSOR_H(name, kind)               \
1335 Handle<Code> Builtins::name() {                             \
1336   Code** code_address =                                     \
1337       reinterpret_cast<Code**>(builtin_address(k##name));   \
1338   return Handle<Code>(code_address);                        \
1339 }
1340 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1341 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
1342 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
1343 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1344 #undef DEFINE_BUILTIN_ACCESSOR_C
1345 #undef DEFINE_BUILTIN_ACCESSOR_A
1346
1347
1348 }  // namespace internal
1349 }  // namespace v8