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 12namespace v8 { 13namespace internal { 14 15 16int 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 55int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { 56 STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); 57 return IsExternalArrayElementsKind(elements_kind) 58 ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag); 59} 60 61 62const char* ElementsKindToString(ElementsKind kind) { 63 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 64 return accessor->name(); 65} 66 67 68struct InitializeFastElementsKindSequence { 69 static void Construct( 70 ElementsKind** fast_elements_kind_sequence_ptr) { 71 ElementsKind* fast_elements_kind_sequence = 72 new ElementsKind[kFastElementsKindCount]; 73 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; 74 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); 75 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS; 76 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS; 77 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS; 78 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS; 79 fast_elements_kind_sequence[4] = FAST_ELEMENTS; 80 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS; 81 82 // Verify that kFastElementsKindPackedToHoley is correct. 83 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley == 84 FAST_HOLEY_SMI_ELEMENTS); 85 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == 86 FAST_HOLEY_DOUBLE_ELEMENTS); 87 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley == 88 FAST_HOLEY_ELEMENTS); 89 } 90}; 91 92 93static base::LazyInstance<ElementsKind*, 94 InitializeFastElementsKindSequence>::type 95 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; 96 97 98ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { 99 DCHECK(sequence_number >= 0 && 100 sequence_number < kFastElementsKindCount); 101 return fast_elements_kind_sequence.Get()[sequence_number]; 102} 103 104 105int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { 106 for (int i = 0; i < kFastElementsKindCount; ++i) { 107 if (fast_elements_kind_sequence.Get()[i] == elements_kind) { 108 return i; 109 } 110 } 111 UNREACHABLE(); 112 return 0; 113} 114 115 116ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { 117 switch (kind) { 118#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 119 case TYPE##_ELEMENTS: return EXTERNAL_##TYPE##_ELEMENTS; 120 121 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE) 122#undef FIXED_TYPED_ARRAY_CASE 123 default: { 124 int index = GetSequenceIndexFromFastElementsKind(kind); 125 return GetFastElementsKindFromSequenceIndex(index + 1); 126 } 127 } 128} 129 130 131ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, 132 bool allow_only_packed) { 133 DCHECK(IsFastElementsKind(elements_kind)); 134 DCHECK(elements_kind != TERMINAL_FAST_ELEMENTS_KIND); 135 while (true) { 136 elements_kind = GetNextTransitionElementsKind(elements_kind); 137 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) { 138 return elements_kind; 139 } 140 } 141 UNREACHABLE(); 142 return TERMINAL_FAST_ELEMENTS_KIND; 143} 144 145 146static bool IsTypedArrayElementsKind(ElementsKind elements_kind) { 147 return IsFixedTypedArrayElementsKind(elements_kind) || 148 IsExternalArrayElementsKind(elements_kind); 149} 150 151 152static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { 153 return IsFastElementsKind(elements_kind) || 154 elements_kind == DICTIONARY_ELEMENTS; 155} 156 157bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, 158 ElementsKind to_kind) { 159 if (IsTypedArrayElementsKind(from_kind) || 160 IsTypedArrayElementsKind(to_kind)) { 161 switch (from_kind) { 162#define FIXED_TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) \ 163 case TYPE##_ELEMENTS: \ 164 return to_kind == EXTERNAL_##TYPE##_ELEMENTS; 165 166 TYPED_ARRAYS(FIXED_TYPED_ARRAY_CASE); 167#undef FIXED_TYPED_ARRAY_CASE 168 default: 169 return false; 170 } 171 } 172 if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) { 173 switch (from_kind) { 174 case FAST_SMI_ELEMENTS: 175 return to_kind != FAST_SMI_ELEMENTS; 176 case FAST_HOLEY_SMI_ELEMENTS: 177 return to_kind != FAST_SMI_ELEMENTS && 178 to_kind != FAST_HOLEY_SMI_ELEMENTS; 179 case FAST_DOUBLE_ELEMENTS: 180 return to_kind != FAST_SMI_ELEMENTS && 181 to_kind != FAST_HOLEY_SMI_ELEMENTS && 182 to_kind != FAST_DOUBLE_ELEMENTS; 183 case FAST_HOLEY_DOUBLE_ELEMENTS: 184 return to_kind == FAST_ELEMENTS || 185 to_kind == FAST_HOLEY_ELEMENTS; 186 case FAST_ELEMENTS: 187 return to_kind == FAST_HOLEY_ELEMENTS; 188 case FAST_HOLEY_ELEMENTS: 189 return false; 190 default: 191 return false; 192 } 193 } 194 return false; 195} 196 197 198} } // namespace v8::internal 199