Line data Source code
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 : #include "src/objects/slots.h"
14 : #include "src/objects/smi.h"
15 :
16 : // Has to be the last include (doesn't have include guards):
17 : #include "src/objects/object-macros.h"
18 :
19 : namespace v8 {
20 : namespace internal {
21 :
22 : TransitionArray TransitionsAccessor::transitions() {
23 : DCHECK_EQ(kFullTransitionArray, encoding());
24 : return TransitionArray::cast(raw_transitions_->GetHeapObjectAssumeStrong());
25 : }
26 :
27 : OBJECT_CONSTRUCTORS_IMPL(TransitionArray, WeakFixedArray)
28 :
29 : CAST_ACCESSOR(TransitionArray)
30 :
31 : bool TransitionArray::HasPrototypeTransitions() {
32 : return Get(kPrototypeTransitionsIndex) != MaybeObject::FromSmi(Smi::zero());
33 : }
34 :
35 : WeakFixedArray TransitionArray::GetPrototypeTransitions() {
36 : DCHECK(HasPrototypeTransitions()); // Callers must check first.
37 : Object prototype_transitions =
38 : Get(kPrototypeTransitionsIndex)->GetHeapObjectAssumeStrong();
39 : return WeakFixedArray::cast(prototype_transitions);
40 : }
41 :
42 : HeapObjectSlot TransitionArray::GetKeySlot(int transition_number) {
43 : DCHECK(transition_number < number_of_transitions());
44 : return HeapObjectSlot(RawFieldOfElementAt(ToKeyIndex(transition_number)));
45 : }
46 :
47 : void TransitionArray::SetPrototypeTransitions(WeakFixedArray transitions) {
48 : DCHECK(transitions->IsWeakFixedArray());
49 : WeakFixedArray::Set(kPrototypeTransitionsIndex,
50 136337 : HeapObjectReference::Strong(transitions));
51 : }
52 :
53 617685 : int TransitionArray::NumberOfPrototypeTransitions(
54 : WeakFixedArray proto_transitions) {
55 617685 : if (proto_transitions->length() == 0) return 0;
56 : MaybeObject raw =
57 : proto_transitions->Get(kProtoTransitionNumberOfEntriesOffset);
58 : return raw.ToSmi().value();
59 : }
60 :
61 91843808 : Name TransitionArray::GetKey(int transition_number) {
62 : DCHECK(transition_number < number_of_transitions());
63 : return Name::cast(
64 91843808 : Get(ToKeyIndex(transition_number))->GetHeapObjectAssumeStrong());
65 : }
66 :
67 210 : Name TransitionsAccessor::GetKey(int transition_number) {
68 210 : switch (encoding()) {
69 : case kPrototypeInfo:
70 : case kUninitialized:
71 : case kMigrationTarget:
72 0 : UNREACHABLE();
73 : return Name();
74 : case kWeakRef: {
75 5 : Map map = Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
76 5 : return GetSimpleTransitionKey(map);
77 : }
78 : case kFullTransitionArray:
79 205 : return transitions()->GetKey(transition_number);
80 : }
81 0 : UNREACHABLE();
82 : }
83 :
84 : void TransitionArray::SetKey(int transition_number, Name key) {
85 : DCHECK(transition_number < number_of_transitions());
86 10 : WeakFixedArray::Set(ToKeyIndex(transition_number),
87 22324330 : HeapObjectReference::Strong(key));
88 : }
89 :
90 : HeapObjectSlot TransitionArray::GetTargetSlot(int transition_number) {
91 : DCHECK(transition_number < number_of_transitions());
92 : return HeapObjectSlot(RawFieldOfElementAt(ToTargetIndex(transition_number)));
93 : }
94 :
95 : // static
96 12081401 : PropertyDetails TransitionsAccessor::GetTargetDetails(Name name, Map target) {
97 : DCHECK(!IsSpecialTransition(name->GetReadOnlyRoots(), name));
98 : int descriptor = target->LastAdded();
99 12081401 : DescriptorArray descriptors = target->instance_descriptors();
100 : // Transitions are allowed only for the last added property.
101 : DCHECK(descriptors->GetKey(descriptor)->Equals(name));
102 12081401 : return descriptors->GetDetails(descriptor);
103 : }
104 :
105 : // static
106 : PropertyDetails TransitionsAccessor::GetSimpleTargetDetails(Map transition) {
107 21847147 : return transition->GetLastDescriptorDetails();
108 : }
109 :
110 : // static
111 21908191 : Name TransitionsAccessor::GetSimpleTransitionKey(Map transition) {
112 : int descriptor = transition->LastAdded();
113 21908191 : return transition->instance_descriptors()->GetKey(descriptor);
114 : }
115 :
116 : // static
117 : Map TransitionsAccessor::GetTargetFromRaw(MaybeObject raw) {
118 : return Map::cast(raw->GetHeapObjectAssumeWeak());
119 : }
120 :
121 32295155 : MaybeObject TransitionArray::GetRawTarget(int transition_number) {
122 : DCHECK(transition_number < number_of_transitions());
123 32295155 : return Get(ToTargetIndex(transition_number));
124 : }
125 :
126 : Map TransitionArray::GetTarget(int transition_number) {
127 20532630 : MaybeObject raw = GetRawTarget(transition_number);
128 : return TransitionsAccessor::GetTargetFromRaw(raw);
129 : }
130 :
131 23033609 : Map TransitionsAccessor::GetTarget(int transition_number) {
132 23033609 : switch (encoding()) {
133 : case kPrototypeInfo:
134 : case kUninitialized:
135 : case kMigrationTarget:
136 0 : UNREACHABLE();
137 : return Map();
138 : case kWeakRef:
139 : return Map::cast(raw_transitions_->GetHeapObjectAssumeWeak());
140 : case kFullTransitionArray:
141 4154 : return transitions()->GetTarget(transition_number);
142 : }
143 0 : UNREACHABLE();
144 : }
145 :
146 : void TransitionArray::SetRawTarget(int transition_number, MaybeObject value) {
147 : DCHECK(transition_number < number_of_transitions());
148 : DCHECK(value->IsWeak());
149 : DCHECK(value->GetHeapObjectAssumeWeak()->IsMap());
150 11162768 : WeakFixedArray::Set(ToTargetIndex(transition_number), value);
151 : }
152 :
153 511075 : bool TransitionArray::GetTargetIfExists(int transition_number, Isolate* isolate,
154 : Map* target) {
155 511075 : MaybeObject raw = GetRawTarget(transition_number);
156 : HeapObject heap_object;
157 511075 : if (raw->GetHeapObjectIfStrong(&heap_object) &&
158 : heap_object->IsUndefined(isolate)) {
159 : return false;
160 : }
161 511075 : *target = TransitionsAccessor::GetTargetFromRaw(raw);
162 511075 : return true;
163 : }
164 :
165 1200 : int TransitionArray::SearchNameForTesting(Name name, int* out_insertion_index) {
166 1200 : return SearchName(name, out_insertion_index);
167 : }
168 :
169 8244062 : int TransitionArray::SearchSpecial(Symbol symbol, int* out_insertion_index) {
170 8244063 : return SearchName(symbol, out_insertion_index);
171 : }
172 :
173 : int TransitionArray::SearchName(Name name, int* out_insertion_index) {
174 : DCHECK(name->IsUniqueName());
175 : return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
176 20569319 : out_insertion_index);
177 : }
178 :
179 42320372 : int TransitionArray::number_of_transitions() const {
180 42320372 : if (length() < kFirstIndex) return 0;
181 : return Get(kTransitionLengthIndex).ToSmi().value();
182 : }
183 :
184 : int TransitionArray::CompareKeys(Name key1, uint32_t hash1, PropertyKind kind1,
185 : PropertyAttributes attributes1, Name key2,
186 : uint32_t hash2, PropertyKind kind2,
187 : PropertyAttributes attributes2) {
188 : int cmp = CompareNames(key1, hash1, key2, hash2);
189 5 : if (cmp != 0) return cmp;
190 :
191 : return CompareDetails(kind1, attributes1, kind2, attributes2);
192 : }
193 :
194 : int TransitionArray::CompareNames(Name key1, uint32_t hash1, Name key2,
195 : uint32_t hash2) {
196 5 : if (key1 != key2) {
197 : // In case of hash collisions key1 is always "less" than key2.
198 5 : return hash1 <= hash2 ? -1 : 1;
199 : }
200 :
201 : return 0;
202 : }
203 :
204 : int TransitionArray::CompareDetails(PropertyKind kind1,
205 : PropertyAttributes attributes1,
206 : PropertyKind kind2,
207 : PropertyAttributes attributes2) {
208 11790753 : if (kind1 != kind2) {
209 14467 : return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
210 : }
211 :
212 11776286 : if (attributes1 != attributes2) {
213 24050 : return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
214 24050 : : 1;
215 : }
216 :
217 : return 0;
218 : }
219 :
220 541253 : void TransitionArray::Set(int transition_number, Name key, MaybeObject target) {
221 541253 : WeakFixedArray::Set(ToKeyIndex(transition_number),
222 607189 : MaybeObject::FromObject(key));
223 607187 : WeakFixedArray::Set(ToTargetIndex(transition_number), target);
224 541253 : }
225 :
226 : Name TransitionArray::GetSortedKey(int transition_number) {
227 25934134 : return GetKey(transition_number);
228 : }
229 :
230 : int TransitionArray::number_of_entries() const {
231 29749060 : return number_of_transitions();
232 : }
233 :
234 : int TransitionArray::Capacity() {
235 469371 : if (length() <= kFirstIndex) return 0;
236 465308 : return (length() - kFirstIndex) / kEntrySize;
237 : }
238 :
239 : void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
240 : DCHECK(number_of_transitions <= Capacity());
241 72227 : WeakFixedArray::Set(
242 : kTransitionLengthIndex,
243 469370 : MaybeObject::FromSmi(Smi::FromInt(number_of_transitions)));
244 : }
245 :
246 : } // namespace internal
247 : } // namespace v8
248 :
249 : #include "src/objects/object-macros-undef.h"
250 :
251 : #endif // V8_TRANSITIONS_INL_H_
|