OLD | NEW |
---|---|
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/builtins.h" | 5 #include "src/builtins.h" |
6 | 6 |
7 #include "src/api.h" | 7 #include "src/api.h" |
8 #include "src/api-natives.h" | 8 #include "src/api-natives.h" |
9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
10 #include "src/base/once.h" | 10 #include "src/base/once.h" |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
127 int args_length, Object** args_object, Isolate* isolate) { \ | 127 int args_length, Object** args_object, Isolate* isolate) { \ |
128 name##ArgumentsType args(args_length, args_object); \ | 128 name##ArgumentsType args(args_length, args_object); \ |
129 return Builtin_impl##name(args, isolate); \ | 129 return Builtin_impl##name(args, isolate); \ |
130 } \ | 130 } \ |
131 static Object* Builtin_impl##name( \ | 131 static Object* Builtin_impl##name( \ |
132 name##ArgumentsType args, Isolate* isolate) | 132 name##ArgumentsType args, Isolate* isolate) |
133 #endif | 133 #endif |
134 | 134 |
135 | 135 |
136 #ifdef DEBUG | 136 #ifdef DEBUG |
137 static inline bool CalledAsConstructor(Isolate* isolate) { | 137 inline bool CalledAsConstructor(Isolate* isolate) { |
138 // Calculate the result using a full stack frame iterator and check | 138 // Calculate the result using a full stack frame iterator and check |
139 // that the state of the stack is as we assume it to be in the | 139 // that the state of the stack is as we assume it to be in the |
140 // code below. | 140 // code below. |
141 StackFrameIterator it(isolate); | 141 StackFrameIterator it(isolate); |
142 DCHECK(it.frame()->is_exit()); | 142 DCHECK(it.frame()->is_exit()); |
143 it.Advance(); | 143 it.Advance(); |
144 StackFrame* frame = it.frame(); | 144 StackFrame* frame = it.frame(); |
145 bool reference_result = frame->is_construct(); | 145 bool reference_result = frame->is_construct(); |
146 Address fp = Isolate::c_entry_fp(isolate->thread_local_top()); | 146 Address fp = Isolate::c_entry_fp(isolate->thread_local_top()); |
147 // Because we know fp points to an exit frame we can use the relevant | 147 // Because we know fp points to an exit frame we can use the relevant |
(...skipping 10 matching lines...) Expand all Loading... | |
158 bool result = (marker == kConstructMarker); | 158 bool result = (marker == kConstructMarker); |
159 DCHECK_EQ(result, reference_result); | 159 DCHECK_EQ(result, reference_result); |
160 return result; | 160 return result; |
161 } | 161 } |
162 #endif | 162 #endif |
163 | 163 |
164 | 164 |
165 // ---------------------------------------------------------------------------- | 165 // ---------------------------------------------------------------------------- |
166 | 166 |
167 | 167 |
168 bool ClampedToInteger(Object* object, int* out) { | 168 inline bool ClampedToInteger(Object* object, int* out) { |
169 // This is an extended version of ECMA-262 7.1.11 handling signed values | 169 // This is an extended version of ECMA-262 7.1.11 handling signed values |
170 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt] | 170 // Try to convert object to a number and clamp values to [kMinInt, kMaxInt] |
171 if (object->IsSmi()) { | 171 if (object->IsSmi()) { |
172 *out = Smi::cast(object)->value(); | 172 *out = Smi::cast(object)->value(); |
173 return true; | 173 return true; |
174 } else if (object->IsHeapNumber()) { | 174 } else if (object->IsHeapNumber()) { |
175 *out = FastD2IChecked(HeapNumber::cast(object)->value()); | 175 *out = FastD2IChecked(HeapNumber::cast(object)->value()); |
176 return true; | 176 return true; |
177 } else if (object->IsUndefined()) { | 177 } else if (object->IsUndefined() || object->IsNull()) { |
178 *out = 0; | 178 *out = 0; |
179 return true; | 179 return true; |
180 } else if (object->IsBoolean()) { | 180 } else if (object->IsBoolean()) { |
181 *out = object->IsTrue(); | 181 *out = object->IsTrue(); |
182 return true; | 182 return true; |
183 } | 183 } |
184 return false; | 184 return false; |
185 } | 185 } |
186 | 186 |
187 | 187 |
188 static void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, | 188 void MoveDoubleElements(FixedDoubleArray* dst, int dst_index, |
189 FixedDoubleArray* src, int src_index, int len) { | 189 FixedDoubleArray* src, int src_index, int len) { |
190 if (len == 0) return; | 190 if (len == 0) return; |
191 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, | 191 MemMove(dst->data_start() + dst_index, src->data_start() + src_index, |
192 len * kDoubleSize); | 192 len * kDoubleSize); |
193 } | 193 } |
194 | 194 |
195 | 195 |
196 static bool ArrayPrototypeHasNoElements(PrototypeIterator* iter) { | 196 inline bool GetSloppyArgumentsLength(Isolate* isolate, Handle<JSObject> object, |
197 int* out) { | |
198 Map* arguments_map = | |
199 isolate->context()->native_context()->sloppy_arguments_map(); | |
200 if (object->map() != arguments_map || !object->HasFastElements()) { | |
201 return false; | |
202 } | |
203 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); | |
204 if (!len_obj->IsSmi()) { | |
205 return false; | |
206 } | |
207 *out = Smi::cast(len_obj)->value(); | |
208 return *out <= object->elements()->length(); | |
209 } | |
210 | |
211 | |
212 bool PrototypeHasNoElements(PrototypeIterator* iter) { | |
197 DisallowHeapAllocation no_gc; | 213 DisallowHeapAllocation no_gc; |
198 for (; !iter->IsAtEnd(); iter->Advance()) { | 214 for (; !iter->IsAtEnd(); iter->Advance()) { |
199 if (iter->GetCurrent()->IsJSProxy()) return false; | 215 if (iter->GetCurrent()->IsJSProxy()) return false; |
200 JSObject* current = JSObject::cast(iter->GetCurrent()); | 216 JSObject* current = JSObject::cast(iter->GetCurrent()); |
201 if (current->IsAccessCheckNeeded()) return false; | 217 if (current->IsAccessCheckNeeded()) return false; |
202 if (current->HasIndexedInterceptor()) return false; | 218 if (current->HasIndexedInterceptor()) return false; |
203 if (current->elements()->length() != 0) return false; | 219 if (current->elements()->length() != 0) return false; |
204 } | 220 } |
205 return true; | 221 return true; |
206 } | 222 } |
207 | 223 |
208 | 224 |
209 static inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, | 225 inline bool IsJSArrayFastElementMovingAllowed(Isolate* isolate, |
210 JSArray* receiver) { | 226 JSArray* receiver) { |
211 DisallowHeapAllocation no_gc; | 227 DisallowHeapAllocation no_gc; |
212 // If the array prototype chain is intact (and free of elements), and if the | 228 // If the array prototype chain is intact (and free of elements), and if the |
213 // receiver's prototype is the array prototype, then we are done. | 229 // receiver's prototype is the array prototype, then we are done. |
214 Object* prototype = receiver->map()->prototype(); | 230 Object* prototype = receiver->map()->prototype(); |
215 if (prototype->IsJSArray() && | 231 if (prototype->IsJSArray() && |
216 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && | 232 isolate->is_initial_array_prototype(JSArray::cast(prototype)) && |
217 isolate->IsFastArrayConstructorPrototypeChainIntact()) { | 233 isolate->IsFastArrayConstructorPrototypeChainIntact()) { |
218 return true; | 234 return true; |
219 } | 235 } |
220 | 236 |
221 // Slow case. | 237 // Slow case. |
222 PrototypeIterator iter(isolate, receiver); | 238 PrototypeIterator iter(isolate, receiver); |
223 return ArrayPrototypeHasNoElements(&iter); | 239 return PrototypeHasNoElements(&iter); |
224 } | 240 } |
225 | 241 |
226 | 242 |
227 // Returns empty handle if not applicable. | 243 // Returns empty handle if not applicable. |
228 MUST_USE_RESULT | 244 MUST_USE_RESULT |
229 static inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( | 245 inline MaybeHandle<FixedArrayBase> EnsureJSArrayWithWritableFastElements( |
230 Isolate* isolate, | 246 Isolate* isolate, Handle<Object> receiver, Arguments* args, |
231 Handle<Object> receiver, | |
232 Arguments* args, | |
233 int first_added_arg) { | 247 int first_added_arg) { |
234 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); | 248 if (!receiver->IsJSArray()) return MaybeHandle<FixedArrayBase>(); |
235 Handle<JSArray> array = Handle<JSArray>::cast(receiver); | 249 Handle<JSArray> array = Handle<JSArray>::cast(receiver); |
236 // If there may be elements accessors in the prototype chain, the fast path | 250 // If there may be elements accessors in the prototype chain, the fast path |
237 // cannot be used if there arguments to add to the array. | 251 // cannot be used if there arguments to add to the array. |
238 Heap* heap = isolate->heap(); | 252 Heap* heap = isolate->heap(); |
239 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { | 253 if (args != NULL && !IsJSArrayFastElementMovingAllowed(isolate, *array)) { |
240 return MaybeHandle<FixedArrayBase>(); | 254 return MaybeHandle<FixedArrayBase>(); |
241 } | 255 } |
242 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); | 256 if (array->map()->is_observed()) return MaybeHandle<FixedArrayBase>(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
284 } | 298 } |
285 } | 299 } |
286 } | 300 } |
287 if (target_kind != origin_kind) { | 301 if (target_kind != origin_kind) { |
288 JSObject::TransitionElementsKind(array, target_kind); | 302 JSObject::TransitionElementsKind(array, target_kind); |
289 return handle(array->elements(), isolate); | 303 return handle(array->elements(), isolate); |
290 } | 304 } |
291 return elms; | 305 return elms; |
292 } | 306 } |
293 | 307 |
294 | |
Igor Sheludko
2015/08/31 10:42:51
Spurious change.
Camillo Bruni
2015/08/31 11:10:08
I moved everything in to an anonymous namespace, w
| |
295 MUST_USE_RESULT static Object* CallJsIntrinsic( | 308 MUST_USE_RESULT static Object* CallJsIntrinsic( |
296 Isolate* isolate, Handle<JSFunction> function, | 309 Isolate* isolate, Handle<JSFunction> function, |
297 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { | 310 BuiltinArguments<NO_EXTRA_ARGUMENTS> args) { |
298 HandleScope handleScope(isolate); | 311 HandleScope handleScope(isolate); |
299 int argc = args.length() - 1; | 312 int argc = args.length() - 1; |
300 ScopedVector<Handle<Object> > argv(argc); | 313 ScopedVector<Handle<Object> > argv(argc); |
301 for (int i = 0; i < argc; ++i) { | 314 for (int i = 0; i < argc; ++i) { |
302 argv[i] = args.at<Object>(i + 1); | 315 argv[i] = args.at<Object>(i + 1); |
303 } | 316 } |
304 Handle<Object> result; | 317 Handle<Object> result; |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
488 | 501 |
489 // Set the length. | 502 // Set the length. |
490 array->set_length(Smi::FromInt(new_length)); | 503 array->set_length(Smi::FromInt(new_length)); |
491 return Smi::FromInt(new_length); | 504 return Smi::FromInt(new_length); |
492 } | 505 } |
493 | 506 |
494 | 507 |
495 BUILTIN(ArraySlice) { | 508 BUILTIN(ArraySlice) { |
496 HandleScope scope(isolate); | 509 HandleScope scope(isolate); |
497 Handle<Object> receiver = args.receiver(); | 510 Handle<Object> receiver = args.receiver(); |
511 Handle<JSObject> object; | |
512 Handle<FixedArrayBase> elms_obj; | |
498 int len = -1; | 513 int len = -1; |
499 int relative_start = 0; | 514 int relative_start = 0; |
500 int relative_end = 0; | 515 int relative_end = 0; |
501 { | 516 bool is_sloppy_arguments = false; |
517 | |
518 if (receiver->IsJSArray()) { | |
502 DisallowHeapAllocation no_gc; | 519 DisallowHeapAllocation no_gc; |
503 if (receiver->IsJSArray()) { | 520 JSArray* array = JSArray::cast(*receiver); |
504 JSArray* array = JSArray::cast(*receiver); | 521 if (!array->HasFastElements() || |
505 if (!IsJSArrayFastElementMovingAllowed(isolate, array)) { | 522 !IsJSArrayFastElementMovingAllowed(isolate, array)) { |
523 AllowHeapAllocation allow_allocation; | |
524 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
525 } | |
526 len = Smi::cast(array->length())->value(); | |
527 object = Handle<JSObject>::cast(receiver); | |
528 elms_obj = handle(array->elements(), isolate); | |
529 } else if (receiver->IsJSObject() && | |
530 GetSloppyArgumentsLength(isolate, Handle<JSObject>::cast(receiver), | |
531 &len)) { | |
532 // Array.prototype.slice(arguments, ...) is quite a common idiom | |
533 // (notably more than 50% of invocations in Web apps). | |
534 // Treat it in C++ as well. | |
535 is_sloppy_arguments = true; | |
536 object = Handle<JSObject>::cast(receiver); | |
537 elms_obj = handle(object->elements(), isolate); | |
538 } else { | |
539 AllowHeapAllocation allow_allocation; | |
540 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
541 } | |
542 DCHECK(len >= 0); | |
543 int argument_count = args.length() - 1; | |
544 // Note carefully chosen defaults---if argument is missing, | |
545 // it's undefined which gets converted to 0 for relative_start | |
546 // and to len for relative_end. | |
547 relative_start = 0; | |
548 relative_end = len; | |
549 if (argument_count > 0) { | |
550 DisallowHeapAllocation no_gc; | |
551 if (!ClampedToInteger(args[1], &relative_start)) { | |
Igor Sheludko
2015/08/31 10:42:51
I think clamping could be wrong if we ever have a
Camillo Bruni
2015/08/31 11:10:08
I agree that the name ClampedToInteger is not a go
| |
552 AllowHeapAllocation allow_allocation; | |
553 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
554 } | |
555 if (argument_count > 1) { | |
556 Object* end_arg = args[2]; | |
557 // slice handles the end_arg specially | |
558 if (end_arg->IsUndefined()) { | |
559 relative_end = len; | |
560 } else if (!ClampedToInteger(end_arg, &relative_end)) { | |
506 AllowHeapAllocation allow_allocation; | 561 AllowHeapAllocation allow_allocation; |
507 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | 562 return CallJsIntrinsic(isolate, isolate->array_slice(), args); |
508 } | 563 } |
509 | |
510 if (!array->HasFastElements()) { | |
511 AllowHeapAllocation allow_allocation; | |
512 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
513 } | |
514 | |
515 len = Smi::cast(array->length())->value(); | |
516 } else { | |
517 // Array.slice(arguments, ...) is quite a common idiom (notably more | |
518 // than 50% of invocations in Web apps). Treat it in C++ as well. | |
519 Map* arguments_map = | |
520 isolate->context()->native_context()->sloppy_arguments_map(); | |
521 | |
522 bool is_arguments_object_with_fast_elements = | |
523 receiver->IsJSObject() && | |
524 JSObject::cast(*receiver)->map() == arguments_map; | |
525 if (!is_arguments_object_with_fast_elements) { | |
526 AllowHeapAllocation allow_allocation; | |
527 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
528 } | |
529 JSObject* object = JSObject::cast(*receiver); | |
530 | |
531 if (!object->HasFastElements()) { | |
532 AllowHeapAllocation allow_allocation; | |
533 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
534 } | |
535 | |
536 Object* len_obj = object->InObjectPropertyAt(Heap::kArgumentsLengthIndex); | |
537 if (!len_obj->IsSmi()) { | |
538 AllowHeapAllocation allow_allocation; | |
539 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
540 } | |
541 len = Smi::cast(len_obj)->value(); | |
542 if (len > object->elements()->length()) { | |
543 AllowHeapAllocation allow_allocation; | |
544 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
545 } | |
546 } | |
547 | |
548 DCHECK(len >= 0); | |
549 int n_arguments = args.length() - 1; | |
550 | |
551 // Note carefully choosen defaults---if argument is missing, | |
552 // it's undefined which gets converted to 0 for relative_start | |
553 // and to len for relative_end. | |
554 relative_start = 0; | |
555 relative_end = len; | |
556 if (n_arguments > 0) { | |
557 Object* arg1 = args[1]; | |
558 if (arg1->IsSmi()) { | |
559 relative_start = Smi::cast(arg1)->value(); | |
560 } else if (arg1->IsHeapNumber()) { | |
561 double start = HeapNumber::cast(arg1)->value(); | |
562 if (start < kMinInt || start > kMaxInt) { | |
563 AllowHeapAllocation allow_allocation; | |
564 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
565 } | |
566 relative_start = std::isnan(start) ? 0 : static_cast<int>(start); | |
567 } else if (!arg1->IsUndefined()) { | |
568 AllowHeapAllocation allow_allocation; | |
569 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
570 } | |
571 if (n_arguments > 1) { | |
572 Object* arg2 = args[2]; | |
573 if (arg2->IsSmi()) { | |
574 relative_end = Smi::cast(arg2)->value(); | |
575 } else if (arg2->IsHeapNumber()) { | |
576 double end = HeapNumber::cast(arg2)->value(); | |
577 if (end < kMinInt || end > kMaxInt) { | |
578 AllowHeapAllocation allow_allocation; | |
579 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
580 } | |
581 relative_end = std::isnan(end) ? 0 : static_cast<int>(end); | |
582 } else if (!arg2->IsUndefined()) { | |
583 AllowHeapAllocation allow_allocation; | |
584 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
585 } | |
586 } | |
587 } | 564 } |
588 } | 565 } |
589 | 566 |
590 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. | 567 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 6. |
591 int k = (relative_start < 0) ? Max(len + relative_start, 0) | 568 uint32_t actual_start = (relative_start < 0) ? Max(len + relative_start, 0) |
592 : Min(relative_start, len); | 569 : Min(relative_start, len); |
593 | 570 |
594 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. | 571 // ECMAScript 232, 3rd Edition, Section 15.4.4.10, step 8. |
595 int final = (relative_end < 0) ? Max(len + relative_end, 0) | 572 uint32_t actual_end = |
596 : Min(relative_end, len); | 573 (relative_end < 0) ? Max(len + relative_end, 0) : Min(relative_end, len); |
597 | |
598 // Calculate the length of result array. | |
599 int result_len = Max(final - k, 0); | |
600 | |
601 Handle<JSObject> object = Handle<JSObject>::cast(receiver); | |
602 Handle<FixedArrayBase> elms(object->elements(), isolate); | |
603 | |
604 ElementsKind kind = object->GetElementsKind(); | |
605 if (IsHoleyElementsKind(kind)) { | |
606 DisallowHeapAllocation no_gc; | |
607 bool packed = true; | |
608 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); | |
609 for (int i = k; i < final; i++) { | |
610 if (!accessor->HasElement(object, i, elms)) { | |
611 packed = false; | |
612 break; | |
613 } | |
614 } | |
615 if (packed) { | |
616 kind = GetPackedElementsKind(kind); | |
617 } else if (!receiver->IsJSArray()) { | |
618 AllowHeapAllocation allow_allocation; | |
619 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
620 } | |
621 } | |
622 | |
623 Handle<JSArray> result_array = | |
624 isolate->factory()->NewJSArray(kind, result_len, result_len); | |
625 | |
626 DisallowHeapAllocation no_gc; | |
627 if (result_len == 0) return *result_array; | |
628 | 574 |
629 ElementsAccessor* accessor = object->GetElementsAccessor(); | 575 ElementsAccessor* accessor = object->GetElementsAccessor(); |
630 accessor->CopyElements( | 576 if (is_sloppy_arguments && |
631 elms, k, kind, handle(result_array->elements(), isolate), 0, result_len); | 577 !accessor->IsPacked(object, elms_obj, actual_start, actual_end)) { |
578 // Don't deal with arguments with holes in C++ | |
579 AllowHeapAllocation allow_allocation; | |
580 return CallJsIntrinsic(isolate, isolate->array_slice(), args); | |
581 } | |
582 Handle<JSArray> result_array = | |
583 accessor->Slice(object, elms_obj, actual_start, actual_end); | |
632 return *result_array; | 584 return *result_array; |
633 } | 585 } |
634 | 586 |
635 | 587 |
636 BUILTIN(ArraySplice) { | 588 BUILTIN(ArraySplice) { |
637 HandleScope scope(isolate); | 589 HandleScope scope(isolate); |
638 Handle<Object> receiver = args.receiver(); | 590 Handle<Object> receiver = args.receiver(); |
639 MaybeHandle<FixedArrayBase> maybe_elms_obj = | 591 MaybeHandle<FixedArrayBase> maybe_elms_obj = |
640 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); | 592 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); |
641 Handle<FixedArrayBase> elms_obj; | 593 Handle<FixedArrayBase> elms_obj; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
680 } | 632 } |
681 | 633 |
682 int add_count = (argument_count > 1) ? (argument_count - 2) : 0; | 634 int add_count = (argument_count > 1) ? (argument_count - 2) : 0; |
683 int new_length = len - actual_delete_count + add_count; | 635 int new_length = len - actual_delete_count + add_count; |
684 | 636 |
685 if (new_length != len && JSArray::HasReadOnlyLength(array)) { | 637 if (new_length != len && JSArray::HasReadOnlyLength(array)) { |
686 AllowHeapAllocation allow_allocation; | 638 AllowHeapAllocation allow_allocation; |
687 return CallJsIntrinsic(isolate, isolate->array_splice(), args); | 639 return CallJsIntrinsic(isolate, isolate->array_splice(), args); |
688 } | 640 } |
689 ElementsAccessor* accessor = array->GetElementsAccessor(); | 641 ElementsAccessor* accessor = array->GetElementsAccessor(); |
690 Handle<JSArray> result = accessor->Splice( | 642 Handle<JSArray> result_array = accessor->Splice( |
691 array, elms_obj, actual_start, actual_delete_count, args, add_count); | 643 array, elms_obj, actual_start, actual_delete_count, args, add_count); |
692 return *result; | 644 return *result_array; |
693 } | 645 } |
694 | 646 |
695 | 647 |
696 BUILTIN(ArrayConcat) { | 648 BUILTIN(ArrayConcat) { |
697 HandleScope scope(isolate); | 649 HandleScope scope(isolate); |
698 | 650 |
699 int n_arguments = args.length(); | 651 int n_arguments = args.length(); |
700 int result_len = 0; | 652 int result_len = 0; |
701 ElementsKind elements_kind = GetInitialFastElementsKind(); | 653 ElementsKind elements_kind = GetInitialFastElementsKind(); |
702 bool has_double = false; | 654 bool has_double = false; |
703 { | 655 { |
704 DisallowHeapAllocation no_gc; | 656 DisallowHeapAllocation no_gc; |
705 Context* native_context = isolate->context()->native_context(); | 657 Context* native_context = isolate->context()->native_context(); |
706 Object* array_proto = native_context->array_function()->prototype(); | 658 Object* array_proto = native_context->array_function()->prototype(); |
707 PrototypeIterator iter(isolate, array_proto, | 659 PrototypeIterator iter(isolate, array_proto, |
708 PrototypeIterator::START_AT_RECEIVER); | 660 PrototypeIterator::START_AT_RECEIVER); |
709 if (!ArrayPrototypeHasNoElements(&iter)) { | 661 if (!PrototypeHasNoElements(&iter)) { |
710 AllowHeapAllocation allow_allocation; | 662 AllowHeapAllocation allow_allocation; |
711 return CallJsIntrinsic(isolate, isolate->array_concat(), args); | 663 return CallJsIntrinsic(isolate, isolate->array_concat(), args); |
712 } | 664 } |
713 | 665 |
714 // Iterate through all the arguments performing checks | 666 // Iterate through all the arguments performing checks |
715 // and calculating total length. | 667 // and calculating total length. |
716 bool is_holey = false; | 668 bool is_holey = false; |
717 for (int i = 0; i < n_arguments; i++) { | 669 for (int i = 0; i < n_arguments; i++) { |
718 Object* arg = args[i]; | 670 Object* arg = args[i]; |
719 PrototypeIterator iter(isolate, arg); | 671 PrototypeIterator iter(isolate, arg); |
(...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1389 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 1341 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
1390 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 1342 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
1391 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 1343 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
1392 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 1344 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
1393 #undef DEFINE_BUILTIN_ACCESSOR_C | 1345 #undef DEFINE_BUILTIN_ACCESSOR_C |
1394 #undef DEFINE_BUILTIN_ACCESSOR_A | 1346 #undef DEFINE_BUILTIN_ACCESSOR_A |
1395 | 1347 |
1396 | 1348 |
1397 } // namespace internal | 1349 } // namespace internal |
1398 } // namespace v8 | 1350 } // namespace v8 |
OLD | NEW |