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 :
12 : namespace v8 {
13 : namespace internal {
14 :
15 : template <TransitionsAccessor::Encoding enc>
16 : WeakCell* TransitionsAccessor::GetTargetCell() {
17 : DCHECK(!needs_reload_);
18 46563197 : if (target_cell_ != nullptr) return target_cell_;
19 : if (enc == kWeakCell) {
20 26781564 : target_cell_ = WeakCell::cast(raw_transitions_);
21 : } else if (enc == kHandler) {
22 251191 : target_cell_ = StoreHandler::GetTransitionCell(raw_transitions_);
23 : } else {
24 : UNREACHABLE();
25 : }
26 : return target_cell_;
27 : }
28 :
29 : TransitionArray* TransitionsAccessor::transitions() {
30 : DCHECK_EQ(kFullTransitionArray, encoding());
31 : return TransitionArray::cast(raw_transitions_);
32 : }
33 :
34 : // static
35 659042 : TransitionArray* TransitionArray::cast(Object* object) {
36 : DCHECK(object->IsTransitionArray());
37 659042 : return reinterpret_cast<TransitionArray*>(object);
38 : }
39 :
40 :
41 : bool TransitionArray::HasPrototypeTransitions() {
42 : return get(kPrototypeTransitionsIndex) != Smi::kZero;
43 : }
44 :
45 :
46 : FixedArray* TransitionArray::GetPrototypeTransitions() {
47 : DCHECK(HasPrototypeTransitions()); // Callers must check first.
48 : Object* prototype_transitions = get(kPrototypeTransitionsIndex);
49 : return FixedArray::cast(prototype_transitions);
50 : }
51 :
52 :
53 : void TransitionArray::SetPrototypeTransitions(FixedArray* transitions) {
54 : DCHECK(transitions->IsFixedArray());
55 182456 : set(kPrototypeTransitionsIndex, transitions);
56 : }
57 :
58 :
59 : Object** TransitionArray::GetPrototypeTransitionsSlot() {
60 : return RawFieldOfElementAt(kPrototypeTransitionsIndex);
61 : }
62 :
63 :
64 : Object** TransitionArray::GetKeySlot(int transition_number) {
65 : DCHECK(transition_number < number_of_transitions());
66 : return RawFieldOfElementAt(ToKeyIndex(transition_number));
67 : }
68 :
69 :
70 : Name* TransitionArray::GetKey(int transition_number) {
71 : DCHECK(transition_number < number_of_transitions());
72 : return Name::cast(get(ToKeyIndex(transition_number)));
73 : }
74 :
75 504 : Name* TransitionsAccessor::GetKey(int transition_number) {
76 : WeakCell* cell = nullptr;
77 252 : switch (encoding()) {
78 : case kPrototypeInfo:
79 : case kUninitialized:
80 0 : UNREACHABLE();
81 : return nullptr;
82 : case kWeakCell:
83 : cell = GetTargetCell<kWeakCell>();
84 6 : break;
85 : case kHandler:
86 : cell = GetTargetCell<kHandler>();
87 0 : break;
88 : case kFullTransitionArray:
89 246 : return transitions()->GetKey(transition_number);
90 : }
91 : DCHECK(!cell->cleared());
92 6 : return GetSimpleTransitionKey(Map::cast(cell->value()));
93 : }
94 :
95 : void TransitionArray::SetKey(int transition_number, Name* key) {
96 : DCHECK(transition_number < number_of_transitions());
97 10036245 : set(ToKeyIndex(transition_number), key);
98 : }
99 :
100 : Object** TransitionArray::GetTargetSlot(int transition_number) {
101 : DCHECK(transition_number < number_of_transitions());
102 : return RawFieldOfElementAt(ToTargetIndex(transition_number));
103 : }
104 :
105 : // static
106 : PropertyDetails TransitionsAccessor::GetTargetDetails(Name* name, Map* target) {
107 : DCHECK(!IsSpecialTransition(name));
108 : int descriptor = target->LastAdded();
109 : DescriptorArray* descriptors = target->instance_descriptors();
110 : // Transitions are allowed only for the last added property.
111 : DCHECK(descriptors->GetKey(descriptor)->Equals(name));
112 11019469 : return descriptors->GetDetails(descriptor);
113 : }
114 :
115 : // static
116 23946736 : Map* TransitionsAccessor::GetTargetFromRaw(Object* raw) {
117 47850936 : if (raw->IsWeakCell()) return Map::cast(WeakCell::cast(raw)->value());
118 85072 : return Map::cast(StoreHandler::GetTransitionCell(raw)->value());
119 : }
120 :
121 34037887 : Object* TransitionArray::GetRawTarget(int transition_number) {
122 : DCHECK(transition_number < number_of_transitions());
123 34037887 : return get(ToTargetIndex(transition_number));
124 : }
125 :
126 : Map* TransitionArray::GetTarget(int transition_number) {
127 23946737 : Object* raw = GetRawTarget(transition_number);
128 23946737 : return TransitionsAccessor::GetTargetFromRaw(raw);
129 : }
130 :
131 42179648 : Map* TransitionsAccessor::GetTarget(int transition_number) {
132 : WeakCell* cell = nullptr;
133 21089824 : switch (encoding()) {
134 : case kPrototypeInfo:
135 : case kUninitialized:
136 0 : UNREACHABLE();
137 : return nullptr;
138 : case kWeakCell:
139 : cell = GetTargetCell<kWeakCell>();
140 21086286 : break;
141 : case kHandler:
142 : cell = GetTargetCell<kHandler>();
143 2449 : break;
144 : case kFullTransitionArray:
145 1089 : return transitions()->GetTarget(transition_number);
146 : }
147 : DCHECK(!cell->cleared());
148 21088735 : return Map::cast(cell->value());
149 : }
150 :
151 : void TransitionArray::SetTarget(int transition_number, Object* value) {
152 : DCHECK(!value->IsMap());
153 : DCHECK(transition_number < number_of_transitions());
154 10058728 : set(ToTargetIndex(transition_number), value);
155 : }
156 :
157 :
158 12789039 : int TransitionArray::SearchName(Name* name, int* out_insertion_index) {
159 : DCHECK(name->IsUniqueName());
160 : return internal::Search<ALL_ENTRIES>(this, name, number_of_entries(),
161 12789039 : out_insertion_index);
162 : }
163 :
164 : int TransitionArray::CompareKeys(Name* key1, uint32_t hash1, PropertyKind kind1,
165 : PropertyAttributes attributes1, Name* key2,
166 : uint32_t hash2, PropertyKind kind2,
167 : PropertyAttributes attributes2) {
168 : int cmp = CompareNames(key1, hash1, key2, hash2);
169 0 : if (cmp != 0) return cmp;
170 :
171 : return CompareDetails(kind1, attributes1, kind2, attributes2);
172 : }
173 :
174 : int TransitionArray::CompareNames(Name* key1, uint32_t hash1, Name* key2,
175 : uint32_t hash2) {
176 0 : if (key1 != key2) {
177 : // In case of hash collisions key1 is always "less" than key2.
178 0 : return hash1 <= hash2 ? -1 : 1;
179 : }
180 :
181 : return 0;
182 : }
183 :
184 : int TransitionArray::CompareDetails(PropertyKind kind1,
185 : PropertyAttributes attributes1,
186 : PropertyKind kind2,
187 : PropertyAttributes attributes2) {
188 10697626 : if (kind1 != kind2) {
189 15258 : return static_cast<int>(kind1) < static_cast<int>(kind2) ? -1 : 1;
190 : }
191 :
192 10682368 : if (attributes1 != attributes2) {
193 9473 : return static_cast<int>(attributes1) < static_cast<int>(attributes2) ? -1
194 9473 : : 1;
195 : }
196 :
197 : return 0;
198 : }
199 :
200 588090 : void TransitionArray::Set(int transition_number, Name* key, Object* target) {
201 588090 : set(ToKeyIndex(transition_number), key);
202 588090 : set(ToTargetIndex(transition_number), target);
203 588090 : }
204 :
205 : int TransitionArray::Capacity() {
206 493802 : if (length() <= kFirstIndex) return 0;
207 490002 : return (length() - kFirstIndex) / kTransitionSize;
208 : }
209 :
210 : void TransitionArray::SetNumberOfTransitions(int number_of_transitions) {
211 : DCHECK(number_of_transitions <= Capacity());
212 : set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
213 : }
214 :
215 : } // namespace internal
216 : } // namespace v8
217 :
218 : #endif // V8_TRANSITIONS_INL_H_
|