Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(143)

Side by Side Diff: src/transitions.cc

Issue 982143002: Revert of Simplify and compact transitions storage (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/transitions.h ('k') | src/transitions-inl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/objects.h" 7 #include "src/objects.h"
8 #include "src/transitions-inl.h" 8 #include "src/transitions-inl.h"
9 #include "src/utils.h" 9 #include "src/utils.h"
10 10
11 namespace v8 { 11 namespace v8 {
12 namespace internal { 12 namespace internal {
13 13
14 14
15 // static
16 void TransitionArray::Insert(Handle<Map> map, Handle<Name> name,
17 Handle<Map> target, SimpleTransitionFlag flag) {
18 Isolate* isolate = map->GetIsolate();
19 target->SetBackPointer(*map);
20
21 // If the map doesn't have any transitions at all yet, install the new one.
22 if (CanStoreSimpleTransition(map->raw_transitions())) {
23 if (flag == SIMPLE_PROPERTY_TRANSITION) {
24 Handle<WeakCell> cell = Map::WeakCellForMap(target);
25 map->set_raw_transitions(*cell);
26 return;
27 }
28 // If the flag requires a full TransitionArray, allocate one.
29 Handle<TransitionArray> result = Allocate(isolate, 0, 1);
30 map->set_raw_transitions(*result);
31 }
32
33 bool is_special_transition = flag == SPECIAL_TRANSITION;
34 // If the map has a simple transition, check if it should be overwritten.
35 if (IsSimpleTransition(map->raw_transitions())) {
36 Map* old_target = GetSimpleTransition(map->raw_transitions());
37 Name* key = GetSimpleTransitionKey(old_target);
38 PropertyDetails old_details = GetSimpleTargetDetails(old_target);
39 PropertyDetails new_details = is_special_transition
40 ? PropertyDetails(NONE, DATA, 0)
41 : GetTargetDetails(*name, *target);
42 if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) &&
43 old_details.kind() == new_details.kind() &&
44 old_details.attributes() == new_details.attributes()) {
45 Handle<WeakCell> cell = Map::WeakCellForMap(target);
46 map->set_raw_transitions(*cell);
47 return;
48 }
49 // Otherwise allocate a full TransitionArray with slack for a new entry.
50 Handle<TransitionArray> result = Allocate(isolate, 1, 1);
51 // Re-read existing data; the allocation might have caused it to be cleared.
52 if (IsSimpleTransition(map->raw_transitions())) {
53 old_target = GetSimpleTransition(map->raw_transitions());
54 result->NoIncrementalWriteBarrierSet(
55 0, GetSimpleTransitionKey(old_target), old_target);
56 } else {
57 result->SetNumberOfTransitions(0);
58 }
59 map->set_raw_transitions(*result);
60 }
61
62 // At this point, we know that the map has a full TransitionArray.
63 DCHECK(IsFullTransitionArray(map->raw_transitions()));
64
65 int number_of_transitions = 0;
66 int new_nof = 0;
67 int insertion_index = kNotFound;
68 DCHECK_EQ(is_special_transition, IsSpecialTransition(*name));
69 PropertyDetails details = is_special_transition
70 ? PropertyDetails(NONE, DATA, 0)
71 : GetTargetDetails(*name, *target);
72
73 {
74 DisallowHeapAllocation no_gc;
75 TransitionArray* array = TransitionArray::cast(map->raw_transitions());
76 number_of_transitions = array->number_of_transitions();
77 new_nof = number_of_transitions;
78
79 int index =
80 is_special_transition
81 ? array->SearchSpecial(Symbol::cast(*name), &insertion_index)
82 : array->Search(details.kind(), *name, details.attributes(),
83 &insertion_index);
84 // If an existing entry was found, overwrite it and return.
85 if (index != kNotFound) {
86 array->SetTarget(index, *target);
87 return;
88 }
89
90 ++new_nof;
91 CHECK(new_nof <= kMaxNumberOfTransitions);
92 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
93
94 // If there is enough capacity, insert new entry into the existing array.
95 if (new_nof <= Capacity(array)) {
96 array->SetNumberOfTransitions(new_nof);
97 for (index = number_of_transitions; index > insertion_index; --index) {
98 array->SetKey(index, array->GetKey(index - 1));
99 array->SetTarget(index, array->GetTarget(index - 1));
100 }
101 array->SetKey(index, *name);
102 array->SetTarget(index, *target);
103 SLOW_DCHECK(array->IsSortedNoDuplicates());
104 return;
105 }
106 }
107
108 // We're gonna need a bigger TransitionArray.
109 Handle<TransitionArray> result = Allocate(
110 map->GetIsolate(), new_nof,
111 Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions));
112
113 // The map's transition array may have shrunk during the allocation above as
114 // it was weakly traversed, though it is guaranteed not to disappear. Trim the
115 // result copy if needed, and recompute variables.
116 DCHECK(IsFullTransitionArray(map->raw_transitions()));
117 DisallowHeapAllocation no_gc;
118 TransitionArray* array = TransitionArray::cast(map->raw_transitions());
119 if (array->number_of_transitions() != number_of_transitions) {
120 DCHECK(array->number_of_transitions() < number_of_transitions);
121
122 number_of_transitions = array->number_of_transitions();
123 new_nof = number_of_transitions;
124
125 insertion_index = kNotFound;
126 int index =
127 is_special_transition
128 ? array->SearchSpecial(Symbol::cast(*name), &insertion_index)
129 : array->Search(details.kind(), *name, details.attributes(),
130 &insertion_index);
131 if (index == kNotFound) {
132 ++new_nof;
133 } else {
134 insertion_index = index;
135 }
136 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
137
138 result->Shrink(ToKeyIndex(new_nof));
139 result->SetNumberOfTransitions(new_nof);
140 }
141
142 if (array->HasPrototypeTransitions()) {
143 result->SetPrototypeTransitions(array->GetPrototypeTransitions());
144 }
145
146 DCHECK_NE(kNotFound, insertion_index);
147 for (int i = 0; i < insertion_index; ++i) {
148 result->NoIncrementalWriteBarrierCopyFrom(array, i, i);
149 }
150 result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
151 for (int i = insertion_index; i < number_of_transitions; ++i) {
152 result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1);
153 }
154
155 SLOW_DCHECK(result->IsSortedNoDuplicates());
156 map->set_raw_transitions(*result);
157 }
158
159
160 // static
161 Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name,
162 PropertyAttributes attributes) {
163 Object* raw_transitions = map->raw_transitions();
164 if (IsSimpleTransition(raw_transitions)) {
165 Map* target = GetSimpleTransition(raw_transitions);
166 Name* key = GetSimpleTransitionKey(target);
167 if (!key->Equals(name)) return NULL;
168 PropertyDetails details = GetSimpleTargetDetails(target);
169 if (details.attributes() != attributes) return NULL;
170 if (details.kind() != kind) return NULL;
171 return target;
172 }
173 if (IsFullTransitionArray(raw_transitions)) {
174 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
175 int transition = transitions->Search(kind, name, attributes);
176 if (transition == kNotFound) return NULL;
177 return transitions->GetTarget(transition);
178 }
179 return NULL;
180 }
181
182
183 // static
184 Map* TransitionArray::SearchSpecial(Map* map, Symbol* name) {
185 Object* raw_transitions = map->raw_transitions();
186 if (IsFullTransitionArray(raw_transitions)) {
187 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
188 int transition = transitions->SearchSpecial(name);
189 if (transition == kNotFound) return NULL;
190 return transitions->GetTarget(transition);
191 }
192 return NULL;
193 }
194
195
196 // static
197 Handle<Map> TransitionArray::FindTransitionToField(Handle<Map> map,
198 Handle<Name> name) {
199 DisallowHeapAllocation no_gc;
200 Map* target = SearchTransition(*map, kData, *name, NONE);
201 if (target == NULL) return Handle<Map>::null();
202 PropertyDetails details = target->GetLastDescriptorDetails();
203 DCHECK_EQ(NONE, details.attributes());
204 if (details.type() != DATA) return Handle<Map>::null();
205 return Handle<Map>(target);
206 }
207
208
209 // static
210 Handle<String> TransitionArray::ExpectedTransitionKey(Handle<Map> map) {
211 DisallowHeapAllocation no_gc;
212 Object* raw_transition = map->raw_transitions();
213 if (!IsSimpleTransition(raw_transition)) return Handle<String>::null();
214 Map* target = GetSimpleTransition(raw_transition);
215 PropertyDetails details = GetSimpleTargetDetails(target);
216 if (details.type() != DATA) return Handle<String>::null();
217 if (details.attributes() != NONE) return Handle<String>::null();
218 Name* name = GetSimpleTransitionKey(target);
219 if (!name->IsString()) return Handle<String>::null();
220 return Handle<String>(String::cast(name));
221 }
222
223
224 // static
225 bool TransitionArray::CanHaveMoreTransitions(Handle<Map> map) {
226 Object* raw_transitions = map->raw_transitions();
227 if (IsFullTransitionArray(raw_transitions)) {
228 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
229 return transitions->number_of_transitions() < kMaxNumberOfTransitions;
230 }
231 return true;
232 }
233
234
235 // static
236 Handle<Map> TransitionArray::PutPrototypeTransition(Handle<Map> map,
237 Handle<Object> prototype,
238 Handle<Map> target_map) {
239 DCHECK(HeapObject::cast(*prototype)->map()->IsMap());
240 // Don't cache prototype transition if this map is either shared, or a map of
241 // a prototype.
242 if (map->is_prototype_map()) return map;
243 if (map->is_dictionary_map() || !FLAG_cache_prototype_transitions) return map;
244
245 const int header = kProtoTransitionHeaderSize;
246
247 Handle<FixedArray> cache(GetPrototypeTransitions(*map));
248 int capacity = cache->length() - header;
249 int transitions = NumberOfPrototypeTransitions(*cache) + 1;
250
251 if (transitions > capacity) {
252 // Grow array by factor 2 up to MaxCachedPrototypeTransitions.
253 int new_capacity = Min(kMaxCachedPrototypeTransitions, transitions * 2);
254 if (new_capacity == capacity) return map;
255
256 cache = FixedArray::CopySize(cache, header + new_capacity);
257 if (capacity < 0) {
258 // There was no prototype transitions array before, so the size
259 // couldn't be copied. Initialize it explicitly.
260 SetNumberOfPrototypeTransitions(*cache, 0);
261 }
262
263 SetPrototypeTransitions(map, cache);
264 }
265
266 // Reload number of transitions as GC might shrink them.
267 int last = NumberOfPrototypeTransitions(*cache);
268 int entry = header + last;
269
270 cache->set(entry, *target_map);
271 SetNumberOfPrototypeTransitions(*cache, last + 1);
272
273 return map;
274 }
275
276
277 // static
278 Handle<Map> TransitionArray::GetPrototypeTransition(Handle<Map> map,
279 Handle<Object> prototype) {
280 DisallowHeapAllocation no_gc;
281 FixedArray* cache = GetPrototypeTransitions(*map);
282 int number_of_transitions = NumberOfPrototypeTransitions(cache);
283 for (int i = 0; i < number_of_transitions; i++) {
284 Map* target = Map::cast(cache->get(kProtoTransitionHeaderSize + i));
285 if (target->prototype() == *prototype) return handle(target);
286 }
287 return Handle<Map>();
288 }
289
290
291 // static
292 FixedArray* TransitionArray::GetPrototypeTransitions(Map* map) {
293 Object* raw_transitions = map->raw_transitions();
294 Heap* heap = map->GetHeap();
295 if (!IsFullTransitionArray(raw_transitions)) {
296 return heap->empty_fixed_array();
297 }
298 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
299 if (!transitions->HasPrototypeTransitions()) {
300 return heap->empty_fixed_array();
301 }
302 return transitions->GetPrototypeTransitions();
303 }
304
305
306 // static
307 void TransitionArray::SetNumberOfPrototypeTransitions(
308 FixedArray* proto_transitions, int value) {
309 DCHECK(proto_transitions->length() != 0);
310 proto_transitions->set(kProtoTransitionNumberOfEntriesOffset,
311 Smi::FromInt(value));
312 }
313
314
315 // static
316 int TransitionArray::NumberOfTransitions(Object* raw_transitions) {
317 if (CanStoreSimpleTransition(raw_transitions)) return 0;
318 if (IsSimpleTransition(raw_transitions)) return 1;
319 DCHECK(IsFullTransitionArray(raw_transitions));
320 return TransitionArray::cast(raw_transitions)->number_of_transitions();
321 }
322
323
324 // static
325 int TransitionArray::Capacity(Object* raw_transitions) {
326 if (!IsFullTransitionArray(raw_transitions)) return 1;
327 TransitionArray* t = TransitionArray::cast(raw_transitions);
328 if (t->length() <= kFirstIndex) return 0;
329 return (t->length() - kFirstIndex) / kTransitionSize;
330 }
331
332
333 // Private static helper functions.
334
335 Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate, 15 Handle<TransitionArray> TransitionArray::Allocate(Isolate* isolate,
336 int number_of_transitions, 16 int number_of_transitions,
337 int slack) { 17 int slack) {
338 Handle<FixedArray> array = isolate->factory()->NewFixedArray( 18 Handle<FixedArray> array = isolate->factory()->NewFixedArray(
339 LengthFor(number_of_transitions + slack)); 19 LengthFor(number_of_transitions + slack));
340 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); 20 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0));
341 array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); 21 array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions));
342 return Handle<TransitionArray>::cast(array); 22 return Handle<TransitionArray>::cast(array);
343 } 23 }
344 24
345 25
26 Handle<TransitionArray> TransitionArray::AllocateSimple(Isolate* isolate,
27 Handle<Map> target) {
28 Handle<FixedArray> array =
29 isolate->factory()->NewFixedArray(kSimpleTransitionSize);
30 array->set(kSimpleTransitionTarget, *target);
31 return Handle<TransitionArray>::cast(array);
32 }
33
34
346 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, 35 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin,
347 int origin_transition, 36 int origin_transition,
348 int target_transition) { 37 int target_transition) {
349 NoIncrementalWriteBarrierSet(target_transition, 38 NoIncrementalWriteBarrierSet(target_transition,
350 origin->GetKey(origin_transition), 39 origin->GetKey(origin_transition),
351 origin->GetTarget(origin_transition)); 40 origin->GetTarget(origin_transition));
352 } 41 }
353 42
354 43
355 static void ZapTransitionArray(TransitionArray* transitions) { 44 Handle<TransitionArray> TransitionArray::NewWith(Handle<Map> map,
356 MemsetPointer(transitions->data_start(), 45 Handle<Name> name,
357 transitions->GetHeap()->the_hole_value(), 46 Handle<Map> target,
358 transitions->length()); 47 SimpleTransitionFlag flag) {
48 Handle<TransitionArray> result;
49 Isolate* isolate = name->GetIsolate();
50
51 if (flag == SIMPLE_PROPERTY_TRANSITION) {
52 result = AllocateSimple(isolate, target);
53 } else {
54 result = Allocate(isolate, 1);
55 result->NoIncrementalWriteBarrierSet(0, *name, *target);
56 }
57 result->set_back_pointer_storage(map->GetBackPointer());
58 return result;
359 } 59 }
360 60
361 61
362 void TransitionArray::ReplaceTransitions(Handle<Map> map, 62 Handle<TransitionArray> TransitionArray::ExtendToFullTransitionArray(
363 Object* new_transitions) { 63 Handle<Map> containing_map) {
364 Object* raw_transitions = map->raw_transitions(); 64 DCHECK(!containing_map->transitions()->IsFullTransitionArray());
365 if (IsFullTransitionArray(raw_transitions)) { 65 int nof = containing_map->transitions()->number_of_transitions();
366 TransitionArray* old_transitions = TransitionArray::cast(raw_transitions);
367 #ifdef DEBUG
368 CheckNewTransitionsAreConsistent(map, old_transitions, new_transitions);
369 DCHECK(old_transitions != new_transitions);
370 #endif
371 // Transition arrays are not shared. When one is replaced, it should not
372 // keep referenced objects alive, so we zap it.
373 // When there is another reference to the array somewhere (e.g. a handle),
374 // not zapping turns from a waste of memory into a source of crashes.
375 ZapTransitionArray(old_transitions);
376 }
377 map->set_raw_transitions(new_transitions);
378 }
379 66
380 67 // A transition array may shrink during GC.
381 static void ZapPrototypeTransitions(Object* raw_transitions) { 68 Handle<TransitionArray> result = Allocate(containing_map->GetIsolate(), nof);
382 DCHECK(TransitionArray::IsFullTransitionArray(raw_transitions));
383 TransitionArray* transitions = TransitionArray::cast(raw_transitions);
384 if (!transitions->HasPrototypeTransitions()) return;
385 FixedArray* proto_transitions = transitions->GetPrototypeTransitions();
386 MemsetPointer(proto_transitions->data_start(),
387 proto_transitions->GetHeap()->the_hole_value(),
388 proto_transitions->length());
389 }
390
391
392 void TransitionArray::SetPrototypeTransitions(
393 Handle<Map> map, Handle<FixedArray> proto_transitions) {
394 EnsureHasFullTransitionArray(map);
395 if (Heap::ShouldZapGarbage()) {
396 Object* raw_transitions = map->raw_transitions();
397 DCHECK(raw_transitions != *proto_transitions);
398 ZapPrototypeTransitions(raw_transitions);
399 }
400 TransitionArray* transitions = TransitionArray::cast(map->raw_transitions());
401 transitions->SetPrototypeTransitions(*proto_transitions);
402 }
403
404
405 void TransitionArray::EnsureHasFullTransitionArray(Handle<Map> map) {
406 Object* raw_transitions = map->raw_transitions();
407 if (IsFullTransitionArray(raw_transitions)) return;
408 int nof = IsSimpleTransition(raw_transitions) ? 1 : 0;
409 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof);
410 DisallowHeapAllocation no_gc; 69 DisallowHeapAllocation no_gc;
411 // Reload pointer after the allocation that just happened. 70 int new_nof = containing_map->transitions()->number_of_transitions();
412 raw_transitions = map->raw_transitions();
413 int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0;
414 if (new_nof != nof) { 71 if (new_nof != nof) {
415 DCHECK(new_nof == 0); 72 DCHECK(new_nof == 0);
416 result->Shrink(ToKeyIndex(0)); 73 result->Shrink(ToKeyIndex(0));
417 result->SetNumberOfTransitions(0); 74 result->SetNumberOfTransitions(0);
418 } else if (nof == 1) { 75 } else if (nof == 1) {
419 Map* target = GetSimpleTransition(raw_transitions); 76 result->NoIncrementalWriteBarrierCopyFrom(
420 Name* key = GetSimpleTransitionKey(target); 77 containing_map->transitions(), kSimpleTransitionIndex, 0);
421 result->NoIncrementalWriteBarrierSet(0, key, target);
422 } 78 }
423 ReplaceTransitions(map, *result); 79
80 result->set_back_pointer_storage(
81 containing_map->transitions()->back_pointer_storage());
82 return result;
424 } 83 }
425 84
426 85
427 void TransitionArray::TraverseTransitionTreeInternal(Map* map, 86 Handle<TransitionArray> TransitionArray::Insert(Handle<Map> map,
428 TraverseCallback callback, 87 Handle<Name> name,
429 void* data) { 88 Handle<Map> target,
430 Object* raw_transitions = map->raw_transitions(); 89 SimpleTransitionFlag flag) {
431 if (IsFullTransitionArray(raw_transitions)) { 90 if (!map->HasTransitionArray()) {
432 TransitionArray* transitions = TransitionArray::cast(raw_transitions); 91 return TransitionArray::NewWith(map, name, target, flag);
433 if (transitions->HasPrototypeTransitions()) { 92 }
434 FixedArray* proto_trans = transitions->GetPrototypeTransitions(); 93
435 for (int i = 0; i < NumberOfPrototypeTransitions(proto_trans); ++i) { 94 int number_of_transitions = map->transitions()->number_of_transitions();
436 int index = TransitionArray::kProtoTransitionHeaderSize + i; 95 int new_nof = number_of_transitions;
437 TraverseTransitionTreeInternal(Map::cast(proto_trans->get(index)), 96
438 callback, data); 97 bool is_special_transition = flag == SPECIAL_TRANSITION;
439 } 98 DCHECK_EQ(is_special_transition, IsSpecialTransition(*name));
99 PropertyDetails details = is_special_transition
100 ? PropertyDetails(NONE, DATA, 0)
101 : GetTargetDetails(*name, *target);
102
103 int insertion_index = kNotFound;
104 int index =
105 is_special_transition
106 ? map->transitions()->SearchSpecial(Symbol::cast(*name),
107 &insertion_index)
108 : map->transitions()->Search(details.kind(), *name,
109 details.attributes(), &insertion_index);
110 if (index == kNotFound) {
111 ++new_nof;
112 } else {
113 insertion_index = index;
114 }
115 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
116
117 CHECK(new_nof <= kMaxNumberOfTransitions);
118
119 if (new_nof <= map->transitions()->number_of_transitions_storage()) {
120 DisallowHeapAllocation no_gc;
121 TransitionArray* array = map->transitions();
122
123 if (index != kNotFound) {
124 array->SetTarget(index, *target);
125 return handle(array);
440 } 126 }
441 for (int i = 0; i < transitions->number_of_transitions(); ++i) { 127
442 TraverseTransitionTreeInternal(transitions->GetTarget(i), callback, data); 128 array->SetNumberOfTransitions(new_nof);
129 for (index = number_of_transitions; index > insertion_index; --index) {
130 Name* key = array->GetKey(index - 1);
131 array->SetKey(index, key);
132 array->SetTarget(index, array->GetTarget(index - 1));
443 } 133 }
444 } else if (IsSimpleTransition(raw_transitions)) { 134 array->SetKey(index, *name);
445 TraverseTransitionTreeInternal(GetSimpleTransition(raw_transitions), 135 array->SetTarget(index, *target);
446 callback, data); 136 SLOW_DCHECK(array->IsSortedNoDuplicates());
137 return handle(array);
447 } 138 }
448 callback(map, data); 139
140 Handle<TransitionArray> result = Allocate(
141 map->GetIsolate(), new_nof,
142 Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions));
143
144 // The map's transition array may grown smaller during the allocation above as
145 // it was weakly traversed, though it is guaranteed not to disappear. Trim the
146 // result copy if needed, and recompute variables.
147 DCHECK(map->HasTransitionArray());
148 DisallowHeapAllocation no_gc;
149 TransitionArray* array = map->transitions();
150 if (array->number_of_transitions() != number_of_transitions) {
151 DCHECK(array->number_of_transitions() < number_of_transitions);
152
153 number_of_transitions = array->number_of_transitions();
154 new_nof = number_of_transitions;
155
156 insertion_index = kNotFound;
157 index = is_special_transition ? map->transitions()->SearchSpecial(
158 Symbol::cast(*name), &insertion_index)
159 : map->transitions()->Search(
160 details.kind(), *name,
161 details.attributes(), &insertion_index);
162 if (index == kNotFound) {
163 ++new_nof;
164 } else {
165 insertion_index = index;
166 }
167 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions);
168
169 result->Shrink(ToKeyIndex(new_nof));
170 result->SetNumberOfTransitions(new_nof);
171 }
172
173 if (array->HasPrototypeTransitions()) {
174 result->SetPrototypeTransitions(array->GetPrototypeTransitions());
175 }
176
177 DCHECK_NE(kNotFound, insertion_index);
178 for (int i = 0; i < insertion_index; ++i) {
179 result->NoIncrementalWriteBarrierCopyFrom(array, i, i);
180 }
181 result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target);
182 for (int i = insertion_index; i < number_of_transitions; ++i) {
183 result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1);
184 }
185
186 result->set_back_pointer_storage(array->back_pointer_storage());
187 SLOW_DCHECK(result->IsSortedNoDuplicates());
188 return result;
449 } 189 }
450 190
451 191
452 #ifdef DEBUG
453 void TransitionArray::CheckNewTransitionsAreConsistent(
454 Handle<Map> map, TransitionArray* old_transitions, Object* transitions) {
455 // This function only handles full transition arrays.
456 DCHECK(IsFullTransitionArray(transitions));
457 TransitionArray* new_transitions = TransitionArray::cast(transitions);
458 for (int i = 0; i < old_transitions->number_of_transitions(); i++) {
459 Map* target = old_transitions->GetTarget(i);
460 if (target->instance_descriptors() == map->instance_descriptors()) {
461 Name* key = old_transitions->GetKey(i);
462 int new_target_index;
463 if (TransitionArray::IsSpecialTransition(key)) {
464 new_target_index = new_transitions->SearchSpecial(Symbol::cast(key));
465 } else {
466 PropertyDetails details =
467 TransitionArray::GetTargetDetails(key, target);
468 new_target_index =
469 new_transitions->Search(details.kind(), key, details.attributes());
470 }
471 DCHECK_NE(TransitionArray::kNotFound, new_target_index);
472 DCHECK_EQ(target, new_transitions->GetTarget(new_target_index));
473 }
474 }
475 }
476 #endif
477
478
479 // Private non-static helper functions (operating on full transition arrays).
480
481 int TransitionArray::SearchDetails(int transition, PropertyKind kind, 192 int TransitionArray::SearchDetails(int transition, PropertyKind kind,
482 PropertyAttributes attributes, 193 PropertyAttributes attributes,
483 int* out_insertion_index) { 194 int* out_insertion_index) {
484 int nof_transitions = number_of_transitions(); 195 int nof_transitions = number_of_transitions();
485 DCHECK(transition < nof_transitions); 196 DCHECK(transition < nof_transitions);
486 Name* key = GetKey(transition); 197 Name* key = GetKey(transition);
487 for (; transition < nof_transitions && GetKey(transition) == key; 198 for (; transition < nof_transitions && GetKey(transition) == key;
488 transition++) { 199 transition++) {
489 Map* target = GetTarget(transition); 200 Map* target = GetTarget(transition);
490 PropertyDetails target_details = GetTargetDetails(key, target); 201 PropertyDetails target_details = GetTargetDetails(key, target);
(...skipping 14 matching lines...) Expand all
505 int TransitionArray::Search(PropertyKind kind, Name* name, 216 int TransitionArray::Search(PropertyKind kind, Name* name,
506 PropertyAttributes attributes, 217 PropertyAttributes attributes,
507 int* out_insertion_index) { 218 int* out_insertion_index) {
508 int transition = SearchName(name, out_insertion_index); 219 int transition = SearchName(name, out_insertion_index);
509 if (transition == kNotFound) { 220 if (transition == kNotFound) {
510 return kNotFound; 221 return kNotFound;
511 } 222 }
512 return SearchDetails(transition, kind, attributes, out_insertion_index); 223 return SearchDetails(transition, kind, attributes, out_insertion_index);
513 } 224 }
514 } } // namespace v8::internal 225 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/transitions.h ('k') | src/transitions-inl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698