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 3 // found in the LICENSE file. 4 5 #include "src/elements-kind.h" 6 7 #include "src/api.h" 8 #include "src/base/lazy-instance.h" 9 #include "src/elements.h" 10 #include "src/objects.h" 11 12 namespace v8 { 13 namespace internal { 14 15 16 int ElementsKindToShiftSize(ElementsKind elements_kind) { 17 switch (elements_kind) { 18 case EXTERNAL_INT8_ELEMENTS: 19 case EXTERNAL_UINT8_CLAMPED_ELEMENTS: 20 case EXTERNAL_UINT8_ELEMENTS: 21 case UINT8_ELEMENTS: 22 case INT8_ELEMENTS: 23 case UINT8_CLAMPED_ELEMENTS: 24 return 0; 25 case EXTERNAL_INT16_ELEMENTS: 26 case EXTERNAL_UINT16_ELEMENTS: 27 case UINT16_ELEMENTS: 28 case INT16_ELEMENTS: 29 return 1; 30 case EXTERNAL_INT32_ELEMENTS: 31 case EXTERNAL_UINT32_ELEMENTS: 32 case EXTERNAL_FLOAT32_ELEMENTS: 33 case UINT32_ELEMENTS: 34 case INT32_ELEMENTS: 35 case FLOAT32_ELEMENTS: 36 return 2; 37 case EXTERNAL_FLOAT64_ELEMENTS: 38 case FAST_DOUBLE_ELEMENTS: 39 case FAST_HOLEY_DOUBLE_ELEMENTS: 40 case FLOAT64_ELEMENTS: 41 return 3; 42 case FAST_SMI_ELEMENTS: 43 case FAST_ELEMENTS: 44 case FAST_HOLEY_SMI_ELEMENTS: 45 case FAST_HOLEY_ELEMENTS: 46 case DICTIONARY_ELEMENTS: 47 case SLOPPY_ARGUMENTS_ELEMENTS: 48 return kPointerSizeLog2; 49 } 50 UNREACHABLE(); 51 return 0; 52 } 53 54 55 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { 56 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 57 return IsExternalArrayElementsKind(elements_kind) 58 ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag); 59 } 60 61 62 const char* ElementsKindToString(ElementsKind kind) { 63 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 64 return accessor->name(); 65 } 66 67 68 void PrintElementsKind(FILE* out, ElementsKind kind) { 69 PrintF(out, "%s", ElementsKindToString(kind)); 70 } 71 72 73 ElementsKind GetInitialFastElementsKind() { 74 if (FLAG_packed_arrays) { 75 return FAST_SMI_ELEMENTS; 76 } else { 77 return FAST_HOLEY_SMI_ELEMENTS; 78 } 79 } 80 81 82 struct InitializeFastElementsKindSequence { 83 static void Construct( 84 ElementsKind** fast_elements_kind_sequence_ptr) { 85 ElementsKind* fast_elements_kind_sequence = 86 new ElementsKind[kFastElementsKindCount]; 87 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; 88 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); 89 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS; 90 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS; 91 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS; 92 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS; 93 fast_elements_kind_sequence[4] = FAST_ELEMENTS; 94 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS; 95 96 // Verify that kFastElementsKindPackedToHoley is correct. 97 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley == 98 FAST_HOLEY_SMI_ELEMENTS); 99 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == 100 FAST_HOLEY_DOUBLE_ELEMENTS); 101 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley == 102 FAST_HOLEY_ELEMENTS); 103 } 104 }; 105 106 107 static base::LazyInstance<ElementsKind*, 108 InitializeFastElementsKindSequence>::type 109 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; 110 111 112 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { 113 ASSERT(sequence_number >= 0 && 114 sequence_number < kFastElementsKindCount); 115 return fast_elements_kind_sequence.Get()[sequence_number]; 116 } 117 118 119 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { 120 for (int i = 0; i < kFastElementsKindCount; ++i) { 121 if (fast_elements_kind_sequence.Get()[i] == elements_kind) { 122 return i; 123 } 124 } 125 UNREACHABLE(); 126 return 0; 127 } 128 129 130 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { 131 switch (kind) { 132 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 133 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS; 134 135 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE) 136 #undef FIXED_TYPED_ARRAY_CASE 137 default: { 138 int index = GetSequenceIndexFromFastElementsKind(kind); 139 return GetFastElementsKindFromSequenceIndex(index + 1); 140 } 141 } 142 } 143 144 145 ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, 146 bool allow_only_packed) { 147 ASSERT(IsFastElementsKind(elements_kind)); 148 ASSERT(elements_kind != TERMINAL_FAST_ELEMENTS_KIND); 149 while (true) { 150 elements_kind = GetNextTransitionElementsKind(elements_kind); 151 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) { 152 return elements_kind; 153 } 154 } 155 UNREACHABLE(); 156 return TERMINAL_FAST_ELEMENTS_KIND; 157 } 158 159 160 static bool IsTypedArrayElementsKind(ElementsKind elements_kind) { 161 return IsFixedTypedArrayElementsKind(elements_kind) || 162 IsExternalArrayElementsKind(elements_kind); 163 } 164 165 166 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { 167 return IsFastElementsKind(elements_kind) || 168 elements_kind == DICTIONARY_ELEMENTS; 169 } 170 171 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, 172 ElementsKind to_kind) { 173 if (IsTypedArrayElementsKind(from_kind) || 174 IsTypedArrayElementsKind(to_kind)) { 175 switch (from_kind) { 176 #define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 177 case TYPE##_ELEMENTS: \ 178 return to_kind == EXTERNAL_##TYPE##_ELEMENTS; 179 180 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE); 181 #undef FIXED_TYPED_ARRAY_CASE 182 default: 183 return false; 184 } 185 } 186 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) { 187 switch (from_kind) { 188 case FAST_SMI_ELEMENTS: 189 return to_kind != FAST_SMI_ELEMENTS; 190 case FAST_HOLEY_SMI_ELEMENTS: 191 return to_kind != FAST_SMI_ELEMENTS && 192 to_kind != FAST_HOLEY_SMI_ELEMENTS; 193 case FAST_DOUBLE_ELEMENTS: 194 return to_kind != FAST_SMI_ELEMENTS && 195 to_kind != FAST_HOLEY_SMI_ELEMENTS && 196 to_kind != FAST_DOUBLE_ELEMENTS; 197 case FAST_HOLEY_DOUBLE_ELEMENTS: 198 return to_kind == FAST_ELEMENTS || 199 to_kind == FAST_HOLEY_ELEMENTS; 200 case FAST_ELEMENTS: 201 return to_kind == FAST_HOLEY_ELEMENTS; 202 case FAST_HOLEY_ELEMENTS: 203 return false; 204 default: 205 return false; 206 } 207 } 208 return false; 209 } 210 211 212 } } // namespace v8::internal 213