| 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 609 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 * or a dictionary for sparse array. Since Dictionary is a subtype | 620 * or a dictionary for sparse array. Since Dictionary is a subtype |
| 621 * 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. |
| 622 * The second parameter of the constructor, fast_elements, specifies | 622 * The second parameter of the constructor, fast_elements, specifies |
| 623 * whether the storage is a FixedArray or Dictionary. | 623 * whether the storage is a FixedArray or Dictionary. |
| 624 * | 624 * |
| 625 * 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 |
| 626 * length overflows 32-bit non-negative integer. | 626 * length overflows 32-bit non-negative integer. |
| 627 */ | 627 */ |
| 628 class ArrayConcatVisitor { | 628 class ArrayConcatVisitor { |
| 629 public: | 629 public: |
| 630 ArrayConcatVisitor(Isolate* isolate, Handle<FixedArray> storage, | 630 ArrayConcatVisitor(Isolate* isolate, Handle<Object> storage, |
| 631 bool fast_elements) | 631 bool fast_elements) |
| 632 : isolate_(isolate), | 632 : isolate_(isolate), |
| 633 storage_(Handle<FixedArray>::cast( | 633 storage_(isolate->global_handles()->Create(*storage)), |
| 634 isolate->global_handles()->Create(*storage))), | |
| 635 index_offset_(0u), | 634 index_offset_(0u), |
| 636 bit_field_(FastElementsField::encode(fast_elements) | | 635 bit_field_(FastElementsField::encode(fast_elements) | |
| 637 ExceedsLimitField::encode(false)) {} | 636 ExceedsLimitField::encode(false) | |
| 637 IsFixedArrayField::encode(storage->IsFixedArray())) { |
| 638 DCHECK(!(this->fast_elements() && !is_fixed_array())); |
| 639 } |
| 638 | 640 |
| 639 ~ArrayConcatVisitor() { clear_storage(); } | 641 ~ArrayConcatVisitor() { clear_storage(); } |
| 640 | 642 |
| 641 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 |
| 642 if (i >= JSObject::kMaxElementCount - index_offset_) { | 654 if (i >= JSObject::kMaxElementCount - index_offset_) { |
| 643 set_exceeds_array_limit(true); | 655 set_exceeds_array_limit(true); |
| 644 return; | 656 // Exception hasn't been thrown at this point. Return true to |
| 657 // break out, and caller will throw. !visit would imply that |
| 658 // there is already a pending exception. |
| 659 return true; |
| 645 } | 660 } |
| 646 uint32_t index = index_offset_ + i; | |
| 647 | 661 |
| 648 if (fast_elements()) { | 662 if (fast_elements()) { |
| 649 if (index < static_cast<uint32_t>(storage_->length())) { | 663 if (index < static_cast<uint32_t>(storage_fixed_array()->length())) { |
| 650 storage_->set(index, *elm); | 664 storage_fixed_array()->set(index, *elm); |
| 651 return; | 665 return true; |
| 652 } | 666 } |
| 653 // Our initial estimate of length was foiled, possibly by | 667 // Our initial estimate of length was foiled, possibly by |
| 654 // getters on the arrays increasing the length of later arrays | 668 // getters on the arrays increasing the length of later arrays |
| 655 // during iteration. | 669 // during iteration. |
| 656 // This shouldn't happen in anything but pathological cases. | 670 // This shouldn't happen in anything but pathological cases. |
| 657 SetDictionaryMode(); | 671 SetDictionaryMode(); |
| 658 // Fall-through to dictionary mode. | 672 // Fall-through to dictionary mode. |
| 659 } | 673 } |
| 660 DCHECK(!fast_elements()); | 674 DCHECK(!fast_elements()); |
| 661 Handle<SeededNumberDictionary> dict( | 675 Handle<SeededNumberDictionary> dict( |
| 662 SeededNumberDictionary::cast(*storage_)); | 676 SeededNumberDictionary::cast(*storage_)); |
| 663 // The object holding this backing store has just been allocated, so | 677 // The object holding this backing store has just been allocated, so |
| 664 // it cannot yet be used as a prototype. | 678 // it cannot yet be used as a prototype. |
| 665 Handle<SeededNumberDictionary> result = | 679 Handle<SeededNumberDictionary> result = |
| 666 SeededNumberDictionary::AtNumberPut(dict, index, elm, false); | 680 SeededNumberDictionary::AtNumberPut(dict, index, elm, false); |
| 667 if (!result.is_identical_to(dict)) { | 681 if (!result.is_identical_to(dict)) { |
| 668 // Dictionary needed to grow. | 682 // Dictionary needed to grow. |
| 669 clear_storage(); | 683 clear_storage(); |
| 670 set_storage(*result); | 684 set_storage(*result); |
| 671 } | 685 } |
| 686 return true; |
| 672 } | 687 } |
| 673 | 688 |
| 674 void increase_index_offset(uint32_t delta) { | 689 void increase_index_offset(uint32_t delta) { |
| 675 if (JSObject::kMaxElementCount - index_offset_ < delta) { | 690 if (JSObject::kMaxElementCount - index_offset_ < delta) { |
| 676 index_offset_ = JSObject::kMaxElementCount; | 691 index_offset_ = JSObject::kMaxElementCount; |
| 677 } else { | 692 } else { |
| 678 index_offset_ += delta; | 693 index_offset_ += delta; |
| 679 } | 694 } |
| 680 // If the initial length estimate was off (see special case in visit()), | 695 // If the initial length estimate was off (see special case in visit()), |
| 681 // but the array blowing the limit didn't contain elements beyond the | 696 // but the array blowing the limit didn't contain elements beyond the |
| 682 // provided-for index range, go to dictionary mode now. | 697 // provided-for index range, go to dictionary mode now. |
| 683 if (fast_elements() && | 698 if (fast_elements() && |
| 684 index_offset_ > | 699 index_offset_ > |
| 685 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { | 700 static_cast<uint32_t>(FixedArrayBase::cast(*storage_)->length())) { |
| 686 SetDictionaryMode(); | 701 SetDictionaryMode(); |
| 687 } | 702 } |
| 688 } | 703 } |
| 689 | 704 |
| 690 bool exceeds_array_limit() const { | 705 bool exceeds_array_limit() const { |
| 691 return ExceedsLimitField::decode(bit_field_); | 706 return ExceedsLimitField::decode(bit_field_); |
| 692 } | 707 } |
| 693 | 708 |
| 694 Handle<JSArray> ToArray() { | 709 Handle<JSArray> ToArray() { |
| 710 DCHECK(is_fixed_array()); |
| 695 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); | 711 Handle<JSArray> array = isolate_->factory()->NewJSArray(0); |
| 696 Handle<Object> length = | 712 Handle<Object> length = |
| 697 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); | 713 isolate_->factory()->NewNumber(static_cast<double>(index_offset_)); |
| 698 Handle<Map> map = JSObject::GetElementsTransitionMap( | 714 Handle<Map> map = JSObject::GetElementsTransitionMap( |
| 699 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); | 715 array, fast_elements() ? FAST_HOLEY_ELEMENTS : DICTIONARY_ELEMENTS); |
| 700 array->set_map(*map); | 716 array->set_map(*map); |
| 701 array->set_length(*length); | 717 array->set_length(*length); |
| 702 array->set_elements(*storage_); | 718 array->set_elements(*storage_fixed_array()); |
| 703 return array; | 719 return array; |
| 704 } | 720 } |
| 705 | 721 |
| 722 // Storage is either a FixedArray (if is_fixed_array()) or a JSReciever |
| 723 // (otherwise) |
| 724 Handle<FixedArray> storage_fixed_array() { |
| 725 DCHECK(is_fixed_array()); |
| 726 return Handle<FixedArray>::cast(storage_); |
| 727 } |
| 728 Handle<JSReceiver> storage_jsreceiver() { |
| 729 DCHECK(!is_fixed_array()); |
| 730 return Handle<JSReceiver>::cast(storage_); |
| 731 } |
| 732 |
| 706 private: | 733 private: |
| 707 // Convert storage to dictionary mode. | 734 // Convert storage to dictionary mode. |
| 708 void SetDictionaryMode() { | 735 void SetDictionaryMode() { |
| 709 DCHECK(fast_elements()); | 736 DCHECK(fast_elements() && is_fixed_array()); |
| 710 Handle<FixedArray> current_storage(*storage_); | 737 Handle<FixedArray> current_storage = storage_fixed_array(); |
| 711 Handle<SeededNumberDictionary> slow_storage( | 738 Handle<SeededNumberDictionary> slow_storage( |
| 712 SeededNumberDictionary::New(isolate_, current_storage->length())); | 739 SeededNumberDictionary::New(isolate_, current_storage->length())); |
| 713 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); | 740 uint32_t current_length = static_cast<uint32_t>(current_storage->length()); |
| 714 for (uint32_t i = 0; i < current_length; i++) { | 741 for (uint32_t i = 0; i < current_length; i++) { |
| 715 HandleScope loop_scope(isolate_); | 742 HandleScope loop_scope(isolate_); |
| 716 Handle<Object> element(current_storage->get(i), isolate_); | 743 Handle<Object> element(current_storage->get(i), isolate_); |
| 717 if (!element->IsTheHole()) { | 744 if (!element->IsTheHole()) { |
| 718 // The object holding this backing store has just been allocated, so | 745 // The object holding this backing store has just been allocated, so |
| 719 // it cannot yet be used as a prototype. | 746 // it cannot yet be used as a prototype. |
| 720 Handle<SeededNumberDictionary> new_storage = | 747 Handle<SeededNumberDictionary> new_storage = |
| 721 SeededNumberDictionary::AtNumberPut(slow_storage, i, element, | 748 SeededNumberDictionary::AtNumberPut(slow_storage, i, element, |
| 722 false); | 749 false); |
| 723 if (!new_storage.is_identical_to(slow_storage)) { | 750 if (!new_storage.is_identical_to(slow_storage)) { |
| 724 slow_storage = loop_scope.CloseAndEscape(new_storage); | 751 slow_storage = loop_scope.CloseAndEscape(new_storage); |
| 725 } | 752 } |
| 726 } | 753 } |
| 727 } | 754 } |
| 728 clear_storage(); | 755 clear_storage(); |
| 729 set_storage(*slow_storage); | 756 set_storage(*slow_storage); |
| 730 set_fast_elements(false); | 757 set_fast_elements(false); |
| 731 } | 758 } |
| 732 | 759 |
| 733 inline void clear_storage() { | 760 inline void clear_storage() { |
| 734 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); | 761 GlobalHandles::Destroy(Handle<Object>::cast(storage_).location()); |
| 735 } | 762 } |
| 736 | 763 |
| 737 inline void set_storage(FixedArray* storage) { | 764 inline void set_storage(FixedArray* storage) { |
| 738 storage_ = | 765 DCHECK(is_fixed_array()); |
| 739 Handle<FixedArray>::cast(isolate_->global_handles()->Create(storage)); | 766 storage_ = isolate_->global_handles()->Create(storage); |
| 740 } | 767 } |
| 741 | 768 |
| 742 class FastElementsField : public BitField<bool, 0, 1> {}; | 769 class FastElementsField : public BitField<bool, 0, 1> {}; |
| 743 class ExceedsLimitField : public BitField<bool, 1, 1> {}; | 770 class ExceedsLimitField : public BitField<bool, 1, 1> {}; |
| 771 class IsFixedArrayField : public BitField<bool, 2, 1> {}; |
| 744 | 772 |
| 745 bool fast_elements() const { return FastElementsField::decode(bit_field_); } | 773 bool fast_elements() const { return FastElementsField::decode(bit_field_); } |
| 746 void set_fast_elements(bool fast) { | 774 void set_fast_elements(bool fast) { |
| 747 bit_field_ = FastElementsField::update(bit_field_, fast); | 775 bit_field_ = FastElementsField::update(bit_field_, fast); |
| 748 } | 776 } |
| 749 void set_exceeds_array_limit(bool exceeds) { | 777 void set_exceeds_array_limit(bool exceeds) { |
| 750 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds); | 778 bit_field_ = ExceedsLimitField::update(bit_field_, exceeds); |
| 751 } | 779 } |
| 780 bool is_fixed_array() const { return IsFixedArrayField::decode(bit_field_); } |
| 752 | 781 |
| 753 Isolate* isolate_; | 782 Isolate* isolate_; |
| 754 Handle<FixedArray> storage_; // Always a global handle. | 783 Handle<Object> storage_; // Always a global handle. |
| 755 // Index after last seen index. Always less than or equal to | 784 // Index after last seen index. Always less than or equal to |
| 756 // JSObject::kMaxElementCount. | 785 // JSObject::kMaxElementCount. |
| 757 uint32_t index_offset_; | 786 uint32_t index_offset_; |
| 758 uint32_t bit_field_; | 787 uint32_t bit_field_; |
| 759 }; | 788 }; |
| 760 | 789 |
| 761 | 790 |
| 762 uint32_t EstimateElementCount(Handle<JSArray> array) { | 791 uint32_t EstimateElementCount(Handle<JSArray> array) { |
| 763 uint32_t length = static_cast<uint32_t>(array->length()->Number()); | 792 uint32_t length = static_cast<uint32_t>(array->length()->Number()); |
| 764 int element_count = 0; | 793 int element_count = 0; |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 815 // External arrays are always dense. | 844 // External arrays are always dense. |
| 816 return length; | 845 return length; |
| 817 } | 846 } |
| 818 // As an estimate, we assume that the prototype doesn't contain any | 847 // As an estimate, we assume that the prototype doesn't contain any |
| 819 // inherited elements. | 848 // inherited elements. |
| 820 return element_count; | 849 return element_count; |
| 821 } | 850 } |
| 822 | 851 |
| 823 | 852 |
| 824 template <class ExternalArrayClass, class ElementType> | 853 template <class ExternalArrayClass, class ElementType> |
| 825 void IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver, | 854 bool IterateTypedArrayElements(Isolate* isolate, Handle<JSObject> receiver, |
| 826 bool elements_are_ints, | 855 bool elements_are_ints, |
| 827 bool elements_are_guaranteed_smis, | 856 bool elements_are_guaranteed_smis, |
| 828 ArrayConcatVisitor* visitor) { | 857 ArrayConcatVisitor* visitor) { |
| 829 Handle<ExternalArrayClass> array( | 858 Handle<ExternalArrayClass> array( |
| 830 ExternalArrayClass::cast(receiver->elements())); | 859 ExternalArrayClass::cast(receiver->elements())); |
| 831 uint32_t len = static_cast<uint32_t>(array->length()); | 860 uint32_t len = static_cast<uint32_t>(array->length()); |
| 832 | 861 |
| 833 DCHECK(visitor != NULL); | 862 DCHECK(visitor != NULL); |
| 834 if (elements_are_ints) { | 863 if (elements_are_ints) { |
| 835 if (elements_are_guaranteed_smis) { | 864 if (elements_are_guaranteed_smis) { |
| 836 for (uint32_t j = 0; j < len; j++) { | 865 for (uint32_t j = 0; j < len; j++) { |
| 837 HandleScope loop_scope(isolate); | 866 HandleScope loop_scope(isolate); |
| 838 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))), | 867 Handle<Smi> e(Smi::FromInt(static_cast<int>(array->get_scalar(j))), |
| 839 isolate); | 868 isolate); |
| 840 visitor->visit(j, e); | 869 if (!visitor->visit(j, e)) return false; |
| 841 } | 870 } |
| 842 } else { | 871 } else { |
| 843 for (uint32_t j = 0; j < len; j++) { | 872 for (uint32_t j = 0; j < len; j++) { |
| 844 HandleScope loop_scope(isolate); | 873 HandleScope loop_scope(isolate); |
| 845 int64_t val = static_cast<int64_t>(array->get_scalar(j)); | 874 int64_t val = static_cast<int64_t>(array->get_scalar(j)); |
| 846 if (Smi::IsValid(static_cast<intptr_t>(val))) { | 875 if (Smi::IsValid(static_cast<intptr_t>(val))) { |
| 847 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate); | 876 Handle<Smi> e(Smi::FromInt(static_cast<int>(val)), isolate); |
| 848 visitor->visit(j, e); | 877 if (!visitor->visit(j, e)) return false; |
| 849 } else { | 878 } else { |
| 850 Handle<Object> e = | 879 Handle<Object> e = |
| 851 isolate->factory()->NewNumber(static_cast<ElementType>(val)); | 880 isolate->factory()->NewNumber(static_cast<ElementType>(val)); |
| 852 visitor->visit(j, e); | 881 if (!visitor->visit(j, e)) return false; |
| 853 } | 882 } |
| 854 } | 883 } |
| 855 } | 884 } |
| 856 } else { | 885 } else { |
| 857 for (uint32_t j = 0; j < len; j++) { | 886 for (uint32_t j = 0; j < len; j++) { |
| 858 HandleScope loop_scope(isolate); | 887 HandleScope loop_scope(isolate); |
| 859 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j)); | 888 Handle<Object> e = isolate->factory()->NewNumber(array->get_scalar(j)); |
| 860 visitor->visit(j, e); | 889 if (!visitor->visit(j, e)) return false; |
| 861 } | 890 } |
| 862 } | 891 } |
| 892 return true; |
| 863 } | 893 } |
| 864 | 894 |
| 865 | 895 |
| 866 // Used for sorting indices in a List<uint32_t>. | 896 // Used for sorting indices in a List<uint32_t>. |
| 867 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { | 897 int compareUInt32(const uint32_t* ap, const uint32_t* bp) { |
| 868 uint32_t a = *ap; | 898 uint32_t a = *ap; |
| 869 uint32_t b = *bp; | 899 uint32_t b = *bp; |
| 870 return (a == b) ? 0 : (a < b) ? -1 : 1; | 900 return (a == b) ? 0 : (a < b) ? -1 : 1; |
| 871 } | 901 } |
| 872 | 902 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 969 uint32_t length, ArrayConcatVisitor* visitor) { | 999 uint32_t length, ArrayConcatVisitor* visitor) { |
| 970 for (uint32_t i = 0; i < length; ++i) { | 1000 for (uint32_t i = 0; i < length; ++i) { |
| 971 HandleScope loop_scope(isolate); | 1001 HandleScope loop_scope(isolate); |
| 972 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); | 1002 Maybe<bool> maybe = JSReceiver::HasElement(receiver, i); |
| 973 if (!maybe.IsJust()) return false; | 1003 if (!maybe.IsJust()) return false; |
| 974 if (maybe.FromJust()) { | 1004 if (maybe.FromJust()) { |
| 975 Handle<Object> element_value; | 1005 Handle<Object> element_value; |
| 976 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, | 1006 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, element_value, |
| 977 Object::GetElement(isolate, receiver, i), | 1007 Object::GetElement(isolate, receiver, i), |
| 978 false); | 1008 false); |
| 979 visitor->visit(i, element_value); | 1009 if (!visitor->visit(i, element_value)) return false; |
| 980 } | 1010 } |
| 981 } | 1011 } |
| 982 visitor->increase_index_offset(length); | 1012 visitor->increase_index_offset(length); |
| 983 return true; | 1013 return true; |
| 984 } | 1014 } |
| 985 | 1015 |
| 986 | 1016 |
| 987 /** | 1017 /** |
| 988 * A helper function that visits "array" elements of a JSReceiver in numerical | 1018 * A helper function that visits "array" elements of a JSReceiver in numerical |
| 989 * order. | 1019 * order. |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 case FAST_HOLEY_ELEMENTS: { | 1059 case FAST_HOLEY_ELEMENTS: { |
| 1030 // Run through the elements FixedArray and use HasElement and GetElement | 1060 // Run through the elements FixedArray and use HasElement and GetElement |
| 1031 // to check the prototype for missing elements. | 1061 // to check the prototype for missing elements. |
| 1032 Handle<FixedArray> elements(FixedArray::cast(array->elements())); | 1062 Handle<FixedArray> elements(FixedArray::cast(array->elements())); |
| 1033 int fast_length = static_cast<int>(length); | 1063 int fast_length = static_cast<int>(length); |
| 1034 DCHECK(fast_length <= elements->length()); | 1064 DCHECK(fast_length <= elements->length()); |
| 1035 for (int j = 0; j < fast_length; j++) { | 1065 for (int j = 0; j < fast_length; j++) { |
| 1036 HandleScope loop_scope(isolate); | 1066 HandleScope loop_scope(isolate); |
| 1037 Handle<Object> element_value(elements->get(j), isolate); | 1067 Handle<Object> element_value(elements->get(j), isolate); |
| 1038 if (!element_value->IsTheHole()) { | 1068 if (!element_value->IsTheHole()) { |
| 1039 visitor->visit(j, element_value); | 1069 if (!visitor->visit(j, element_value)) return false; |
| 1040 } else { | 1070 } else { |
| 1041 Maybe<bool> maybe = JSReceiver::HasElement(array, j); | 1071 Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
| 1042 if (!maybe.IsJust()) return false; | 1072 if (!maybe.IsJust()) return false; |
| 1043 if (maybe.FromJust()) { | 1073 if (maybe.FromJust()) { |
| 1044 // Call GetElement on array, not its prototype, or getters won't | 1074 // Call GetElement on array, not its prototype, or getters won't |
| 1045 // have the correct receiver. | 1075 // have the correct receiver. |
| 1046 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1076 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1047 isolate, element_value, Object::GetElement(isolate, array, j), | 1077 isolate, element_value, Object::GetElement(isolate, array, j), |
| 1048 false); | 1078 false); |
| 1049 visitor->visit(j, element_value); | 1079 if (!visitor->visit(j, element_value)) return false; |
| 1050 } | 1080 } |
| 1051 } | 1081 } |
| 1052 } | 1082 } |
| 1053 break; | 1083 break; |
| 1054 } | 1084 } |
| 1055 case FAST_HOLEY_DOUBLE_ELEMENTS: | 1085 case FAST_HOLEY_DOUBLE_ELEMENTS: |
| 1056 case FAST_DOUBLE_ELEMENTS: { | 1086 case FAST_DOUBLE_ELEMENTS: { |
| 1057 // Empty array is FixedArray but not FixedDoubleArray. | 1087 // Empty array is FixedArray but not FixedDoubleArray. |
| 1058 if (length == 0) break; | 1088 if (length == 0) break; |
| 1059 // Run through the elements FixedArray and use HasElement and GetElement | 1089 // Run through the elements FixedArray and use HasElement and GetElement |
| 1060 // to check the prototype for missing elements. | 1090 // to check the prototype for missing elements. |
| 1061 if (array->elements()->IsFixedArray()) { | 1091 if (array->elements()->IsFixedArray()) { |
| 1062 DCHECK(array->elements()->length() == 0); | 1092 DCHECK(array->elements()->length() == 0); |
| 1063 break; | 1093 break; |
| 1064 } | 1094 } |
| 1065 Handle<FixedDoubleArray> elements( | 1095 Handle<FixedDoubleArray> elements( |
| 1066 FixedDoubleArray::cast(array->elements())); | 1096 FixedDoubleArray::cast(array->elements())); |
| 1067 int fast_length = static_cast<int>(length); | 1097 int fast_length = static_cast<int>(length); |
| 1068 DCHECK(fast_length <= elements->length()); | 1098 DCHECK(fast_length <= elements->length()); |
| 1069 for (int j = 0; j < fast_length; j++) { | 1099 for (int j = 0; j < fast_length; j++) { |
| 1070 HandleScope loop_scope(isolate); | 1100 HandleScope loop_scope(isolate); |
| 1071 if (!elements->is_the_hole(j)) { | 1101 if (!elements->is_the_hole(j)) { |
| 1072 double double_value = elements->get_scalar(j); | 1102 double double_value = elements->get_scalar(j); |
| 1073 Handle<Object> element_value = | 1103 Handle<Object> element_value = |
| 1074 isolate->factory()->NewNumber(double_value); | 1104 isolate->factory()->NewNumber(double_value); |
| 1075 visitor->visit(j, element_value); | 1105 if (!visitor->visit(j, element_value)) return false; |
| 1076 } else { | 1106 } else { |
| 1077 Maybe<bool> maybe = JSReceiver::HasElement(array, j); | 1107 Maybe<bool> maybe = JSReceiver::HasElement(array, j); |
| 1078 if (!maybe.IsJust()) return false; | 1108 if (!maybe.IsJust()) return false; |
| 1079 if (maybe.FromJust()) { | 1109 if (maybe.FromJust()) { |
| 1080 // Call GetElement on array, not its prototype, or getters won't | 1110 // Call GetElement on array, not its prototype, or getters won't |
| 1081 // have the correct receiver. | 1111 // have the correct receiver. |
| 1082 Handle<Object> element_value; | 1112 Handle<Object> element_value; |
| 1083 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1113 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1084 isolate, element_value, Object::GetElement(isolate, array, j), | 1114 isolate, element_value, Object::GetElement(isolate, array, j), |
| 1085 false); | 1115 false); |
| 1086 visitor->visit(j, element_value); | 1116 if (!visitor->visit(j, element_value)) return false; |
| 1087 } | 1117 } |
| 1088 } | 1118 } |
| 1089 } | 1119 } |
| 1090 break; | 1120 break; |
| 1091 } | 1121 } |
| 1092 case DICTIONARY_ELEMENTS: { | 1122 case DICTIONARY_ELEMENTS: { |
| 1093 // CollectElementIndices() can't be called when there's a JSProxy | 1123 // CollectElementIndices() can't be called when there's a JSProxy |
| 1094 // on the prototype chain. | 1124 // on the prototype chain. |
| 1095 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); | 1125 for (PrototypeIterator iter(isolate, array); !iter.IsAtEnd(); |
| 1096 iter.Advance()) { | 1126 iter.Advance()) { |
| 1097 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { | 1127 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { |
| 1098 return IterateElementsSlow(isolate, array, length, visitor); | 1128 return IterateElementsSlow(isolate, array, length, visitor); |
| 1099 } | 1129 } |
| 1100 } | 1130 } |
| 1101 Handle<SeededNumberDictionary> dict(array->element_dictionary()); | 1131 Handle<SeededNumberDictionary> dict(array->element_dictionary()); |
| 1102 List<uint32_t> indices(dict->Capacity() / 2); | 1132 List<uint32_t> indices(dict->Capacity() / 2); |
| 1103 // Collect all indices in the object and the prototypes less | 1133 // Collect all indices in the object and the prototypes less |
| 1104 // than length. This might introduce duplicates in the indices list. | 1134 // than length. This might introduce duplicates in the indices list. |
| 1105 CollectElementIndices(array, length, &indices); | 1135 CollectElementIndices(array, length, &indices); |
| 1106 indices.Sort(&compareUInt32); | 1136 indices.Sort(&compareUInt32); |
| 1107 int j = 0; | 1137 int j = 0; |
| 1108 int n = indices.length(); | 1138 int n = indices.length(); |
| 1109 while (j < n) { | 1139 while (j < n) { |
| 1110 HandleScope loop_scope(isolate); | 1140 HandleScope loop_scope(isolate); |
| 1111 uint32_t index = indices[j]; | 1141 uint32_t index = indices[j]; |
| 1112 Handle<Object> element; | 1142 Handle<Object> element; |
| 1113 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1143 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1114 isolate, element, Object::GetElement(isolate, array, index), false); | 1144 isolate, element, Object::GetElement(isolate, array, index), false); |
| 1115 visitor->visit(index, element); | 1145 if (!visitor->visit(index, element)) return false; |
| 1116 // Skip to next different index (i.e., omit duplicates). | 1146 // Skip to next different index (i.e., omit duplicates). |
| 1117 do { | 1147 do { |
| 1118 j++; | 1148 j++; |
| 1119 } while (j < n && indices[j] == index); | 1149 } while (j < n && indices[j] == index); |
| 1120 } | 1150 } |
| 1121 break; | 1151 break; |
| 1122 } | 1152 } |
| 1123 case UINT8_CLAMPED_ELEMENTS: { | 1153 case UINT8_CLAMPED_ELEMENTS: { |
| 1124 Handle<FixedUint8ClampedArray> pixels( | 1154 Handle<FixedUint8ClampedArray> pixels( |
| 1125 FixedUint8ClampedArray::cast(array->elements())); | 1155 FixedUint8ClampedArray::cast(array->elements())); |
| 1126 for (uint32_t j = 0; j < length; j++) { | 1156 for (uint32_t j = 0; j < length; j++) { |
| 1127 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); | 1157 Handle<Smi> e(Smi::FromInt(pixels->get_scalar(j)), isolate); |
| 1128 visitor->visit(j, e); | 1158 visitor->visit(j, e); |
| 1129 } | 1159 } |
| 1130 break; | 1160 break; |
| 1131 } | 1161 } |
| 1132 case INT8_ELEMENTS: { | 1162 case INT8_ELEMENTS: { |
| 1133 IterateTypedArrayElements<FixedInt8Array, int8_t>(isolate, array, true, | 1163 if (!IterateTypedArrayElements<FixedInt8Array, int8_t>( |
| 1134 true, visitor); | 1164 isolate, array, true, true, visitor)) |
| 1165 return false; |
| 1135 break; | 1166 break; |
| 1136 } | 1167 } |
| 1137 case UINT8_ELEMENTS: { | 1168 case UINT8_ELEMENTS: { |
| 1138 IterateTypedArrayElements<FixedUint8Array, uint8_t>(isolate, array, true, | 1169 if (!IterateTypedArrayElements<FixedUint8Array, uint8_t>( |
| 1139 true, visitor); | 1170 isolate, array, true, true, visitor)) |
| 1171 return false; |
| 1140 break; | 1172 break; |
| 1141 } | 1173 } |
| 1142 case INT16_ELEMENTS: { | 1174 case INT16_ELEMENTS: { |
| 1143 IterateTypedArrayElements<FixedInt16Array, int16_t>(isolate, array, true, | 1175 if (!IterateTypedArrayElements<FixedInt16Array, int16_t>( |
| 1144 true, visitor); | 1176 isolate, array, true, true, visitor)) |
| 1177 return false; |
| 1145 break; | 1178 break; |
| 1146 } | 1179 } |
| 1147 case UINT16_ELEMENTS: { | 1180 case UINT16_ELEMENTS: { |
| 1148 IterateTypedArrayElements<FixedUint16Array, uint16_t>( | 1181 if (!IterateTypedArrayElements<FixedUint16Array, uint16_t>( |
| 1149 isolate, array, true, true, visitor); | 1182 isolate, array, true, true, visitor)) |
| 1183 return false; |
| 1150 break; | 1184 break; |
| 1151 } | 1185 } |
| 1152 case INT32_ELEMENTS: { | 1186 case INT32_ELEMENTS: { |
| 1153 IterateTypedArrayElements<FixedInt32Array, int32_t>(isolate, array, true, | 1187 if (!IterateTypedArrayElements<FixedInt32Array, int32_t>( |
| 1154 false, visitor); | 1188 isolate, array, true, false, visitor)) |
| 1189 return false; |
| 1155 break; | 1190 break; |
| 1156 } | 1191 } |
| 1157 case UINT32_ELEMENTS: { | 1192 case UINT32_ELEMENTS: { |
| 1158 IterateTypedArrayElements<FixedUint32Array, uint32_t>( | 1193 if (!IterateTypedArrayElements<FixedUint32Array, uint32_t>( |
| 1159 isolate, array, true, false, visitor); | 1194 isolate, array, true, false, visitor)) |
| 1195 return false; |
| 1160 break; | 1196 break; |
| 1161 } | 1197 } |
| 1162 case FLOAT32_ELEMENTS: { | 1198 case FLOAT32_ELEMENTS: { |
| 1163 IterateTypedArrayElements<FixedFloat32Array, float>(isolate, array, false, | 1199 if (!IterateTypedArrayElements<FixedFloat32Array, float>( |
| 1164 false, visitor); | 1200 isolate, array, false, false, visitor)) |
| 1201 return false; |
| 1165 break; | 1202 break; |
| 1166 } | 1203 } |
| 1167 case FLOAT64_ELEMENTS: { | 1204 case FLOAT64_ELEMENTS: { |
| 1168 IterateTypedArrayElements<FixedFloat64Array, double>( | 1205 if (!IterateTypedArrayElements<FixedFloat64Array, double>( |
| 1169 isolate, array, false, false, visitor); | 1206 isolate, array, false, false, visitor)) |
| 1207 return false; |
| 1170 break; | 1208 break; |
| 1171 } | 1209 } |
| 1172 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 1210 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| 1173 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | 1211 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
| 1174 for (uint32_t index = 0; index < length; index++) { | 1212 for (uint32_t index = 0; index < length; index++) { |
| 1175 HandleScope loop_scope(isolate); | 1213 HandleScope loop_scope(isolate); |
| 1176 Handle<Object> element; | 1214 Handle<Object> element; |
| 1177 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | 1215 ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| 1178 isolate, element, Object::GetElement(isolate, array, index), false); | 1216 isolate, element, Object::GetElement(isolate, array, index), false); |
| 1179 visitor->visit(index, element); | 1217 if (!visitor->visit(index, element)) return false; |
| 1180 } | 1218 } |
| 1181 break; | 1219 break; |
| 1182 } | 1220 } |
| 1183 } | 1221 } |
| 1184 visitor->increase_index_offset(length); | 1222 visitor->increase_index_offset(length); |
| 1185 return true; | 1223 return true; |
| 1186 } | 1224 } |
| 1187 | 1225 |
| 1188 | 1226 |
| 1189 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { | 1227 bool HasConcatSpreadableModifier(Isolate* isolate, Handle<JSArray> obj) { |
| (...skipping 13 matching lines...) Expand all Loading... |
| 1203 Handle<Object> value; | 1241 Handle<Object> value; |
| 1204 MaybeHandle<Object> maybeValue = | 1242 MaybeHandle<Object> maybeValue = |
| 1205 i::Runtime::GetObjectProperty(isolate, obj, key); | 1243 i::Runtime::GetObjectProperty(isolate, obj, key); |
| 1206 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); | 1244 if (!maybeValue.ToHandle(&value)) return Nothing<bool>(); |
| 1207 if (!value->IsUndefined()) return Just(value->BooleanValue()); | 1245 if (!value->IsUndefined()) return Just(value->BooleanValue()); |
| 1208 } | 1246 } |
| 1209 return Object::IsArray(obj); | 1247 return Object::IsArray(obj); |
| 1210 } | 1248 } |
| 1211 | 1249 |
| 1212 | 1250 |
| 1213 Object* Slow_ArrayConcat(Arguments* args, Isolate* isolate) { | 1251 Object* Slow_ArrayConcat(Arguments* args, Handle<Object> species, |
| 1252 Isolate* isolate) { |
| 1214 int argument_count = args->length(); | 1253 int argument_count = args->length(); |
| 1215 | 1254 |
| 1255 bool is_array_species = *species == isolate->context()->array_function(); |
| 1256 |
| 1216 // Pass 1: estimate the length and number of elements of the result. | 1257 // Pass 1: estimate the length and number of elements of the result. |
| 1217 // The actual length can be larger if any of the arguments have getters | 1258 // The actual length can be larger if any of the arguments have getters |
| 1218 // that mutate other arguments (but will otherwise be precise). | 1259 // that mutate other arguments (but will otherwise be precise). |
| 1219 // The number of elements is precise if there are no inherited elements. | 1260 // The number of elements is precise if there are no inherited elements. |
| 1220 | 1261 |
| 1221 ElementsKind kind = FAST_SMI_ELEMENTS; | 1262 ElementsKind kind = FAST_SMI_ELEMENTS; |
| 1222 | 1263 |
| 1223 uint32_t estimate_result_length = 0; | 1264 uint32_t estimate_result_length = 0; |
| 1224 uint32_t estimate_nof_elements = 0; | 1265 uint32_t estimate_nof_elements = 0; |
| 1225 for (int i = 0; i < argument_count; i++) { | 1266 for (int i = 0; i < argument_count; i++) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1256 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) { | 1297 if (JSObject::kMaxElementCount - estimate_nof_elements < element_estimate) { |
| 1257 estimate_nof_elements = JSObject::kMaxElementCount; | 1298 estimate_nof_elements = JSObject::kMaxElementCount; |
| 1258 } else { | 1299 } else { |
| 1259 estimate_nof_elements += element_estimate; | 1300 estimate_nof_elements += element_estimate; |
| 1260 } | 1301 } |
| 1261 } | 1302 } |
| 1262 | 1303 |
| 1263 // If estimated number of elements is more than half of length, a | 1304 // If estimated number of elements is more than half of length, a |
| 1264 // fixed array (fast case) is more time and space-efficient than a | 1305 // fixed array (fast case) is more time and space-efficient than a |
| 1265 // dictionary. | 1306 // dictionary. |
| 1266 bool fast_case = (estimate_nof_elements * 2) >= estimate_result_length; | 1307 bool fast_case = |
| 1308 is_array_species && (estimate_nof_elements * 2) >= estimate_result_length; |
| 1267 | 1309 |
| 1268 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) { | 1310 if (fast_case && kind == FAST_DOUBLE_ELEMENTS) { |
| 1269 Handle<FixedArrayBase> storage = | 1311 Handle<FixedArrayBase> storage = |
| 1270 isolate->factory()->NewFixedDoubleArray(estimate_result_length); | 1312 isolate->factory()->NewFixedDoubleArray(estimate_result_length); |
| 1271 int j = 0; | 1313 int j = 0; |
| 1272 bool failure = false; | 1314 bool failure = false; |
| 1273 if (estimate_result_length > 0) { | 1315 if (estimate_result_length > 0) { |
| 1274 Handle<FixedDoubleArray> double_storage = | 1316 Handle<FixedDoubleArray> double_storage = |
| 1275 Handle<FixedDoubleArray>::cast(storage); | 1317 Handle<FixedDoubleArray>::cast(storage); |
| 1276 for (int i = 0; i < argument_count; i++) { | 1318 for (int i = 0; i < argument_count; i++) { |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 Handle<Map> map; | 1382 Handle<Map> map; |
| 1341 map = JSObject::GetElementsTransitionMap(array, kind); | 1383 map = JSObject::GetElementsTransitionMap(array, kind); |
| 1342 array->set_map(*map); | 1384 array->set_map(*map); |
| 1343 array->set_length(length); | 1385 array->set_length(length); |
| 1344 array->set_elements(*storage); | 1386 array->set_elements(*storage); |
| 1345 return *array; | 1387 return *array; |
| 1346 } | 1388 } |
| 1347 // In case of failure, fall through. | 1389 // In case of failure, fall through. |
| 1348 } | 1390 } |
| 1349 | 1391 |
| 1350 Handle<FixedArray> storage; | 1392 Handle<Object> storage; |
| 1351 if (fast_case) { | 1393 if (fast_case) { |
| 1352 // The backing storage array must have non-existing elements to preserve | 1394 // The backing storage array must have non-existing elements to preserve |
| 1353 // holes across concat operations. | 1395 // holes across concat operations. |
| 1354 storage = | 1396 storage = |
| 1355 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); | 1397 isolate->factory()->NewFixedArrayWithHoles(estimate_result_length); |
| 1356 } else { | 1398 } else if (is_array_species) { |
| 1357 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate | 1399 // TODO(126): move 25% pre-allocation logic into Dictionary::Allocate |
| 1358 uint32_t at_least_space_for = | 1400 uint32_t at_least_space_for = |
| 1359 estimate_nof_elements + (estimate_nof_elements >> 2); | 1401 estimate_nof_elements + (estimate_nof_elements >> 2); |
| 1360 storage = Handle<FixedArray>::cast( | 1402 storage = SeededNumberDictionary::New(isolate, at_least_space_for); |
| 1361 SeededNumberDictionary::New(isolate, at_least_space_for)); | 1403 } else { |
| 1404 DCHECK(species->IsConstructor()); |
| 1405 Handle<Object> length(Smi::FromInt(0), isolate); |
| 1406 Handle<Object> storage_object; |
| 1407 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1408 isolate, storage_object, |
| 1409 Execution::New(isolate, species, species, 1, &length)); |
| 1410 storage = storage_object; |
| 1362 } | 1411 } |
| 1363 | 1412 |
| 1364 ArrayConcatVisitor visitor(isolate, storage, fast_case); | 1413 ArrayConcatVisitor visitor(isolate, storage, fast_case); |
| 1365 | 1414 |
| 1366 for (int i = 0; i < argument_count; i++) { | 1415 for (int i = 0; i < argument_count; i++) { |
| 1367 Handle<Object> obj((*args)[i], isolate); | 1416 Handle<Object> obj((*args)[i], isolate); |
| 1368 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); | 1417 Maybe<bool> spreadable = IsConcatSpreadable(isolate, obj); |
| 1369 MAYBE_RETURN(spreadable, isolate->heap()->exception()); | 1418 MAYBE_RETURN(spreadable, isolate->heap()->exception()); |
| 1370 if (spreadable.FromJust()) { | 1419 if (spreadable.FromJust()) { |
| 1371 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); | 1420 Handle<JSReceiver> object = Handle<JSReceiver>::cast(obj); |
| 1372 if (!IterateElements(isolate, object, &visitor)) { | 1421 if (!IterateElements(isolate, object, &visitor)) { |
| 1373 return isolate->heap()->exception(); | 1422 return isolate->heap()->exception(); |
| 1374 } | 1423 } |
| 1375 } else { | 1424 } else { |
| 1376 visitor.visit(0, obj); | 1425 visitor.visit(0, obj); |
| 1377 visitor.increase_index_offset(1); | 1426 visitor.increase_index_offset(1); |
| 1378 } | 1427 } |
| 1379 } | 1428 } |
| 1380 | 1429 |
| 1381 if (visitor.exceeds_array_limit()) { | 1430 if (visitor.exceeds_array_limit()) { |
| 1382 THROW_NEW_ERROR_RETURN_FAILURE( | 1431 THROW_NEW_ERROR_RETURN_FAILURE( |
| 1383 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); | 1432 isolate, NewRangeError(MessageTemplate::kInvalidArrayLength)); |
| 1384 } | 1433 } |
| 1385 return *visitor.ToArray(); | 1434 |
| 1435 if (is_array_species) { |
| 1436 return *visitor.ToArray(); |
| 1437 } else { |
| 1438 return *visitor.storage_jsreceiver(); |
| 1439 } |
| 1386 } | 1440 } |
| 1387 | 1441 |
| 1388 | 1442 |
| 1389 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { | 1443 MaybeHandle<JSArray> Fast_ArrayConcat(Isolate* isolate, Arguments* args) { |
| 1390 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { | 1444 if (!isolate->IsFastArrayConstructorPrototypeChainIntact()) { |
| 1391 return MaybeHandle<JSArray>(); | 1445 return MaybeHandle<JSArray>(); |
| 1392 } | 1446 } |
| 1393 int n_arguments = args->length(); | 1447 int n_arguments = args->length(); |
| 1394 int result_len = 0; | 1448 int result_len = 0; |
| 1395 { | 1449 { |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1439 THROW_NEW_ERROR_RETURN_FAILURE( | 1493 THROW_NEW_ERROR_RETURN_FAILURE( |
| 1440 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, | 1494 isolate, NewTypeError(MessageTemplate::kCalledOnNullOrUndefined, |
| 1441 isolate->factory()->NewStringFromAsciiChecked( | 1495 isolate->factory()->NewStringFromAsciiChecked( |
| 1442 "Array.prototype.concat"))); | 1496 "Array.prototype.concat"))); |
| 1443 } | 1497 } |
| 1444 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1498 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1445 isolate, receiver, Object::ToObject(isolate, args.receiver())); | 1499 isolate, receiver, Object::ToObject(isolate, args.receiver())); |
| 1446 args[0] = *receiver; | 1500 args[0] = *receiver; |
| 1447 | 1501 |
| 1448 Handle<JSArray> result_array; | 1502 Handle<JSArray> result_array; |
| 1449 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { | 1503 |
| 1450 return *result_array; | 1504 // Reading @@species happens before anything else with a side effect, so |
| 1505 // we can do it here to determine whether to take the fast path. |
| 1506 Handle<Object> species; |
| 1507 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 1508 isolate, species, Object::ArraySpeciesConstructor(isolate, receiver)); |
| 1509 if (*species == isolate->context()->native_context()->array_function()) { |
| 1510 if (Fast_ArrayConcat(isolate, &args).ToHandle(&result_array)) { |
| 1511 return *result_array; |
| 1512 } |
| 1513 if (isolate->has_pending_exception()) return isolate->heap()->exception(); |
| 1451 } | 1514 } |
| 1452 if (isolate->has_pending_exception()) return isolate->heap()->exception(); | 1515 return Slow_ArrayConcat(&args, species, isolate); |
| 1453 return Slow_ArrayConcat(&args, isolate); | |
| 1454 } | 1516 } |
| 1455 | 1517 |
| 1456 | 1518 |
| 1457 // ES6 22.1.2.2 Array.isArray | 1519 // ES6 22.1.2.2 Array.isArray |
| 1458 BUILTIN(ArrayIsArray) { | 1520 BUILTIN(ArrayIsArray) { |
| 1459 HandleScope scope(isolate); | 1521 HandleScope scope(isolate); |
| 1460 DCHECK_EQ(2, args.length()); | 1522 DCHECK_EQ(2, args.length()); |
| 1461 Handle<Object> object = args.at<Object>(1); | 1523 Handle<Object> object = args.at<Object>(1); |
| 1462 Maybe<bool> result = Object::IsArray(object); | 1524 Maybe<bool> result = Object::IsArray(object); |
| 1463 MAYBE_RETURN(result, isolate->heap()->exception()); | 1525 MAYBE_RETURN(result, isolate->heap()->exception()); |
| (...skipping 2590 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4054 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) | 4116 BUILTIN_LIST_C(DEFINE_BUILTIN_ACCESSOR_C) |
| 4055 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) | 4117 BUILTIN_LIST_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4056 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) | 4118 BUILTIN_LIST_H(DEFINE_BUILTIN_ACCESSOR_H) |
| 4057 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) | 4119 BUILTIN_LIST_DEBUG_A(DEFINE_BUILTIN_ACCESSOR_A) |
| 4058 #undef DEFINE_BUILTIN_ACCESSOR_C | 4120 #undef DEFINE_BUILTIN_ACCESSOR_C |
| 4059 #undef DEFINE_BUILTIN_ACCESSOR_A | 4121 #undef DEFINE_BUILTIN_ACCESSOR_A |
| 4060 | 4122 |
| 4061 | 4123 |
| 4062 } // namespace internal | 4124 } // namespace internal |
| 4063 } // namespace v8 | 4125 } // namespace v8 |
| OLD | NEW |