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