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

Side by Side Diff: src/transitions.cc

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

Powered by Google App Engine
This is Rietveld 408576698