Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(151)

Side by Side Diff: src/builtins.cc

Issue 1560763002: Add Array support for @@species and subclassing (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Some fixes Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/js/array.js » ('j') | src/js/typedarray.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
451 BUILTIN(ArraySlice) { 451 BUILTIN(ArraySlice) {
452 HandleScope scope(isolate); 452 HandleScope scope(isolate);
453 Handle<Object> receiver = args.receiver(); 453 Handle<Object> receiver = args.receiver();
454 Handle<JSObject> object; 454 Handle<JSObject> object;
455 Handle<FixedArrayBase> elms_obj; 455 Handle<FixedArrayBase> elms_obj;
456 int len = -1; 456 int len = -1;
457 int relative_start = 0; 457 int relative_start = 0;
458 int relative_end = 0; 458 int relative_end = 0;
459 bool is_sloppy_arguments = false; 459 bool is_sloppy_arguments = false;
460 460
461 // TODO(littledan): Look up @@species only once, not once here and
adamk 2016/01/06 00:10:12 Please add a test that exercises this; that'll mak
Dan Ehrenberg 2016/01/07 00:42:57 Done
462 // again in the JS builtin. Pass the species out?
463 Handle<Object> species;
464 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
465 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
466 if (*species != isolate->context()->native_context()->array_function()) {
467 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
468 }
461 if (receiver->IsJSArray()) { 469 if (receiver->IsJSArray()) {
462 DisallowHeapAllocation no_gc; 470 DisallowHeapAllocation no_gc;
463 JSArray* array = JSArray::cast(*receiver); 471 JSArray* array = JSArray::cast(*receiver);
464 if (!array->HasFastElements() || 472 if (!array->HasFastElements() ||
465 !IsJSArrayFastElementMovingAllowed(isolate, array)) { 473 !IsJSArrayFastElementMovingAllowed(isolate, array)) {
466 AllowHeapAllocation allow_allocation; 474 AllowHeapAllocation allow_allocation;
467 return CallJsIntrinsic(isolate, isolate->array_slice(), args); 475 return CallJsIntrinsic(isolate, isolate->array_slice(), args);
468 } 476 }
469 len = Smi::cast(array->length())->value(); 477 len = Smi::cast(array->length())->value();
470 object = Handle<JSObject>::cast(receiver); 478 object = Handle<JSObject>::cast(receiver);
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
536 544
537 BUILTIN(ArraySplice) { 545 BUILTIN(ArraySplice) {
538 HandleScope scope(isolate); 546 HandleScope scope(isolate);
539 Handle<Object> receiver = args.receiver(); 547 Handle<Object> receiver = args.receiver();
540 MaybeHandle<FixedArrayBase> maybe_elms_obj = 548 MaybeHandle<FixedArrayBase> maybe_elms_obj =
541 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3); 549 EnsureJSArrayWithWritableFastElements(isolate, receiver, &args, 3);
542 Handle<FixedArrayBase> elms_obj; 550 Handle<FixedArrayBase> elms_obj;
543 if (!maybe_elms_obj.ToHandle(&elms_obj)) { 551 if (!maybe_elms_obj.ToHandle(&elms_obj)) {
544 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 552 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
545 } 553 }
554 // TODO(littledan): Look up @@species only once, not once here and
adamk 2016/01/06 00:10:11 Same note as the TODO above.
Dan Ehrenberg 2016/01/07 00:42:57 Done
555 // again in the JS builtin. Pass the species out?
556 Handle<Object> species;
557 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
558 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
559 if (*species != isolate->context()->native_context()->array_function()) {
560 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
561 }
546 Handle<JSArray> array = Handle<JSArray>::cast(receiver); 562 Handle<JSArray> array = Handle<JSArray>::cast(receiver);
547 DCHECK(!array->map()->is_observed()); 563 DCHECK(!array->map()->is_observed());
548 564
549 int argument_count = args.length() - 1; 565 int argument_count = args.length() - 1;
550 int relative_start = 0; 566 int relative_start = 0;
551 if (argument_count > 0) { 567 if (argument_count > 0) {
552 DisallowHeapAllocation no_gc; 568 DisallowHeapAllocation no_gc;
553 if (!ClampedToInteger(args[1], &relative_start)) { 569 if (!ClampedToInteger(args[1], &relative_start)) {
554 AllowHeapAllocation allow_allocation; 570 AllowHeapAllocation allow_allocation;
555 return CallJsIntrinsic(isolate, isolate->array_splice(), args); 571 return CallJsIntrinsic(isolate, isolate->array_splice(), args);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
604 * or a dictionary for sparse array. Since Dictionary is a subtype 620 * or a dictionary for sparse array. Since Dictionary is a subtype
605 * of FixedArray, the class can be used by both fast and slow cases. 621 * of FixedArray, the class can be used by both fast and slow cases.
606 * The second parameter of the constructor, fast_elements, specifies 622 * The second parameter of the constructor, fast_elements, specifies
607 * whether the storage is a FixedArray or Dictionary. 623 * whether the storage is a FixedArray or Dictionary.
608 * 624 *
609 * An index limit is used to deal with the situation that a result array 625 * An index limit is used to deal with the situation that a result array
610 * length overflows 32-bit non-negative integer. 626 * length overflows 32-bit non-negative integer.
611 */ 627 */
612 class ArrayConcatVisitor { 628 class ArrayConcatVisitor {
613 public: 629 public:
614 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage, 630 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage,
adamk 2016/01/06 00:10:11 I think you should consider doing the concat stuff
Dan Ehrenberg 2016/01/07 00:42:57 Good idea; this patch doesn't include the concat s
615 bool fast_elements) 631 bool fast_elements)
616 : isolate_(isolate), 632 : isolate_(isolate),
617 storage_(Handle<FixedArray>::cast( 633 storage_(isolate->global_handles()->Create(*storage)),
618 isolate->global_handles()->Create(*storage))),
619 index_offset_(0u), 634 index_offset_(0u),
620 bit_field_(FastElementsField::encode(fast_elements) | 635 bit_field_(FastElementsField::encode(fast_elements) |
621 ExceedsLimitField::encode(false)) {} 636 ExceedsLimitField::encode(false) |
637 IsFixedArrayField::encode(storage->IsFixedArray())) {
638 DCHECK(!(this->fast_elements() && !is_fixed_array()));
639 }
622 640
623 ~ArrayConcatVisitor() { clear_storage(); } 641 ~ArrayConcatVisitor() { clear_storage(); }
624 642
625 void visit(uint32_t i, Handle<Object> elm) { 643 bool visit(uint32_t i, Handle<Object> elm) {
644 uint32_t index = index_offset_ + i;
645
646 if (!is_fixed_array()) {
647 Handle<Object> element_value;
648 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
649 isolate_, element_value,
650 Object::SetElement(isolate_, storage_, index, elm, STRICT), false);
651 return true;
652 }
653
626 if (i >= JSObject::kMaxElementCount - index_offset_) { 654 if (i >= JSObject::kMaxElementCount - index_offset_) {
627 set_exceeds_array_limit(true); 655 set_exceeds_array_limit(true);
628 return; 656 return true;
629 } 657 }
630 uint32_t index = index_offset_ + i;
631 658
632 if (fast_elements()) { 659 if (fast_elements()) {
633 if (index < static_cast<uint32_t>(storage_->length())) { 660 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) {
634 storage_->set(index, *elm); 661 storage_fixed_array()->set(index, *elm);
635 return; 662 return true;
636 } 663 }
637 // Our initial estimate of length was foiled, possibly by 664 // Our initial estimate of length was foiled, possibly by
638 // getters on the arrays increasing the length of later arrays 665 // getters on the arrays increasing the length of later arrays
639 // during iteration. 666 // during iteration.
640 // This shouldn't happen in anything but pathological cases. 667 // This shouldn't happen in anything but pathological cases.
641 SetDictionaryMode(); 668 SetDictionaryMode();
642 // Fall-through to dictionary mode. 669 // Fall-through to dictionary mode.
643 } 670 }
644 DCHECK(!fast_elements()); 671 DCHECK(!fast_elements());
645 Handle<SeededNumberDictionary> dict( 672 Handle<SeededNumberDictionary> dict(
646 SeededNumberDictionary::cast(*storage_)); 673 SeededNumberDictionary::cast(*storage_));
647 // The object holding this backing store has just been allocated, so 674 // The object holding this backing store has just been allocated, so
648 // it cannot yet be used as a prototype. 675 // it cannot yet be used as a prototype.
649 Handle<SeededNumberDictionary> result = 676 Handle<SeededNumberDictionary> result =
650 SeededNumberDictionary::AtNumberPut(dict, index, elm, false); 677 SeededNumberDictionary::AtNumberPut(dict, index, elm, false);
651 if (!result.is_identical_to(dict)) { 678 if (!result.is_identical_to(dict)) {
652 // Dictionary needed to grow. 679 // Dictionary needed to grow.
653 clear_storage(); 680 clear_storage();
654 set_storage(*result); 681 set_storage(*result);
655 } 682 }
683 return true;
656 } 684 }
657 685
658 void increase_index_offset(uint32_t delta) { 686 void increase_index_offset(uint32_t delta) {
659 if (JSObject::kMaxElementCount - index_offset_ < delta) { 687 if (JSObject::kMaxElementCount - index_offset_ < delta) {
660 index_offset_ = JSObject::kMaxElementCount; 688 index_offset_ = JSObject::kMaxElementCount;
661 } else { 689 } else {
662 index_offset_ += delta; 690 index_offset_ += delta;
663 } 691 }
664 // If the initial length estimate was off (see special case in visit()), 692 // If the initial length estimate was off (see special case in visit()),
665 // but the array blowing the limit didn't contain elements beyond the 693 // but the array blowing the limit didn't contain elements beyond the
666 // provided-for index range, go to dictionary mode now. 694 // provided-for index range, go to dictionary mode now.
667 if (fast_elements() && 695 if (fast_elements() &&
668 index_offset_ > 696 index_offset_ >
669 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { 697 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) {
670 SetDictionaryMode(); 698 SetDictionaryMode();
671 } 699 }
672 } 700 }
673 701
674 bool exceeds_array_limit() const { 702 bool exceeds_array_limit() const {
675 return ExceedsLimitField::decode(bit_field_); 703 return ExceedsLimitField::decode(bit_field_);
676 } 704 }
677 705
678 Handle<JSArray> ToArray() { 706 Handle<JSArray> ToArray() {
707 DCHECK(is_fixed_array());
679 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); 708 Handle<JSArray> array = isolate_->factory()->NewJSArray(0);
680 Handle<Object> length = 709 Handle<Object> length =
681 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); 710 isolate_->factory()->NewNumber(static_cast<double>(index_offset_));
682 Handle<Map> map = JSObject::GetElementsTransitionMap( 711 Handle<Map> map = JSObject::GetElementsTransitionMap(
683 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); 712 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS);
684 array->set_map(*map); 713 array->set_map(*map);
685 array->set_length(*length); 714 array->set_length(*length);
686 array->set_elements(*storage_); 715 array->set_elements(*storage_fixed_array());
687 return array; 716 return array;
688 } 717 }
689 718
719 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever
720 // (otherwise)
721 Handle<FixedArray> storage_fixed_array() {
722 DCHECK(is_fixed_array());
723 return Handle<FixedArray>::cast(storage_);
724 }
725 Handle<JSReceiver> storage_jsreceiver() {
726 DCHECK(!is_fixed_array());
727 return Handle<JSReceiver>::cast(storage_);
728 }
729
690 private: 730 private:
691 // Convert storage to dictionary mode. 731 // Convert storage to dictionary mode.
692 void SetDictionaryMode() { 732 void SetDictionaryMode() {
693 DCHECK(fast_elements()); 733 DCHECK(fast_elements() && is_fixed_array());
694 Handle<FixedArray> current_storage(*storage_); 734 Handle<FixedArray> current_storage = storage_fixed_array();
695 Handle<SeededNumberDictionary> slow_storage( 735 Handle<SeededNumberDictionary> slow_storage(
696 SeededNumberDictionary::New(isolate_, current_storage->length())); 736 SeededNumberDictionary::New(isolate_, current_storage->length()));
697 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); 737 uint32_t current_length = static_cast<uint32_t>(current_storage->length());
698 for (uint32_t i = 0; i < current_length; i++) { 738 for (uint32_t i = 0; i < current_length; i++) {
699 HandleScope loop_scope(isolate_); 739 HandleScope loop_scope(isolate_);
700 Handle<Object> element(current_storage->get(i), isolate_); 740 Handle<Object> element(current_storage->get(i), isolate_);
701 if (!element->IsTheHole()) { 741 if (!element->IsTheHole()) {
702 // The object holding this backing store has just been allocated, so 742 // The object holding this backing store has just been allocated, so
703 // it cannot yet be used as a prototype. 743 // it cannot yet be used as a prototype.
704 Handle<SeededNumberDictionary> new_storage = 744 Handle<SeededNumberDictionary> new_storage =
705 SeededNumberDictionary::AtNumberPut(slow_storage, i, element, 745 SeededNumberDictionary::AtNumberPut(slow_storage, i, element,
706 false); 746 false);
707 if (!new_storage.is_identical_to(slow_storage)) { 747 if (!new_storage.is_identical_to(slow_storage)) {
708 slow_storage = loop_scope.CloseAndEscape(new_storage); 748 slow_storage = loop_scope.CloseAndEscape(new_storage);
709 } 749 }
710 } 750 }
711 } 751 }
712 clear_storage(); 752 clear_storage();
713 set_storage(*slow_storage); 753 set_storage(*slow_storage);
714 set_fast_elements(false); 754 set_fast_elements(false);
715 } 755 }
716 756
717 inline void clear_storage() { 757 inline void clear_storage() {
718 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); 758 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location());
719 } 759 }
720 760
721 inline void set_storage(FixedArray* storage) { 761 inline void set_storage(FixedArray* storage) {
722 storage_ = 762 DCHECK(is_fixed_array());
723 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage)); 763 storage_ = isolate_->global_handles()->Create(storage);
724 } 764 }
725 765
726 class FastElementsField : public BitField<bool, 0, 1> {}; 766 class FastElementsField : public BitField<bool, 0, 1> {};
727 class ExceedsLimitField : public BitField<bool, 1, 1> {}; 767 class ExceedsLimitField : public BitField<bool, 1, 1> {};
768 class IsFixedArrayField : public BitField<bool, 2, 1> {};
728 769
729 bool fast_elements() const { return FastElementsField::decode(bit_field_); } 770 bool fast_elements() const { return FastElementsField::decode(bit_field_); }
730 void set_fast_elements(bool fast) { 771 void set_fast_elements(bool fast) {
731 bit_field_ = FastElementsField::update(bit_field_, fast); 772 bit_field_ = FastElementsField::update(bit_field_, fast);
732 } 773 }
733 void set_exceeds_array_limit(bool exceeds) { 774 void set_exceeds_array_limit(bool exceeds) {
734 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds); 775 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds);
735 } 776 }
777 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); }
736 778
737 Isolate* isolate_; 779 Isolate* isolate_;
738 Handle<FixedArray> storage_; // Always a global handle. 780 Handle<Object> storage_; // Always a global handle.
739 // Index after last seen index. Always less than or equal to 781 // Index after last seen index. Always less than or equal to
740 // JSObject::kMaxElementCount. 782 // JSObject::kMaxElementCount.
741 uint32_t index_offset_; 783 uint32_t index_offset_;
742 uint32_t bit_field_; 784 uint32_t bit_field_;
743 }; 785 };
744 786
745 787
746 uint32_t EstimateElementCount(Handle<JSArray> array) { 788 uint32_t EstimateElementCount(Handle<JSArray> array) {
747 uint32_t length = static_cast<uint32_t>(array->length()->Number()); 789 uint32_t length = static_cast<uint32_t>(array->length()->Number());
748 int element_count = 0; 790 int element_count = 0;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
799 // External arrays are always dense. 841 // External arrays are always dense.
800 return length; 842 return length;
801 } 843 }
802 // As an estimate, we assume that the prototype doesn't contain any 844 // As an estimate, we assume that the prototype doesn't contain any
803 // inherited elements. 845 // inherited elements.
804 return element_count; 846 return element_count;
805 } 847 }
806 848
807 849
808 template <class ExternalArrayClass, class ElementType> 850 template <class ExternalArrayClass, class ElementType>
809 void IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver, 851 bool IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver,
810 bool elements_are_ints, 852 bool elements_are_ints,
811 bool elements_are_guaranteed_smis, 853 bool elements_are_guaranteed_smis,
812 ArrayConcatVisitor* visitor) { 854 ArrayConcatVisitor* visitor) {
813 Handle<ExternalArrayClass> array( 855 Handle<ExternalArrayClass> array(
814 ExternalArrayClass::cast(receiver->elements())); 856 ExternalArrayClass::cast(receiver->elements()));
815 uint32_t len = static_cast<uint32_t>(array->length()); 857 uint32_t len = static_cast<uint32_t>(array->length());
816 858
817 DCHECK(visitor != NULL); 859 DCHECK(visitor != NULL);
818 if (elements_are_ints) { 860 if (elements_are_ints) {
819 if (elements_are_guaranteed_smis) { 861 if (elements_are_guaranteed_smis) {
820 for (uint32_t j = 0; j < len; j++) { 862 for (uint32_t j = 0; j < len; j++) {
821 HandleScope loop_scope(isolate); 863 HandleScope loop_scope(isolate);
822 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))), 864 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))),
823 isolate); 865 isolate);
824 visitor->visit(j, e); 866 if (!visitor->visit(j, e)) return false;
825 } 867 }
826 } else { 868 } else {
827 for (uint32_t j = 0; j < len; j++) { 869 for (uint32_t j = 0; j < len; j++) {
828 HandleScope loop_scope(isolate); 870 HandleScope loop_scope(isolate);
829 int64_t val = static_cast<int64_t>(array->get_scalar(j)); 871 int64_t val = static_cast<int64_t>(array->get_scalar(j));
830 if (Smi::IsValid(static_cast<intptr_t>(val))) { 872 if (Smi::IsValid(static_cast<intptr_t>(val))) {
831 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate); 873 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate);
832 visitor->visit(j, e); 874 if (!visitor->visit(j, e)) return false;
833 } else { 875 } else {
834 Handle<Object> e = 876 Handle<Object> e =
835 isolate->factory()->NewNumber(static_cast<ElementType>(val)); 877 isolate->factory()->NewNumber(static_cast<ElementType>(val));
836 visitor->visit(j, e); 878 if (!visitor->visit(j, e)) return false;
837 } 879 }
838 } 880 }
839 } 881 }
840 } else { 882 } else {
841 for (uint32_t j = 0; j < len; j++) { 883 for (uint32_t j = 0; j < len; j++) {
842 HandleScope loop_scope(isolate); 884 HandleScope loop_scope(isolate);
843 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j)); 885 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j));
844 visitor->visit(j, e); 886 if (!visitor->visit(j, e)) return false;
845 } 887 }
846 } 888 }
889 return true;
847 } 890 }
848 891
849 892
850 // Used for sorting indices in a List<uint32_t>. 893 // Used for sorting indices in a List<uint32_t>.
851 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { 894 int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
852 uint32_t a = *ap; 895 uint32_t a = *ap;
853 uint32_t b = *bp; 896 uint32_t b = *bp;
854 return (a == b) ? 0 : (a < b) ? -1 : 1; 897 return (a == b) ? 0 : (a < b) ? -1 : 1;
855 } 898 }
856 899
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 uint32_t length, ArrayConcatVisitor* visitor) { 996 uint32_t length, ArrayConcatVisitor* visitor) {
954 for (uint32_t i = 0; i < length; ++i) { 997 for (uint32_t i = 0; i < length; ++i) {
955 HandleScope loop_scope(isolate); 998 HandleScope loop_scope(isolate);
956 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); 999 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i);
957 if (!maybe.IsJust()) return false; 1000 if (!maybe.IsJust()) return false;
958 if (maybe.FromJust()) { 1001 if (maybe.FromJust()) {
959 Handle<Object> element_value; 1002 Handle<Object> element_value;
960 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, 1003 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value,
961 Object::GetElement(isolate, receiver, i), 1004 Object::GetElement(isolate, receiver, i),
962 false); 1005 false);
963 visitor->visit(i, element_value); 1006 if (!visitor->visit(i, element_value)) return false;
964 } 1007 }
965 } 1008 }
966 visitor->increase_index_offset(length); 1009 visitor->increase_index_offset(length);
967 return true; 1010 return true;
968 } 1011 }
969 1012
970 1013
971 /** 1014 /**
972 * A helper function that visits "array" elements of a JSReceiver in numerical 1015 * A helper function that visits "array" elements of a JSReceiver in numerical
973 * order. 1016 * order.
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 case FAST_HOLEY_ELEMENTS: { 1056 case FAST_HOLEY_ELEMENTS: {
1014 // Run through the elements FixedArray and use HasElement and GetElement 1057 // Run through the elements FixedArray and use HasElement and GetElement
1015 // to check the prototype for missing elements. 1058 // to check the prototype for missing elements.
1016 Handle<FixedArray> elements(FixedArray::cast(array->elements())); 1059 Handle<FixedArray> elements(FixedArray::cast(array->elements()));
1017 int fast_length = static_cast<int>(length); 1060 int fast_length = static_cast<int>(length);
1018 DCHECK(fast_length <= elements->length()); 1061 DCHECK(fast_length <= elements->length());
1019 for (int j = 0; j < fast_length; j++) { 1062 for (int j = 0; j < fast_length; j++) {
1020 HandleScope loop_scope(isolate); 1063 HandleScope loop_scope(isolate);
1021 Handle<Object> element_value(elements->get(j), isolate); 1064 Handle<Object> element_value(elements->get(j), isolate);
1022 if (!element_value->IsTheHole()) { 1065 if (!element_value->IsTheHole()) {
1023 visitor->visit(j, element_value); 1066 if (!visitor->visit(j, element_value)) return false;
1024 } else { 1067 } else {
1025 Maybe<bool> maybe = JSReceiver::HasElement(array, j); 1068 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1026 if (!maybe.IsJust()) return false; 1069 if (!maybe.IsJust()) return false;
1027 if (maybe.FromJust()) { 1070 if (maybe.FromJust()) {
1028 // Call GetElement on array, not its prototype, or getters won't 1071 // Call GetElement on array, not its prototype, or getters won't
1029 // have the correct receiver. 1072 // have the correct receiver.
1030 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1073 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1031 isolate, element_value, Object::GetElement(isolate, array, j), 1074 isolate, element_value, Object::GetElement(isolate, array, j),
1032 false); 1075 false);
1033 visitor->visit(j, element_value); 1076 if (!visitor->visit(j, element_value)) return false;
1034 } 1077 }
1035 } 1078 }
1036 } 1079 }
1037 break; 1080 break;
1038 } 1081 }
1039 case FAST_HOLEY_DOUBLE_ELEMENTS: 1082 case FAST_HOLEY_DOUBLE_ELEMENTS:
1040 case FAST_DOUBLE_ELEMENTS: { 1083 case FAST_DOUBLE_ELEMENTS: {
1041 // Empty array is FixedArray but not FixedDoubleArray. 1084 // Empty array is FixedArray but not FixedDoubleArray.
1042 if (length == 0) break; 1085 if (length == 0) break;
1043 // Run through the elements FixedArray and use HasElement and GetElement 1086 // Run through the elements FixedArray and use HasElement and GetElement
1044 // to check the prototype for missing elements. 1087 // to check the prototype for missing elements.
1045 if (array->elements()->IsFixedArray()) { 1088 if (array->elements()->IsFixedArray()) {
1046 DCHECK(array->elements()->length() == 0); 1089 DCHECK(array->elements()->length() == 0);
1047 break; 1090 break;
1048 } 1091 }
1049 Handle<FixedDoubleArray> elements( 1092 Handle<FixedDoubleArray> elements(
1050 FixedDoubleArray::cast(array->elements())); 1093 FixedDoubleArray::cast(array->elements()));
1051 int fast_length = static_cast<int>(length); 1094 int fast_length = static_cast<int>(length);
1052 DCHECK(fast_length <= elements->length()); 1095 DCHECK(fast_length <= elements->length());
1053 for (int j = 0; j < fast_length; j++) { 1096 for (int j = 0; j < fast_length; j++) {
1054 HandleScope loop_scope(isolate); 1097 HandleScope loop_scope(isolate);
1055 if (!elements->is_the_hole(j)) { 1098 if (!elements->is_the_hole(j)) {
1056 double double_value = elements->get_scalar(j); 1099 double double_value = elements->get_scalar(j);
1057 Handle<Object> element_value = 1100 Handle<Object> element_value =
1058 isolate->factory()->NewNumber(double_value); 1101 isolate->factory()->NewNumber(double_value);
1059 visitor->visit(j, element_value); 1102 if (!visitor->visit(j, element_value)) return false;
1060 } else { 1103 } else {
1061 Maybe<bool> maybe = JSReceiver::HasElement(array, j); 1104 Maybe<bool> maybe = JSReceiver::HasElement(array, j);
1062 if (!maybe.IsJust()) return false; 1105 if (!maybe.IsJust()) return false;
1063 if (maybe.FromJust()) { 1106 if (maybe.FromJust()) {
1064 // Call GetElement on array, not its prototype, or getters won't 1107 // Call GetElement on array, not its prototype, or getters won't
1065 // have the correct receiver. 1108 // have the correct receiver.
1066 Handle<Object> element_value; 1109 Handle<Object> element_value;
1067 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1110 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1068 isolate, element_value, Object::GetElement(isolate, array, j), 1111 isolate, element_value, Object::GetElement(isolate, array, j),
1069 false); 1112 false);
1070 visitor->visit(j, element_value); 1113 if (!visitor->visit(j, element_value)) return false;
1071 } 1114 }
1072 } 1115 }
1073 } 1116 }
1074 break; 1117 break;
1075 } 1118 }
1076 case DICTIONARY_ELEMENTS: { 1119 case DICTIONARY_ELEMENTS: {
1077 // CollectElementIndices() can't be called when there's a JSProxy 1120 // CollectElementIndices() can't be called when there's a JSProxy
1078 // on the prototype chain. 1121 // on the prototype chain.
1079 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); 1122 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd();
1080 iter.Advance()) { 1123 iter.Advance()) {
1081 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 1124 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
1082 return IterateElementsSlow(isolate, array, length, visitor); 1125 return IterateElementsSlow(isolate, array, length, visitor);
1083 } 1126 }
1084 } 1127 }
1085 Handle<SeededNumberDictionary> dict(array->element_dictionary()); 1128 Handle<SeededNumberDictionary> dict(array->element_dictionary());
1086 List<uint32_t> indices(dict->Capacity() / 2); 1129 List<uint32_t> indices(dict->Capacity() / 2);
1087 // Collect all indices in the object and the prototypes less 1130 // Collect all indices in the object and the prototypes less
1088 // than length. This might introduce duplicates in the indices list. 1131 // than length. This might introduce duplicates in the indices list.
1089 CollectElementIndices(array, length, &indices); 1132 CollectElementIndices(array, length, &indices);
1090 indices.Sort(&compareUInt32); 1133 indices.Sort(&compareUInt32);
1091 int j = 0; 1134 int j = 0;
1092 int n = indices.length(); 1135 int n = indices.length();
1093 while (j < n) { 1136 while (j < n) {
1094 HandleScope loop_scope(isolate); 1137 HandleScope loop_scope(isolate);
1095 uint32_t index = indices[j]; 1138 uint32_t index = indices[j];
1096 Handle<Object> element; 1139 Handle<Object> element;
1097 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1140 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1098 isolate, element, Object::GetElement(isolate, array, index), false); 1141 isolate, element, Object::GetElement(isolate, array, index), false);
1099 visitor->visit(index, element); 1142 if (!visitor->visit(index, element)) return false;
1100 // Skip to next different index (i.e., omit duplicates). 1143 // Skip to next different index (i.e., omit duplicates).
1101 do { 1144 do {
1102 j++; 1145 j++;
1103 } while (j < n && indices[j] == index); 1146 } while (j < n && indices[j] == index);
1104 } 1147 }
1105 break; 1148 break;
1106 } 1149 }
1107 case UINT8_CLAMPED_ELEMENTS: { 1150 case UINT8_CLAMPED_ELEMENTS: {
1108 Handle<FixedUint8ClampedArray> pixels( 1151 Handle<FixedUint8ClampedArray> pixels(
1109 FixedUint8ClampedArray::cast(array->elements())); 1152 FixedUint8ClampedArray::cast(array->elements()));
1110 for (uint32_t j = 0; j < length; j++) { 1153 for (uint32_t j = 0; j < length; j++) {
1111 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); 1154 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate);
1112 visitor->visit(j, e); 1155 visitor->visit(j, e);
1113 } 1156 }
1114 break; 1157 break;
1115 } 1158 }
1116 case INT8_ELEMENTS: { 1159 case INT8_ELEMENTS: {
1117 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true, 1160 if (!IterateTypedArrayElements<FixedInt8Array, int8_t>(
1118 true, visitor); 1161 isolate, array, true, true, visitor))
1162 return false;
1119 break; 1163 break;
1120 } 1164 }
1121 case UINT8_ELEMENTS: { 1165 case UINT8_ELEMENTS: {
1122 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true, 1166 if (!IterateTypedArrayElements<FixedUint8Array, uint8_t>(
1123 true, visitor); 1167 isolate, array, true, true, visitor))
1168 return false;
1124 break; 1169 break;
1125 } 1170 }
1126 case INT16_ELEMENTS: { 1171 case INT16_ELEMENTS: {
1127 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true, 1172 if (!IterateTypedArrayElements<FixedInt16Array, int16_t>(
1128 true, visitor); 1173 isolate, array, true, true, visitor))
1174 return false;
1129 break; 1175 break;
1130 } 1176 }
1131 case UINT16_ELEMENTS: { 1177 case UINT16_ELEMENTS: {
1132 IterateTypedArrayElements<FixedUint16Array, uint16_t>( 1178 if (!IterateTypedArrayElements<FixedUint16Array, uint16_t>(
1133 isolate, array, true, true, visitor); 1179 isolate, array, true, true, visitor))
1180 return false;
1134 break; 1181 break;
1135 } 1182 }
1136 case INT32_ELEMENTS: { 1183 case INT32_ELEMENTS: {
1137 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true, 1184 if (!IterateTypedArrayElements<FixedInt32Array, int32_t>(
1138 false, visitor); 1185 isolate, array, true, false, visitor))
1186 return false;
1139 break; 1187 break;
1140 } 1188 }
1141 case UINT32_ELEMENTS: { 1189 case UINT32_ELEMENTS: {
1142 IterateTypedArrayElements<FixedUint32Array, uint32_t>( 1190 if (!IterateTypedArrayElements<FixedUint32Array, uint32_t>(
1143 isolate, array, true, false, visitor); 1191 isolate, array, true, false, visitor))
1192 return false;
1144 break; 1193 break;
1145 } 1194 }
1146 case FLOAT32_ELEMENTS: { 1195 case FLOAT32_ELEMENTS: {
1147 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false, 1196 if (!IterateTypedArrayElements<FixedFloat32Array, float>(
1148 false, visitor); 1197 isolate, array, false, false, visitor))
1198 return false;
1149 break; 1199 break;
1150 } 1200 }
1151 case FLOAT64_ELEMENTS: { 1201 case FLOAT64_ELEMENTS: {
1152 IterateTypedArrayElements<FixedFloat64Array, double>( 1202 if (!IterateTypedArrayElements<FixedFloat64Array, double>(
1153 isolate, array, false, false, visitor); 1203 isolate, array, false, false, visitor))
1204 return false;
1154 break; 1205 break;
1155 } 1206 }
1156 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 1207 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
1157 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { 1208 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
1158 for (uint32_t index = 0; index < length; index++) { 1209 for (uint32_t index = 0; index < length; index++) {
1159 HandleScope loop_scope(isolate); 1210 HandleScope loop_scope(isolate);
1160 Handle<Object> element; 1211 Handle<Object> element;
1161 ASSIGN_RETURN_ON_EXCEPTION_VALUE( 1212 ASSIGN_RETURN_ON_EXCEPTION_VALUE(
1162 isolate, element, Object::GetElement(isolate, array, index), false); 1213 isolate, element, Object::GetElement(isolate, array, index), false);
1163 visitor->visit(index, element); 1214 if (!visitor->visit(index, element)) return false;
1164 } 1215 }
1165 break; 1216 break;
1166 } 1217 }
1167 } 1218 }
1168 visitor->increase_index_offset(length); 1219 visitor->increase_index_offset(length);
1169 return true; 1220 return true;
1170 } 1221 }
1171 1222
1172 1223
1173 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { 1224 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) {
(...skipping 13 matching lines...) Expand all
1187 Handle<Object> value; 1238 Handle<Object> value;
1188 MaybeHandle<Object> maybeValue = 1239 MaybeHandle<Object> maybeValue =
1189 i::Runtime::GetObjectProperty(isolate, obj, key); 1240 i::Runtime::GetObjectProperty(isolate, obj, key);
1190 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); 1241 if (!maybeValue.ToHandle(&value)) return Nothing<bool>();
1191 if (!value->IsUndefined()) return Just(value->BooleanValue()); 1242 if (!value->IsUndefined()) return Just(value->BooleanValue());
1192 } 1243 }
1193 return Object::IsArray(obj); 1244 return Object::IsArray(obj);
1194 } 1245 }
1195 1246
1196 1247
1197 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { 1248 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species,
1249 Isolate* isolate) {
1198 int argument_count = args->length(); 1250 int argument_count = args->length();
1199 1251
1252 bool array_species = *species == isolate->context()->array_function();
1253
1200 // Pass 1: estimate the length and number of elements of the result. 1254 // Pass 1: estimate the length and number of elements of the result.
1201 // The actual length can be larger if any of the arguments have getters 1255 // The actual length can be larger if any of the arguments have getters
1202 // that mutate other arguments (but will otherwise be precise). 1256 // that mutate other arguments (but will otherwise be precise).
1203 // The number of elements is precise if there are no inherited elements. 1257 // The number of elements is precise if there are no inherited elements.
1204 1258
1205 ElementsKind kind = FAST_SMI_ELEMENTS; 1259 ElementsKind kind = FAST_SMI_ELEMENTS;
1206 1260
1207 uint32_t estimate_result_length = 0; 1261 uint32_t estimate_result_length = 0;
1208 uint32_t estimate_nof_elements = 0; 1262 uint32_t estimate_nof_elements = 0;
1209 for (int i = 0; i < argument_count; i++) { 1263 for (int i = 0; i < argument_count; i++) {
(...skipping 30 matching lines...) Expand all
1240 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) { 1294 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) {
1241 estimate_nof_elements = JSObject::kMaxElementCount; 1295 estimate_nof_elements = JSObject::kMaxElementCount;
1242 } else { 1296 } else {
1243 estimate_nof_elements += element_estimate; 1297 estimate_nof_elements += element_estimate;
1244 } 1298 }
1245 } 1299 }
1246 1300
1247 // If estimated number of elements is more than half of length, a 1301 // If estimated number of elements is more than half of length, a
1248 // fixed array (fast case) is more time and space-efficient than a 1302 // fixed array (fast case) is more time and space-efficient than a
1249 // dictionary. 1303 // dictionary.
1250 bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length; 1304 bool fast_case =
1305 array_species && (estimate_nof_elements * 2) >= estimate_result_length;
1251 1306
1252 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) { 1307 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) {
1253 Handle<FixedArrayBase> storage = 1308 Handle<FixedArrayBase> storage =
1254 isolate->factory()->NewFixedDoubleArray(estimate_result_length); 1309 isolate->factory()->NewFixedDoubleArray(estimate_result_length);
1255 int j = 0; 1310 int j = 0;
1256 bool failure = false; 1311 bool failure = false;
1257 if (estimate_result_length > 0) { 1312 if (estimate_result_length > 0) {
1258 Handle<FixedDoubleArray> double_storage = 1313 Handle<FixedDoubleArray> double_storage =
1259 Handle<FixedDoubleArray>::cast(storage); 1314 Handle<FixedDoubleArray>::cast(storage);
1260 for (int i = 0; i < argument_count; i++) { 1315 for (int i = 0; i < argument_count; i++) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1324 Handle<Map> map; 1379 Handle<Map> map;
1325 map = JSObject::GetElementsTransitionMap(array, kind); 1380 map = JSObject::GetElementsTransitionMap(array, kind);
1326 array->set_map(*map); 1381 array->set_map(*map);
1327 array->set_length(length); 1382 array->set_length(length);
1328 array->set_elements(*storage); 1383 array->set_elements(*storage);
1329 return *array; 1384 return *array;
1330 } 1385 }
1331 // In case of failure, fall through. 1386 // In case of failure, fall through.
1332 } 1387 }
1333 1388
1334 Handle<FixedArray> storage; 1389 Handle<Object> storage;
1335 if (fast_case) { 1390 if (fast_case) {
1336 // The backing storage array must have non-existing elements to preserve 1391 // The backing storage array must have non-existing elements to preserve
1337 // holes across concat operations. 1392 // holes across concat operations.
1338 storage = 1393 storage =
1339 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); 1394 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length);
1340 } else { 1395 } else if (array_species) {
1341 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate 1396 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate
1342 uint32_t at_least_space_for = 1397 uint32_t at_least_space_for =
1343 estimate_nof_elements + (estimate_nof_elements >> 2); 1398 estimate_nof_elements + (estimate_nof_elements >> 2);
1344 storage = Handle<FixedArray>::cast( 1399 storage = SeededNumberDictionary::New(isolate, at_least_space_for);
1345 SeededNumberDictionary::New(isolate, at_least_space_for)); 1400 } else {
1401 DCHECK(species->IsConstructor());
1402 Handle<Object> length(Smi::FromInt(0), isolate);
1403 Handle<Object> storage_object;
1404 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1405 isolate, storage_object,
1406 Execution::New(isolate, species, species, 1, &length));
1407 storage = storage_object;
1346 } 1408 }
1347 1409
1348 ArrayConcatVisitor visitor(isolate, storage, fast_case); 1410 ArrayConcatVisitor visitor(isolate, storage, fast_case);
1349 1411
1350 for (int i = 0; i < argument_count; i++) { 1412 for (int i = 0; i < argument_count; i++) {
1351 Handle<Object> obj((*args)[i], isolate); 1413 Handle<Object> obj((*args)[i], isolate);
1352 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); 1414 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj);
1353 MAYBE_RETURN(spreadable, isolate->heap()->exception()); 1415 MAYBE_RETURN(spreadable, isolate->heap()->exception());
1354 if (spreadable.FromJust()) { 1416 if (spreadable.FromJust()) {
1355 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); 1417 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj);
1356 if (!IterateElements(isolate, object, &visitor)) { 1418 if (!IterateElements(isolate, object, &visitor)) {
1357 return isolate->heap()->exception(); 1419 return isolate->heap()->exception();
1358 } 1420 }
1359 } else { 1421 } else {
1360 visitor.visit(0, obj); 1422 visitor.visit(0, obj);
1361 visitor.increase_index_offset(1); 1423 visitor.increase_index_offset(1);
1362 } 1424 }
1363 } 1425 }
1364 1426
1365 if (visitor.exceeds_array_limit()) { 1427 if (visitor.exceeds_array_limit()) {
1366 THROW_NEW_ERROR_RETURN_FAILURE( 1428 THROW_NEW_ERROR_RETURN_FAILURE(
1367 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); 1429 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength));
1368 } 1430 }
1369 return *visitor.ToArray(); 1431
1432 if (array_species) {
1433 return *visitor.ToArray();
1434 } else {
1435 return *visitor.storage_jsreceiver();
1436 }
1370 } 1437 }
1371 1438
1372 1439
1373 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { 1440 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) {
1374 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { 1441 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) {
1375 return MaybeHandle<JSArray>(); 1442 return MaybeHandle<JSArray>();
1376 } 1443 }
1377 int n_arguments = args->length(); 1444 int n_arguments = args->length();
1378 int result_len = 0; 1445 int result_len = 0;
1379 { 1446 {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1420 if (!Object::ToObject(isolate, handle(args[0], isolate)) 1487 if (!Object::ToObject(isolate, handle(args[0], isolate))
1421 .ToHandle(&receiver)) { 1488 .ToHandle(&receiver)) {
1422 THROW_NEW_ERROR_RETURN_FAILURE( 1489 THROW_NEW_ERROR_RETURN_FAILURE(
1423 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, 1490 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined,
1424 isolate->factory()->NewStringFromAsciiChecked( 1491 isolate->factory()->NewStringFromAsciiChecked(
1425 "Array.prototype.concat"))); 1492 "Array.prototype.concat")));
1426 } 1493 }
1427 args[0] = *receiver; 1494 args[0] = *receiver;
1428 1495
1429 Handle<JSArray> result_array; 1496 Handle<JSArray> result_array;
1430 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { 1497
1431 return *result_array; 1498 // Reading @@species happens before anything else with a side effect, so
1499 // we can do it here to determine whether to take the fast path.
1500 Handle<Object> species;
1501 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1502 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver));
1503 if (*species == isolate->context()->native_context()->array_function()) {
1504 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) {
1505 return *result_array;
1506 }
1507 if (isolate->has_pending_exception()) return isolate->heap()->exception();
1432 } 1508 }
1433 if (isolate->has_pending_exception()) return isolate->heap()->exception(); 1509 return Slow_ArrayConcat(&args, species, isolate);
1434 return Slow_ArrayConcat(&args, isolate);
1435 } 1510 }
1436 1511
1437 1512
1438 // ES6 22.1.2.2 Array.isArray 1513 // ES6 22.1.2.2 Array.isArray
1439 BUILTIN(ArrayIsArray) { 1514 BUILTIN(ArrayIsArray) {
1440 HandleScope scope(isolate); 1515 HandleScope scope(isolate);
1441 DCHECK_EQ(2, args.length()); 1516 DCHECK_EQ(2, args.length());
1442 Handle<Object> object = args.at<Object>(1); 1517 Handle<Object> object = args.at<Object>(1);
1443 Maybe<bool> result = Object::IsArray(object); 1518 Maybe<bool> result = Object::IsArray(object);
1444 MAYBE_RETURN(result, isolate->heap()->exception()); 1519 MAYBE_RETURN(result, isolate->heap()->exception());
(...skipping 1848 matching lines...) Expand 10 before | Expand all | Expand 10 after
3293 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) 3368 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C)
3294 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) 3369 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A)
3295 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) 3370 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H)
3296 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) 3371 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A)
3297 #undef DEFINE_BUILTIN_ACCESSOR_C 3372 #undef DEFINE_BUILTIN_ACCESSOR_C
3298 #undef DEFINE_BUILTIN_ACCESSOR_A 3373 #undef DEFINE_BUILTIN_ACCESSOR_A
3299 3374
3300 3375
3301 } // namespace internal 3376 } // namespace internal
3302 } // namespace v8 3377 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/js/array.js » ('j') | src/js/typedarray.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698