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/elements.h" | 5 #include "src/elements.h" |
6 | 6 |
7 #include "src/arguments.h" | 7 #include "src/arguments.h" |
8 #include "src/conversions.h" | 8 #include "src/conversions.h" |
9 #include "src/factory.h" | 9 #include "src/factory.h" |
10 #include "src/messages.h" | 10 #include "src/messages.h" |
(...skipping 2836 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2847 if (elements_accessors_ == NULL) return; | 2847 if (elements_accessors_ == NULL) return; |
2848 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; | 2848 #define ACCESSOR_DELETE(Class, Kind, Store) delete elements_accessors_[Kind]; |
2849 ELEMENTS_LIST(ACCESSOR_DELETE) | 2849 ELEMENTS_LIST(ACCESSOR_DELETE) |
2850 #undef ACCESSOR_DELETE | 2850 #undef ACCESSOR_DELETE |
2851 elements_accessors_ = NULL; | 2851 elements_accessors_ = NULL; |
2852 } | 2852 } |
2853 | 2853 |
2854 | 2854 |
2855 Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args, | 2855 Handle<JSArray> ElementsAccessor::Concat(Isolate* isolate, Arguments* args, |
2856 uint32_t concat_size) { | 2856 uint32_t concat_size) { |
2857 int result_len = 0; | 2857 uint32_t result_len = 0; |
2858 ElementsKind elements_kind = GetInitialFastElementsKind(); | 2858 bool has_raw_doubles = false; |
2859 bool has_double = false; | 2859 ElementsKind result_elements_kind = GetInitialFastElementsKind(); |
2860 { | 2860 { |
2861 DisallowHeapAllocation no_gc; | 2861 DisallowHeapAllocation no_gc; |
| 2862 bool is_holey = false; |
2862 // Iterate through all the arguments performing checks | 2863 // Iterate through all the arguments performing checks |
2863 // and calculating total length. | 2864 // and calculating total length. |
2864 bool is_holey = false; | |
2865 for (uint32_t i = 0; i < concat_size; i++) { | 2865 for (uint32_t i = 0; i < concat_size; i++) { |
2866 Object* arg = (*args)[i]; | 2866 JSArray* array = JSArray::cast((*args)[i]); |
2867 int len = Smi::cast(JSArray::cast(arg)->length())->value(); | 2867 uint32_t len = 0; |
| 2868 array->length()->ToArrayLength(&len); |
2868 | 2869 |
2869 // We shouldn't overflow when adding another len. | 2870 // We shouldn't overflow when adding another len. |
2870 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); | 2871 const int kHalfOfMaxInt = 1 << (kBitsPerInt - 2); |
2871 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); | 2872 STATIC_ASSERT(FixedArray::kMaxLength < kHalfOfMaxInt); |
2872 USE(kHalfOfMaxInt); | 2873 USE(kHalfOfMaxInt); |
2873 result_len += len; | 2874 result_len += len; |
2874 DCHECK(0 <= result_len); | 2875 DCHECK(0 <= result_len); |
2875 DCHECK(result_len <= FixedDoubleArray::kMaxLength); | 2876 DCHECK(result_len <= FixedDoubleArray::kMaxLength); |
2876 | 2877 |
2877 ElementsKind arg_kind = JSArray::cast(arg)->map()->elements_kind(); | 2878 ElementsKind arg_kind = array->GetElementsKind(); |
2878 has_double = has_double || IsFastDoubleElementsKind(arg_kind); | 2879 has_raw_doubles = has_raw_doubles || IsFastDoubleElementsKind(arg_kind); |
2879 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); | 2880 is_holey = is_holey || IsFastHoleyElementsKind(arg_kind); |
2880 elements_kind = GetMoreGeneralElementsKind(elements_kind, arg_kind); | 2881 result_elements_kind = |
| 2882 GetMoreGeneralElementsKind(result_elements_kind, arg_kind); |
2881 } | 2883 } |
2882 if (is_holey) { | 2884 if (is_holey) { |
2883 elements_kind = GetHoleyElementsKind(elements_kind); | 2885 result_elements_kind = GetHoleyElementsKind(result_elements_kind); |
2884 } | 2886 } |
2885 } | 2887 } |
2886 | 2888 |
2887 // If a double array is concatted into a fast elements array, the fast | 2889 // If a double array is concatted into a fast elements array, the fast |
2888 // elements array needs to be initialized to contain proper holes, since | 2890 // elements array needs to be initialized to contain proper holes, since |
2889 // boxing doubles may cause incremental marking. | 2891 // boxing doubles may cause incremental marking. |
2890 ArrayStorageAllocationMode mode = | 2892 bool requires_double_boxing = |
2891 has_double && IsFastObjectElementsKind(elements_kind) | 2893 has_raw_doubles && !IsFastDoubleElementsKind(result_elements_kind); |
2892 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE | 2894 ArrayStorageAllocationMode mode = requires_double_boxing |
2893 : DONT_INITIALIZE_ARRAY_ELEMENTS; | 2895 ? INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE |
| 2896 : DONT_INITIALIZE_ARRAY_ELEMENTS; |
2894 Handle<JSArray> result_array = isolate->factory()->NewJSArray( | 2897 Handle<JSArray> result_array = isolate->factory()->NewJSArray( |
2895 elements_kind, result_len, result_len, mode); | 2898 result_elements_kind, result_len, result_len, mode); |
2896 if (result_len == 0) return result_array; | 2899 if (result_len == 0) return result_array; |
2897 int j = 0; | 2900 |
| 2901 uint32_t insertion_index = 0; |
2898 Handle<FixedArrayBase> storage(result_array->elements(), isolate); | 2902 Handle<FixedArrayBase> storage(result_array->elements(), isolate); |
2899 ElementsAccessor* accessor = ElementsAccessor::ForKind(elements_kind); | 2903 ElementsAccessor* accessor = ElementsAccessor::ForKind(result_elements_kind); |
2900 for (uint32_t i = 0; i < concat_size; i++) { | 2904 for (uint32_t i = 0; i < concat_size; i++) { |
2901 // It is crucial to keep |array| in a raw pointer form to avoid | 2905 // It is crucial to keep |array| in a raw pointer form to avoid |
2902 // performance degradation. | 2906 // performance degradation. |
2903 JSArray* array = JSArray::cast((*args)[i]); | 2907 JSArray* array = JSArray::cast((*args)[i]); |
2904 int len = Smi::cast(array->length())->value(); | 2908 uint32_t len = 0; |
2905 if (len > 0) { | 2909 array->length()->ToArrayLength(&len); |
2906 ElementsKind from_kind = array->GetElementsKind(); | 2910 if (len == 0) continue; |
2907 accessor->CopyElements(array, 0, from_kind, storage, j, len); | 2911 ElementsKind from_kind = array->GetElementsKind(); |
2908 j += len; | 2912 accessor->CopyElements(array, 0, from_kind, storage, insertion_index, len); |
2909 } | 2913 insertion_index += len; |
2910 } | 2914 } |
2911 | 2915 |
2912 DCHECK(j == result_len); | 2916 DCHECK_EQ(insertion_index, result_len); |
2913 return result_array; | 2917 return result_array; |
2914 } | 2918 } |
2915 | 2919 |
2916 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; | 2920 ElementsAccessor** ElementsAccessor::elements_accessors_ = NULL; |
2917 } // namespace internal | 2921 } // namespace internal |
2918 } // namespace v8 | 2922 } // namespace v8 |
OLD | NEW |