Home | History | Annotate | Download | only in src
      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 
     16 int 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 
     55 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
     56   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
     57   return IsExternalArrayElementsKind(elements_kind)
     58       ? 0 : (FixedArray::kHeaderSize - kHeapObjectTag);
     59 }
     60 
     61 
     62 const char* ElementsKindToString(ElementsKind kind) {
     63   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     64   return accessor->name();
     65 }
     66 
     67 
     68 struct 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 
     93 static base::LazyInstance<ElementsKind*,
     94                           InitializeFastElementsKindSequence>::type
     95     fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
     96 
     97 
     98 ElementsKind 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 
    105 int 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 
    116 ElementsKind 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 
    131 ElementsKind 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 
    146 static bool IsTypedArrayElementsKind(ElementsKind elements_kind) {
    147   return IsFixedTypedArrayElementsKind(elements_kind) ||
    148       IsExternalArrayElementsKind(elements_kind);
    149 }
    150 
    151 
    152 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
    153   return IsFastElementsKind(elements_kind) ||
    154       elements_kind == DICTIONARY_ELEMENTS;
    155 }
    156 
    157 bool 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