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