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/base/lazy-instance.h"
      8 #include "src/elements.h"
      9 #include "src/objects-inl.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 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 PACKED_DOUBLE_ELEMENTS:
     30     case HOLEY_DOUBLE_ELEMENTS:
     31     case FLOAT64_ELEMENTS:
     32     case BIGINT64_ELEMENTS:
     33     case BIGUINT64_ELEMENTS:
     34       return 3;
     35     case PACKED_SMI_ELEMENTS:
     36     case PACKED_ELEMENTS:
     37     case HOLEY_SMI_ELEMENTS:
     38     case HOLEY_ELEMENTS:
     39     case DICTIONARY_ELEMENTS:
     40     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
     41     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
     42     case FAST_STRING_WRAPPER_ELEMENTS:
     43     case SLOW_STRING_WRAPPER_ELEMENTS:
     44       return kPointerSizeLog2;
     45     case NO_ELEMENTS:
     46       UNREACHABLE();
     47   }
     48   UNREACHABLE();
     49 }
     50 
     51 int ElementsKindToByteSize(ElementsKind elements_kind) {
     52   return 1 << ElementsKindToShiftSize(elements_kind);
     53 }
     54 
     55 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
     56   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
     57 
     58   if (IsFixedTypedArrayElementsKind(elements_kind)) {
     59     return 0;
     60   } else {
     61     return FixedArray::kHeaderSize - kHeapObjectTag;
     62   }
     63 }
     64 
     65 
     66 const char* ElementsKindToString(ElementsKind kind) {
     67   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
     68   return accessor->name();
     69 }
     70 
     71 
     72 struct InitializeFastElementsKindSequence {
     73   static void Construct(void* fast_elements_kind_sequence_ptr_arg) {
     74     auto fast_elements_kind_sequence_ptr =
     75         reinterpret_cast<ElementsKind**>(fast_elements_kind_sequence_ptr_arg);
     76     ElementsKind* fast_elements_kind_sequence =
     77         new ElementsKind[kFastElementsKindCount];
     78     *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
     79     STATIC_ASSERT(PACKED_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
     80     fast_elements_kind_sequence[0] = PACKED_SMI_ELEMENTS;
     81     fast_elements_kind_sequence[1] = HOLEY_SMI_ELEMENTS;
     82     fast_elements_kind_sequence[2] = PACKED_DOUBLE_ELEMENTS;
     83     fast_elements_kind_sequence[3] = HOLEY_DOUBLE_ELEMENTS;
     84     fast_elements_kind_sequence[4] = PACKED_ELEMENTS;
     85     fast_elements_kind_sequence[5] = HOLEY_ELEMENTS;
     86 
     87     // Verify that kFastElementsKindPackedToHoley is correct.
     88     STATIC_ASSERT(PACKED_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
     89                   HOLEY_SMI_ELEMENTS);
     90     STATIC_ASSERT(PACKED_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
     91                   HOLEY_DOUBLE_ELEMENTS);
     92     STATIC_ASSERT(PACKED_ELEMENTS + kFastElementsKindPackedToHoley ==
     93                   HOLEY_ELEMENTS);
     94   }
     95 };
     96 
     97 
     98 static base::LazyInstance<ElementsKind*,
     99                           InitializeFastElementsKindSequence>::type
    100     fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
    101 
    102 
    103 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
    104   DCHECK(sequence_number >= 0 &&
    105          sequence_number < kFastElementsKindCount);
    106   return fast_elements_kind_sequence.Get()[sequence_number];
    107 }
    108 
    109 
    110 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
    111   for (int i = 0; i < kFastElementsKindCount; ++i) {
    112     if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
    113       return i;
    114     }
    115   }
    116   UNREACHABLE();
    117 }
    118 
    119 
    120 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
    121   int index = GetSequenceIndexFromFastElementsKind(kind);
    122   return GetFastElementsKindFromSequenceIndex(index + 1);
    123 }
    124 
    125 
    126 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
    127   return IsFastElementsKind(elements_kind) ||
    128       elements_kind == DICTIONARY_ELEMENTS;
    129 }
    130 
    131 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
    132                                          ElementsKind to_kind) {
    133   if (!IsFastElementsKind(from_kind)) return false;
    134   if (!IsFastTransitionTarget(to_kind)) return false;
    135   DCHECK(!IsFixedTypedArrayElementsKind(from_kind));
    136   DCHECK(!IsFixedTypedArrayElementsKind(to_kind));
    137   switch (from_kind) {
    138     case PACKED_SMI_ELEMENTS:
    139       return to_kind != PACKED_SMI_ELEMENTS;
    140     case HOLEY_SMI_ELEMENTS:
    141       return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS;
    142     case PACKED_DOUBLE_ELEMENTS:
    143       return to_kind != PACKED_SMI_ELEMENTS && to_kind != HOLEY_SMI_ELEMENTS &&
    144              to_kind != PACKED_DOUBLE_ELEMENTS;
    145     case HOLEY_DOUBLE_ELEMENTS:
    146       return to_kind == PACKED_ELEMENTS || to_kind == HOLEY_ELEMENTS;
    147     case PACKED_ELEMENTS:
    148       return to_kind == HOLEY_ELEMENTS;
    149     case HOLEY_ELEMENTS:
    150       return false;
    151     default:
    152       return false;
    153   }
    154 }
    155 
    156 bool UnionElementsKindUptoSize(ElementsKind* a_out, ElementsKind b) {
    157   // Assert that the union of two ElementKinds can be computed via std::max.
    158   static_assert(PACKED_SMI_ELEMENTS < HOLEY_SMI_ELEMENTS,
    159                 "ElementsKind union not computable via std::max.");
    160   static_assert(HOLEY_SMI_ELEMENTS < PACKED_ELEMENTS,
    161                 "ElementsKind union not computable via std::max.");
    162   static_assert(PACKED_ELEMENTS < HOLEY_ELEMENTS,
    163                 "ElementsKind union not computable via std::max.");
    164   static_assert(PACKED_DOUBLE_ELEMENTS < HOLEY_DOUBLE_ELEMENTS,
    165                 "ElementsKind union not computable via std::max.");
    166   ElementsKind a = *a_out;
    167   switch (a) {
    168     case PACKED_SMI_ELEMENTS:
    169       switch (b) {
    170         case PACKED_SMI_ELEMENTS:
    171         case HOLEY_SMI_ELEMENTS:
    172         case PACKED_ELEMENTS:
    173         case HOLEY_ELEMENTS:
    174           *a_out = b;
    175           return true;
    176         default:
    177           return false;
    178       }
    179     case HOLEY_SMI_ELEMENTS:
    180       switch (b) {
    181         case PACKED_SMI_ELEMENTS:
    182         case HOLEY_SMI_ELEMENTS:
    183           *a_out = HOLEY_SMI_ELEMENTS;
    184           return true;
    185         case PACKED_ELEMENTS:
    186         case HOLEY_ELEMENTS:
    187           *a_out = HOLEY_ELEMENTS;
    188           return true;
    189         default:
    190           return false;
    191       }
    192     case PACKED_ELEMENTS:
    193       switch (b) {
    194         case PACKED_SMI_ELEMENTS:
    195         case PACKED_ELEMENTS:
    196           *a_out = PACKED_ELEMENTS;
    197           return true;
    198         case HOLEY_SMI_ELEMENTS:
    199         case HOLEY_ELEMENTS:
    200           *a_out = HOLEY_ELEMENTS;
    201           return true;
    202         default:
    203           return false;
    204       }
    205     case HOLEY_ELEMENTS:
    206       switch (b) {
    207         case PACKED_SMI_ELEMENTS:
    208         case HOLEY_SMI_ELEMENTS:
    209         case PACKED_ELEMENTS:
    210         case HOLEY_ELEMENTS:
    211           *a_out = HOLEY_ELEMENTS;
    212           return true;
    213         default:
    214           return false;
    215       }
    216       break;
    217     case PACKED_DOUBLE_ELEMENTS:
    218       switch (b) {
    219         case PACKED_DOUBLE_ELEMENTS:
    220         case HOLEY_DOUBLE_ELEMENTS:
    221           *a_out = b;
    222           return true;
    223         default:
    224           return false;
    225       }
    226     case HOLEY_DOUBLE_ELEMENTS:
    227       switch (b) {
    228         case PACKED_DOUBLE_ELEMENTS:
    229         case HOLEY_DOUBLE_ELEMENTS:
    230           *a_out = HOLEY_DOUBLE_ELEMENTS;
    231           return true;
    232         default:
    233           return false;
    234       }
    235 
    236       break;
    237     default:
    238       break;
    239   }
    240   return false;
    241 }
    242 
    243 }  // namespace internal
    244 }  // namespace v8
    245