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
transitions()20 TransitionArray* TransitionsAccessor::transitions() {
21 DCHECK_EQ(kFullTransitionArray, encoding());
22 return TransitionArray::cast(raw_transitions_->ToStrongHeapObject());
23 }
24
CAST_ACCESSOR(TransitionArray)25 CAST_ACCESSOR(TransitionArray)
26
27 bool TransitionArray::HasPrototypeTransitions() {
28 return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::kZero);
29 }
30
GetPrototypeTransitions()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
GetKeySlot(int transition_number)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
SetPrototypeTransitions(WeakFixedArray * transitions)44 void TransitionArray::SetPrototypeTransitions(WeakFixedArray* transitions) {
45 DCHECK(transitions->IsWeakFixedArray());
46 WeakFixedArray::Set(kPrototypeTransitionsIndex,
47 HeapObjectReference::Strong(transitions));
48 }
49
NumberOfPrototypeTransitions(WeakFixedArray * proto_transitions)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
GetKey(int transition_number)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
GetKey(int transition_number)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
SetKey(int transition_number,Name * key)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
GetTargetSlot(int transition_number)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
GetTargetDetails(Name * name,Map * target)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
GetTargetFromRaw(MaybeObject * raw)102 Map* TransitionsAccessor::GetTargetFromRaw(MaybeObject* raw) {
103 return Map::cast(raw->ToWeakHeapObject());
104 }
105
GetRawTarget(int transition_number)106 MaybeObject* TransitionArray::GetRawTarget(int transition_number) {
107 DCHECK(transition_number < number_of_transitions());
108 return Get(ToTargetIndex(transition_number));
109 }
110
GetTarget(int transition_number)111 Map* TransitionArray::GetTarget(int transition_number) {
112 MaybeObject* raw = GetRawTarget(transition_number);
113 return TransitionsAccessor::GetTargetFromRaw(raw);
114 }
115
GetTarget(int transition_number)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
SetRawTarget(int transition_number,MaybeObject * value)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
GetTargetIfExists(int transition_number,Isolate * isolate,Map ** target)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
SearchName(Name * name,int * out_insertion_index)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
number_of_transitions()154 int TransitionArray::number_of_transitions() const {
155 if (length() < kFirstIndex) return 0;
156 return Smi::ToInt(Get(kTransitionLengthIndex)->ToSmi());
157 }
158
CompareKeys(Name * key1,uint32_t hash1,PropertyKind kind1,PropertyAttributes attributes1,Name * key2,uint32_t hash2,PropertyKind kind2,PropertyAttributes attributes2)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
CompareNames(Name * key1,uint32_t hash1,Name * key2,uint32_t hash2)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
CompareDetails(PropertyKind kind1,PropertyAttributes attributes1,PropertyKind kind2,PropertyAttributes attributes2)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
Set(int transition_number,Name * key,MaybeObject * target)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
Capacity()202 int TransitionArray::Capacity() {
203 if (length() <= kFirstIndex) return 0;
204 return (length() - kFirstIndex) / kEntrySize;
205 }
206
SetNumberOfTransitions(int number_of_transitions)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