blob: b8d0b42d50e8f757497c12696d5112b1d03043b8 [file] [log] [blame]
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001// Copyright 2012 the V8 project authors. All rights reserved.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
Steve Blocka7e24c12009-10-30 11:49:00 +00004
Ben Murdochb8a8cc12014-11-26 15:28:44 +00005#include "src/v8.h"
Steve Blocka7e24c12009-10-30 11:49:00 +00006
Ben Murdochb8a8cc12014-11-26 15:28:44 +00007#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"
16#include "src/ic/handler-compiler.h"
17#include "src/ic/ic.h"
18#include "src/prototype.h"
19#include "src/vm-state-inl.h"
Steve Blocka7e24c12009-10-30 11:49:00 +000020
21namespace v8 {
22namespace internal {
23
Leon Clarkee46be812010-01-19 14:06:41 +000024namespace {
25
26// Arguments object passed to C++ builtins.
27template <BuiltinExtraArguments extra_args>
28class BuiltinArguments : public Arguments {
29 public:
30 BuiltinArguments(int length, Object** arguments)
31 : Arguments(length, arguments) { }
32
33 Object*& operator[] (int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000034 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000035 return Arguments::operator[](index);
36 }
37
38 template <class S> Handle<S> at(int index) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000039 DCHECK(index < length());
Leon Clarkee46be812010-01-19 14:06:41 +000040 return Arguments::at<S>(index);
41 }
42
43 Handle<Object> receiver() {
44 return Arguments::at<Object>(0);
45 }
46
47 Handle<JSFunction> called_function() {
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.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000062 DCHECK(Arguments::length() >= 1);
Leon Clarkee46be812010-01-19 14:06:41 +000063 }
64#endif
65};
66
67
68// Specialize BuiltinArguments for the called function extra argument.
69
70template <>
71int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
72 return Arguments::length() - 1;
73}
74
75#ifdef DEBUG
76template <>
77void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
78 // Check we have at least the receiver and the called function.
Ben Murdochb8a8cc12014-11-26 15:28:44 +000079 DCHECK(Arguments::length() >= 2);
Leon Clarkee46be812010-01-19 14:06:41 +000080 // 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;
88BUILTIN_LIST_C(DEF_ARG_TYPE)
89#undef DEF_ARG_TYPE
90
91} // namespace
92
Steve Blocka7e24c12009-10-30 11:49:00 +000093// ----------------------------------------------------------------------------
Leon Clarkee46be812010-01-19 14:06:41 +000094// Support macro for defining builtins in C++.
Steve Blocka7e24c12009-10-30 11:49:00 +000095// ----------------------------------------------------------------------------
96//
97// A builtin function is defined by writing:
98//
99// BUILTIN(name) {
100// ...
101// }
Steve Blocka7e24c12009-10-30 11:49:00 +0000102//
Leon Clarkee46be812010-01-19 14:06:41 +0000103// In the body of the builtin function the arguments can be accessed
104// through the BuiltinArguments object args.
Steve Blocka7e24c12009-10-30 11:49:00 +0000105
Leon Clarkee46be812010-01-19 14:06:41 +0000106#ifdef DEBUG
Steve Blocka7e24c12009-10-30 11:49:00 +0000107
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000108#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( \
Steve Block44f0eee2011-05-26 01:26:41 +0100118 name##ArgumentsType args, Isolate* isolate)
Steve Blocka7e24c12009-10-30 11:49:00 +0000119
Leon Clarkee46be812010-01-19 14:06:41 +0000120#else // For release mode.
Steve Blocka7e24c12009-10-30 11:49:00 +0000121
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000122#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)
Leon Clarkee46be812010-01-19 14:06:41 +0000132#endif
Steve Blocka7e24c12009-10-30 11:49:00 +0000133
134
Steve Blocka7e24c12009-10-30 11:49:00 +0000135#ifdef DEBUG
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000136static inline bool CalledAsConstructor(Isolate* isolate) {
Steve Blocka7e24c12009-10-30 11:49:00 +0000137 // 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.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000140 StackFrameIterator it(isolate);
141 DCHECK(it.frame()->is_exit());
Steve Blocka7e24c12009-10-30 11:49:00 +0000142 it.Advance();
143 StackFrame* frame = it.frame();
144 bool reference_result = frame->is_construct();
Steve Block44f0eee2011-05-26 01:26:41 +0100145 Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
Steve Blocka7e24c12009-10-30 11:49:00 +0000146 // 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000158 DCHECK_EQ(result, reference_result);
Steve Blocka7e24c12009-10-30 11:49:00 +0000159 return result;
160}
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000161#endif
162
Steve Blocka7e24c12009-10-30 11:49:00 +0000163
164// ----------------------------------------------------------------------------
165
Steve Blocka7e24c12009-10-30 11:49:00 +0000166BUILTIN(Illegal) {
167 UNREACHABLE();
Steve Block44f0eee2011-05-26 01:26:41 +0100168 return isolate->heap()->undefined_value(); // Make compiler happy.
Steve Blocka7e24c12009-10-30 11:49:00 +0000169}
Steve Blocka7e24c12009-10-30 11:49:00 +0000170
171
172BUILTIN(EmptyFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +0100173 return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000174}
Steve Blocka7e24c12009-10-30 11:49:00 +0000175
176
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000177static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index,
178 FixedDoubleArray* src, int src_index, int len) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100179 if (len == 0) return;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000180 MemMove(dst->data_start() + dst_index, src->data_start() + src_index,
181 len * kDoubleSize);
Steve Block6ded16b2010-05-10 14:33:55 +0100182}
183
184
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400185static bool ArrayPrototypeHasNoElements(Heap* heap, PrototypeIterator* iter) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000186 DisallowHeapAllocation no_gc;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400187 for (; !iter->IsAtEnd(); iter->Advance()) {
188 if (iter->GetCurrent()->IsJSProxy()) return false;
189 if (JSObject::cast(iter->GetCurrent())->elements() !=
190 heap->empty_fixed_array()) {
191 return false;
192 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000193 }
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400194 return true;
195}
196
197
198static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
199 JSArray* receiver) {
200 DisallowHeapAllocation no_gc;
201 PrototypeIterator iter(heap->isolate(), receiver);
202 return ArrayPrototypeHasNoElements(heap, &iter);
Steve Block6ded16b2010-05-10 14:33:55 +0100203}
204
205
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000206// Returns empty handle if not applicable.
John Reck59135872010-11-02 12:39:01 -0700207MUST_USE_RESULT
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
209 Isolate* isolate,
210 Handle<Object> receiver,
211 Arguments* args,
212 int first_added_arg) {
213 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
214 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
215 // If there may be elements accessors in the prototype chain, the fast path
216 // cannot be used if there arguments to add to the array.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400217 Heap* heap = isolate->heap();
218 if (args != NULL && !IsJSArrayFastElementMovingAllowed(heap, *array)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000219 return MaybeHandle<FixedArrayBase>();
220 }
221 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
222 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
223 Handle<FixedArrayBase> elms(array->elements(), isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100224 Map* map = elms->map();
225 if (map == heap->fixed_array_map()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000226 if (args == NULL || array->HasFastObjectElements()) return elms;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100227 } else if (map == heap->fixed_cow_array_map()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000228 elms = JSObject::EnsureWritableFastElements(array);
229 if (args == NULL || array->HasFastObjectElements()) return elms;
230 } else if (map == heap->fixed_double_array_map()) {
231 if (args == NULL) return elms;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100232 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000233 return MaybeHandle<FixedArrayBase>();
Steve Block6ded16b2010-05-10 14:33:55 +0100234 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100235
236 // Need to ensure that the arguments passed in args can be contained in
237 // the array.
238 int args_length = args->length();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000239 if (first_added_arg >= args_length) return handle(array->elements(), isolate);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100240
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000241 ElementsKind origin_kind = array->map()->elements_kind();
242 DCHECK(!IsFastObjectElementsKind(origin_kind));
243 ElementsKind target_kind = origin_kind;
244 {
245 DisallowHeapAllocation no_gc;
246 int arg_count = args->length() - first_added_arg;
247 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
248 for (int i = 0; i < arg_count; i++) {
249 Object* arg = arguments[i];
250 if (arg->IsHeapObject()) {
251 if (arg->IsHeapNumber()) {
252 target_kind = FAST_DOUBLE_ELEMENTS;
253 } else {
254 target_kind = FAST_ELEMENTS;
255 break;
256 }
257 }
258 }
259 }
260 if (target_kind != origin_kind) {
261 JSObject::TransitionElementsKind(array, target_kind);
262 return handle(array->elements(), isolate);
263 }
264 return elms;
Steve Block6ded16b2010-05-10 14:33:55 +0100265}
266
267
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000268MUST_USE_RESULT static Object* CallJsBuiltin(
Steve Block44f0eee2011-05-26 01:26:41 +0100269 Isolate* isolate,
John Reck59135872010-11-02 12:39:01 -0700270 const char* name,
271 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
Steve Block44f0eee2011-05-26 01:26:41 +0100272 HandleScope handleScope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100273
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000274 Handle<Object> js_builtin = Object::GetProperty(
275 isolate,
276 handle(isolate->native_context()->builtins(), isolate),
277 name).ToHandleChecked();
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100278 Handle<JSFunction> function = Handle<JSFunction>::cast(js_builtin);
279 int argc = args.length() - 1;
280 ScopedVector<Handle<Object> > argv(argc);
281 for (int i = 0; i < argc; ++i) {
282 argv[i] = args.at<Object>(i + 1);
Steve Block6ded16b2010-05-10 14:33:55 +0100283 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000284 Handle<Object> result;
285 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
286 isolate, result,
287 Execution::Call(isolate,
288 function,
289 args.receiver(),
290 argc,
291 argv.start()));
Steve Block6ded16b2010-05-10 14:33:55 +0100292 return *result;
293}
294
295
Steve Blocka7e24c12009-10-30 11:49:00 +0000296BUILTIN(ArrayPush) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000297 HandleScope scope(isolate);
298 Handle<Object> receiver = args.receiver();
299 MaybeHandle<FixedArrayBase> maybe_elms_obj =
300 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
301 Handle<FixedArrayBase> elms_obj;
302 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
303 return CallJsBuiltin(isolate, "ArrayPush", args);
John Reck59135872010-11-02 12:39:01 -0700304 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000305
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000306 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +0000307 int len = Smi::cast(array->length())->value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000308 int to_add = args.length() - 1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000309 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
310 return CallJsBuiltin(isolate, "ArrayPush", args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000311 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000312 DCHECK(!array->map()->is_observed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000313
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000314 ElementsKind kind = array->GetElementsKind();
Steve Blocka7e24c12009-10-30 11:49:00 +0000315
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000316 if (IsFastSmiOrObjectElementsKind(kind)) {
317 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
318 if (to_add == 0) {
319 return Smi::FromInt(len);
John Reck59135872010-11-02 12:39:01 -0700320 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000321 // Currently fixed arrays cannot grow too big, so
322 // we should never hit this case.
323 DCHECK(to_add <= (Smi::kMaxValue - len));
Leon Clarke4515c472010-02-03 11:58:03 +0000324
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000325 int new_length = len + to_add;
Steve Block6ded16b2010-05-10 14:33:55 +0100326
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000327 if (new_length > elms->length()) {
328 // New backing storage is needed.
329 int capacity = new_length + (new_length >> 1) + 16;
330 Handle<FixedArray> new_elms =
331 isolate->factory()->NewUninitializedFixedArray(capacity);
332
333 ElementsAccessor* accessor = array->GetElementsAccessor();
334 accessor->CopyElements(
335 elms_obj, 0, kind, new_elms, 0,
336 ElementsAccessor::kCopyToEndAndInitializeToHole);
337
338 elms = new_elms;
339 }
340
341 // Add the provided values.
342 DisallowHeapAllocation no_gc;
343 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
344 for (int index = 0; index < to_add; index++) {
345 elms->set(index + len, args[index + 1], mode);
346 }
347
348 if (*elms != array->elements()) {
349 array->set_elements(*elms);
350 }
351
352 // Set the length.
353 array->set_length(Smi::FromInt(new_length));
354 return Smi::FromInt(new_length);
355 } else {
356 int elms_len = elms_obj->length();
357 if (to_add == 0) {
358 return Smi::FromInt(len);
359 }
360 // Currently fixed arrays cannot grow too big, so
361 // we should never hit this case.
362 DCHECK(to_add <= (Smi::kMaxValue - len));
363
364 int new_length = len + to_add;
365
366 Handle<FixedDoubleArray> new_elms;
367
368 if (new_length > elms_len) {
369 // New backing storage is needed.
370 int capacity = new_length + (new_length >> 1) + 16;
371 // Create new backing store; since capacity > 0, we can
372 // safely cast to FixedDoubleArray.
373 new_elms = Handle<FixedDoubleArray>::cast(
374 isolate->factory()->NewFixedDoubleArray(capacity));
375
376 ElementsAccessor* accessor = array->GetElementsAccessor();
377 accessor->CopyElements(
378 elms_obj, 0, kind, new_elms, 0,
379 ElementsAccessor::kCopyToEndAndInitializeToHole);
380
381 } else {
382 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the
383 // empty_fixed_array.
384 new_elms = Handle<FixedDoubleArray>::cast(elms_obj);
385 }
386
387 // Add the provided values.
388 DisallowHeapAllocation no_gc;
389 int index;
390 for (index = 0; index < to_add; index++) {
391 Object* arg = args[index + 1];
392 new_elms->set(index + len, arg->Number());
393 }
394
395 if (*new_elms != array->elements()) {
396 array->set_elements(*new_elms);
397 }
398
399 // Set the length.
400 array->set_length(Smi::FromInt(new_length));
401 return Smi::FromInt(new_length);
Steve Blocka7e24c12009-10-30 11:49:00 +0000402 }
Steve Blocka7e24c12009-10-30 11:49:00 +0000403}
Steve Blocka7e24c12009-10-30 11:49:00 +0000404
405
406BUILTIN(ArrayPop) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000407 HandleScope scope(isolate);
408 Handle<Object> receiver = args.receiver();
409 MaybeHandle<FixedArrayBase> maybe_elms_obj =
410 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
411 Handle<FixedArrayBase> elms_obj;
412 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
413 return CallJsBuiltin(isolate, "ArrayPop", args);
John Reck59135872010-11-02 12:39:01 -0700414 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000415
416 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
417 DCHECK(!array->map()->is_observed());
Steve Blocka7e24c12009-10-30 11:49:00 +0000418
419 int len = Smi::cast(array->length())->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000420 if (len == 0) return isolate->heap()->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +0000421
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400422 if (JSArray::HasReadOnlyLength(array)) {
423 return CallJsBuiltin(isolate, "ArrayPop", args);
424 }
425
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000426 ElementsAccessor* accessor = array->GetElementsAccessor();
427 int new_length = len - 1;
428 Handle<Object> element =
429 accessor->Get(array, array, new_length, elms_obj).ToHandleChecked();
430 if (element->IsTheHole()) {
431 return CallJsBuiltin(isolate, "ArrayPop", args);
Steve Blocka7e24c12009-10-30 11:49:00 +0000432 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000433 RETURN_FAILURE_ON_EXCEPTION(
434 isolate,
435 accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
436 return *element;
Steve Blocka7e24c12009-10-30 11:49:00 +0000437}
Steve Blocka7e24c12009-10-30 11:49:00 +0000438
439
Andrei Popescu402d9372010-02-26 13:31:12 +0000440BUILTIN(ArrayShift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000441 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100442 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000443 Handle<Object> receiver = args.receiver();
444 MaybeHandle<FixedArrayBase> maybe_elms_obj =
445 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
446 Handle<FixedArrayBase> elms_obj;
447 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400448 !IsJSArrayFastElementMovingAllowed(heap, JSArray::cast(*receiver))) {
Steve Block44f0eee2011-05-26 01:26:41 +0100449 return CallJsBuiltin(isolate, "ArrayShift", args);
Steve Block6ded16b2010-05-10 14:33:55 +0100450 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000451 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
452 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000453
454 int len = Smi::cast(array->length())->value();
Steve Block44f0eee2011-05-26 01:26:41 +0100455 if (len == 0) return heap->undefined_value();
Andrei Popescu402d9372010-02-26 13:31:12 +0000456
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400457 if (JSArray::HasReadOnlyLength(array)) {
458 return CallJsBuiltin(isolate, "ArrayShift", args);
459 }
460
Andrei Popescu402d9372010-02-26 13:31:12 +0000461 // Get first element
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000462 ElementsAccessor* accessor = array->GetElementsAccessor();
463 Handle<Object> first =
464 accessor->Get(array, array, 0, elms_obj).ToHandleChecked();
Andrei Popescu402d9372010-02-26 13:31:12 +0000465 if (first->IsTheHole()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000466 return CallJsBuiltin(isolate, "ArrayShift", args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000467 }
468
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000469 if (heap->CanMoveObjectStart(*elms_obj)) {
470 array->set_elements(heap->LeftTrimFixedArray(*elms_obj, 1));
Steve Block6ded16b2010-05-10 14:33:55 +0100471 } else {
472 // Shift the elements.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000473 if (elms_obj->IsFixedArray()) {
474 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
475 DisallowHeapAllocation no_gc;
476 heap->MoveElements(*elms, 0, 1, len - 1);
477 elms->set(len - 1, heap->the_hole_value());
478 } else {
479 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
480 MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
481 elms->set_the_hole(len - 1);
482 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000483 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000484
485 // Set the length.
486 array->set_length(Smi::FromInt(len - 1));
487
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000488 return *first;
Andrei Popescu402d9372010-02-26 13:31:12 +0000489}
490
491
492BUILTIN(ArrayUnshift) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000493 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100494 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000495 Handle<Object> receiver = args.receiver();
496 MaybeHandle<FixedArrayBase> maybe_elms_obj =
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400497 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000498 Handle<FixedArrayBase> elms_obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400499 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100500 return CallJsBuiltin(isolate, "ArrayUnshift", args);
Steve Block6ded16b2010-05-10 14:33:55 +0100501 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000502 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
503 DCHECK(!array->map()->is_observed());
504 if (!array->HasFastSmiOrObjectElements()) {
505 return CallJsBuiltin(isolate, "ArrayUnshift", args);
506 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000507 int len = Smi::cast(array->length())->value();
508 int to_add = args.length() - 1;
Andrei Popescu402d9372010-02-26 13:31:12 +0000509 int new_length = len + to_add;
510 // Currently fixed arrays cannot grow too big, so
511 // we should never hit this case.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000512 DCHECK(to_add <= (Smi::kMaxValue - len));
Andrei Popescu402d9372010-02-26 13:31:12 +0000513
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000514 if (to_add > 0 && JSArray::WouldChangeReadOnlyLength(array, len + to_add)) {
515 return CallJsBuiltin(isolate, "ArrayUnshift", args);
516 }
517
518 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
519
Andrei Popescu402d9372010-02-26 13:31:12 +0000520 if (new_length > elms->length()) {
521 // New backing storage is needed.
522 int capacity = new_length + (new_length >> 1) + 16;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000523 Handle<FixedArray> new_elms =
524 isolate->factory()->NewUninitializedFixedArray(capacity);
525
526 ElementsKind kind = array->GetElementsKind();
527 ElementsAccessor* accessor = array->GetElementsAccessor();
528 accessor->CopyElements(
529 elms, 0, kind, new_elms, to_add,
530 ElementsAccessor::kCopyToEndAndInitializeToHole);
531
Andrei Popescu402d9372010-02-26 13:31:12 +0000532 elms = new_elms;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000533 array->set_elements(*elms);
Andrei Popescu402d9372010-02-26 13:31:12 +0000534 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000535 DisallowHeapAllocation no_gc;
536 heap->MoveElements(*elms, to_add, 0, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000537 }
538
539 // Add the provided values.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000540 DisallowHeapAllocation no_gc;
Andrei Popescu402d9372010-02-26 13:31:12 +0000541 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
542 for (int i = 0; i < to_add; i++) {
543 elms->set(i, args[i + 1], mode);
544 }
545
546 // Set the length.
547 array->set_length(Smi::FromInt(new_length));
548 return Smi::FromInt(new_length);
549}
550
551
Andrei Popescu402d9372010-02-26 13:31:12 +0000552BUILTIN(ArraySlice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000553 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100554 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000555 Handle<Object> receiver = args.receiver();
Ben Murdochb0fe1622011-05-05 13:52:32 +0100556 int len = -1;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000557 int relative_start = 0;
558 int relative_end = 0;
559 {
560 DisallowHeapAllocation no_gc;
561 if (receiver->IsJSArray()) {
562 JSArray* array = JSArray::cast(*receiver);
563 if (!IsJSArrayFastElementMovingAllowed(heap, array)) {
564 AllowHeapAllocation allow_allocation;
565 return CallJsBuiltin(isolate, "ArraySlice", args);
566 }
Steve Block9fac8402011-05-12 15:51:54 +0100567
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000568 if (!array->HasFastElements()) {
569 AllowHeapAllocation allow_allocation;
570 return CallJsBuiltin(isolate, "ArraySlice", args);
571 }
Steve Block9fac8402011-05-12 15:51:54 +0100572
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000573 len = Smi::cast(array->length())->value();
574 } else {
575 // Array.slice(arguments, ...) is quite a common idiom (notably more
576 // than 50% of invocations in Web apps). Treat it in C++ as well.
577 Map* arguments_map =
578 isolate->context()->native_context()->sloppy_arguments_map();
579
580 bool is_arguments_object_with_fast_elements =
581 receiver->IsJSObject() &&
582 JSObject::cast(*receiver)->map() == arguments_map;
583 if (!is_arguments_object_with_fast_elements) {
584 AllowHeapAllocation allow_allocation;
585 return CallJsBuiltin(isolate, "ArraySlice", args);
586 }
587 JSObject* object = JSObject::cast(*receiver);
588
589 if (!object->HasFastElements()) {
590 AllowHeapAllocation allow_allocation;
591 return CallJsBuiltin(isolate, "ArraySlice", args);
592 }
593
594 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
595 if (!len_obj->IsSmi()) {
596 AllowHeapAllocation allow_allocation;
597 return CallJsBuiltin(isolate, "ArraySlice", args);
598 }
599 len = Smi::cast(len_obj)->value();
600 if (len > object->elements()->length()) {
601 AllowHeapAllocation allow_allocation;
Steve Block44f0eee2011-05-26 01:26:41 +0100602 return CallJsBuiltin(isolate, "ArraySlice", args);
Steve Block9fac8402011-05-12 15:51:54 +0100603 }
604 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000605
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000606 DCHECK(len >= 0);
607 int n_arguments = args.length() - 1;
608
609 // Note carefully choosen defaults---if argument is missing,
610 // it's undefined which gets converted to 0 for relative_start
611 // and to len for relative_end.
612 relative_start = 0;
613 relative_end = len;
614 if (n_arguments > 0) {
615 Object* arg1 = args[1];
616 if (arg1->IsSmi()) {
617 relative_start = Smi::cast(arg1)->value();
618 } else if (arg1->IsHeapNumber()) {
619 double start = HeapNumber::cast(arg1)->value();
620 if (start < kMinInt || start > kMaxInt) {
621 AllowHeapAllocation allow_allocation;
622 return CallJsBuiltin(isolate, "ArraySlice", args);
623 }
624 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
625 } else if (!arg1->IsUndefined()) {
626 AllowHeapAllocation allow_allocation;
Steve Block44f0eee2011-05-26 01:26:41 +0100627 return CallJsBuiltin(isolate, "ArraySlice", args);
Andrei Popescu402d9372010-02-26 13:31:12 +0000628 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000629 if (n_arguments > 1) {
630 Object* arg2 = args[2];
631 if (arg2->IsSmi()) {
632 relative_end = Smi::cast(arg2)->value();
633 } else if (arg2->IsHeapNumber()) {
634 double end = HeapNumber::cast(arg2)->value();
635 if (end < kMinInt || end > kMaxInt) {
636 AllowHeapAllocation allow_allocation;
637 return CallJsBuiltin(isolate, "ArraySlice", args);
638 }
639 relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
640 } else if (!arg2->IsUndefined()) {
641 AllowHeapAllocation allow_allocation;
642 return CallJsBuiltin(isolate, "ArraySlice", args);
643 }
644 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000645 }
646 }
647
648 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
Steve Block6ded16b2010-05-10 14:33:55 +0100649 int k = (relative_start < 0) ? Max(len + relative_start, 0)
650 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000651
652 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
Steve Block6ded16b2010-05-10 14:33:55 +0100653 int final = (relative_end < 0) ? Max(len + relative_end, 0)
654 : Min(relative_end, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000655
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100656 // Calculate the length of result array.
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100657 int result_len = Max(final - k, 0);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100658
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000659 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
660 Handle<FixedArrayBase> elms(object->elements(), isolate);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100661
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000662 ElementsKind kind = object->GetElementsKind();
663 if (IsHoleyElementsKind(kind)) {
664 DisallowHeapAllocation no_gc;
665 bool packed = true;
666 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
667 for (int i = k; i < final; i++) {
668 if (!accessor->HasElement(object, object, i, elms)) {
669 packed = false;
670 break;
671 }
672 }
673 if (packed) {
674 kind = GetPackedElementsKind(kind);
675 } else if (!receiver->IsJSArray()) {
676 AllowHeapAllocation allow_allocation;
677 return CallJsBuiltin(isolate, "ArraySlice", args);
678 }
679 }
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +0100680
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000681 Handle<JSArray> result_array =
682 isolate->factory()->NewJSArray(kind, result_len, result_len);
683
684 DisallowHeapAllocation no_gc;
685 if (result_len == 0) return *result_array;
686
687 ElementsAccessor* accessor = object->GetElementsAccessor();
688 accessor->CopyElements(
689 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
690 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000691}
692
693
694BUILTIN(ArraySplice) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000695 HandleScope scope(isolate);
Steve Block44f0eee2011-05-26 01:26:41 +0100696 Heap* heap = isolate->heap();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000697 Handle<Object> receiver = args.receiver();
698 MaybeHandle<FixedArrayBase> maybe_elms_obj =
699 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
700 Handle<FixedArrayBase> elms_obj;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400701 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
Steve Block44f0eee2011-05-26 01:26:41 +0100702 return CallJsBuiltin(isolate, "ArraySplice", args);
Steve Block6ded16b2010-05-10 14:33:55 +0100703 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000704 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
705 DCHECK(!array->map()->is_observed());
Andrei Popescu402d9372010-02-26 13:31:12 +0000706
707 int len = Smi::cast(array->length())->value();
708
709 int n_arguments = args.length() - 1;
710
Steve Block6ded16b2010-05-10 14:33:55 +0100711 int relative_start = 0;
Steve Block1e0659c2011-05-24 12:43:12 +0100712 if (n_arguments > 0) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000713 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +0100714 Object* arg1 = args[1];
715 if (arg1->IsSmi()) {
716 relative_start = Smi::cast(arg1)->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000717 } else if (arg1->IsHeapNumber()) {
718 double start = HeapNumber::cast(arg1)->value();
719 if (start < kMinInt || start > kMaxInt) {
720 AllowHeapAllocation allow_allocation;
721 return CallJsBuiltin(isolate, "ArraySplice", args);
722 }
723 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
Steve Block1e0659c2011-05-24 12:43:12 +0100724 } else if (!arg1->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000725 AllowHeapAllocation allow_allocation;
Steve Block44f0eee2011-05-26 01:26:41 +0100726 return CallJsBuiltin(isolate, "ArraySplice", args);
Steve Block1e0659c2011-05-24 12:43:12 +0100727 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000728 }
Steve Block6ded16b2010-05-10 14:33:55 +0100729 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
730 : Min(relative_start, len);
Andrei Popescu402d9372010-02-26 13:31:12 +0000731
732 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
Steve Block1e0659c2011-05-24 12:43:12 +0100733 // given as a request to delete all the elements from the start.
734 // And it differs from the case of undefined delete count.
Andrei Popescu402d9372010-02-26 13:31:12 +0000735 // This does not follow ECMA-262, but we do the same for
736 // compatibility.
Steve Block1e0659c2011-05-24 12:43:12 +0100737 int actual_delete_count;
738 if (n_arguments == 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000739 DCHECK(len - actual_start >= 0);
Steve Block1e0659c2011-05-24 12:43:12 +0100740 actual_delete_count = len - actual_start;
741 } else {
742 int value = 0; // ToInteger(undefined) == 0
743 if (n_arguments > 1) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000744 DisallowHeapAllocation no_gc;
Steve Block1e0659c2011-05-24 12:43:12 +0100745 Object* arg2 = args[2];
746 if (arg2->IsSmi()) {
747 value = Smi::cast(arg2)->value();
748 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000749 AllowHeapAllocation allow_allocation;
Steve Block44f0eee2011-05-26 01:26:41 +0100750 return CallJsBuiltin(isolate, "ArraySplice", args);
Steve Block1e0659c2011-05-24 12:43:12 +0100751 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000752 }
Steve Block1e0659c2011-05-24 12:43:12 +0100753 actual_delete_count = Min(Max(value, 0), len - actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000754 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000755
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000756 ElementsKind elements_kind = array->GetElementsKind();
Andrei Popescu402d9372010-02-26 13:31:12 +0000757
Steve Block6ded16b2010-05-10 14:33:55 +0100758 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
Steve Block6ded16b2010-05-10 14:33:55 +0100759 int new_length = len - actual_delete_count + item_count;
Andrei Popescu402d9372010-02-26 13:31:12 +0000760
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000761 // For double mode we do not support changing the length.
762 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
763 return CallJsBuiltin(isolate, "ArraySplice", args);
764 }
765
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400766 if (new_length != len && JSArray::HasReadOnlyLength(array)) {
767 AllowHeapAllocation allow_allocation;
768 return CallJsBuiltin(isolate, "ArraySplice", args);
769 }
770
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000771 if (new_length == 0) {
772 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
773 elms_obj, elements_kind, actual_delete_count);
774 array->set_elements(heap->empty_fixed_array());
775 array->set_length(Smi::FromInt(0));
776 return *result;
777 }
778
779 Handle<JSArray> result_array =
780 isolate->factory()->NewJSArray(elements_kind,
781 actual_delete_count,
782 actual_delete_count);
783
784 if (actual_delete_count > 0) {
785 DisallowHeapAllocation no_gc;
786 ElementsAccessor* accessor = array->GetElementsAccessor();
787 accessor->CopyElements(
788 elms_obj, actual_start, elements_kind,
789 handle(result_array->elements(), isolate), 0, actual_delete_count);
790 }
791
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100792 bool elms_changed = false;
Steve Block6ded16b2010-05-10 14:33:55 +0100793 if (item_count < actual_delete_count) {
Andrei Popescu402d9372010-02-26 13:31:12 +0000794 // Shrink the array.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000795 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) &&
Steve Block6ded16b2010-05-10 14:33:55 +0100796 ((actual_start + item_count) <
797 (len - actual_delete_count - actual_start));
798 if (trim_array) {
799 const int delta = actual_delete_count - item_count;
Andrei Popescu402d9372010-02-26 13:31:12 +0000800
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000801 if (elms_obj->IsFixedDoubleArray()) {
802 Handle<FixedDoubleArray> elms =
803 Handle<FixedDoubleArray>::cast(elms_obj);
804 MoveDoubleElements(*elms, delta, *elms, 0, actual_start);
805 } else {
806 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
807 DisallowHeapAllocation no_gc;
808 heap->MoveElements(*elms, delta, 0, actual_start);
Steve Block6ded16b2010-05-10 14:33:55 +0100809 }
810
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000811 if (heap->CanMoveObjectStart(*elms_obj)) {
812 // On the fast path we move the start of the object in memory.
813 elms_obj = handle(heap->LeftTrimFixedArray(*elms_obj, delta));
814 } else {
815 // This is the slow path. We are going to move the elements to the left
816 // by copying them. For trimmed values we store the hole.
817 if (elms_obj->IsFixedDoubleArray()) {
818 Handle<FixedDoubleArray> elms =
819 Handle<FixedDoubleArray>::cast(elms_obj);
820 MoveDoubleElements(*elms, 0, *elms, delta, len - delta);
821 elms->FillWithHoles(len - delta, len);
822 } else {
823 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
824 DisallowHeapAllocation no_gc;
825 heap->MoveElements(*elms, 0, delta, len - delta);
826 elms->FillWithHoles(len - delta, len);
827 }
828 }
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100829 elms_changed = true;
Steve Block6ded16b2010-05-10 14:33:55 +0100830 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000831 if (elms_obj->IsFixedDoubleArray()) {
832 Handle<FixedDoubleArray> elms =
833 Handle<FixedDoubleArray>::cast(elms_obj);
834 MoveDoubleElements(*elms, actual_start + item_count,
835 *elms, actual_start + actual_delete_count,
836 (len - actual_delete_count - actual_start));
837 elms->FillWithHoles(new_length, len);
838 } else {
839 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
840 DisallowHeapAllocation no_gc;
841 heap->MoveElements(*elms, actual_start + item_count,
842 actual_start + actual_delete_count,
843 (len - actual_delete_count - actual_start));
844 elms->FillWithHoles(new_length, len);
845 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000846 }
Steve Block6ded16b2010-05-10 14:33:55 +0100847 } else if (item_count > actual_delete_count) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000848 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
Andrei Popescu402d9372010-02-26 13:31:12 +0000849 // Currently fixed arrays cannot grow too big, so
850 // we should never hit this case.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000851 DCHECK((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
Andrei Popescu402d9372010-02-26 13:31:12 +0000852
853 // Check if array need to grow.
854 if (new_length > elms->length()) {
855 // New backing storage is needed.
856 int capacity = new_length + (new_length >> 1) + 16;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000857 Handle<FixedArray> new_elms =
858 isolate->factory()->NewUninitializedFixedArray(capacity);
Andrei Popescu402d9372010-02-26 13:31:12 +0000859
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000860 DisallowHeapAllocation no_gc;
861
862 ElementsKind kind = array->GetElementsKind();
863 ElementsAccessor* accessor = array->GetElementsAccessor();
864 if (actual_start > 0) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100865 // Copy the part before actual_start as is.
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000866 accessor->CopyElements(
867 elms, 0, kind, new_elms, 0, actual_start);
Andrei Popescu402d9372010-02-26 13:31:12 +0000868 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000869 accessor->CopyElements(
870 elms, actual_start + actual_delete_count, kind,
871 new_elms, actual_start + item_count,
872 ElementsAccessor::kCopyToEndAndInitializeToHole);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100873
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000874 elms_obj = new_elms;
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100875 elms_changed = true;
Steve Block6ded16b2010-05-10 14:33:55 +0100876 } else {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000877 DisallowHeapAllocation no_gc;
878 heap->MoveElements(*elms, actual_start + item_count,
879 actual_start + actual_delete_count,
880 (len - actual_delete_count - actual_start));
Andrei Popescu402d9372010-02-26 13:31:12 +0000881 }
882 }
883
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000884 if (IsFastDoubleElementsKind(elements_kind)) {
885 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
886 for (int k = actual_start; k < actual_start + item_count; k++) {
887 Object* arg = args[3 + k - actual_start];
888 if (arg->IsSmi()) {
889 elms->set(k, Smi::cast(arg)->value());
890 } else {
891 elms->set(k, HeapNumber::cast(arg)->value());
892 }
893 }
894 } else {
895 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
896 DisallowHeapAllocation no_gc;
897 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
898 for (int k = actual_start; k < actual_start + item_count; k++) {
899 elms->set(k, args[3 + k - actual_start], mode);
900 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000901 }
902
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100903 if (elms_changed) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000904 array->set_elements(*elms_obj);
Ben Murdoch3ef787d2012-04-12 10:51:47 +0100905 }
Andrei Popescu402d9372010-02-26 13:31:12 +0000906 // Set the length.
907 array->set_length(Smi::FromInt(new_length));
908
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000909 return *result_array;
Andrei Popescu402d9372010-02-26 13:31:12 +0000910}
911
912
Steve Block6ded16b2010-05-10 14:33:55 +0100913BUILTIN(ArrayConcat) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000914 HandleScope scope(isolate);
Steve Block6ded16b2010-05-10 14:33:55 +0100915
Steve Block6ded16b2010-05-10 14:33:55 +0100916 int n_arguments = args.length();
917 int result_len = 0;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000918 ElementsKind elements_kind = GetInitialFastElementsKind();
919 bool has_double = false;
920 {
921 DisallowHeapAllocation no_gc;
922 Heap* heap = isolate->heap();
923 Context* native_context = isolate->context()->native_context();
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400924 Object* array_proto = native_context->array_function()->prototype();
925 PrototypeIterator iter(isolate, array_proto,
926 PrototypeIterator::START_AT_RECEIVER);
927 if (!ArrayPrototypeHasNoElements(heap, &iter)) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000928 AllowHeapAllocation allow_allocation;
929 return CallJsBuiltin(isolate, "ArrayConcatJS", args);
Steve Block6ded16b2010-05-10 14:33:55 +0100930 }
931
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000932 // Iterate through all the arguments performing checks
933 // and calculating total length.
934 bool is_holey = false;
935 for (int i = 0; i < n_arguments; i++) {
936 Object* arg = args[i];
937 PrototypeIterator iter(isolate, arg);
938 if (!arg->IsJSArray() || !JSArray::cast(arg)->HasFastElements() ||
939 iter.GetCurrent() != array_proto) {
940 AllowHeapAllocation allow_allocation;
941 return CallJsBuiltin(isolate, "ArrayConcatJS", args);
942 }
943 int len = Smi::cast(JSArray::cast(arg)->length())->value();
Steve Block6ded16b2010-05-10 14:33:55 +0100944
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000945 // We shouldn't overflow when adding another len.
946 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
947 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
948 USE(kHalfOfMaxInt);
949 result_len += len;
950 DCHECK(result_len >= 0);
Steve Block6ded16b2010-05-10 14:33:55 +0100951
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000952 if (result_len > FixedDoubleArray::kMaxLength) {
953 AllowHeapAllocation allow_allocation;
954 return CallJsBuiltin(isolate, "ArrayConcatJS", args);
955 }
956
957 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
958 has_double = has_double || IsFastDoubleElementsKind(arg_kind);
959 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
960 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
961 elements_kind = arg_kind;
962 }
Steve Block6ded16b2010-05-10 14:33:55 +0100963 }
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000964 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
Steve Block6ded16b2010-05-10 14:33:55 +0100965 }
966
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000967 // If a double array is concatted into a fast elements array, the fast
968 // elements array needs to be initialized to contain proper holes, since
969 // boxing doubles may cause incremental marking.
970 ArrayStorageAllocationMode mode =
971 has_double && IsFastObjectElementsKind(elements_kind)
972 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
973 Handle<JSArray> result_array =
974 isolate->factory()->NewJSArray(elements_kind,
975 result_len,
976 result_len,
977 mode);
978 if (result_len == 0) return *result_array;
Ben Murdoch592a9fc2012-03-05 11:04:45 +0000979
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000980 int j = 0;
981 Handle<FixedArrayBase> storage(result_array->elements(), isolate);
982 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
Steve Block6ded16b2010-05-10 14:33:55 +0100983 for (int i = 0; i < n_arguments; i++) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400984 // It is crucial to keep |array| in a raw pointer form to avoid performance
985 // degradation.
Steve Block6ded16b2010-05-10 14:33:55 +0100986 JSArray* array = JSArray::cast(args[i]);
987 int len = Smi::cast(array->length())->value();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000988 if (len > 0) {
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400989 ElementsKind from_kind = array->GetElementsKind();
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000990 accessor->CopyElements(array, 0, from_kind, storage, j, len);
991 j += len;
992 }
Steve Block6ded16b2010-05-10 14:33:55 +0100993 }
Steve Block6ded16b2010-05-10 14:33:55 +0100994
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000995 DCHECK(j == result_len);
996
997 return *result_array;
Steve Block6ded16b2010-05-10 14:33:55 +0100998}
999
1000
Steve Blocka7e24c12009-10-30 11:49:00 +00001001// -----------------------------------------------------------------------------
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001002// Generator and strict mode poison pills
Steve Block44f0eee2011-05-26 01:26:41 +01001003
1004
Ben Murdoch257744e2011-11-30 15:57:28 +00001005BUILTIN(StrictModePoisonPill) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001006 HandleScope scope(isolate);
1007 THROW_NEW_ERROR_RETURN_FAILURE(
1008 isolate,
1009 NewTypeError("strict_poison_pill", HandleVector<Object>(NULL, 0)));
Steve Block44f0eee2011-05-26 01:26:41 +01001010}
1011
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001012
1013BUILTIN(GeneratorPoisonPill) {
1014 HandleScope scope(isolate);
1015 THROW_NEW_ERROR_RETURN_FAILURE(
1016 isolate,
1017 NewTypeError("generator_poison_pill", HandleVector<Object>(NULL, 0)));
1018}
1019
1020
Steve Block44f0eee2011-05-26 01:26:41 +01001021// -----------------------------------------------------------------------------
Steve Blocka7e24c12009-10-30 11:49:00 +00001022//
1023
1024
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001025// Searches the hidden prototype chain of the given object for the first
1026// object that is an instance of the given type. If no such object can
1027// be found then Heap::null_value() is returned.
1028static inline Object* FindHidden(Heap* heap,
1029 Object* object,
1030 FunctionTemplateInfo* type) {
1031 for (PrototypeIterator iter(heap->isolate(), object,
1032 PrototypeIterator::START_AT_RECEIVER);
1033 !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
1034 if (type->IsTemplateFor(iter.GetCurrent())) {
1035 return iter.GetCurrent();
1036 }
1037 }
1038 return heap->null_value();
1039}
1040
1041
Steve Blocka7e24c12009-10-30 11:49:00 +00001042// Returns the holder JSObject if the function can legally be called
1043// with this receiver. Returns Heap::null_value() if the call is
1044// illegal. Any arguments that don't fit the expected type is
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001045// overwritten with undefined. Note that holder and the arguments are
1046// implicitly rewritten with the first object in the hidden prototype
1047// chain that actually has the expected type.
Steve Block44f0eee2011-05-26 01:26:41 +01001048static inline Object* TypeCheck(Heap* heap,
1049 int argc,
Steve Blocka7e24c12009-10-30 11:49:00 +00001050 Object** argv,
1051 FunctionTemplateInfo* info) {
1052 Object* recv = argv[0];
Ben Murdoch257744e2011-11-30 15:57:28 +00001053 // API calls are only supported with JSObject receivers.
1054 if (!recv->IsJSObject()) return heap->null_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001055 Object* sig_obj = info->signature();
1056 if (sig_obj->IsUndefined()) return recv;
1057 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
1058 // If necessary, check the receiver
1059 Object* recv_type = sig->receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00001060 Object* holder = recv;
1061 if (!recv_type->IsUndefined()) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001062 holder = FindHidden(heap, holder, FunctionTemplateInfo::cast(recv_type));
1063 if (holder == heap->null_value()) return heap->null_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001064 }
1065 Object* args_obj = sig->args();
1066 // If there is no argument signature we're done
1067 if (args_obj->IsUndefined()) return holder;
1068 FixedArray* args = FixedArray::cast(args_obj);
1069 int length = args->length();
1070 if (argc <= length) length = argc - 1;
1071 for (int i = 0; i < length; i++) {
1072 Object* argtype = args->get(i);
1073 if (argtype->IsUndefined()) continue;
1074 Object** arg = &argv[-1 - i];
1075 Object* current = *arg;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001076 current = FindHidden(heap, current, FunctionTemplateInfo::cast(argtype));
1077 if (current == heap->null_value()) current = heap->undefined_value();
1078 *arg = current;
Steve Blocka7e24c12009-10-30 11:49:00 +00001079 }
1080 return holder;
1081}
1082
1083
Leon Clarkee46be812010-01-19 14:06:41 +00001084template <bool is_construct>
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001085MUST_USE_RESULT static Object* HandleApiCallHelper(
Steve Block44f0eee2011-05-26 01:26:41 +01001086 BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001087 DCHECK(is_construct == CalledAsConstructor(isolate));
Steve Block44f0eee2011-05-26 01:26:41 +01001088 Heap* heap = isolate->heap();
Steve Blocka7e24c12009-10-30 11:49:00 +00001089
Steve Block44f0eee2011-05-26 01:26:41 +01001090 HandleScope scope(isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00001091 Handle<JSFunction> function = args.called_function();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001092 DCHECK(function->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00001093
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001094 Handle<FunctionTemplateInfo> fun_data(
1095 function->shared()->get_api_func_data(), isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001096 if (is_construct) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001097 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1098 isolate, fun_data,
1099 isolate->factory()->ConfigureInstance(
1100 fun_data, Handle<JSObject>::cast(args.receiver())));
Steve Blocka7e24c12009-10-30 11:49:00 +00001101 }
1102
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001103 SharedFunctionInfo* shared = function->shared();
1104 if (shared->strict_mode() == SLOPPY && !shared->native()) {
1105 Object* recv = args[0];
1106 DCHECK(!recv->IsNull());
1107 if (recv->IsUndefined()) args[0] = function->global_proxy();
1108 }
1109
1110 Object* raw_holder = TypeCheck(heap, args.length(), &args[0], *fun_data);
Steve Blocka7e24c12009-10-30 11:49:00 +00001111
1112 if (raw_holder->IsNull()) {
1113 // This function cannot be called with the given receiver. Abort!
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001114 THROW_NEW_ERROR_RETURN_FAILURE(
1115 isolate,
1116 NewTypeError("illegal_invocation", HandleVector(&function, 1)));
Steve Blocka7e24c12009-10-30 11:49:00 +00001117 }
1118
1119 Object* raw_call_data = fun_data->call_code();
1120 if (!raw_call_data->IsUndefined()) {
1121 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1122 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001123 v8::FunctionCallback callback =
1124 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00001125 Object* data_obj = call_data->data();
1126 Object* result;
1127
Steve Block44f0eee2011-05-26 01:26:41 +01001128 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001129 DCHECK(raw_holder->IsJSObject());
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001130
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001131 FunctionCallbackArguments custom(isolate,
1132 data_obj,
1133 *function,
1134 raw_holder,
1135 &args[0] - 1,
1136 args.length() - 1,
1137 is_construct);
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001138
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001139 v8::Handle<v8::Value> value = custom.Call(callback);
Steve Blocka7e24c12009-10-30 11:49:00 +00001140 if (value.IsEmpty()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001141 result = heap->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001142 } else {
1143 result = *reinterpret_cast<Object**>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001144 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00001145 }
1146
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001147 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001148 if (!is_construct || result->IsJSObject()) return result;
1149 }
1150
Leon Clarkee46be812010-01-19 14:06:41 +00001151 return *args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00001152}
Leon Clarkee46be812010-01-19 14:06:41 +00001153
1154
1155BUILTIN(HandleApiCall) {
Steve Block44f0eee2011-05-26 01:26:41 +01001156 return HandleApiCallHelper<false>(args, isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00001157}
1158
1159
1160BUILTIN(HandleApiCallConstruct) {
Steve Block44f0eee2011-05-26 01:26:41 +01001161 return HandleApiCallHelper<true>(args, isolate);
Leon Clarkee46be812010-01-19 14:06:41 +00001162}
Steve Blocka7e24c12009-10-30 11:49:00 +00001163
1164
1165// Helper function to handle calls to non-function objects created through the
1166// API. The object can be called as either a constructor (using new) or just as
1167// a function (without new).
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001168MUST_USE_RESULT static Object* HandleApiCallAsFunctionOrConstructor(
Steve Block44f0eee2011-05-26 01:26:41 +01001169 Isolate* isolate,
Leon Clarkee46be812010-01-19 14:06:41 +00001170 bool is_construct_call,
1171 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001172 // Non-functions are never called as constructors. Even if this is an object
1173 // called as a constructor the delegate call is not a construct call.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001174 DCHECK(!CalledAsConstructor(isolate));
Steve Block44f0eee2011-05-26 01:26:41 +01001175 Heap* heap = isolate->heap();
Steve Blocka7e24c12009-10-30 11:49:00 +00001176
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001177 Handle<Object> receiver = args.receiver();
Steve Blocka7e24c12009-10-30 11:49:00 +00001178
1179 // Get the object called.
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001180 JSObject* obj = JSObject::cast(*receiver);
Steve Blocka7e24c12009-10-30 11:49:00 +00001181
1182 // Get the invocation callback from the function descriptor that was
1183 // used to create the called object.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001184 DCHECK(obj->map()->has_instance_call_handler());
Steve Blocka7e24c12009-10-30 11:49:00 +00001185 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001186 DCHECK(constructor->shared()->IsApiFunction());
Steve Blocka7e24c12009-10-30 11:49:00 +00001187 Object* handler =
Steve Block6ded16b2010-05-10 14:33:55 +01001188 constructor->shared()->get_api_func_data()->instance_call_handler();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001189 DCHECK(!handler->IsUndefined());
Steve Blocka7e24c12009-10-30 11:49:00 +00001190 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
1191 Object* callback_obj = call_data->callback();
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001192 v8::FunctionCallback callback =
1193 v8::ToCData<v8::FunctionCallback>(callback_obj);
Steve Blocka7e24c12009-10-30 11:49:00 +00001194
1195 // Get the data for the call and perform the callback.
Steve Blocka7e24c12009-10-30 11:49:00 +00001196 Object* result;
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001197 {
Steve Block44f0eee2011-05-26 01:26:41 +01001198 HandleScope scope(isolate);
1199 LOG(isolate, ApiObjectAccess("call non-function", obj));
Teng-Hui Zhu3e5fa292010-11-09 16:16:48 -08001200
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001201 FunctionCallbackArguments custom(isolate,
1202 call_data->data(),
1203 constructor,
1204 obj,
1205 &args[0] - 1,
1206 args.length() - 1,
1207 is_construct_call);
1208 v8::Handle<v8::Value> value = custom.Call(callback);
Steve Blocka7e24c12009-10-30 11:49:00 +00001209 if (value.IsEmpty()) {
Steve Block44f0eee2011-05-26 01:26:41 +01001210 result = heap->undefined_value();
Steve Blocka7e24c12009-10-30 11:49:00 +00001211 } else {
1212 result = *reinterpret_cast<Object**>(*value);
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001213 result->VerifyApiCallResultType();
Steve Blocka7e24c12009-10-30 11:49:00 +00001214 }
1215 }
1216 // Check for exceptions and return result.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001217 RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001218 return result;
1219}
1220
1221
1222// Handle calls to non-function objects created through the API. This delegate
1223// function is used when the call is a normal function call.
1224BUILTIN(HandleApiCallAsFunction) {
Steve Block44f0eee2011-05-26 01:26:41 +01001225 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00001226}
Steve Blocka7e24c12009-10-30 11:49:00 +00001227
1228
1229// Handle calls to non-function objects created through the API. This delegate
1230// function is used when the call is a construct call.
1231BUILTIN(HandleApiCallAsConstructor) {
Steve Block44f0eee2011-05-26 01:26:41 +01001232 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
Steve Blocka7e24c12009-10-30 11:49:00 +00001233}
Steve Blocka7e24c12009-10-30 11:49:00 +00001234
1235
Steve Blocka7e24c12009-10-30 11:49:00 +00001236static void Generate_LoadIC_Miss(MacroAssembler* masm) {
1237 LoadIC::GenerateMiss(masm);
1238}
1239
1240
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001241static void Generate_LoadIC_Normal(MacroAssembler* masm) {
1242 LoadIC::GenerateNormal(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001243}
1244
1245
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001246static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
1247 NamedLoadHandlerCompiler::GenerateLoadViaGetterForDeopt(masm);
1248}
1249
1250
1251static void Generate_LoadIC_Slow(MacroAssembler* masm) {
1252 LoadIC::GenerateRuntimeGetProperty(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001253}
1254
1255
1256static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
1257 KeyedLoadIC::GenerateInitialize(masm);
1258}
1259
1260
Ben Murdoch257744e2011-11-30 15:57:28 +00001261static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
1262 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
1263}
1264
1265
Steve Blocka7e24c12009-10-30 11:49:00 +00001266static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001267 KeyedLoadIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001268}
1269
1270
1271static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
1272 KeyedLoadIC::GenerateGeneric(masm);
1273}
1274
1275
1276static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
1277 KeyedLoadIC::GeneratePreMonomorphic(masm);
1278}
1279
Steve Block1e0659c2011-05-24 12:43:12 +01001280
Steve Blocka7e24c12009-10-30 11:49:00 +00001281static void Generate_StoreIC_Miss(MacroAssembler* masm) {
1282 StoreIC::GenerateMiss(masm);
1283}
1284
1285
Steve Block8defd9f2010-07-08 12:39:36 +01001286static void Generate_StoreIC_Normal(MacroAssembler* masm) {
1287 StoreIC::GenerateNormal(masm);
1288}
1289
1290
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001291static void Generate_StoreIC_Slow(MacroAssembler* masm) {
1292 NamedStoreHandlerCompiler::GenerateSlow(masm);
Ben Murdoch257744e2011-11-30 15:57:28 +00001293}
1294
1295
1296static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001297 ElementHandlerCompiler::GenerateStoreSlow(masm);
1298}
1299
1300
1301static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
1302 NamedStoreHandlerCompiler::GenerateStoreViaSetterForDeopt(masm);
1303}
1304
1305
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001306static void Generate_KeyedStoreIC_Megamorphic(MacroAssembler* masm) {
1307 KeyedStoreIC::GenerateMegamorphic(masm, SLOPPY);
1308}
1309
1310
1311static void Generate_KeyedStoreIC_Megamorphic_Strict(MacroAssembler* masm) {
1312 KeyedStoreIC::GenerateMegamorphic(masm, STRICT);
1313}
1314
1315
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001316static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
1317 KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
1318}
1319
1320
1321static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
1322 KeyedStoreIC::GenerateGeneric(masm, STRICT);
1323}
1324
1325
1326static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
1327 KeyedStoreIC::GenerateMiss(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001328}
1329
1330
1331static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
1332 KeyedStoreIC::GenerateInitialize(masm);
1333}
1334
1335
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001336static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
1337 KeyedStoreIC::GenerateInitialize(masm);
1338}
1339
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001340
1341static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
1342 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3fb3ca82011-12-02 17:19:32 +00001343}
Ben Murdoche0cee9b2011-05-25 10:26:03 +01001344
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001345
1346static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
1347 KeyedStoreIC::GeneratePreMonomorphic(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001348}
1349
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001350
1351static void Generate_KeyedStoreIC_SloppyArguments(MacroAssembler* masm) {
1352 KeyedStoreIC::GenerateSloppyArguments(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001353}
1354
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001355
1356static void Generate_CallICStub_DebugBreak(MacroAssembler* masm) {
1357 DebugCodegen::GenerateCallICStubDebugBreak(masm);
1358}
1359
1360
Steve Blocka7e24c12009-10-30 11:49:00 +00001361static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001362 DebugCodegen::GenerateLoadICDebugBreak(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001363}
1364
1365
1366static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001367 DebugCodegen::GenerateStoreICDebugBreak(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001368}
1369
1370
1371static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001372 DebugCodegen::GenerateKeyedLoadICDebugBreak(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001373}
1374
1375
1376static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001377 DebugCodegen::GenerateKeyedStoreICDebugBreak(masm);
1378}
1379
1380
1381static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) {
1382 DebugCodegen::GenerateCompareNilICDebugBreak(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001383}
1384
1385
Steve Blocka7e24c12009-10-30 11:49:00 +00001386static void Generate_Return_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001387 DebugCodegen::GenerateReturnDebugBreak(masm);
Steve Blocka7e24c12009-10-30 11:49:00 +00001388}
1389
1390
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001391static void Generate_CallFunctionStub_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001392 DebugCodegen::GenerateCallFunctionStubDebugBreak(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001393}
1394
1395
1396static void Generate_CallConstructStub_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001397 DebugCodegen::GenerateCallConstructStubDebugBreak(masm);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001398}
1399
1400
1401static void Generate_CallConstructStub_Recording_DebugBreak(
1402 MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001403 DebugCodegen::GenerateCallConstructStubRecordDebugBreak(masm);
Ben Murdoch5d4cdbf2012-04-11 10:23:59 +01001404}
1405
1406
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001407static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001408 DebugCodegen::GenerateSlotDebugBreak(masm);
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001409}
1410
1411
Steve Block6ded16b2010-05-10 14:33:55 +01001412static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001413 DebugCodegen::GeneratePlainReturnLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01001414}
1415
Ben Murdoch7f4d5bd2010-06-15 11:15:29 +01001416
Steve Block6ded16b2010-05-10 14:33:55 +01001417static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001418 DebugCodegen::GenerateFrameDropperLiveEdit(masm);
Steve Block6ded16b2010-05-10 14:33:55 +01001419}
Steve Blocka7e24c12009-10-30 11:49:00 +00001420
Steve Block44f0eee2011-05-26 01:26:41 +01001421
1422Builtins::Builtins() : initialized_(false) {
1423 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
1424 memset(names_, 0, sizeof(names_[0]) * builtin_count);
1425}
1426
1427
1428Builtins::~Builtins() {
1429}
1430
Steve Blocka7e24c12009-10-30 11:49:00 +00001431
Leon Clarkee46be812010-01-19 14:06:41 +00001432#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
Steve Block44f0eee2011-05-26 01:26:41 +01001433Address const Builtins::c_functions_[cfunction_count] = {
1434 BUILTIN_LIST_C(DEF_ENUM_C)
1435};
Steve Blocka7e24c12009-10-30 11:49:00 +00001436#undef DEF_ENUM_C
1437
1438#define DEF_JS_NAME(name, ignore) #name,
1439#define DEF_JS_ARGC(ignore, argc) argc,
Steve Block44f0eee2011-05-26 01:26:41 +01001440const char* const Builtins::javascript_names_[id_count] = {
Steve Blocka7e24c12009-10-30 11:49:00 +00001441 BUILTINS_LIST_JS(DEF_JS_NAME)
1442};
1443
Steve Block44f0eee2011-05-26 01:26:41 +01001444int const Builtins::javascript_argc_[id_count] = {
Steve Blocka7e24c12009-10-30 11:49:00 +00001445 BUILTINS_LIST_JS(DEF_JS_ARGC)
1446};
1447#undef DEF_JS_NAME
1448#undef DEF_JS_ARGC
1449
Steve Block44f0eee2011-05-26 01:26:41 +01001450struct BuiltinDesc {
1451 byte* generator;
1452 byte* c_code;
1453 const char* s_name; // name is only used for generating log information.
1454 int name;
1455 Code::Flags flags;
1456 BuiltinExtraArguments extra_args;
1457};
1458
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001459#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
1460
Steve Block44f0eee2011-05-26 01:26:41 +01001461class BuiltinFunctionTable {
1462 public:
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001463 BuiltinDesc* functions() {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001464 base::CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001465 return functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01001466 }
1467
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001468 base::OnceType once_;
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001469 BuiltinDesc functions_[Builtins::builtin_count + 1];
Steve Block44f0eee2011-05-26 01:26:41 +01001470
1471 friend class Builtins;
1472};
1473
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001474static BuiltinFunctionTable builtin_function_table =
1475 BUILTIN_FUNCTION_TABLE_INIT;
Steve Block44f0eee2011-05-26 01:26:41 +01001476
1477// Define array of pointers to generators and C builtin functions.
1478// We do this in a sort of roundabout way so that we can do the initialization
1479// within the lexical scope of Builtins:: and within a context where
1480// Code::Flags names a non-abstract type.
1481void Builtins::InitBuiltinFunctionTable() {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001482 BuiltinDesc* functions = builtin_function_table.functions_;
Steve Block44f0eee2011-05-26 01:26:41 +01001483 functions[builtin_count].generator = NULL;
1484 functions[builtin_count].c_code = NULL;
1485 functions[builtin_count].s_name = NULL;
1486 functions[builtin_count].name = builtin_count;
1487 functions[builtin_count].flags = static_cast<Code::Flags>(0);
1488 functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
1489
1490#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
1491 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
1492 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
1493 functions->s_name = #aname; \
1494 functions->name = c_##aname; \
1495 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
1496 functions->extra_args = aextra_args; \
1497 ++functions;
1498
1499#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
1500 functions->generator = FUNCTION_ADDR(Generate_##aname); \
1501 functions->c_code = NULL; \
1502 functions->s_name = #aname; \
1503 functions->name = k##aname; \
1504 functions->flags = Code::ComputeFlags(Code::kind, \
Steve Block44f0eee2011-05-26 01:26:41 +01001505 state, \
1506 extra); \
1507 functions->extra_args = NO_EXTRA_ARGUMENTS; \
1508 ++functions;
1509
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001510#define DEF_FUNCTION_PTR_H(aname, kind) \
1511 functions->generator = FUNCTION_ADDR(Generate_##aname); \
1512 functions->c_code = NULL; \
1513 functions->s_name = #aname; \
1514 functions->name = k##aname; \
1515 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
1516 functions->extra_args = NO_EXTRA_ARGUMENTS; \
1517 ++functions;
1518
Steve Block44f0eee2011-05-26 01:26:41 +01001519 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1520 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001521 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01001522 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1523
1524#undef DEF_FUNCTION_PTR_C
1525#undef DEF_FUNCTION_PTR_A
1526}
1527
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001528
1529void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
1530 DCHECK(!initialized_);
Steve Blocka7e24c12009-10-30 11:49:00 +00001531
1532 // Create a scope for the handles in the builtins.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001533 HandleScope scope(isolate);
Steve Blocka7e24c12009-10-30 11:49:00 +00001534
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001535 const BuiltinDesc* functions = builtin_function_table.functions();
Steve Blocka7e24c12009-10-30 11:49:00 +00001536
1537 // For now we generate builtin adaptor code into a stack-allocated
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001538 // buffer, before copying it into individual code objects. Be careful
1539 // with alignment, some platforms don't like unaligned code.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001540#ifdef DEBUG
1541 // We can generate a lot of debug code on Arm64.
1542 const size_t buffer_size = 32*KB;
1543#else
1544 const size_t buffer_size = 8*KB;
1545#endif
1546 union { int force_alignment; byte buffer[buffer_size]; } u;
Steve Blocka7e24c12009-10-30 11:49:00 +00001547
1548 // Traverse the list of builtins and generate an adaptor in a
1549 // separate code object for each one.
1550 for (int i = 0; i < builtin_count; i++) {
1551 if (create_heap_objects) {
Ben Murdoch3ef787d2012-04-12 10:51:47 +01001552 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
Steve Blocka7e24c12009-10-30 11:49:00 +00001553 // Generate the code/adaptor.
Leon Clarkee46be812010-01-19 14:06:41 +00001554 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
Steve Blocka7e24c12009-10-30 11:49:00 +00001555 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1556 // We pass all arguments to the generator, but it may not use all of
1557 // them. This works because the first arguments are on top of the
1558 // stack.
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001559 DCHECK(!masm.has_frame());
Leon Clarkee46be812010-01-19 14:06:41 +00001560 g(&masm, functions[i].name, functions[i].extra_args);
Steve Blocka7e24c12009-10-30 11:49:00 +00001561 // Move the code into the object heap.
1562 CodeDesc desc;
1563 masm.GetCode(&desc);
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001564 Code::Flags flags = functions[i].flags;
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001565 Handle<Code> code =
1566 isolate->factory()->NewCode(desc, flags, masm.CodeObject());
Steve Blocka7e24c12009-10-30 11:49:00 +00001567 // Log the event and add the code to the builtins array.
Ben Murdoch8b112d22011-06-08 16:22:53 +01001568 PROFILE(isolate,
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001569 CodeCreateEvent(Logger::BUILTIN_TAG, *code, functions[i].s_name));
1570 builtins_[i] = *code;
Emily Bernierd0a1eb72015-03-24 16:35:39 -04001571 code->set_builtin_index(i);
Steve Blocka7e24c12009-10-30 11:49:00 +00001572#ifdef ENABLE_DISASSEMBLER
1573 if (FLAG_print_builtin_code) {
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001574 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
1575 OFStream os(trace_scope.file());
1576 os << "Builtin: " << functions[i].s_name << "\n";
1577 code->Disassemble(functions[i].s_name, os);
1578 os << "\n";
Steve Blocka7e24c12009-10-30 11:49:00 +00001579 }
1580#endif
1581 } else {
1582 // Deserializing. The values will be filled in during IterateBuiltins.
1583 builtins_[i] = NULL;
1584 }
1585 names_[i] = functions[i].s_name;
1586 }
1587
1588 // Mark as initialized.
Steve Block44f0eee2011-05-26 01:26:41 +01001589 initialized_ = true;
Steve Blocka7e24c12009-10-30 11:49:00 +00001590}
1591
1592
1593void Builtins::TearDown() {
Steve Block44f0eee2011-05-26 01:26:41 +01001594 initialized_ = false;
Steve Blocka7e24c12009-10-30 11:49:00 +00001595}
1596
1597
1598void Builtins::IterateBuiltins(ObjectVisitor* v) {
1599 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
1600}
1601
1602
1603const char* Builtins::Lookup(byte* pc) {
Steve Block44f0eee2011-05-26 01:26:41 +01001604 // may be called during initialization (disassembler!)
1605 if (initialized_) {
Steve Blocka7e24c12009-10-30 11:49:00 +00001606 for (int i = 0; i < builtin_count; i++) {
1607 Code* entry = Code::cast(builtins_[i]);
1608 if (entry->contains(pc)) {
1609 return names_[i];
1610 }
1611 }
1612 }
1613 return NULL;
1614}
1615
Ben Murdochb0fe1622011-05-05 13:52:32 +01001616
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001617void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
1618 masm->TailCallRuntime(Runtime::kInterrupt, 0, 1);
1619}
1620
1621
1622void Builtins::Generate_StackCheck(MacroAssembler* masm) {
1623 masm->TailCallRuntime(Runtime::kStackGuard, 0, 1);
1624}
1625
1626
Steve Block44f0eee2011-05-26 01:26:41 +01001627#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
1628Handle<Code> Builtins::name() { \
1629 Code** code_address = \
1630 reinterpret_cast<Code**>(builtin_address(k##name)); \
1631 return Handle<Code>(code_address); \
1632}
1633#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
1634Handle<Code> Builtins::name() { \
1635 Code** code_address = \
1636 reinterpret_cast<Code**>(builtin_address(k##name)); \
1637 return Handle<Code>(code_address); \
1638}
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001639#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
1640Handle<Code> Builtins::name() { \
1641 Code** code_address = \
1642 reinterpret_cast<Code**>(builtin_address(k##name)); \
1643 return Handle<Code>(code_address); \
1644}
Steve Block44f0eee2011-05-26 01:26:41 +01001645BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1646BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001647BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
Steve Block44f0eee2011-05-26 01:26:41 +01001648BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1649#undef DEFINE_BUILTIN_ACCESSOR_C
1650#undef DEFINE_BUILTIN_ACCESSOR_A
1651
1652
Steve Blocka7e24c12009-10-30 11:49:00 +00001653} } // namespace v8::internal