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 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 FAST_DOUBLE_ELEMENTS: 30 case FAST_HOLEY_DOUBLE_ELEMENTS: 31 case FLOAT64_ELEMENTS: 32 return 3; 33 case FAST_SMI_ELEMENTS: 34 case FAST_ELEMENTS: 35 case FAST_HOLEY_SMI_ELEMENTS: 36 case FAST_HOLEY_ELEMENTS: 37 case DICTIONARY_ELEMENTS: 38 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: 39 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: 40 case FAST_STRING_WRAPPER_ELEMENTS: 41 case SLOW_STRING_WRAPPER_ELEMENTS: 42 return kPointerSizeLog2; 43 case NO_ELEMENTS: 44 UNREACHABLE(); 45 return 0; 46 } 47 UNREACHABLE(); 48 return 0; 49 } 50 51 GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)52int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { 53 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 54 55 if (IsFixedTypedArrayElementsKind(elements_kind)) { 56 return 0; 57 } else { 58 return FixedArray::kHeaderSize - kHeapObjectTag; 59 } 60 } 61 62 ElementsKindToString(ElementsKind kind)63const char* ElementsKindToString(ElementsKind kind) { 64 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 65 return accessor->name(); 66 } 67 68 69 struct InitializeFastElementsKindSequence { Constructv8::internal::InitializeFastElementsKindSequence70 static void Construct( 71 ElementsKind** fast_elements_kind_sequence_ptr) { 72 ElementsKind* fast_elements_kind_sequence = 73 new ElementsKind[kFastElementsKindCount]; 74 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; 75 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); 76 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS; 77 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS; 78 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS; 79 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS; 80 fast_elements_kind_sequence[4] = FAST_ELEMENTS; 81 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS; 82 83 // Verify that kFastElementsKindPackedToHoley is correct. 84 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley == 85 FAST_HOLEY_SMI_ELEMENTS); 86 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == 87 FAST_HOLEY_DOUBLE_ELEMENTS); 88 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley == 89 FAST_HOLEY_ELEMENTS); 90 } 91 }; 92 93 94 static base::LazyInstance<ElementsKind*, 95 InitializeFastElementsKindSequence>::type 96 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; 97 98 GetFastElementsKindFromSequenceIndex(int sequence_number)99ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { 100 DCHECK(sequence_number >= 0 && 101 sequence_number < kFastElementsKindCount); 102 return fast_elements_kind_sequence.Get()[sequence_number]; 103 } 104 105 GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)106int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { 107 for (int i = 0; i < kFastElementsKindCount; ++i) { 108 if (fast_elements_kind_sequence.Get()[i] == elements_kind) { 109 return i; 110 } 111 } 112 UNREACHABLE(); 113 return 0; 114 } 115 116 GetNextTransitionElementsKind(ElementsKind kind)117ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { 118 int index = GetSequenceIndexFromFastElementsKind(kind); 119 return GetFastElementsKindFromSequenceIndex(index + 1); 120 } 121 122 IsFastTransitionTarget(ElementsKind elements_kind)123static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { 124 return IsFastElementsKind(elements_kind) || 125 elements_kind == DICTIONARY_ELEMENTS; 126 } 127 IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)128bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, 129 ElementsKind to_kind) { 130 if (IsFixedTypedArrayElementsKind(from_kind) || 131 IsFixedTypedArrayElementsKind(to_kind)) { 132 return false; 133 } 134 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) { 135 switch (from_kind) { 136 case FAST_SMI_ELEMENTS: 137 return to_kind != FAST_SMI_ELEMENTS; 138 case FAST_HOLEY_SMI_ELEMENTS: 139 return to_kind != FAST_SMI_ELEMENTS && 140 to_kind != FAST_HOLEY_SMI_ELEMENTS; 141 case FAST_DOUBLE_ELEMENTS: 142 return to_kind != FAST_SMI_ELEMENTS && 143 to_kind != FAST_HOLEY_SMI_ELEMENTS && 144 to_kind != FAST_DOUBLE_ELEMENTS; 145 case FAST_HOLEY_DOUBLE_ELEMENTS: 146 return to_kind == FAST_ELEMENTS || 147 to_kind == FAST_HOLEY_ELEMENTS; 148 case FAST_ELEMENTS: 149 return to_kind == FAST_HOLEY_ELEMENTS; 150 case FAST_HOLEY_ELEMENTS: 151 return false; 152 default: 153 return false; 154 } 155 } 156 return false; 157 } 158 159 160 } // namespace internal 161 } // namespace v8 162