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 #include "src/ic/handler-configuration-inl.h" 11 #include "src/objects/fixed-array-inl.h" 12 #include "src/objects/maybe-object-inl.h" 13 14 // Has to be the last include (doesn't have include guards): 15 #include "src/objects/object-macros.h" 16 17 namespace v8 { 18 namespace internal { 19 20 TransitionArray* TransitionsAccessor::transitions() { 21 DCHECK_EQ(kFullTransitionArray, encoding()); 22 return TransitionArray::cast(raw_transitions_->ToStrongHeapObject()); 23 } 24 25 CAST_ACCESSOR(TransitionArray) 26 27 bool TransitionArray::HasPrototypeTransitions() { 28 return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero); 29 } 30 31 WeakFixedArray* TransitionArray::GetPrototypeTransitions() { 32 DCHECK(HasPrototypeTransitions()); // Callers must check first. 33 Object* prototype_transitions = 34 Get(kPrototypeTransitionsIndex)->ToStrongHeapObject(); 35 return WeakFixedArray::cast(prototype_transitions); 36 } 37 38 HeapObjectReference** TransitionArray::GetKeySlot(int transition_number) { 39 DCHECK(transition_number < number_of_transitions()); 40 return reinterpret_cast<HeapObjectReference**>( 41 RawFieldOfElementAt(ToKeyIndex(transition_number))); 42 } 43 44 void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) { 45 DCHECK(transitions->IsWeakFixedArray()); 46 WeakFixedArray::Set(kPrototypeTransitionsIndex, 47 HeapObjectReference::Strong(transitions)); 48 } 49 50 int TransitionArray::NumberOfPrototypeTransitions( 51 WeakFixedArray* proto_transitions) { 52 if (proto_transitions->length() == 0) return 0; 53 MaybeObject* raw = 54 proto_transitions->Get(kProtoTransitionNumberOfEntriesOffset); 55 return Smi::ToInt(raw->ToSmi()); 56 } 57 58 Name* TransitionArray::GetKey(int transition_number) { 59 DCHECK(transition_number < number_of_transitions()); 60 return Name::cast(Get(ToKeyIndex(transition_number))->ToStrongHeapObject()); 61 } 62 63 Name* TransitionsAccessor::GetKey(int transition_number) { 64 switch (encoding()) { 65 case kPrototypeInfo: 66 case kUninitialized: 67 UNREACHABLE(); 68 return nullptr; 69 case kWeakRef: { 70 Map* map = Map::cast(raw_transitions_->ToWeakHeapObject()); 71 return GetSimpleTransitionKey(map); 72 } 73 case kFullTransitionArray: 74 return transitions()->GetKey(transition_number); 75 } 76 UNREACHABLE(); 77 } 78 79 void TransitionArray::SetKey(int transition_number, Name* key) { 80 DCHECK(transition_number < number_of_transitions()); 81 WeakFixedArray::Set(ToKeyIndex(transition_number), 82 HeapObjectReference::Strong(key)); 83 } 84 85 HeapObjectReference** TransitionArray::GetTargetSlot(int transition_number) { 86 DCHECK(transition_number < number_of_transitions()); 87 return reinterpret_cast<HeapObjectReference**>( 88 RawFieldOfElementAt(ToTargetIndex(transition_number))); 89 } 90 91 // static 92 PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) { 93 DCHECK(!IsSpecialTransition(name->GetReadOnlyRoots(), name)); 94 int descriptor = target->LastAdded(); 95 DescriptorArray* descriptors = target->instance_descriptors(); 96 // Transitions are allowed only for the last added property. 97 DCHECK(descriptors->GetKey(descriptor)->Equals(name)); 98 return descriptors->GetDetails(descriptor); 99 } 100 101 // static 102 Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) { 103 return Map::cast(raw->ToWeakHeapObject()); 104 } 105 106 MaybeObject* TransitionArray::GetRawTarget(int transition_number) { 107 DCHECK(transition_number < number_of_transitions()); 108 return Get(ToTargetIndex(transition_number)); 109 } 110 111 Map* TransitionArray::GetTarget(int transition_number) { 112 MaybeObject* raw = GetRawTarget(transition_number); 113 return TransitionsAccessor::GetTargetFromRaw(raw); 114 } 115 116 Map* TransitionsAccessor::GetTarget(int transition_number) { 117 switch (encoding()) { 118 case kPrototypeInfo: 119 case kUninitialized: 120 UNREACHABLE(); 121 return nullptr; 122 case kWeakRef: 123 return Map::cast(raw_transitions_->ToWeakHeapObject()); 124 case kFullTransitionArray: 125 return transitions()->GetTarget(transition_number); 126 } 127 UNREACHABLE(); 128 } 129 130 void TransitionArray::SetRawTarget(int transition_number, MaybeObject* value) { 131 DCHECK(transition_number < number_of_transitions()); 132 DCHECK(value->IsWeakHeapObject() && value->ToWeakHeapObject()->IsMap()); 133 WeakFixedArray::Set(ToTargetIndex(transition_number), value); 134 } 135 136 bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate, 137 Map** target) { 138 MaybeObject* raw = GetRawTarget(transition_number); 139 HeapObject* heap_object; 140 if (raw->ToStrongHeapObject(&heap_object) && 141 heap_object->IsUndefined(isolate)) { 142 return false; 143 } 144 *target = TransitionsAccessor::GetTargetFromRaw(raw); 145 return true; 146 } 147 148 int TransitionArray::SearchName(Name* name, int* out_insertion_index) { 149 DCHECK(name->IsUniqueName()); 150 return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(), 151 out_insertion_index); 152 } 153 154 int TransitionArray::number_of_transitions() const { 155 if (length() < kFirstIndex) return 0; 156 return Smi::ToInt(Get(kTransitionLengthIndex)->ToSmi()); 157 } 158 159 int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1, 160 PropertyAttributes attributes1, Name* key2, 161 uint32_t hash2, PropertyKind kind2, 162 PropertyAttributes attributes2) { 163 int cmp = CompareNames(key1, hash1, key2, hash2); 164 if (cmp != 0) return cmp; 165 166 return CompareDetails(kind1, attributes1, kind2, attributes2); 167 } 168 169 int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2, 170 uint32_t hash2) { 171 if (key1 != key2) { 172 // In case of hash collisions key1 is always "less" than key2. 173 return hash1 <= hash2 ? -1 : 1; 174 } 175 176 return 0; 177 } 178 179 int TransitionArray::CompareDetails(PropertyKind kind1, 180 PropertyAttributes attributes1, 181 PropertyKind kind2, 182 PropertyAttributes attributes2) { 183 if (kind1 != kind2) { 184 return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1; 185 } 186 187 if (attributes1 != attributes2) { 188 return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1 189 : 1; 190 } 191 192 return 0; 193 } 194 195 void TransitionArray::Set(int transition_number, Name* key, 196 MaybeObject* target) { 197 WeakFixedArray::Set(ToKeyIndex(transition_number), 198 MaybeObject::FromObject(key)); 199 WeakFixedArray::Set(ToTargetIndex(transition_number), target); 200 } 201 202 int TransitionArray::Capacity() { 203 if (length() <= kFirstIndex) return 0; 204 return (length() - kFirstIndex) / kEntrySize; 205 } 206 207 void TransitionArray::SetNumberOfTransitions(int number_of_transitions) { 208 DCHECK(number_of_transitions <= Capacity()); 209 WeakFixedArray::Set( 210 kTransitionLengthIndex, 211 MaybeObject::FromSmi(Smi::FromInt(number_of_transitions))); 212 } 213 214 } // namespace internal 215 } // namespace v8 216 217 #include "src/objects/object-macros-undef.h" 218 219 #endif // V8_TRANSITIONS_INL_H_ 220