| // Copyright 2012 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "src/elements-kind.h" |
| |
| #include "src/api.h" |
| #include "src/base/lazy-instance.h" |
| #include "src/elements.h" |
| #include "src/objects-inl.h" |
| #include "src/objects.h" |
| |
| namespace v8 { |
| namespace internal { |
| |
| |
| int ElementsKindToShiftSize(ElementsKind elements_kind) { |
| switch (elements_kind) { |
| case UINT8_ELEMENTS: |
| case INT8_ELEMENTS: |
| case UINT8_CLAMPED_ELEMENTS: |
| return 0; |
| case UINT16_ELEMENTS: |
| case INT16_ELEMENTS: |
| return 1; |
| case UINT32_ELEMENTS: |
| case INT32_ELEMENTS: |
| case FLOAT32_ELEMENTS: |
| return 2; |
| case PACKED_DOUBLE_ELEMENTS: |
| case HOLEY_DOUBLE_ELEMENTS: |
| case FLOAT64_ELEMENTS: |
| return 3; |
| case PACKED_SMI_ELEMENTS: |
| case PACKED_ELEMENTS: |
| case HOLEY_SMI_ELEMENTS: |
| case HOLEY_ELEMENTS: |
| case DICTIONARY_ELEMENTS: |
| case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
| case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: |
| case FAST_STRING_WRAPPER_ELEMENTS: |
| case SLOW_STRING_WRAPPER_ELEMENTS: |
| return kPointerSizeLog2; |
| case NO_ELEMENTS: |
| UNREACHABLE(); |
| } |
| UNREACHABLE(); |
| } |
| |
| |
| int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) { |
| STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize); |
| |
| if (IsFixedTypedArrayElementsKind(elements_kind)) { |
| return 0; |
| } else { |
| return FixedArray::kHeaderSize - kHeapObjectTag; |
| } |
| } |
| |
| |
| const char* ElementsKindToString(ElementsKind kind) { |
| ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); |
| return accessor->name(); |
| } |
| |
| |
| struct InitializeFastElementsKindSequence { |
| static void Construct(void* fast_elements_kind_sequence_ptr_arg) { |
| auto fast_elements_kind_sequence_ptr = |
| reinterpret_cast<ElementsKind**>(fast_elements_kind_sequence_ptr_arg); |
| ElementsKind* fast_elements_kind_sequence = |
| new ElementsKind[kFastElementsKindCount]; |
| *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; |
| STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); |
| fast_elements_kind_sequence[0] = PACKED_SMI_ELEMENTS; |
| fast_elements_kind_sequence[1] = HOLEY_SMI_ELEMENTS; |
| fast_elements_kind_sequence[2] = PACKED_DOUBLE_ELEMENTS; |
| fast_elements_kind_sequence[3] = HOLEY_DOUBLE_ELEMENTS; |
| fast_elements_kind_sequence[4] = PACKED_ELEMENTS; |
| fast_elements_kind_sequence[5] = HOLEY_ELEMENTS; |
| |
| // Verify that kFastElementsKindPackedToHoley is correct. |
| STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley == |
| HOLEY_SMI_ELEMENTS); |
| STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == |
| HOLEY_DOUBLE_ELEMENTS); |
| STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley == |
| HOLEY_ELEMENTS); |
| } |
| }; |
| |
| |
| static base::LazyInstance<ElementsKind*, |
| InitializeFastElementsKindSequence>::type |
| fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; |
| |
| |
| ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { |
| DCHECK(sequence_number >= 0 && |
| sequence_number < kFastElementsKindCount); |
| return fast_elements_kind_sequence.Get()[sequence_number]; |
| } |
| |
| |
| int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { |
| for (int i = 0; i < kFastElementsKindCount; ++i) { |
| if (fast_elements_kind_sequence.Get()[i] == elements_kind) { |
| return i; |
| } |
| } |
| UNREACHABLE(); |
| } |
| |
| |
| ElementsKind GetNextTransitionElementsKind(ElementsKind kind) { |
| int index = GetSequenceIndexFromFastElementsKind(kind); |
| return GetFastElementsKindFromSequenceIndex(index + 1); |
| } |
| |
| |
| static inline bool IsFastTransitionTarget(ElementsKind elements_kind) { |
| return IsFastElementsKind(elements_kind) || |
| elements_kind == DICTIONARY_ELEMENTS; |
| } |
| |
| bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, |
| ElementsKind to_kind) { |
| if (IsFixedTypedArrayElementsKind(from_kind) || |
| IsFixedTypedArrayElementsKind(to_kind)) { |
| return false; |
| } |
| if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) { |
| switch (from_kind) { |
| case PACKED_SMI_ELEMENTS: |
| return to_kind != PACKED_SMI_ELEMENTS; |
| case HOLEY_SMI_ELEMENTS: |
| return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS; |
| case PACKED_DOUBLE_ELEMENTS: |
| return to_kind != PACKED_SMI_ELEMENTS && |
| to_kind != HOLEY_SMI_ELEMENTS && |
| to_kind != PACKED_DOUBLE_ELEMENTS; |
| case HOLEY_DOUBLE_ELEMENTS: |
| return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS; |
| case PACKED_ELEMENTS: |
| return to_kind == HOLEY_ELEMENTS; |
| case HOLEY_ELEMENTS: |
| return false; |
| default: |
| return false; |
| } |
| } |
| return false; |
| } |
| |
| |
| } // namespace internal |
| } // namespace v8 |