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 #ifndef V8_TRANSITIONS_INL_H_ 6 #define V8_TRANSITIONS_INL_H_ 7 8 #include "src/transitions.h" 9 10 namespace v8 { 11 namespace internal { 12 13 14 TransitionArray* TransitionArray::cast(Object* object) { 15 DCHECK(object->IsTransitionArray()); 16 return reinterpret_cast<TransitionArray*>(object); 17 } 18 19 20 Object* TransitionArray::next_link() { return get(kNextLinkIndex); } 21 22 23 void TransitionArray::set_next_link(Object* next, WriteBarrierMode mode) { 24 return set(kNextLinkIndex, next, mode); 25 } 26 27 28 bool TransitionArray::HasPrototypeTransitions() { 29 return get(kPrototypeTransitionsIndex) != Smi::FromInt(0); 30 } 31 32 33 FixedArray* TransitionArray::GetPrototypeTransitions() { 34 DCHECK(HasPrototypeTransitions()); // Callers must check first. 35 Object* prototype_transitions = get(kPrototypeTransitionsIndex); 36 return FixedArray::cast(prototype_transitions); 37 } 38 39 40 void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) { 41 DCHECK(transitions->IsFixedArray()); 42 set(kPrototypeTransitionsIndex, transitions); 43 } 44 45 46 Object** TransitionArray::GetPrototypeTransitionsSlot() { 47 return RawFieldOfElementAt(kPrototypeTransitionsIndex); 48 } 49 50 51 Object** TransitionArray::GetKeySlot(int transition_number) { 52 DCHECK(transition_number < number_of_transitions()); 53 return RawFieldOfElementAt(ToKeyIndex(transition_number)); 54 } 55 56 57 Name* TransitionArray::GetKey(int transition_number) { 58 DCHECK(transition_number < number_of_transitions()); 59 return Name::cast(get(ToKeyIndex(transition_number))); 60 } 61 62 63 Name* TransitionArray::GetKey(Object* raw_transitions, int transition_number) { 64 if (IsSimpleTransition(raw_transitions)) { 65 DCHECK(transition_number == 0); 66 return GetSimpleTransitionKey(GetSimpleTransition(raw_transitions)); 67 } 68 DCHECK(IsFullTransitionArray(raw_transitions)); 69 return TransitionArray::cast(raw_transitions)->GetKey(transition_number); 70 } 71 72 73 void TransitionArray::SetKey(int transition_number, Name* key) { 74 DCHECK(transition_number < number_of_transitions()); 75 set(ToKeyIndex(transition_number), key); 76 } 77 78 79 Map* TransitionArray::GetTarget(int transition_number) { 80 DCHECK(transition_number < number_of_transitions()); 81 return Map::cast(get(ToTargetIndex(transition_number))); 82 } 83 84 85 Map* TransitionArray::GetTarget(Object* raw_transitions, 86 int transition_number) { 87 if (IsSimpleTransition(raw_transitions)) { 88 DCHECK(transition_number == 0); 89 return GetSimpleTransition(raw_transitions); 90 } 91 DCHECK(IsFullTransitionArray(raw_transitions)); 92 return TransitionArray::cast(raw_transitions)->GetTarget(transition_number); 93 } 94 95 96 void TransitionArray::SetTarget(int transition_number, Map* value) { 97 DCHECK(transition_number < number_of_transitions()); 98 set(ToTargetIndex(transition_number), value); 99 } 100 101 102 int TransitionArray::SearchName(Name* name, int* out_insertion_index) { 103 return internal::Search<ALL_ENTRIES>(this, name, 0, out_insertion_index); 104 } 105 106 107 #ifdef DEBUG 108 bool TransitionArray::IsSpecialTransition(Name* name) { 109 if (!name->IsSymbol()) return false; 110 Heap* heap = name->GetHeap(); 111 return name == heap->nonextensible_symbol() || 112 name == heap->sealed_symbol() || name == heap->frozen_symbol() || 113 name == heap->elements_transition_symbol() || 114 name == heap->strict_function_transition_symbol() || 115 name == heap->strong_function_transition_symbol() || 116 name == heap->observed_symbol(); 117 } 118 #endif 119 120 121 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1, 122 PropertyAttributes attributes1, Name* key2, 123 uint32_t hash2, PropertyKind kind2, 124 PropertyAttributes attributes2) { 125 int cmp = CompareNames(key1, hash1, key2, hash2); 126 if (cmp != 0) return cmp; 127 128 return CompareDetails(kind1, attributes1, kind2, attributes2); 129 } 130 131 132 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2, 133 uint32_t hash2) { 134 if (key1 != key2) { 135 // In case of hash collisions key1 is always "less" than key2. 136 return hash1 <= hash2 ? -1 : 1; 137 } 138 139 return 0; 140 } 141 142 143 int TransitionArray::CompareDetails(PropertyKind kind1, 144 PropertyAttributes attributes1, 145 PropertyKind kind2, 146 PropertyAttributes attributes2) { 147 if (kind1 != kind2) { 148 return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1; 149 } 150 151 if (attributes1 != attributes2) { 152 return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1 153 : 1; 154 } 155 156 return 0; 157 } 158 159 160 PropertyDetails TransitionArray::GetTargetDetails(Name* name, Map* target) { 161 DCHECK(!IsSpecialTransition(name)); 162 int descriptor = target->LastAdded(); 163 DescriptorArray* descriptors = target->instance_descriptors(); 164 // Transitions are allowed only for the last added property. 165 DCHECK(descriptors->GetKey(descriptor)->Equals(name)); 166 return descriptors->GetDetails(descriptor); 167 } 168 169 170 void TransitionArray::Set(int transition_number, Name* key, Map* target) { 171 set(ToKeyIndex(transition_number), key); 172 set(ToTargetIndex(transition_number), target); 173 } 174 175 176 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) { 177 DCHECK(number_of_transitions <= Capacity(this)); 178 set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); 179 } 180 181 } // namespace internal 182 } // namespace v8 183 184 #endif // V8_TRANSITIONS_INL_H_ 185