blob: 054963d7f3c57bcb526245324bfe2fe7fa5eae96 [file] [log] [blame]
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001// Copyright 2012 the V8 project authors. All rights reserved.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00002// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28#include "v8.h"
29
30#include "api.h"
ager@chromium.org18ad94b2009-09-02 08:22:29 +000031#include "arguments.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000032#include "bootstrapper.h"
33#include "builtins.h"
machenbach@chromium.orgc1789ee2013-07-05 07:09:57 +000034#include "cpu-profiler.h"
erik.corry@gmail.com0511e242011-01-19 11:11:08 +000035#include "gdb-jit.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000036#include "ic-inl.h"
ulan@chromium.org6ff65142012-03-21 09:52:17 +000037#include "heap-profiler.h"
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +000038#include "mark-compact.h"
yangguo@chromium.org46839fb2012-08-28 09:06:19 +000039#include "stub-cache.h"
kasperl@chromium.orga5551262010-12-07 12:49:48 +000040#include "vm-state-inl.h"
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000041
kasperl@chromium.org71affb52009-05-26 05:44:31 +000042namespace v8 {
43namespace internal {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +000044
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +000045namespace {
46
47// Arguments object passed to C++ builtins.
48template <BuiltinExtraArguments extra_args>
49class BuiltinArguments : public Arguments {
50 public:
51 BuiltinArguments(int length, Object** arguments)
52 : Arguments(length, arguments) { }
53
54 Object*& operator[] (int index) {
55 ASSERT(index < length());
56 return Arguments::operator[](index);
57 }
58
59 template <class S> Handle<S> at(int index) {
60 ASSERT(index < length());
61 return Arguments::at<S>(index);
62 }
63
64 Handle<Object> receiver() {
65 return Arguments::at<Object>(0);
66 }
67
68 Handle<JSFunction> called_function() {
69 STATIC_ASSERT(extra_args == NEEDS_CALLED_FUNCTION);
70 return Arguments::at<JSFunction>(Arguments::length() - 1);
71 }
72
73 // Gets the total number of arguments including the receiver (but
74 // excluding extra arguments).
75 int length() const {
76 STATIC_ASSERT(extra_args == NO_EXTRA_ARGUMENTS);
77 return Arguments::length();
78 }
79
80#ifdef DEBUG
81 void Verify() {
82 // Check we have at least the receiver.
83 ASSERT(Arguments::length() >= 1);
84 }
85#endif
86};
87
88
89// Specialize BuiltinArguments for the called function extra argument.
90
91template <>
92int BuiltinArguments<NEEDS_CALLED_FUNCTION>::length() const {
93 return Arguments::length() - 1;
94}
95
96#ifdef DEBUG
97template <>
98void BuiltinArguments<NEEDS_CALLED_FUNCTION>::Verify() {
99 // Check we have at least the receiver and the called function.
100 ASSERT(Arguments::length() >= 2);
101 // Make sure cast to JSFunction succeeds.
102 called_function();
103}
104#endif
105
106
107#define DEF_ARG_TYPE(name, spec) \
108 typedef BuiltinArguments<spec> name##ArgumentsType;
109BUILTIN_LIST_C(DEF_ARG_TYPE)
110#undef DEF_ARG_TYPE
111
112} // namespace
113
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000114// ----------------------------------------------------------------------------
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000115// Support macro for defining builtins in C++.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000116// ----------------------------------------------------------------------------
117//
118// A builtin function is defined by writing:
119//
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000120// BUILTIN(name) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000121// ...
122// }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000123//
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000124// In the body of the builtin function the arguments can be accessed
125// through the BuiltinArguments object args.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000126
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000127#ifdef DEBUG
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000128
danno@chromium.orgf005df62013-04-30 16:36:45 +0000129#define BUILTIN(name) \
130 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
131 name##ArgumentsType args, Isolate* isolate); \
132 MUST_USE_RESULT static MaybeObject* Builtin_##name( \
133 int args_length, Object** args_object, Isolate* isolate) { \
134 name##ArgumentsType args(args_length, args_object); \
danno@chromium.orgf005df62013-04-30 16:36:45 +0000135 args.Verify(); \
136 return Builtin_Impl_##name(args, isolate); \
137 } \
138 MUST_USE_RESULT static MaybeObject* Builtin_Impl_##name( \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000139 name##ArgumentsType args, Isolate* isolate)
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000140
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000141#else // For release mode.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000142
danno@chromium.orgf005df62013-04-30 16:36:45 +0000143#define BUILTIN(name) \
144 static MaybeObject* Builtin_impl##name( \
145 name##ArgumentsType args, Isolate* isolate); \
146 static MaybeObject* Builtin_##name( \
147 int args_length, Object** args_object, Isolate* isolate) { \
148 name##ArgumentsType args(args_length, args_object); \
149 return Builtin_impl##name(args, isolate); \
150 } \
151 static MaybeObject* Builtin_impl##name( \
152 name##ArgumentsType args, Isolate* isolate)
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000153#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000154
155
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000156#ifdef DEBUG
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +0000157static inline bool CalledAsConstructor(Isolate* isolate) {
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000158 // Calculate the result using a full stack frame iterator and check
159 // that the state of the stack is as we assume it to be in the
160 // code below.
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +0000161 StackFrameIterator it(isolate);
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000162 ASSERT(it.frame()->is_exit());
163 it.Advance();
164 StackFrame* frame = it.frame();
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000165 bool reference_result = frame->is_construct();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000166 Address fp = Isolate::c_entry_fp(isolate->thread_local_top());
sgjesse@chromium.org0b6db592009-07-30 14:48:31 +0000167 // Because we know fp points to an exit frame we can use the relevant
168 // part of ExitFrame::ComputeCallerState directly.
169 const int kCallerOffset = ExitFrameConstants::kCallerFPOffset;
170 Address caller_fp = Memory::Address_at(fp + kCallerOffset);
171 // This inlines the part of StackFrame::ComputeType that grabs the
172 // type of the current frame. Note that StackFrame::ComputeType
173 // has been specialized for each architecture so if any one of them
174 // changes this code has to be changed as well.
175 const int kMarkerOffset = StandardFrameConstants::kMarkerOffset;
176 const Smi* kConstructMarker = Smi::FromInt(StackFrame::CONSTRUCT);
177 Object* marker = Memory::Object_at(caller_fp + kMarkerOffset);
178 bool result = (marker == kConstructMarker);
179 ASSERT_EQ(result, reference_result);
180 return result;
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000181}
machenbach@chromium.orgafbdadc2013-12-09 16:12:18 +0000182#endif
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000183
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +0000184
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000185// ----------------------------------------------------------------------------
186
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000187BUILTIN(Illegal) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000188 UNREACHABLE();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000189 return isolate->heap()->undefined_value(); // Make compiler happy.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000190}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000191
192
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000193BUILTIN(EmptyFunction) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000194 return isolate->heap()->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000195}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000196
197
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000198static void MoveDoubleElements(FixedDoubleArray* dst,
199 int dst_index,
200 FixedDoubleArray* src,
201 int src_index,
202 int len) {
203 if (len == 0) return;
mstarzinger@chromium.orge27d6172013-04-17 11:51:44 +0000204 OS::MemMove(dst->data_start() + dst_index,
205 src->data_start() + src_index,
206 len * kDoubleSize);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000207}
208
209
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000210static FixedArrayBase* LeftTrimFixedArray(Heap* heap,
211 FixedArrayBase* elms,
212 int to_trim) {
machenbach@chromium.org63a7c9f2014-04-01 00:04:36 +0000213 ASSERT(heap->CanMoveObjectStart(elms));
214
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000215 Map* map = elms->map();
216 int entry_size;
217 if (elms->IsFixedArray()) {
218 entry_size = kPointerSize;
219 } else {
220 entry_size = kDoubleSize;
221 }
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000222 ASSERT(elms->map() != heap->fixed_cow_array_map());
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000223 // For now this trick is only applied to fixed arrays in new and paged space.
lrn@chromium.org25156de2010-04-06 13:10:27 +0000224 // In large object space the object's start must coincide with chunk
225 // and thus the trick is just not applicable.
hpayer@chromium.orgc5d49712013-09-11 08:25:48 +0000226 ASSERT(!heap->lo_space()->Contains(elms));
lrn@chromium.org25156de2010-04-06 13:10:27 +0000227
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000228 STATIC_ASSERT(FixedArrayBase::kMapOffset == 0);
229 STATIC_ASSERT(FixedArrayBase::kLengthOffset == kPointerSize);
230 STATIC_ASSERT(FixedArrayBase::kHeaderSize == 2 * kPointerSize);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000231
232 Object** former_start = HeapObject::RawField(elms, 0);
233
234 const int len = elms->length();
235
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000236 if (to_trim * entry_size > FixedArrayBase::kHeaderSize &&
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000237 elms->IsFixedArray() &&
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000238 !heap->new_space()->Contains(elms)) {
erik.corry@gmail.com145eff52010-08-23 11:36:18 +0000239 // If we are doing a big trim in old space then we zap the space that was
240 // formerly part of the array so that the GC (aided by the card-based
241 // remembered set) won't find pointers to new-space there.
242 Object** zap = reinterpret_cast<Object**>(elms->address());
243 zap++; // Header of filler must be at least one word so skip that.
244 for (int i = 1; i < to_trim; i++) {
245 *zap++ = Smi::FromInt(0);
246 }
247 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000248 // Technically in new space this write might be omitted (except for
249 // debug mode which iterates through the heap), but to play safer
250 // we still do it.
machenbach@chromium.org63a7c9f2014-04-01 00:04:36 +0000251 // Since left trimming is only performed on pages which are not concurrently
252 // swept creating a filler object does not require synchronization.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000253 heap->CreateFillerObjectAt(elms->address(), to_trim * entry_size);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000254
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000255 int new_start_index = to_trim * (entry_size / kPointerSize);
256 former_start[new_start_index] = map;
257 former_start[new_start_index + 1] = Smi::FromInt(len - to_trim);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000258
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000259 // Maintain marking consistency for HeapObjectIterator and
260 // IncrementalMarking.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000261 int size_delta = to_trim * entry_size;
machenbach@chromium.org56971442014-03-19 13:13:40 +0000262 Address new_start = elms->address() + size_delta;
263 heap->marking()->TransferMark(elms->address(), new_start);
264 heap->AdjustLiveBytes(new_start, -size_delta, Heap::FROM_MUTATOR);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000265
machenbach@chromium.org56971442014-03-19 13:13:40 +0000266 FixedArrayBase* new_elms =
267 FixedArrayBase::cast(HeapObject::FromAddress(new_start));
mstarzinger@chromium.org2ed0d022013-10-17 08:06:21 +0000268 HeapProfiler* profiler = heap->isolate()->heap_profiler();
yangguo@chromium.orgcc536052013-11-29 11:43:20 +0000269 if (profiler->is_tracking_object_moves()) {
mstarzinger@chromium.org2ed0d022013-10-17 08:06:21 +0000270 profiler->ObjectMoveEvent(elms->address(),
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +0000271 new_elms->address(),
272 new_elms->Size());
mstarzinger@chromium.org2ed0d022013-10-17 08:06:21 +0000273 }
bmeurer@chromium.org0fdb2a62013-10-21 07:19:36 +0000274 return new_elms;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000275}
276
277
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000278static bool ArrayPrototypeHasNoElements(Heap* heap,
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000279 Context* native_context,
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000280 JSObject* array_proto) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000281 DisallowHeapAllocation no_gc;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000282 // This method depends on non writability of Object and Array prototype
283 // fields.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000284 if (array_proto->elements() != heap->empty_fixed_array()) return false;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000285 // Object.prototype
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000286 Object* proto = array_proto->GetPrototype();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000287 if (proto == heap->null_value()) return false;
erik.corry@gmail.comd91075f2011-02-10 07:45:38 +0000288 array_proto = JSObject::cast(proto);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000289 if (array_proto != native_context->initial_object_prototype()) return false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000290 if (array_proto->elements() != heap->empty_fixed_array()) return false;
danno@chromium.org40cb8782011-05-25 07:58:50 +0000291 return array_proto->GetPrototype()->IsNull();
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000292}
293
294
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000295// Returns empty handle if not applicable.
lrn@chromium.org303ada72010-10-27 09:33:13 +0000296MUST_USE_RESULT
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000297static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements(
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000298 Isolate* isolate,
299 Handle<Object> receiver,
300 Arguments* args,
301 int first_added_arg) {
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000302 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>();
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000303 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000304 // If there may be elements accessors in the prototype chain, the fast path
305 // cannot be used.
306 if (array->map()->DictionaryElementsInPrototypeChainOnly()) {
307 return MaybeHandle<FixedArrayBase>();
308 }
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000309 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>();
310 if (!array->map()->is_extensible()) return MaybeHandle<FixedArrayBase>();
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000311 Handle<FixedArrayBase> elms(array->elements(), isolate);
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000312 Heap* heap = isolate->heap();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000313 Map* map = elms->map();
314 if (map == heap->fixed_array_map()) {
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +0000315 if (args == NULL || array->HasFastObjectElements()) return elms;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000316 } else if (map == heap->fixed_cow_array_map()) {
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000317 elms = JSObject::EnsureWritableFastElements(array);
318 if (args == NULL || array->HasFastObjectElements()) return elms;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000319 } else if (map == heap->fixed_double_array_map()) {
320 if (args == NULL) return elms;
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000321 } else {
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000322 return MaybeHandle<FixedArrayBase>();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000323 }
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000324
325 // Need to ensure that the arguments passed in args can be contained in
326 // the array.
327 int args_length = args->length();
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000328 if (first_added_arg >= args_length) return handle(array->elements(), isolate);
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000329
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000330 ElementsKind origin_kind = array->map()->elements_kind();
331 ASSERT(!IsFastObjectElementsKind(origin_kind));
332 ElementsKind target_kind = origin_kind;
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000333 {
334 DisallowHeapAllocation no_gc;
335 int arg_count = args->length() - first_added_arg;
336 Object** arguments = args->arguments() - first_added_arg - (arg_count - 1);
337 for (int i = 0; i < arg_count; i++) {
338 Object* arg = arguments[i];
339 if (arg->IsHeapObject()) {
340 if (arg->IsHeapNumber()) {
341 target_kind = FAST_DOUBLE_ELEMENTS;
342 } else {
343 target_kind = FAST_ELEMENTS;
344 break;
345 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000346 }
347 }
348 }
349 if (target_kind != origin_kind) {
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000350 JSObject::TransitionElementsKind(array, target_kind);
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000351 return handle(array->elements(), isolate);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000352 }
353 return elms;
vegorov@chromium.orgf8372902010-03-15 10:26:20 +0000354}
355
356
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000357static inline bool IsJSArrayFastElementMovingAllowed(Heap* heap,
358 JSArray* receiver) {
rossberg@chromium.orgb4b2aa62011-10-13 09:49:59 +0000359 if (!FLAG_clever_optimizations) return false;
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000360 DisallowHeapAllocation no_gc;
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000361 Context* native_context = heap->isolate()->context()->native_context();
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000362 JSObject* array_proto =
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000363 JSObject::cast(native_context->array_function()->prototype());
ricow@chromium.org0b9f8502010-08-18 07:45:01 +0000364 return receiver->GetPrototype() == array_proto &&
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000365 ArrayPrototypeHasNoElements(heap, native_context, array_proto);
vegorov@chromium.orgdff694e2010-05-17 09:10:26 +0000366}
367
368
lrn@chromium.org303ada72010-10-27 09:33:13 +0000369MUST_USE_RESULT static MaybeObject* CallJsBuiltin(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000370 Isolate* isolate,
lrn@chromium.org303ada72010-10-27 09:33:13 +0000371 const char* name,
372 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000373 HandleScope handleScope(isolate);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000374
375 Handle<Object> js_builtin =
yangguo@chromium.org46839fb2012-08-28 09:06:19 +0000376 GetProperty(Handle<JSObject>(isolate->native_context()->builtins()),
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000377 name).ToHandleChecked();
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000378 Handle<JSFunction> function = Handle<JSFunction>::cast(js_builtin);
379 int argc = args.length() - 1;
380 ScopedVector<Handle<Object> > argv(argc);
381 for (int i = 0; i < argc; ++i) {
382 argv[i] = args.at<Object>(i + 1);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000383 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000384 bool pending_exception;
jkummerow@chromium.org2c9426b2013-09-05 16:31:13 +0000385 Handle<Object> result = Execution::Call(isolate,
386 function,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000387 args.receiver(),
svenpanne@chromium.orga8bb4d92011-10-10 13:20:40 +0000388 argc,
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000389 argv.start(),
390 &pending_exception);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000391 if (pending_exception) return Failure::Exception();
392 return *result;
393}
394
395
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000396BUILTIN(ArrayPush) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000397 HandleScope scope(isolate);
398 Handle<Object> receiver = args.receiver();
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000399 MaybeHandle<FixedArrayBase> maybe_elms_obj =
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000400 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 1);
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000401 Handle<FixedArrayBase> elms_obj;
402 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
403 return CallJsBuiltin(isolate, "ArrayPush", args);
404 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000405
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000406 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000407 ASSERT(!array->map()->is_observed());
408
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000409 ElementsKind kind = array->GetElementsKind();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000410
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000411 if (IsFastSmiOrObjectElementsKind(kind)) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000412 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000413
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000414 int len = Smi::cast(array->length())->value();
415 int to_add = args.length() - 1;
416 if (to_add == 0) {
417 return Smi::FromInt(len);
lrn@chromium.org303ada72010-10-27 09:33:13 +0000418 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000419 // Currently fixed arrays cannot grow too big, so
420 // we should never hit this case.
421 ASSERT(to_add <= (Smi::kMaxValue - len));
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +0000422
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000423 int new_length = len + to_add;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000424
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000425 if (new_length > elms->length()) {
426 // New backing storage is needed.
427 int capacity = new_length + (new_length >> 1) + 16;
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000428 Handle<FixedArray> new_elms =
429 isolate->factory()->NewUninitializedFixedArray(capacity);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000430
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000431 ElementsAccessor* accessor = array->GetElementsAccessor();
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000432 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000433 elms_obj, 0, kind, new_elms, 0,
434 ElementsAccessor::kCopyToEndAndInitializeToHole);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000435
436 elms = new_elms;
437 }
438
439 // Add the provided values.
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000440 DisallowHeapAllocation no_gc;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000441 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
442 for (int index = 0; index < to_add; index++) {
443 elms->set(index + len, args[index + 1], mode);
444 }
445
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000446 if (*elms != array->elements()) {
447 array->set_elements(*elms);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000448 }
449
450 // Set the length.
451 array->set_length(Smi::FromInt(new_length));
452 return Smi::FromInt(new_length);
453 } else {
454 int len = Smi::cast(array->length())->value();
455 int elms_len = elms_obj->length();
456
457 int to_add = args.length() - 1;
458 if (to_add == 0) {
459 return Smi::FromInt(len);
460 }
461 // Currently fixed arrays cannot grow too big, so
462 // we should never hit this case.
463 ASSERT(to_add <= (Smi::kMaxValue - len));
464
465 int new_length = len + to_add;
466
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000467 Handle<FixedDoubleArray> new_elms;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000468
469 if (new_length > elms_len) {
470 // New backing storage is needed.
471 int capacity = new_length + (new_length >> 1) + 16;
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000472 new_elms = isolate->factory()->NewFixedDoubleArray(capacity);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000473
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000474 ElementsAccessor* accessor = array->GetElementsAccessor();
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000475 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000476 elms_obj, 0, kind, new_elms, 0,
477 ElementsAccessor::kCopyToEndAndInitializeToHole);
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000478
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000479 } else {
480 // to_add is > 0 and new_length <= elms_len, so elms_obj cannot be the
481 // empty_fixed_array.
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000482 new_elms = Handle<FixedDoubleArray>::cast(elms_obj);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000483 }
484
485 // Add the provided values.
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000486 DisallowHeapAllocation no_gc;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000487 int index;
488 for (index = 0; index < to_add; index++) {
489 Object* arg = args[index + 1];
490 new_elms->set(index + len, arg->Number());
491 }
492
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000493 if (*new_elms != array->elements()) {
494 array->set_elements(*new_elms);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000495 }
496
497 // Set the length.
498 array->set_length(Smi::FromInt(new_length));
499 return Smi::FromInt(new_length);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000500 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000501}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000502
503
kasperl@chromium.orgb9123622008-09-17 14:05:56 +0000504BUILTIN(ArrayPop) {
machenbach@chromium.org69f64b12014-03-20 01:04:55 +0000505 HandleScope scope(isolate);
506 Handle<Object> receiver = args.receiver();
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000507 MaybeHandle<FixedArrayBase> maybe_elms_obj =
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000508 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000509 Handle<FixedArrayBase> elms_obj;
510 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
511 return CallJsBuiltin(isolate, "ArrayPop", args);
512 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000513
machenbach@chromium.org69f64b12014-03-20 01:04:55 +0000514 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000515 ASSERT(!array->map()->is_observed());
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000516
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000517 int len = Smi::cast(array->length())->value();
machenbach@chromium.org69f64b12014-03-20 01:04:55 +0000518 if (len == 0) return isolate->heap()->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000519
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000520 ElementsAccessor* accessor = array->GetElementsAccessor();
521 int new_length = len - 1;
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000522 MaybeHandle<Object> maybe_element;
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000523 if (accessor->HasElement(array, array, new_length, elms_obj)) {
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000524 maybe_element = accessor->Get(array, array, new_length, elms_obj);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000525 } else {
machenbach@chromium.org4452a492014-03-18 13:03:00 +0000526 Handle<Object> proto(array->GetPrototype(), isolate);
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000527 maybe_element = Object::GetElement(isolate, proto, len - 1);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000528 }
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000529 Handle<Object> element;
530 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, element, maybe_element);
531 RETURN_IF_EMPTY_HANDLE(
532 isolate,
533 accessor->SetLength(array, handle(Smi::FromInt(new_length), isolate)));
machenbach@chromium.org69f64b12014-03-20 01:04:55 +0000534 return *element;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000535}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +0000536
537
ager@chromium.org5c838252010-02-19 08:53:10 +0000538BUILTIN(ArrayShift) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000539 HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000540 Heap* heap = isolate->heap();
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000541 Handle<Object> receiver = args.receiver();
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000542 MaybeHandle<FixedArrayBase> maybe_elms_obj =
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000543 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000544 Handle<FixedArrayBase> elms_obj;
545 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000546 !IsJSArrayFastElementMovingAllowed(heap,
547 *Handle<JSArray>::cast(receiver))) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000548 return CallJsBuiltin(isolate, "ArrayShift", args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000549 }
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000550 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000551 ASSERT(!array->map()->is_observed());
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000552
ager@chromium.org5c838252010-02-19 08:53:10 +0000553 int len = Smi::cast(array->length())->value();
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000554 if (len == 0) return heap->undefined_value();
ager@chromium.org5c838252010-02-19 08:53:10 +0000555
ager@chromium.org5c838252010-02-19 08:53:10 +0000556 // Get first element
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000557 ElementsAccessor* accessor = array->GetElementsAccessor();
machenbach@chromium.org202b1d82014-04-11 00:04:40 +0000558 Handle<Object> first;
559 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
560 isolate, first, accessor->Get(receiver, array, 0, elms_obj));
ager@chromium.org5c838252010-02-19 08:53:10 +0000561 if (first->IsTheHole()) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000562 first = isolate->factory()->undefined_value();
ager@chromium.org5c838252010-02-19 08:53:10 +0000563 }
564
machenbach@chromium.org63a7c9f2014-04-01 00:04:36 +0000565 if (heap->CanMoveObjectStart(*elms_obj)) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000566 array->set_elements(LeftTrimFixedArray(heap, *elms_obj, 1));
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000567 } else {
568 // Shift the elements.
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000569 if (elms_obj->IsFixedArray()) {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000570 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000571 DisallowHeapAllocation no_gc;
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000572 heap->MoveElements(*elms, 0, 1, len - 1);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000573 elms->set(len - 1, heap->the_hole_value());
574 } else {
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000575 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
576 MoveDoubleElements(*elms, 0, *elms, 1, len - 1);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000577 elms->set_the_hole(len - 1);
578 }
kmillikin@chromium.org5d8f0e62010-03-24 08:21:20 +0000579 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000580
581 // Set the length.
582 array->set_length(Smi::FromInt(len - 1));
583
machenbach@chromium.org7010a2d2014-03-20 15:46:12 +0000584 return *first;
ager@chromium.org5c838252010-02-19 08:53:10 +0000585}
586
587
588BUILTIN(ArrayUnshift) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000589 HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000590 Heap* heap = isolate->heap();
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000591 Handle<Object> receiver = args.receiver();
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000592 MaybeHandle<FixedArrayBase> maybe_elms_obj =
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000593 EnsureJSArrayWithWritableFastElements(isolate, receiver, NULL, 0);
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000594 Handle<FixedArrayBase> elms_obj;
595 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000596 !IsJSArrayFastElementMovingAllowed(heap,
597 *Handle<JSArray>::cast(receiver))) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000598 return CallJsBuiltin(isolate, "ArrayUnshift", args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000599 }
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000600 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000601 ASSERT(!array->map()->is_observed());
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000602 if (!array->HasFastSmiOrObjectElements()) {
603 return CallJsBuiltin(isolate, "ArrayUnshift", args);
604 }
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000605 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
ager@chromium.org5c838252010-02-19 08:53:10 +0000606
607 int len = Smi::cast(array->length())->value();
608 int to_add = args.length() - 1;
ager@chromium.org5c838252010-02-19 08:53:10 +0000609 int new_length = len + to_add;
610 // Currently fixed arrays cannot grow too big, so
611 // we should never hit this case.
612 ASSERT(to_add <= (Smi::kMaxValue - len));
613
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000614 JSObject::EnsureCanContainElements(array, &args, 1, to_add,
615 DONT_ALLOW_DOUBLE_ELEMENTS);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000616
ager@chromium.org5c838252010-02-19 08:53:10 +0000617 if (new_length > elms->length()) {
618 // New backing storage is needed.
619 int capacity = new_length + (new_length >> 1) + 16;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000620 Handle<FixedArray> new_elms =
621 isolate->factory()->NewUninitializedFixedArray(capacity);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000622
svenpanne@chromium.org83130cf2012-11-30 10:13:25 +0000623 ElementsKind kind = array->GetElementsKind();
624 ElementsAccessor* accessor = array->GetElementsAccessor();
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000625 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000626 elms, 0, kind, new_elms, to_add,
627 ElementsAccessor::kCopyToEndAndInitializeToHole);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000628
ager@chromium.org5c838252010-02-19 08:53:10 +0000629 elms = new_elms;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000630 array->set_elements(*elms);
ager@chromium.org5c838252010-02-19 08:53:10 +0000631 } else {
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000632 DisallowHeapAllocation no_gc;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000633 heap->MoveElements(*elms, to_add, 0, len);
ager@chromium.org5c838252010-02-19 08:53:10 +0000634 }
635
636 // Add the provided values.
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000637 DisallowHeapAllocation no_gc;
ager@chromium.org5c838252010-02-19 08:53:10 +0000638 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
639 for (int i = 0; i < to_add; i++) {
640 elms->set(i, args[i + 1], mode);
641 }
642
643 // Set the length.
644 array->set_length(Smi::FromInt(new_length));
645 return Smi::FromInt(new_length);
646}
647
648
ager@chromium.org5c838252010-02-19 08:53:10 +0000649BUILTIN(ArraySlice) {
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +0000650 HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000651 Heap* heap = isolate->heap();
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +0000652 Handle<Object> receiver = args.receiver();
whesse@chromium.org023421e2010-12-21 12:19:12 +0000653 int len = -1;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000654 int relative_start = 0;
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000655 int relative_end = 0;
656 {
657 DisallowHeapAllocation no_gc;
658 if (receiver->IsJSArray()) {
659 JSArray* array = JSArray::cast(*receiver);
660 if (!IsJSArrayFastElementMovingAllowed(heap, array)) {
661 AllowHeapAllocation allow_allocation;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000662 return CallJsBuiltin(isolate, "ArraySlice", args);
663 }
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000664
665 if (!array->HasFastElements()) {
666 AllowHeapAllocation allow_allocation;
667 return CallJsBuiltin(isolate, "ArraySlice", args);
668 }
669
670 len = Smi::cast(array->length())->value();
671 } else {
672 // Array.slice(arguments, ...) is quite a common idiom (notably more
673 // than 50% of invocations in Web apps). Treat it in C++ as well.
674 Map* arguments_map = isolate->context()->native_context()->
675 sloppy_arguments_boilerplate()->map();
676
677 bool is_arguments_object_with_fast_elements =
678 receiver->IsJSObject() &&
679 JSObject::cast(*receiver)->map() == arguments_map;
680 if (!is_arguments_object_with_fast_elements) {
681 AllowHeapAllocation allow_allocation;
682 return CallJsBuiltin(isolate, "ArraySlice", args);
683 }
684 JSObject* object = JSObject::cast(*receiver);
685
686 if (!object->HasFastElements()) {
687 AllowHeapAllocation allow_allocation;
688 return CallJsBuiltin(isolate, "ArraySlice", args);
689 }
690
691 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex);
692 if (!len_obj->IsSmi()) {
693 AllowHeapAllocation allow_allocation;
694 return CallJsBuiltin(isolate, "ArraySlice", args);
695 }
696 len = Smi::cast(len_obj)->value();
697 if (len > object->elements()->length()) {
698 AllowHeapAllocation allow_allocation;
699 return CallJsBuiltin(isolate, "ArraySlice", args);
700 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000701 }
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000702
703 ASSERT(len >= 0);
704 int n_arguments = args.length() - 1;
705
706 // Note carefully choosen defaults---if argument is missing,
707 // it's undefined which gets converted to 0 for relative_start
708 // and to len for relative_end.
709 relative_start = 0;
710 relative_end = len;
711 if (n_arguments > 0) {
712 Object* arg1 = args[1];
713 if (arg1->IsSmi()) {
714 relative_start = Smi::cast(arg1)->value();
715 } else if (arg1->IsHeapNumber()) {
716 double start = HeapNumber::cast(arg1)->value();
717 if (start < kMinInt || start > kMaxInt) {
718 AllowHeapAllocation allow_allocation;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000719 return CallJsBuiltin(isolate, "ArraySlice", args);
720 }
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000721 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
722 } else if (!arg1->IsUndefined()) {
723 AllowHeapAllocation allow_allocation;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000724 return CallJsBuiltin(isolate, "ArraySlice", args);
ager@chromium.org5c838252010-02-19 08:53:10 +0000725 }
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000726 if (n_arguments > 1) {
727 Object* arg2 = args[2];
728 if (arg2->IsSmi()) {
729 relative_end = Smi::cast(arg2)->value();
730 } else if (arg2->IsHeapNumber()) {
731 double end = HeapNumber::cast(arg2)->value();
732 if (end < kMinInt || end > kMaxInt) {
733 AllowHeapAllocation allow_allocation;
734 return CallJsBuiltin(isolate, "ArraySlice", args);
735 }
736 relative_end = std::isnan(end) ? 0 : static_cast<int>(end);
737 } else if (!arg2->IsUndefined()) {
738 AllowHeapAllocation allow_allocation;
739 return CallJsBuiltin(isolate, "ArraySlice", args);
740 }
741 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000742 }
743 }
744
745 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000746 int k = (relative_start < 0) ? Max(len + relative_start, 0)
747 : Min(relative_start, len);
ager@chromium.org5c838252010-02-19 08:53:10 +0000748
749 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000750 int final = (relative_end < 0) ? Max(len + relative_end, 0)
751 : Min(relative_end, len);
ager@chromium.org5c838252010-02-19 08:53:10 +0000752
753 // Calculate the length of result array.
danno@chromium.orgfa458e42012-02-01 10:48:36 +0000754 int result_len = Max(final - k, 0);
ager@chromium.org5c838252010-02-19 08:53:10 +0000755
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000756 Handle<JSObject> object = Handle<JSObject>::cast(receiver);
757 Handle<FixedArrayBase> elms(object->elements(), isolate);
758
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000759 ElementsKind kind = object->GetElementsKind();
760 if (IsHoleyElementsKind(kind)) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000761 DisallowHeapAllocation no_gc;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000762 bool packed = true;
763 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
764 for (int i = k; i < final; i++) {
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000765 if (!accessor->HasElement(object, object, i, elms)) {
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000766 packed = false;
767 break;
768 }
769 }
770 if (packed) {
771 kind = GetPackedElementsKind(kind);
772 } else if (!receiver->IsJSArray()) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000773 AllowHeapAllocation allow_allocation;
yangguo@chromium.orga6bbcc82012-12-21 12:35:02 +0000774 return CallJsBuiltin(isolate, "ArraySlice", args);
775 }
776 }
777
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +0000778 Handle<JSArray> result_array =
779 isolate->factory()->NewJSArray(kind, result_len, result_len);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000780
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000781 DisallowHeapAllocation no_gc;
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +0000782 if (result_len == 0) return *result_array;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000783
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000784 ElementsAccessor* accessor = object->GetElementsAccessor();
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000785 accessor->CopyElements(
786 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len);
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +0000787 return *result_array;
ager@chromium.org5c838252010-02-19 08:53:10 +0000788}
789
790
791BUILTIN(ArraySplice) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000792 HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000793 Heap* heap = isolate->heap();
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000794 Handle<Object> receiver = args.receiver();
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000795 MaybeHandle<FixedArrayBase> maybe_elms_obj =
machenbach@chromium.orga2218802014-03-25 07:30:47 +0000796 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
machenbach@chromium.org8f8fe812014-04-07 00:05:03 +0000797 Handle<FixedArrayBase> elms_obj;
798 if (!maybe_elms_obj.ToHandle(&elms_obj) ||
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000799 !IsJSArrayFastElementMovingAllowed(heap,
800 *Handle<JSArray>::cast(receiver))) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000801 return CallJsBuiltin(isolate, "ArraySplice", args);
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000802 }
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000803 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
hpayer@chromium.org7c3372b2013-02-13 17:26:04 +0000804 ASSERT(!array->map()->is_observed());
mvstanton@chromium.orge4ac3ef2012-11-12 14:53:34 +0000805
ager@chromium.org5c838252010-02-19 08:53:10 +0000806 int len = Smi::cast(array->length())->value();
807
808 int n_arguments = args.length() - 1;
809
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000810 int relative_start = 0;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000811 if (n_arguments > 0) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000812 DisallowHeapAllocation no_gc;
813 Object* arg1 = args[1];
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000814 if (arg1->IsSmi()) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000815 relative_start = Smi::cast(arg1)->value();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000816 } else if (arg1->IsHeapNumber()) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000817 double start = HeapNumber::cast(arg1)->value();
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000818 if (start < kMinInt || start > kMaxInt) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000819 AllowHeapAllocation allow_allocation;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000820 return CallJsBuiltin(isolate, "ArraySplice", args);
821 }
danno@chromium.orgca29dd82013-04-26 11:59:48 +0000822 relative_start = std::isnan(start) ? 0 : static_cast<int>(start);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000823 } else if (!arg1->IsUndefined()) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000824 AllowHeapAllocation allow_allocation;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000825 return CallJsBuiltin(isolate, "ArraySplice", args);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000826 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000827 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000828 int actual_start = (relative_start < 0) ? Max(len + relative_start, 0)
829 : Min(relative_start, len);
ager@chromium.org5c838252010-02-19 08:53:10 +0000830
831 // SpiderMonkey, TraceMonkey and JSC treat the case where no delete count is
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000832 // given as a request to delete all the elements from the start.
833 // And it differs from the case of undefined delete count.
ager@chromium.org5c838252010-02-19 08:53:10 +0000834 // This does not follow ECMA-262, but we do the same for
835 // compatibility.
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000836 int actual_delete_count;
837 if (n_arguments == 1) {
838 ASSERT(len - actual_start >= 0);
839 actual_delete_count = len - actual_start;
840 } else {
841 int value = 0; // ToInteger(undefined) == 0
842 if (n_arguments > 1) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000843 DisallowHeapAllocation no_gc;
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000844 Object* arg2 = args[2];
845 if (arg2->IsSmi()) {
846 value = Smi::cast(arg2)->value();
847 } else {
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000848 AllowHeapAllocation allow_allocation;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +0000849 return CallJsBuiltin(isolate, "ArraySplice", args);
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000850 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000851 }
kmillikin@chromium.org31b12772011-02-02 16:08:26 +0000852 actual_delete_count = Min(Max(value, 0), len - actual_start);
ager@chromium.org5c838252010-02-19 08:53:10 +0000853 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000854
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000855 ElementsKind elements_kind = array->GetElementsKind();
856
857 int item_count = (n_arguments > 1) ? (n_arguments - 2) : 0;
858 int new_length = len - actual_delete_count + item_count;
859
860 // For double mode we do not support changing the length.
861 if (new_length > len && IsFastDoubleElementsKind(elements_kind)) {
862 return CallJsBuiltin(isolate, "ArraySplice", args);
863 }
864
865 if (new_length == 0) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000866 Handle<JSArray> result = isolate->factory()->NewJSArrayWithElements(
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000867 elms_obj, elements_kind, actual_delete_count);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000868 array->set_elements(heap->empty_fixed_array());
869 array->set_length(Smi::FromInt(0));
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000870 return *result;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000871 }
872
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000873 Handle<JSArray> result_array =
874 isolate->factory()->NewJSArray(elements_kind,
875 actual_delete_count,
876 actual_delete_count);
ager@chromium.org5c838252010-02-19 08:53:10 +0000877
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000878 if (actual_delete_count > 0) {
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000879 DisallowHeapAllocation no_gc;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000880 ElementsAccessor* accessor = array->GetElementsAccessor();
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000881 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000882 elms_obj, actual_start, elements_kind,
883 handle(result_array->elements(), isolate), 0, actual_delete_count);
ager@chromium.org5c838252010-02-19 08:53:10 +0000884 }
885
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000886 bool elms_changed = false;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000887 if (item_count < actual_delete_count) {
ager@chromium.org5c838252010-02-19 08:53:10 +0000888 // Shrink the array.
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000889 const bool trim_array = !heap->lo_space()->Contains(*elms_obj) &&
lrn@chromium.org25156de2010-04-06 13:10:27 +0000890 ((actual_start + item_count) <
891 (len - actual_delete_count - actual_start));
892 if (trim_array) {
893 const int delta = actual_delete_count - item_count;
894
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000895 if (elms_obj->IsFixedDoubleArray()) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000896 Handle<FixedDoubleArray> elms =
897 Handle<FixedDoubleArray>::cast(elms_obj);
898 MoveDoubleElements(*elms, delta, *elms, 0, actual_start);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000899 } else {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000900 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000901 DisallowHeapAllocation no_gc;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000902 heap->MoveElements(*elms, delta, 0, actual_start);
lrn@chromium.org25156de2010-04-06 13:10:27 +0000903 }
904
machenbach@chromium.orgb5ed9302014-03-25 13:44:35 +0000905 if (heap->CanMoveObjectStart(*elms_obj)) {
906 // On the fast path we move the start of the object in memory.
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000907 elms_obj = handle(LeftTrimFixedArray(heap, *elms_obj, delta), isolate);
machenbach@chromium.orgb5ed9302014-03-25 13:44:35 +0000908 } else {
909 // This is the slow path. We are going to move the elements to the left
910 // by copying them. For trimmed values we store the hole.
911 if (elms_obj->IsFixedDoubleArray()) {
912 Handle<FixedDoubleArray> elms =
913 Handle<FixedDoubleArray>::cast(elms_obj);
914 MoveDoubleElements(*elms, 0, *elms, delta, len - delta);
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000915 elms->FillWithHoles(len - delta, len);
machenbach@chromium.orgb5ed9302014-03-25 13:44:35 +0000916 } else {
917 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
918 DisallowHeapAllocation no_gc;
919 heap->MoveElements(*elms, 0, delta, len - delta);
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000920 elms->FillWithHoles(len - delta, len);
machenbach@chromium.orgb5ed9302014-03-25 13:44:35 +0000921 }
922 }
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000923 elms_changed = true;
lrn@chromium.org25156de2010-04-06 13:10:27 +0000924 } else {
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000925 if (elms_obj->IsFixedDoubleArray()) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000926 Handle<FixedDoubleArray> elms =
927 Handle<FixedDoubleArray>::cast(elms_obj);
928 MoveDoubleElements(*elms, actual_start + item_count,
929 *elms, actual_start + actual_delete_count,
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000930 (len - actual_delete_count - actual_start));
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000931 elms->FillWithHoles(new_length, len);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000932 } else {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000933 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000934 DisallowHeapAllocation no_gc;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000935 heap->MoveElements(*elms, actual_start + item_count,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000936 actual_start + actual_delete_count,
937 (len - actual_delete_count - actual_start));
machenbach@chromium.org2f599e52014-03-31 14:24:38 +0000938 elms->FillWithHoles(new_length, len);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000939 }
lrn@chromium.org25156de2010-04-06 13:10:27 +0000940 }
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000941 } else if (item_count > actual_delete_count) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000942 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
ager@chromium.org5c838252010-02-19 08:53:10 +0000943 // Currently fixed arrays cannot grow too big, so
944 // we should never hit this case.
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000945 ASSERT((item_count - actual_delete_count) <= (Smi::kMaxValue - len));
ager@chromium.org5c838252010-02-19 08:53:10 +0000946
947 // Check if array need to grow.
948 if (new_length > elms->length()) {
949 // New backing storage is needed.
950 int capacity = new_length + (new_length >> 1) + 16;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000951 Handle<FixedArray> new_elms =
952 isolate->factory()->NewUninitializedFixedArray(capacity);
ager@chromium.org5c838252010-02-19 08:53:10 +0000953
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000954 DisallowHeapAllocation no_gc;
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000955
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000956 ElementsKind kind = array->GetElementsKind();
957 ElementsAccessor* accessor = array->GetElementsAccessor();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000958 if (actual_start > 0) {
959 // Copy the part before actual_start as is.
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000960 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000961 elms, 0, kind, new_elms, 0, actual_start);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +0000962 }
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000963 accessor->CopyElements(
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000964 elms, actual_start + actual_delete_count, kind,
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000965 new_elms, actual_start + item_count,
machenbach@chromium.org255043f2014-04-04 00:04:59 +0000966 ElementsAccessor::kCopyToEndAndInitializeToHole);
ager@chromium.org5c838252010-02-19 08:53:10 +0000967
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000968 elms_obj = new_elms;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000969 elms_changed = true;
ager@chromium.orgce5e87b2010-03-10 10:24:18 +0000970 } else {
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000971 DisallowHeapAllocation no_gc;
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000972 heap->MoveElements(*elms, actual_start + item_count,
jkummerow@chromium.org59297c72013-01-09 16:32:23 +0000973 actual_start + actual_delete_count,
974 (len - actual_delete_count - actual_start));
ager@chromium.org5c838252010-02-19 08:53:10 +0000975 }
976 }
977
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000978 if (IsFastDoubleElementsKind(elements_kind)) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000979 Handle<FixedDoubleArray> elms = Handle<FixedDoubleArray>::cast(elms_obj);
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000980 for (int k = actual_start; k < actual_start + item_count; k++) {
981 Object* arg = args[3 + k - actual_start];
982 if (arg->IsSmi()) {
983 elms->set(k, Smi::cast(arg)->value());
984 } else {
985 elms->set(k, HeapNumber::cast(arg)->value());
986 }
987 }
988 } else {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000989 Handle<FixedArray> elms = Handle<FixedArray>::cast(elms_obj);
rossberg@chromium.org79e79022013-06-03 15:43:46 +0000990 DisallowHeapAllocation no_gc;
yangguo@chromium.orgfb377212012-11-16 14:43:43 +0000991 WriteBarrierMode mode = elms->GetWriteBarrierMode(no_gc);
992 for (int k = actual_start; k < actual_start + item_count; k++) {
993 elms->set(k, args[3 + k - actual_start], mode);
994 }
ager@chromium.org5c838252010-02-19 08:53:10 +0000995 }
996
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000997 if (elms_changed) {
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +0000998 array->set_elements(*elms_obj);
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +0000999 }
ager@chromium.org5c838252010-02-19 08:53:10 +00001000 // Set the length.
1001 array->set_length(Smi::FromInt(new_length));
1002
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +00001003 return *result_array;
ager@chromium.org5c838252010-02-19 08:53:10 +00001004}
1005
1006
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001007BUILTIN(ArrayConcat) {
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +00001008 HandleScope scope(isolate);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001009
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001010 int n_arguments = args.length();
1011 int result_len = 0;
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001012 ElementsKind elements_kind = GetInitialFastElementsKind();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001013 bool has_double = false;
machenbach@chromium.org255043f2014-04-04 00:04:59 +00001014 {
1015 DisallowHeapAllocation no_gc;
1016 Heap* heap = isolate->heap();
1017 Context* native_context = isolate->context()->native_context();
1018 JSObject* array_proto =
1019 JSObject::cast(native_context->array_function()->prototype());
1020 if (!ArrayPrototypeHasNoElements(heap, native_context, array_proto)) {
1021 AllowHeapAllocation allow_allocation;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001022 return CallJsBuiltin(isolate, "ArrayConcat", args);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001023 }
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001024
machenbach@chromium.org255043f2014-04-04 00:04:59 +00001025 // Iterate through all the arguments performing checks
1026 // and calculating total length.
1027 bool is_holey = false;
1028 for (int i = 0; i < n_arguments; i++) {
1029 Object* arg = args[i];
1030 if (!arg->IsJSArray() ||
1031 !JSArray::cast(arg)->HasFastElements() ||
1032 JSArray::cast(arg)->GetPrototype() != array_proto) {
1033 AllowHeapAllocation allow_allocation;
1034 return CallJsBuiltin(isolate, "ArrayConcat", args);
1035 }
1036 int len = Smi::cast(JSArray::cast(arg)->length())->value();
1037
1038 // We shouldn't overflow when adding another len.
1039 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2);
1040 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt);
1041 USE(kHalfOfMaxInt);
1042 result_len += len;
1043 ASSERT(result_len >= 0);
1044
1045 if (result_len > FixedDoubleArray::kMaxLength) {
1046 AllowHeapAllocation allow_allocation;
1047 return CallJsBuiltin(isolate, "ArrayConcat", args);
1048 }
1049
1050 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind();
1051 has_double = has_double || IsFastDoubleElementsKind(arg_kind);
1052 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind);
1053 if (IsMoreGeneralElementsKindTransition(elements_kind, arg_kind)) {
1054 elements_kind = arg_kind;
1055 }
svenpanne@chromium.org830d30c2012-05-29 13:20:14 +00001056 }
machenbach@chromium.org255043f2014-04-04 00:04:59 +00001057 if (is_holey) elements_kind = GetHoleyElementsKind(elements_kind);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001058 }
1059
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001060 // If a double array is concatted into a fast elements array, the fast
1061 // elements array needs to be initialized to contain proper holes, since
1062 // boxing doubles may cause incremental marking.
1063 ArrayStorageAllocationMode mode =
1064 has_double && IsFastObjectElementsKind(elements_kind)
1065 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE : DONT_INITIALIZE_ARRAY_ELEMENTS;
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +00001066 Handle<JSArray> result_array =
1067 isolate->factory()->NewJSArray(elements_kind,
1068 result_len,
1069 result_len,
1070 mode);
1071 if (result_len == 0) return *result_array;
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001072
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001073 int j = 0;
machenbach@chromium.org255043f2014-04-04 00:04:59 +00001074 Handle<FixedArrayBase> storage(result_array->elements(), isolate);
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001075 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001076 for (int i = 0; i < n_arguments; i++) {
machenbach@chromium.org255043f2014-04-04 00:04:59 +00001077 // TODO(ishell): It is crucial to keep |array| as a raw pointer to avoid
1078 // performance degradation. Revisit this later.
1079 JSArray* array = JSArray::cast(args[i]);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001080 int len = Smi::cast(array->length())->value();
yangguo@chromium.org4cd70b42013-01-04 08:57:54 +00001081 ElementsKind from_kind = array->GetElementsKind();
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001082 if (len > 0) {
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +00001083 accessor->CopyElements(array, 0, from_kind, storage, j, len);
ulan@chromium.org8e8d8822012-11-23 14:36:46 +00001084 j += len;
1085 }
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001086 }
yangguo@chromium.orgfb377212012-11-16 14:43:43 +00001087
1088 ASSERT(j == result_len);
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001089
machenbach@chromium.orgc85dc102014-03-28 01:04:39 +00001090 return *result_array;
fschneider@chromium.org086aac62010-03-17 13:18:24 +00001091}
1092
1093
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001094// -----------------------------------------------------------------------------
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001095// Strict mode poison pills
1096
1097
danno@chromium.org40cb8782011-05-25 07:58:50 +00001098BUILTIN(StrictModePoisonPill) {
yangguo@chromium.orgc03a1922013-02-19 13:55:47 +00001099 HandleScope scope(isolate);
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001100 return isolate->Throw(*isolate->factory()->NewTypeError(
danno@chromium.org40cb8782011-05-25 07:58:50 +00001101 "strict_poison_pill", HandleVector<Object>(NULL, 0)));
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001102}
1103
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001104
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001105// -----------------------------------------------------------------------------
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001106//
1107
1108
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001109// Searches the hidden prototype chain of the given object for the first
1110// object that is an instance of the given type. If no such object can
1111// be found then Heap::null_value() is returned.
1112static inline Object* FindHidden(Heap* heap,
1113 Object* object,
1114 FunctionTemplateInfo* type) {
machenbach@chromium.org9af454f2013-11-20 09:25:57 +00001115 if (type->IsTemplateFor(object)) return object;
hpayer@chromium.org8432c912013-02-28 15:55:26 +00001116 Object* proto = object->GetPrototype(heap->isolate());
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001117 if (proto->IsJSObject() &&
1118 JSObject::cast(proto)->map()->is_hidden_prototype()) {
1119 return FindHidden(heap, proto, type);
1120 }
1121 return heap->null_value();
1122}
1123
1124
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001125// Returns the holder JSObject if the function can legally be called
1126// with this receiver. Returns Heap::null_value() if the call is
1127// illegal. Any arguments that don't fit the expected type is
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001128// overwritten with undefined. Note that holder and the arguments are
1129// implicitly rewritten with the first object in the hidden prototype
1130// chain that actually has the expected type.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001131static inline Object* TypeCheck(Heap* heap,
1132 int argc,
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001133 Object** argv,
1134 FunctionTemplateInfo* info) {
1135 Object* recv = argv[0];
lrn@chromium.org1c092762011-05-09 09:42:16 +00001136 // API calls are only supported with JSObject receivers.
1137 if (!recv->IsJSObject()) return heap->null_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001138 Object* sig_obj = info->signature();
1139 if (sig_obj->IsUndefined()) return recv;
1140 SignatureInfo* sig = SignatureInfo::cast(sig_obj);
1141 // If necessary, check the receiver
1142 Object* recv_type = sig->receiver();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001143 Object* holder = recv;
1144 if (!recv_type->IsUndefined()) {
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001145 holder = FindHidden(heap, holder, FunctionTemplateInfo::cast(recv_type));
1146 if (holder == heap->null_value()) return heap->null_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001147 }
1148 Object* args_obj = sig->args();
1149 // If there is no argument signature we're done
1150 if (args_obj->IsUndefined()) return holder;
1151 FixedArray* args = FixedArray::cast(args_obj);
1152 int length = args->length();
mads.s.ager31e71382008-08-13 09:32:07 +00001153 if (argc <= length) length = argc - 1;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001154 for (int i = 0; i < length; i++) {
1155 Object* argtype = args->get(i);
1156 if (argtype->IsUndefined()) continue;
1157 Object** arg = &argv[-1 - i];
1158 Object* current = *arg;
mmassi@chromium.org49a44672012-12-04 13:52:03 +00001159 current = FindHidden(heap, current, FunctionTemplateInfo::cast(argtype));
1160 if (current == heap->null_value()) current = heap->undefined_value();
1161 *arg = current;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001162 }
1163 return holder;
1164}
1165
1166
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001167template <bool is_construct>
lrn@chromium.org303ada72010-10-27 09:33:13 +00001168MUST_USE_RESULT static MaybeObject* HandleApiCallHelper(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001169 BuiltinArguments<NEEDS_CALLED_FUNCTION> args, Isolate* isolate) {
1170 ASSERT(is_construct == CalledAsConstructor(isolate));
1171 Heap* heap = isolate->heap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001172
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001173 HandleScope scope(isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001174 Handle<JSFunction> function = args.called_function();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001175 ASSERT(function->shared()->IsApiFunction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001176
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001177 FunctionTemplateInfo* fun_data = function->shared()->get_api_func_data();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001178 if (is_construct) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001179 Handle<FunctionTemplateInfo> desc(fun_data, isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001180 bool pending_exception = false;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001181 isolate->factory()->ConfigureInstance(
1182 desc, Handle<JSObject>::cast(args.receiver()), &pending_exception);
1183 ASSERT(isolate->has_pending_exception() == pending_exception);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001184 if (pending_exception) return Failure::Exception();
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001185 fun_data = *desc;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001186 }
1187
machenbach@chromium.orge31286d2014-01-15 10:29:52 +00001188 SharedFunctionInfo* shared = function->shared();
dslomov@chromium.org486536d2014-03-12 13:09:18 +00001189 if (shared->strict_mode() == SLOPPY && !shared->native()) {
machenbach@chromium.orge31286d2014-01-15 10:29:52 +00001190 Object* recv = args[0];
1191 ASSERT(!recv->IsNull());
1192 if (recv->IsUndefined()) {
1193 args[0] = function->context()->global_object()->global_receiver();
1194 }
1195 }
1196
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001197 Object* raw_holder = TypeCheck(heap, args.length(), &args[0], fun_data);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001198
1199 if (raw_holder->IsNull()) {
1200 // This function cannot be called with the given receiver. Abort!
1201 Handle<Object> obj =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001202 isolate->factory()->NewTypeError(
1203 "illegal_invocation", HandleVector(&function, 1));
1204 return isolate->Throw(*obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001205 }
1206
1207 Object* raw_call_data = fun_data->call_code();
1208 if (!raw_call_data->IsUndefined()) {
1209 CallHandlerInfo* call_data = CallHandlerInfo::cast(raw_call_data);
1210 Object* callback_obj = call_data->callback();
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001211 v8::FunctionCallback callback =
1212 v8::ToCData<v8::FunctionCallback>(callback_obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001213 Object* data_obj = call_data->data();
1214 Object* result;
1215
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001216 LOG(isolate, ApiObjectAccess("call", JSObject::cast(*args.receiver())));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001217 ASSERT(raw_holder->IsJSObject());
1218
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001219 FunctionCallbackArguments custom(isolate,
1220 data_obj,
1221 *function,
1222 raw_holder,
1223 &args[0] - 1,
1224 args.length() - 1,
1225 is_construct);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001226
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001227 v8::Handle<v8::Value> value = custom.Call(callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001228 if (value.IsEmpty()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001229 result = heap->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001230 } else {
1231 result = *reinterpret_cast<Object**>(*value);
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001232 result->VerifyApiCallResultType();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001233 }
1234
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001235 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001236 if (!is_construct || result->IsJSObject()) return result;
1237 }
1238
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001239 return *args.receiver();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001240}
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001241
1242
1243BUILTIN(HandleApiCall) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001244 return HandleApiCallHelper<false>(args, isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001245}
1246
1247
1248BUILTIN(HandleApiCallConstruct) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001249 return HandleApiCallHelper<true>(args, isolate);
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001250}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001251
1252
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001253// Helper function to handle calls to non-function objects created through the
1254// API. The object can be called as either a constructor (using new) or just as
1255// a function (without new).
lrn@chromium.org303ada72010-10-27 09:33:13 +00001256MUST_USE_RESULT static MaybeObject* HandleApiCallAsFunctionOrConstructor(
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001257 Isolate* isolate,
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001258 bool is_construct_call,
1259 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) {
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001260 // Non-functions are never called as constructors. Even if this is an object
1261 // called as a constructor the delegate call is not a construct call.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001262 ASSERT(!CalledAsConstructor(isolate));
1263 Heap* heap = isolate->heap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001264
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001265 Handle<Object> receiver = args.receiver();
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001266
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001267 // Get the object called.
rossberg@chromium.org717967f2011-07-20 13:44:42 +00001268 JSObject* obj = JSObject::cast(*receiver);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001269
1270 // Get the invocation callback from the function descriptor that was
1271 // used to create the called object.
1272 ASSERT(obj->map()->has_instance_call_handler());
1273 JSFunction* constructor = JSFunction::cast(obj->map()->constructor());
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001274 ASSERT(constructor->shared()->IsApiFunction());
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001275 Object* handler =
vegorov@chromium.orgf8372902010-03-15 10:26:20 +00001276 constructor->shared()->get_api_func_data()->instance_call_handler();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001277 ASSERT(!handler->IsUndefined());
1278 CallHandlerInfo* call_data = CallHandlerInfo::cast(handler);
1279 Object* callback_obj = call_data->callback();
verwaest@chromium.org662436e2013-08-28 08:41:27 +00001280 v8::FunctionCallback callback =
1281 v8::ToCData<v8::FunctionCallback>(callback_obj);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001282
1283 // Get the data for the call and perform the callback.
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001284 Object* result;
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001285 {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001286 HandleScope scope(isolate);
1287 LOG(isolate, ApiObjectAccess("call non-function", obj));
fschneider@chromium.orge03fb642010-11-01 12:34:09 +00001288
ulan@chromium.orgbf9432e2013-05-22 14:05:23 +00001289 FunctionCallbackArguments custom(isolate,
1290 call_data->data(),
1291 constructor,
1292 obj,
1293 &args[0] - 1,
1294 args.length() - 1,
1295 is_construct_call);
mstarzinger@chromium.org1510d582013-06-28 14:00:48 +00001296 v8::Handle<v8::Value> value = custom.Call(callback);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001297 if (value.IsEmpty()) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001298 result = heap->undefined_value();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001299 } else {
1300 result = *reinterpret_cast<Object**>(*value);
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001301 result->VerifyApiCallResultType();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001302 }
1303 }
1304 // Check for exceptions and return result.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001305 RETURN_IF_SCHEDULED_EXCEPTION(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001306 return result;
1307}
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001308
1309
1310// Handle calls to non-function objects created through the API. This delegate
1311// function is used when the call is a normal function call.
1312BUILTIN(HandleApiCallAsFunction) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001313 return HandleApiCallAsFunctionOrConstructor(isolate, false, args);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001314}
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001315
1316
1317// Handle calls to non-function objects created through the API. This delegate
1318// function is used when the call is a construct call.
1319BUILTIN(HandleApiCallAsConstructor) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001320 return HandleApiCallAsFunctionOrConstructor(isolate, true, args);
sgjesse@chromium.org05521fc2009-05-21 07:37:44 +00001321}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001322
1323
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001324static void Generate_LoadIC_Miss(MacroAssembler* masm) {
1325 LoadIC::GenerateMiss(masm);
1326}
1327
1328
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001329static void Generate_LoadIC_Normal(MacroAssembler* masm) {
1330 LoadIC::GenerateNormal(masm);
1331}
1332
1333
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001334static void Generate_LoadIC_Getter_ForDeopt(MacroAssembler* masm) {
machenbach@chromium.orgca2f2042014-03-10 10:03:12 +00001335 LoadStubCompiler::GenerateLoadViaGetterForDeopt(masm);
mstarzinger@chromium.orgde886792012-09-11 13:22:37 +00001336}
1337
1338
verwaest@chromium.orgd4be0f02013-06-05 13:39:03 +00001339static void Generate_LoadIC_Slow(MacroAssembler* masm) {
1340 LoadIC::GenerateRuntimeGetProperty(masm);
1341}
1342
1343
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001344static void Generate_KeyedLoadIC_Initialize(MacroAssembler* masm) {
1345 KeyedLoadIC::GenerateInitialize(masm);
1346}
1347
1348
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001349static void Generate_KeyedLoadIC_Slow(MacroAssembler* masm) {
1350 KeyedLoadIC::GenerateRuntimeGetProperty(masm);
1351}
1352
1353
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001354static void Generate_KeyedLoadIC_Miss(MacroAssembler* masm) {
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001355 KeyedLoadIC::GenerateMiss(masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001356}
1357
1358
1359static void Generate_KeyedLoadIC_Generic(MacroAssembler* masm) {
1360 KeyedLoadIC::GenerateGeneric(masm);
1361}
1362
1363
fschneider@chromium.org0c20e672010-01-14 15:28:53 +00001364static void Generate_KeyedLoadIC_String(MacroAssembler* masm) {
1365 KeyedLoadIC::GenerateString(masm);
1366}
1367
1368
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001369static void Generate_KeyedLoadIC_PreMonomorphic(MacroAssembler* masm) {
1370 KeyedLoadIC::GeneratePreMonomorphic(masm);
1371}
1372
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001373
ager@chromium.org5c838252010-02-19 08:53:10 +00001374static void Generate_KeyedLoadIC_IndexedInterceptor(MacroAssembler* masm) {
1375 KeyedLoadIC::GenerateIndexedInterceptor(masm);
1376}
1377
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001378
dslomov@chromium.org486536d2014-03-12 13:09:18 +00001379static void Generate_KeyedLoadIC_SloppyArguments(MacroAssembler* masm) {
1380 KeyedLoadIC::GenerateSloppyArguments(masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001381}
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001382
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001383
ulan@chromium.org57ff8812013-05-10 08:16:55 +00001384static void Generate_StoreIC_Slow(MacroAssembler* masm) {
1385 StoreIC::GenerateSlow(masm);
1386}
1387
1388
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001389static void Generate_StoreIC_Miss(MacroAssembler* masm) {
1390 StoreIC::GenerateMiss(masm);
1391}
1392
1393
kmillikin@chromium.org69ea3962010-07-05 11:01:40 +00001394static void Generate_StoreIC_Normal(MacroAssembler* masm) {
1395 StoreIC::GenerateNormal(masm);
1396}
1397
1398
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001399static void Generate_StoreIC_Setter_ForDeopt(MacroAssembler* masm) {
machenbach@chromium.orgca2f2042014-03-10 10:03:12 +00001400 StoreStubCompiler::GenerateStoreViaSetterForDeopt(masm);
yangguo@chromium.org46839fb2012-08-28 09:06:19 +00001401}
1402
1403
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001404static void Generate_KeyedStoreIC_Generic(MacroAssembler* masm) {
dslomov@chromium.org486536d2014-03-12 13:09:18 +00001405 KeyedStoreIC::GenerateGeneric(masm, SLOPPY);
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001406}
1407
1408
1409static void Generate_KeyedStoreIC_Generic_Strict(MacroAssembler* masm) {
dslomov@chromium.org486536d2014-03-12 13:09:18 +00001410 KeyedStoreIC::GenerateGeneric(masm, STRICT);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001411}
1412
1413
1414static void Generate_KeyedStoreIC_Miss(MacroAssembler* masm) {
machenbach@chromium.orgaf9cfcb2013-11-19 11:05:18 +00001415 KeyedStoreIC::GenerateMiss(masm);
ager@chromium.orgea91cc52011-05-23 06:06:11 +00001416}
1417
1418
1419static void Generate_KeyedStoreIC_Slow(MacroAssembler* masm) {
1420 KeyedStoreIC::GenerateSlow(masm);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001421}
1422
1423
1424static void Generate_KeyedStoreIC_Initialize(MacroAssembler* masm) {
1425 KeyedStoreIC::GenerateInitialize(masm);
1426}
1427
1428
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001429static void Generate_KeyedStoreIC_Initialize_Strict(MacroAssembler* masm) {
1430 KeyedStoreIC::GenerateInitialize(masm);
1431}
1432
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001433
jkummerow@chromium.org3d00d0a2013-09-04 13:57:32 +00001434static void Generate_KeyedStoreIC_PreMonomorphic(MacroAssembler* masm) {
1435 KeyedStoreIC::GeneratePreMonomorphic(masm);
1436}
1437
1438
1439static void Generate_KeyedStoreIC_PreMonomorphic_Strict(MacroAssembler* masm) {
1440 KeyedStoreIC::GeneratePreMonomorphic(masm);
1441}
1442
1443
dslomov@chromium.org486536d2014-03-12 13:09:18 +00001444static void Generate_KeyedStoreIC_SloppyArguments(MacroAssembler* masm) {
1445 KeyedStoreIC::GenerateSloppyArguments(masm);
whesse@chromium.org7b260152011-06-20 15:33:18 +00001446}
ager@chromium.org9ee27ae2011-03-02 13:43:26 +00001447
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001448
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001449#ifdef ENABLE_DEBUGGER_SUPPORT
ager@chromium.org8bb60582008-12-11 12:02:20 +00001450static void Generate_LoadIC_DebugBreak(MacroAssembler* masm) {
1451 Debug::GenerateLoadICDebugBreak(masm);
1452}
1453
1454
1455static void Generate_StoreIC_DebugBreak(MacroAssembler* masm) {
1456 Debug::GenerateStoreICDebugBreak(masm);
1457}
1458
1459
1460static void Generate_KeyedLoadIC_DebugBreak(MacroAssembler* masm) {
1461 Debug::GenerateKeyedLoadICDebugBreak(masm);
1462}
1463
1464
1465static void Generate_KeyedStoreIC_DebugBreak(MacroAssembler* masm) {
1466 Debug::GenerateKeyedStoreICDebugBreak(masm);
1467}
1468
1469
danno@chromium.orgf005df62013-04-30 16:36:45 +00001470static void Generate_CompareNilIC_DebugBreak(MacroAssembler* masm) {
1471 Debug::GenerateCompareNilICDebugBreak(masm);
1472}
1473
1474
ager@chromium.org8bb60582008-12-11 12:02:20 +00001475static void Generate_Return_DebugBreak(MacroAssembler* masm) {
1476 Debug::GenerateReturnDebugBreak(masm);
1477}
1478
1479
danno@chromium.orgc612e022011-11-10 11:38:15 +00001480static void Generate_CallFunctionStub_DebugBreak(MacroAssembler* masm) {
1481 Debug::GenerateCallFunctionStubDebugBreak(masm);
ager@chromium.org8bb60582008-12-11 12:02:20 +00001482}
ager@chromium.org357bf652010-04-12 11:30:10 +00001483
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001484
danno@chromium.orgfa458e42012-02-01 10:48:36 +00001485static void Generate_CallFunctionStub_Recording_DebugBreak(
1486 MacroAssembler* masm) {
1487 Debug::GenerateCallFunctionStubRecordDebugBreak(masm);
1488}
1489
1490
1491static void Generate_CallConstructStub_DebugBreak(MacroAssembler* masm) {
1492 Debug::GenerateCallConstructStubDebugBreak(masm);
1493}
1494
1495
1496static void Generate_CallConstructStub_Recording_DebugBreak(
1497 MacroAssembler* masm) {
1498 Debug::GenerateCallConstructStubRecordDebugBreak(masm);
1499}
1500
1501
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001502static void Generate_Slot_DebugBreak(MacroAssembler* masm) {
1503 Debug::GenerateSlotDebugBreak(masm);
1504}
1505
1506
ager@chromium.org357bf652010-04-12 11:30:10 +00001507static void Generate_PlainReturn_LiveEdit(MacroAssembler* masm) {
1508 Debug::GeneratePlainReturnLiveEdit(masm);
1509}
1510
vegorov@chromium.org2356e6f2010-06-09 09:38:56 +00001511
ager@chromium.org357bf652010-04-12 11:30:10 +00001512static void Generate_FrameDropper_LiveEdit(MacroAssembler* masm) {
1513 Debug::GenerateFrameDropperLiveEdit(masm);
1514}
ager@chromium.org65dad4b2009-04-23 08:48:43 +00001515#endif
ager@chromium.org8bb60582008-12-11 12:02:20 +00001516
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001517
1518Builtins::Builtins() : initialized_(false) {
1519 memset(builtins_, 0, sizeof(builtins_[0]) * builtin_count);
1520 memset(names_, 0, sizeof(names_[0]) * builtin_count);
1521}
1522
1523
1524Builtins::~Builtins() {
1525}
1526
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001527
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001528#define DEF_ENUM_C(name, ignore) FUNCTION_ADDR(Builtin_##name),
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001529Address const Builtins::c_functions_[cfunction_count] = {
1530 BUILTIN_LIST_C(DEF_ENUM_C)
1531};
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001532#undef DEF_ENUM_C
1533
1534#define DEF_JS_NAME(name, ignore) #name,
1535#define DEF_JS_ARGC(ignore, argc) argc,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001536const char* const Builtins::javascript_names_[id_count] = {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001537 BUILTINS_LIST_JS(DEF_JS_NAME)
1538};
1539
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001540int const Builtins::javascript_argc_[id_count] = {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001541 BUILTINS_LIST_JS(DEF_JS_ARGC)
1542};
1543#undef DEF_JS_NAME
1544#undef DEF_JS_ARGC
1545
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001546struct BuiltinDesc {
1547 byte* generator;
1548 byte* c_code;
1549 const char* s_name; // name is only used for generating log information.
1550 int name;
1551 Code::Flags flags;
1552 BuiltinExtraArguments extra_args;
1553};
1554
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001555#define BUILTIN_FUNCTION_TABLE_INIT { V8_ONCE_INIT, {} }
1556
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001557class BuiltinFunctionTable {
1558 public:
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001559 BuiltinDesc* functions() {
1560 CallOnce(&once_, &Builtins::InitBuiltinFunctionTable);
1561 return functions_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001562 }
1563
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001564 OnceType once_;
1565 BuiltinDesc functions_[Builtins::builtin_count + 1];
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001566
1567 friend class Builtins;
1568};
1569
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001570static BuiltinFunctionTable builtin_function_table =
1571 BUILTIN_FUNCTION_TABLE_INIT;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001572
1573// Define array of pointers to generators and C builtin functions.
1574// We do this in a sort of roundabout way so that we can do the initialization
1575// within the lexical scope of Builtins:: and within a context where
1576// Code::Flags names a non-abstract type.
1577void Builtins::InitBuiltinFunctionTable() {
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001578 BuiltinDesc* functions = builtin_function_table.functions_;
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001579 functions[builtin_count].generator = NULL;
1580 functions[builtin_count].c_code = NULL;
1581 functions[builtin_count].s_name = NULL;
1582 functions[builtin_count].name = builtin_count;
1583 functions[builtin_count].flags = static_cast<Code::Flags>(0);
1584 functions[builtin_count].extra_args = NO_EXTRA_ARGUMENTS;
1585
1586#define DEF_FUNCTION_PTR_C(aname, aextra_args) \
1587 functions->generator = FUNCTION_ADDR(Generate_Adaptor); \
1588 functions->c_code = FUNCTION_ADDR(Builtin_##aname); \
1589 functions->s_name = #aname; \
1590 functions->name = c_##aname; \
1591 functions->flags = Code::ComputeFlags(Code::BUILTIN); \
1592 functions->extra_args = aextra_args; \
1593 ++functions;
1594
1595#define DEF_FUNCTION_PTR_A(aname, kind, state, extra) \
1596 functions->generator = FUNCTION_ADDR(Generate_##aname); \
1597 functions->c_code = NULL; \
1598 functions->s_name = #aname; \
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001599 functions->name = k##aname; \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001600 functions->flags = Code::ComputeFlags(Code::kind, \
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001601 state, \
1602 extra); \
1603 functions->extra_args = NO_EXTRA_ARGUMENTS; \
1604 ++functions;
1605
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00001606#define DEF_FUNCTION_PTR_H(aname, kind) \
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001607 functions->generator = FUNCTION_ADDR(Generate_##aname); \
1608 functions->c_code = NULL; \
1609 functions->s_name = #aname; \
1610 functions->name = k##aname; \
titzer@chromium.orgf5a24542014-03-04 09:06:17 +00001611 functions->flags = Code::ComputeHandlerFlags(Code::kind); \
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001612 functions->extra_args = NO_EXTRA_ARGUMENTS; \
1613 ++functions;
1614
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001615 BUILTIN_LIST_C(DEF_FUNCTION_PTR_C)
1616 BUILTIN_LIST_A(DEF_FUNCTION_PTR_A)
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001617 BUILTIN_LIST_H(DEF_FUNCTION_PTR_H)
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001618 BUILTIN_LIST_DEBUG_A(DEF_FUNCTION_PTR_A)
1619
1620#undef DEF_FUNCTION_PTR_C
1621#undef DEF_FUNCTION_PTR_A
1622}
1623
mstarzinger@chromium.orge0e1b0d2013-07-08 08:38:06 +00001624
mstarzinger@chromium.orge9000182013-09-03 11:25:39 +00001625void Builtins::SetUp(Isolate* isolate, bool create_heap_objects) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001626 ASSERT(!initialized_);
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001627 Heap* heap = isolate->heap();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001628
1629 // Create a scope for the handles in the builtins.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001630 HandleScope scope(isolate);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001631
jkummerow@chromium.org1456e702012-03-30 08:38:13 +00001632 const BuiltinDesc* functions = builtin_function_table.functions();
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001633
1634 // For now we generate builtin adaptor code into a stack-allocated
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001635 // buffer, before copying it into individual code objects. Be careful
1636 // with alignment, some platforms don't like unaligned code.
titzer@chromium.orgf5a24542014-03-04 09:06:17 +00001637 // TODO(jbramley): I had to increase the size of this buffer from 8KB because
machenbach@chromium.orgfa0c3c62014-03-24 08:11:09 +00001638 // we can generate a lot of debug code on ARM64.
titzer@chromium.orgf5a24542014-03-04 09:06:17 +00001639 union { int force_alignment; byte buffer[16*KB]; } u;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001640
1641 // Traverse the list of builtins and generate an adaptor in a
1642 // separate code object for each one.
1643 for (int i = 0; i < builtin_count; i++) {
1644 if (create_heap_objects) {
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001645 MacroAssembler masm(isolate, u.buffer, sizeof u.buffer);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001646 // Generate the code/adaptor.
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001647 typedef void (*Generator)(MacroAssembler*, int, BuiltinExtraArguments);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001648 Generator g = FUNCTION_CAST<Generator>(functions[i].generator);
1649 // We pass all arguments to the generator, but it may not use all of
1650 // them. This works because the first arguments are on top of the
1651 // stack.
erik.corry@gmail.comc3b670f2011-10-05 21:44:48 +00001652 ASSERT(!masm.has_frame());
sgjesse@chromium.orgb302e562010-02-03 11:26:59 +00001653 g(&masm, functions[i].name, functions[i].extra_args);
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001654 // Move the code into the object heap.
1655 CodeDesc desc;
1656 masm.GetCode(&desc);
1657 Code::Flags flags = functions[i].flags;
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001658 Object* code = NULL;
kasperl@chromium.org9bbf9682008-10-30 11:53:07 +00001659 {
1660 // During startup it's OK to always allocate and defer GC to later.
1661 // This simplifies things because we don't need to retry.
machenbach@chromium.org56971442014-03-19 13:13:40 +00001662 AlwaysAllocateScope __scope__(isolate);
lrn@chromium.org303ada72010-10-27 09:33:13 +00001663 { MaybeObject* maybe_code =
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001664 heap->CreateCode(desc, flags, masm.CodeObject());
lrn@chromium.org303ada72010-10-27 09:33:13 +00001665 if (!maybe_code->ToObject(&code)) {
1666 v8::internal::V8::FatalProcessOutOfMemory("CreateCode");
1667 }
ager@chromium.org7c537e22008-10-16 08:43:32 +00001668 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001669 }
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001670 // Log the event and add the code to the builtins array.
kmillikin@chromium.orgc36ce6e2011-04-04 08:25:31 +00001671 PROFILE(isolate,
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001672 CodeCreateEvent(Logger::BUILTIN_TAG,
erik.corry@gmail.com0511e242011-01-19 11:11:08 +00001673 Code::cast(code),
1674 functions[i].s_name));
1675 GDBJIT(AddCode(GDBJITInterface::BUILTIN,
1676 functions[i].s_name,
1677 Code::cast(code)));
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001678 builtins_[i] = code;
kasperl@chromium.org7be3c992009-03-12 07:19:55 +00001679#ifdef ENABLE_DISASSEMBLER
mads.s.ager31e71382008-08-13 09:32:07 +00001680 if (FLAG_print_builtin_code) {
machenbach@chromium.orge8412be2013-11-08 10:23:52 +00001681 CodeTracer::Scope trace_scope(isolate->GetCodeTracer());
1682 PrintF(trace_scope.file(), "Builtin: %s\n", functions[i].s_name);
1683 Code::cast(code)->Disassemble(functions[i].s_name, trace_scope.file());
1684 PrintF(trace_scope.file(), "\n");
mads.s.ager31e71382008-08-13 09:32:07 +00001685 }
1686#endif
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001687 } else {
1688 // Deserializing. The values will be filled in during IterateBuiltins.
1689 builtins_[i] = NULL;
1690 }
1691 names_[i] = functions[i].s_name;
1692 }
1693
1694 // Mark as initialized.
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001695 initialized_ = true;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001696}
1697
1698
1699void Builtins::TearDown() {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001700 initialized_ = false;
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001701}
1702
1703
1704void Builtins::IterateBuiltins(ObjectVisitor* v) {
1705 v->VisitPointers(&builtins_[0], &builtins_[0] + builtin_count);
1706}
1707
1708
1709const char* Builtins::Lookup(byte* pc) {
sgjesse@chromium.orgea88ce92011-03-23 11:19:56 +00001710 // may be called during initialization (disassembler!)
1711 if (initialized_) {
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001712 for (int i = 0; i < builtin_count; i++) {
1713 Code* entry = Code::cast(builtins_[i]);
1714 if (entry->contains(pc)) {
1715 return names_[i];
1716 }
1717 }
1718 }
1719 return NULL;
1720}
1721
kasperl@chromium.orga5551262010-12-07 12:49:48 +00001722
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00001723void Builtins::Generate_InterruptCheck(MacroAssembler* masm) {
machenbach@chromium.org895f00d2014-03-27 01:04:43 +00001724 masm->TailCallRuntime(Runtime::kHiddenInterrupt, 0, 1);
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00001725}
1726
1727
1728void Builtins::Generate_StackCheck(MacroAssembler* masm) {
machenbach@chromium.org895f00d2014-03-27 01:04:43 +00001729 masm->TailCallRuntime(Runtime::kHiddenStackGuard, 0, 1);
jkummerow@chromium.orgdc94e192013-08-30 11:35:42 +00001730}
1731
1732
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001733#define DEFINE_BUILTIN_ACCESSOR_C(name, ignore) \
1734Handle<Code> Builtins::name() { \
1735 Code** code_address = \
1736 reinterpret_cast<Code**>(builtin_address(k##name)); \
1737 return Handle<Code>(code_address); \
1738}
1739#define DEFINE_BUILTIN_ACCESSOR_A(name, kind, state, extra) \
1740Handle<Code> Builtins::name() { \
1741 Code** code_address = \
1742 reinterpret_cast<Code**>(builtin_address(k##name)); \
1743 return Handle<Code>(code_address); \
1744}
machenbach@chromium.orgc86e8c22013-11-27 15:11:04 +00001745#define DEFINE_BUILTIN_ACCESSOR_H(name, kind) \
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001746Handle<Code> Builtins::name() { \
1747 Code** code_address = \
1748 reinterpret_cast<Code**>(builtin_address(k##name)); \
1749 return Handle<Code>(code_address); \
1750}
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001751BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
1752BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
jkummerow@chromium.org32aa03c2013-10-01 08:21:50 +00001753BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
fschneider@chromium.org7979bbb2011-03-28 10:47:03 +00001754BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
1755#undef DEFINE_BUILTIN_ACCESSOR_C
1756#undef DEFINE_BUILTIN_ACCESSOR_A
1757
1758
christian.plesner.hansen43d26ec2008-07-03 15:10:15 +00001759} } // namespace v8::internal