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