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/base/lazy-instance.h" 8 #include "src/elements.h" 9 #include "src/objects-inl.h" 10 #include "src/objects.h" 11 12 namespace v8 { 13 namespace internal { 14 15 ElementsKindToShiftSize(ElementsKind elements_kind)16int ElementsKindToShiftSize(ElementsKind elements_kind) { 17 switch (elements_kind) { 18 case UINT8_ELEMENTS: 19 case INT8_ELEMENTS: 20 case UINT8_CLAMPED_ELEMENTS: 21 return 0; 22 case UINT16_ELEMENTS: 23 case INT16_ELEMENTS: 24 return 1; 25 case UINT32_ELEMENTS: 26 case INT32_ELEMENTS: 27 case FLOAT32_ELEMENTS: 28 return 2; 29 case PACKED_DOUBLE_ELEMENTS: 30 case HOLEY_DOUBLE_ELEMENTS: 31 case FLOAT64_ELEMENTS: 32 case BIGINT64_ELEMENTS: 33 case BIGUINT64_ELEMENTS: 34 return 3; 35 case PACKED_SMI_ELEMENTS: 36 case PACKED_ELEMENTS: 37 case HOLEY_SMI_ELEMENTS: 38 case HOLEY_ELEMENTS: 39 case DICTIONARY_ELEMENTS: 40 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 41 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 42 case FAST_STRING_WRAPPER_ELEMENTS: 43 case SLOW_STRING_WRAPPER_ELEMENTS: 44 return kPointerSizeLog2; 45 case NO_ELEMENTS: 46 UNREACHABLE(); 47 } 48 UNREACHABLE(); 49 } 50 ElementsKindToByteSize(ElementsKind elements_kind)51int ElementsKindToByteSize(ElementsKind elements_kind) { 52 return 1 << ElementsKindToShiftSize(elements_kind); 53 } 54 GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)55int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { 56 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 57 58 if (IsFixedTypedArrayElementsKind(elements_kind)) { 59 return 0; 60 } else { 61 return FixedArray::kHeaderSize - kHeapObjectTag; 62 } 63 } 64 65 ElementsKindToString(ElementsKind kind)66const char* ElementsKindToString(ElementsKind kind) { 67 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 68 return accessor->name(); 69 } 70 71 72 struct InitializeFastElementsKindSequence { Constructv8::internal::InitializeFastElementsKindSequence73 static void Construct(void* fast_elements_kind_sequence_ptr_arg) { 74 auto fast_elements_kind_sequence_ptr = 75 reinterpret_cast<ElementsKind**>(fast_elements_kind_sequence_ptr_arg); 76 ElementsKind* fast_elements_kind_sequence = 77 new ElementsKind[kFastElementsKindCount]; 78 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; 79 STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); 80 fast_elements_kind_sequence[0] = PACKED_SMI_ELEMENTS; 81 fast_elements_kind_sequence[1] = HOLEY_SMI_ELEMENTS; 82 fast_elements_kind_sequence[2] = PACKED_DOUBLE_ELEMENTS; 83 fast_elements_kind_sequence[3] = HOLEY_DOUBLE_ELEMENTS; 84 fast_elements_kind_sequence[4] = PACKED_ELEMENTS; 85 fast_elements_kind_sequence[5] = HOLEY_ELEMENTS; 86 87 // Verify that kFastElementsKindPackedToHoley is correct. 88 STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley == 89 HOLEY_SMI_ELEMENTS); 90 STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == 91 HOLEY_DOUBLE_ELEMENTS); 92 STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley == 93 HOLEY_ELEMENTS); 94 } 95 }; 96 97 98 static base::LazyInstance<ElementsKind*, 99 InitializeFastElementsKindSequence>::type 100 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; 101 102 GetFastElementsKindFromSequenceIndex(int sequence_number)103ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { 104 DCHECK(sequence_number >= 0 && 105 sequence_number < kFastElementsKindCount); 106 return fast_elements_kind_sequence.Get()[sequence_number]; 107 } 108 109 GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)110int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { 111 for (int i = 0; i < kFastElementsKindCount; ++i) { 112 if (fast_elements_kind_sequence.Get()[i] == elements_kind) { 113 return i; 114 } 115 } 116 UNREACHABLE(); 117 } 118 119 GetNextTransitionElementsKind(ElementsKind kind)120ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { 121 int index = GetSequenceIndexFromFastElementsKind(kind); 122 return GetFastElementsKindFromSequenceIndex(index + 1); 123 } 124 125 IsFastTransitionTarget(ElementsKind elements_kind)126static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { 127 return IsFastElementsKind(elements_kind) || 128 elements_kind == DICTIONARY_ELEMENTS; 129 } 130 IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)131bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, 132 ElementsKind to_kind) { 133 if (!IsFastElementsKind(from_kind)) return false; 134 if (!IsFastTransitionTarget(to_kind)) return false; 135 DCHECK(!IsFixedTypedArrayElementsKind(from_kind)); 136 DCHECK(!IsFixedTypedArrayElementsKind(to_kind)); 137 switch (from_kind) { 138 case PACKED_SMI_ELEMENTS: 139 return to_kind != PACKED_SMI_ELEMENTS; 140 case HOLEY_SMI_ELEMENTS: 141 return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS; 142 case PACKED_DOUBLE_ELEMENTS: 143 return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS && 144 to_kind != PACKED_DOUBLE_ELEMENTS; 145 case HOLEY_DOUBLE_ELEMENTS: 146 return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS; 147 case PACKED_ELEMENTS: 148 return to_kind == HOLEY_ELEMENTS; 149 case HOLEY_ELEMENTS: 150 return false; 151 default: 152 return false; 153 } 154 } 155 UnionElementsKindUptoSize(ElementsKind * a_out,ElementsKind b)156bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b) { 157 // Assert that the union of two ElementKinds can be computed via std::max. 158 static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS, 159 "ElementsKind union not computable via std::max."); 160 static_assert(HOLEY_SMI_ELEMENTS < PACKED_ELEMENTS, 161 "ElementsKind union not computable via std::max."); 162 static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS, 163 "ElementsKind union not computable via std::max."); 164 static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS, 165 "ElementsKind union not computable via std::max."); 166 ElementsKind a = *a_out; 167 switch (a) { 168 case PACKED_SMI_ELEMENTS: 169 switch (b) { 170 case PACKED_SMI_ELEMENTS: 171 case HOLEY_SMI_ELEMENTS: 172 case PACKED_ELEMENTS: 173 case HOLEY_ELEMENTS: 174 *a_out = b; 175 return true; 176 default: 177 return false; 178 } 179 case HOLEY_SMI_ELEMENTS: 180 switch (b) { 181 case PACKED_SMI_ELEMENTS: 182 case HOLEY_SMI_ELEMENTS: 183 *a_out = HOLEY_SMI_ELEMENTS; 184 return true; 185 case PACKED_ELEMENTS: 186 case HOLEY_ELEMENTS: 187 *a_out = HOLEY_ELEMENTS; 188 return true; 189 default: 190 return false; 191 } 192 case PACKED_ELEMENTS: 193 switch (b) { 194 case PACKED_SMI_ELEMENTS: 195 case PACKED_ELEMENTS: 196 *a_out = PACKED_ELEMENTS; 197 return true; 198 case HOLEY_SMI_ELEMENTS: 199 case HOLEY_ELEMENTS: 200 *a_out = HOLEY_ELEMENTS; 201 return true; 202 default: 203 return false; 204 } 205 case HOLEY_ELEMENTS: 206 switch (b) { 207 case PACKED_SMI_ELEMENTS: 208 case HOLEY_SMI_ELEMENTS: 209 case PACKED_ELEMENTS: 210 case HOLEY_ELEMENTS: 211 *a_out = HOLEY_ELEMENTS; 212 return true; 213 default: 214 return false; 215 } 216 break; 217 case PACKED_DOUBLE_ELEMENTS: 218 switch (b) { 219 case PACKED_DOUBLE_ELEMENTS: 220 case HOLEY_DOUBLE_ELEMENTS: 221 *a_out = b; 222 return true; 223 default: 224 return false; 225 } 226 case HOLEY_DOUBLE_ELEMENTS: 227 switch (b) { 228 case PACKED_DOUBLE_ELEMENTS: 229 case HOLEY_DOUBLE_ELEMENTS: 230 *a_out = HOLEY_DOUBLE_ELEMENTS; 231 return true; 232 default: 233 return false; 234 } 235 236 break; 237 default: 238 break; 239 } 240 return false; 241 } 242 243 } // namespace internal 244 } // namespace v8 245