1 // Copyright 2012 the V8 project authors. All rights reserved. 2 // Redistribution and use in source and binary forms, with or without 3 // modification, are permitted provided that the following conditions are 4 // met: 5 // 6 // * Redistributions of source code must retain the above copyright 7 // notice, this list of conditions and the following disclaimer. 8 // * Redistributions in binary form must reproduce the above 9 // copyright notice, this list of conditions and the following 10 // disclaimer in the documentation and/or other materials provided 11 // with the distribution. 12 // * Neither the name of Google Inc. nor the names of its 13 // contributors may be used to endorse or promote products derived 14 // from this software without specific prior written permission. 15 // 16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 #include "elements-kind.h" 29 30 #include "api.h" 31 #include "elements.h" 32 #include "objects.h" 33 34 namespace v8 { 35 namespace internal { 36 37 38 int ElementsKindToShiftSize(ElementsKind elements_kind) { 39 switch (elements_kind) { 40 case EXTERNAL_BYTE_ELEMENTS: 41 case EXTERNAL_PIXEL_ELEMENTS: 42 case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 43 return 0; 44 case EXTERNAL_SHORT_ELEMENTS: 45 case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 46 return 1; 47 case EXTERNAL_INT_ELEMENTS: 48 case EXTERNAL_UNSIGNED_INT_ELEMENTS: 49 case EXTERNAL_FLOAT_ELEMENTS: 50 return 2; 51 case EXTERNAL_DOUBLE_ELEMENTS: 52 case FAST_DOUBLE_ELEMENTS: 53 case FAST_HOLEY_DOUBLE_ELEMENTS: 54 return 3; 55 case FAST_SMI_ELEMENTS: 56 case FAST_ELEMENTS: 57 case FAST_HOLEY_SMI_ELEMENTS: 58 case FAST_HOLEY_ELEMENTS: 59 case DICTIONARY_ELEMENTS: 60 case NON_STRICT_ARGUMENTS_ELEMENTS: 61 return kPointerSizeLog2; 62 } 63 UNREACHABLE(); 64 return 0; 65 } 66 67 68 const char* ElementsKindToString(ElementsKind kind) { 69 ElementsAccessor* accessor = ElementsAccessor::ForKind(kind); 70 return accessor->name(); 71 } 72 73 74 void PrintElementsKind(FILE* out, ElementsKind kind) { 75 PrintF(out, "%s", ElementsKindToString(kind)); 76 } 77 78 79 ElementsKind GetInitialFastElementsKind() { 80 if (FLAG_packed_arrays) { 81 return FAST_SMI_ELEMENTS; 82 } else { 83 return FAST_HOLEY_SMI_ELEMENTS; 84 } 85 } 86 87 88 struct InitializeFastElementsKindSequence { 89 static void Construct( 90 ElementsKind** fast_elements_kind_sequence_ptr) { 91 ElementsKind* fast_elements_kind_sequence = 92 new ElementsKind[kFastElementsKindCount]; 93 *fast_elements_kind_sequence_ptr = fast_elements_kind_sequence; 94 STATIC_ASSERT(FAST_SMI_ELEMENTS == FIRST_FAST_ELEMENTS_KIND); 95 fast_elements_kind_sequence[0] = FAST_SMI_ELEMENTS; 96 fast_elements_kind_sequence[1] = FAST_HOLEY_SMI_ELEMENTS; 97 fast_elements_kind_sequence[2] = FAST_DOUBLE_ELEMENTS; 98 fast_elements_kind_sequence[3] = FAST_HOLEY_DOUBLE_ELEMENTS; 99 fast_elements_kind_sequence[4] = FAST_ELEMENTS; 100 fast_elements_kind_sequence[5] = FAST_HOLEY_ELEMENTS; 101 102 // Verify that kFastElementsKindPackedToHoley is correct. 103 STATIC_ASSERT(FAST_SMI_ELEMENTS + kFastElementsKindPackedToHoley == 104 FAST_HOLEY_SMI_ELEMENTS); 105 STATIC_ASSERT(FAST_DOUBLE_ELEMENTS + kFastElementsKindPackedToHoley == 106 FAST_HOLEY_DOUBLE_ELEMENTS); 107 STATIC_ASSERT(FAST_ELEMENTS + kFastElementsKindPackedToHoley == 108 FAST_HOLEY_ELEMENTS); 109 } 110 }; 111 112 113 static LazyInstance<ElementsKind*, 114 InitializeFastElementsKindSequence>::type 115 fast_elements_kind_sequence = LAZY_INSTANCE_INITIALIZER; 116 117 118 ElementsKind GetFastElementsKindFromSequenceIndex(int sequence_number) { 119 ASSERT(sequence_number >= 0 && 120 sequence_number < kFastElementsKindCount); 121 return fast_elements_kind_sequence.Get()[sequence_number]; 122 } 123 124 125 int GetSequenceIndexFromFastElementsKind(ElementsKind elements_kind) { 126 for (int i = 0; i < kFastElementsKindCount; ++i) { 127 if (fast_elements_kind_sequence.Get()[i] == elements_kind) { 128 return i; 129 } 130 } 131 UNREACHABLE(); 132 return 0; 133 } 134 135 136 ElementsKind GetNextMoreGeneralFastElementsKind(ElementsKind elements_kind, 137 bool allow_only_packed) { 138 ASSERT(IsFastElementsKind(elements_kind)); 139 ASSERT(elements_kind != TERMINAL_FAST_ELEMENTS_KIND); 140 while (true) { 141 int index = 142 GetSequenceIndexFromFastElementsKind(elements_kind) + 1; 143 elements_kind = GetFastElementsKindFromSequenceIndex(index); 144 if (!IsFastHoleyElementsKind(elements_kind) || !allow_only_packed) { 145 return elements_kind; 146 } 147 } 148 UNREACHABLE(); 149 return TERMINAL_FAST_ELEMENTS_KIND; 150 } 151 152 153 bool IsMoreGeneralElementsKindTransition(ElementsKind from_kind, 154 ElementsKind to_kind) { 155 switch (from_kind) { 156 case FAST_SMI_ELEMENTS: 157 return to_kind != FAST_SMI_ELEMENTS; 158 case FAST_HOLEY_SMI_ELEMENTS: 159 return to_kind != FAST_SMI_ELEMENTS && 160 to_kind != FAST_HOLEY_SMI_ELEMENTS; 161 case FAST_DOUBLE_ELEMENTS: 162 return to_kind != FAST_SMI_ELEMENTS && 163 to_kind != FAST_HOLEY_SMI_ELEMENTS && 164 to_kind != FAST_DOUBLE_ELEMENTS; 165 case FAST_HOLEY_DOUBLE_ELEMENTS: 166 return to_kind == FAST_ELEMENTS || 167 to_kind == FAST_HOLEY_ELEMENTS; 168 case FAST_ELEMENTS: 169 return to_kind == FAST_HOLEY_ELEMENTS; 170 case FAST_HOLEY_ELEMENTS: 171 return false; 172 default: 173 return false; 174 } 175 } 176 177 178 } } // namespace v8::internal 179