• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ElementsKindToShiftSize(ElementsKind elements_kind)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 FAST_DOUBLE_ELEMENTS:
30     case FAST_HOLEY_DOUBLE_ELEMENTS:
31     case FLOAT64_ELEMENTS:
32       return 3;
33     case FAST_SMI_ELEMENTS:
34     case FAST_ELEMENTS:
35     case FAST_HOLEY_SMI_ELEMENTS:
36     case FAST_HOLEY_ELEMENTS:
37     case DICTIONARY_ELEMENTS:
38     case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
39     case SLOW_SLOPPY_ARGUMENTS_ELEMENTS:
40       return kPointerSizeLog2;
41   }
42   UNREACHABLE();
43   return 0;
44 }
45 
46 
GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind)47 int GetDefaultHeaderSizeForElementsKind(ElementsKind elements_kind) {
48   STATIC_ASSERT(FixedArray::kHeaderSize == FixedDoubleArray::kHeaderSize);
49 
50   if (IsFixedTypedArrayElementsKind(elements_kind)) {
51     return 0;
52   } else {
53     return FixedArray::kHeaderSize - kHeapObjectTag;
54   }
55 }
56 
57 
ElementsKindToString(ElementsKind kind)58 const char* ElementsKindToString(ElementsKind kind) {
59   ElementsAccessor* accessor = ElementsAccessor::ForKind(kind);
60   return accessor->name();
61 }
62 
63 
64 struct InitializeFastElementsKindSequence {
Constructv8::internal::InitializeFastElementsKindSequence65   static void Construct(
66       ElementsKind** fast_elements_kind_sequence_ptr) {
67     ElementsKind* fast_elements_kind_sequence =
68         new ElementsKind[kFastElementsKindCount];
69     *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence;
70     STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND);
71     fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS;
72     fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS;
73     fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS;
74     fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS;
75     fast_elements_kind_sequence[4] = FAST_ELEMENTS;
76     fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS;
77 
78     // Verify that kFastElementsKindPackedToHoley is correct.
79     STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley ==
80                   FAST_HOLEY_SMI_ELEMENTS);
81     STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley ==
82                   FAST_HOLEY_DOUBLE_ELEMENTS);
83     STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley ==
84                   FAST_HOLEY_ELEMENTS);
85   }
86 };
87 
88 
89 static base::LazyInstance<ElementsKind*,
90                           InitializeFastElementsKindSequence>::type
91     fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER;
92 
93 
GetFastElementsKindFromSequenceIndex(int sequence_number)94 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) {
95   DCHECK(sequence_number >= 0 &&
96          sequence_number < kFastElementsKindCount);
97   return fast_elements_kind_sequence.Get()[sequence_number];
98 }
99 
100 
GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind)101 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) {
102   for (int i = 0; i < kFastElementsKindCount; ++i) {
103     if (fast_elements_kind_sequence.Get()[i] == elements_kind) {
104       return i;
105     }
106   }
107   UNREACHABLE();
108   return 0;
109 }
110 
111 
GetNextTransitionElementsKind(ElementsKind kind)112 ElementsKind GetNextTransitionElementsKind(ElementsKind kind) {
113   int index = GetSequenceIndexFromFastElementsKind(kind);
114   return GetFastElementsKindFromSequenceIndex(index + 1);
115 }
116 
117 
IsFastTransitionTarget(ElementsKind elements_kind)118 static inline bool IsFastTransitionTarget(ElementsKind elements_kind) {
119   return IsFastElementsKind(elements_kind) ||
120       elements_kind == DICTIONARY_ELEMENTS;
121 }
122 
IsMoreGeneralElementsKindTransition(ElementsKind from_kind,ElementsKind to_kind)123 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind,
124                                          ElementsKind to_kind) {
125   if (IsFixedTypedArrayElementsKind(from_kind) ||
126       IsFixedTypedArrayElementsKind(to_kind)) {
127     return false;
128   }
129   if (IsFastElementsKind(from_kind) && IsFastTransitionTarget(to_kind)) {
130     switch (from_kind) {
131       case FAST_SMI_ELEMENTS:
132         return to_kind != FAST_SMI_ELEMENTS;
133       case FAST_HOLEY_SMI_ELEMENTS:
134         return to_kind != FAST_SMI_ELEMENTS &&
135             to_kind != FAST_HOLEY_SMI_ELEMENTS;
136       case FAST_DOUBLE_ELEMENTS:
137         return to_kind != FAST_SMI_ELEMENTS &&
138             to_kind != FAST_HOLEY_SMI_ELEMENTS &&
139             to_kind != FAST_DOUBLE_ELEMENTS;
140       case FAST_HOLEY_DOUBLE_ELEMENTS:
141         return to_kind == FAST_ELEMENTS ||
142             to_kind == FAST_HOLEY_ELEMENTS;
143       case FAST_ELEMENTS:
144         return to_kind == FAST_HOLEY_ELEMENTS;
145       case FAST_HOLEY_ELEMENTS:
146         return false;
147       default:
148         return false;
149     }
150   }
151   return false;
152 }
153 
154 
155 }  // namespace internal
156 }  // namespace v8
157