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