OLD | NEW |
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 | 15 // static |
16 void TransitionArray::Insert(Handle<Map> map, Handle<Name> name, | 16 void TransitionArray::Insert(Handle<Map> map, Handle<Name> name, |
17 Handle<Map> target, SimpleTransitionFlag flag) { | 17 Handle<Map> target, SimpleTransitionFlag flag) { |
18 Isolate* isolate = map->GetIsolate(); | 18 Isolate* isolate = map->GetIsolate(); |
19 target->SetBackPointer(*map); | 19 target->SetBackPointer(*map); |
| 20 Handle<WeakCell> cell = Map::WeakCellForMap(target); |
20 | 21 |
21 // If the map doesn't have any transitions at all yet, install the new one. | 22 // If the map doesn't have any transitions at all yet, install the new one. |
22 if (CanStoreSimpleTransition(map->raw_transitions())) { | 23 if (CanStoreSimpleTransition(map->raw_transitions())) { |
23 if (flag == SIMPLE_PROPERTY_TRANSITION) { | 24 if (flag == SIMPLE_PROPERTY_TRANSITION) { |
24 Handle<WeakCell> cell = Map::WeakCellForMap(target); | |
25 ReplaceTransitions(map, *cell); | 25 ReplaceTransitions(map, *cell); |
26 return; | 26 return; |
27 } | 27 } |
28 // If the flag requires a full TransitionArray, allocate one. | 28 // If the flag requires a full TransitionArray, allocate one. |
29 Handle<TransitionArray> result = Allocate(isolate, 0, 1); | 29 Handle<TransitionArray> result = Allocate(isolate, 0, 1); |
30 ReplaceTransitions(map, *result); | 30 ReplaceTransitions(map, *result); |
31 } | 31 } |
32 | 32 |
33 bool is_special_transition = flag == SPECIAL_TRANSITION; | 33 bool is_special_transition = flag == SPECIAL_TRANSITION; |
34 // If the map has a simple transition, check if it should be overwritten. | 34 // If the map has a simple transition, check if it should be overwritten. |
35 if (IsSimpleTransition(map->raw_transitions())) { | 35 if (IsSimpleTransition(map->raw_transitions())) { |
36 Map* old_target = GetSimpleTransition(map->raw_transitions()); | 36 Map* old_target = GetSimpleTransition(map->raw_transitions()); |
37 Name* key = GetSimpleTransitionKey(old_target); | 37 Name* key = GetSimpleTransitionKey(old_target); |
38 PropertyDetails old_details = GetSimpleTargetDetails(old_target); | 38 PropertyDetails old_details = GetSimpleTargetDetails(old_target); |
39 PropertyDetails new_details = is_special_transition | 39 PropertyDetails new_details = is_special_transition |
40 ? PropertyDetails::Empty() | 40 ? PropertyDetails::Empty() |
41 : GetTargetDetails(*name, *target); | 41 : GetTargetDetails(*name, *target); |
42 if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && | 42 if (flag == SIMPLE_PROPERTY_TRANSITION && key->Equals(*name) && |
43 old_details.kind() == new_details.kind() && | 43 old_details.kind() == new_details.kind() && |
44 old_details.attributes() == new_details.attributes()) { | 44 old_details.attributes() == new_details.attributes()) { |
45 Handle<WeakCell> cell = Map::WeakCellForMap(target); | |
46 ReplaceTransitions(map, *cell); | 45 ReplaceTransitions(map, *cell); |
47 return; | 46 return; |
48 } | 47 } |
49 // Otherwise allocate a full TransitionArray with slack for a new entry. | 48 // Otherwise allocate a full TransitionArray with slack for a new entry. |
50 Handle<TransitionArray> result = Allocate(isolate, 1, 1); | 49 Handle<TransitionArray> result = Allocate(isolate, 1, 1); |
51 // Re-read existing data; the allocation might have caused it to be cleared. | 50 // Re-read existing data; the allocation might have caused it to be cleared. |
52 if (IsSimpleTransition(map->raw_transitions())) { | 51 if (IsSimpleTransition(map->raw_transitions())) { |
53 old_target = GetSimpleTransition(map->raw_transitions()); | 52 old_target = GetSimpleTransition(map->raw_transitions()); |
54 result->NoIncrementalWriteBarrierSet( | 53 result->Set(0, GetSimpleTransitionKey(old_target), |
55 0, GetSimpleTransitionKey(old_target), old_target); | 54 GetSimpleTransitionCell(map->raw_transitions())); |
56 } else { | 55 } else { |
57 result->SetNumberOfTransitions(0); | 56 result->SetNumberOfTransitions(0); |
58 } | 57 } |
59 ReplaceTransitions(map, *result); | 58 ReplaceTransitions(map, *result); |
60 } | 59 } |
61 | 60 |
62 // At this point, we know that the map has a full TransitionArray. | 61 // At this point, we know that the map has a full TransitionArray. |
63 DCHECK(IsFullTransitionArray(map->raw_transitions())); | 62 DCHECK(IsFullTransitionArray(map->raw_transitions())); |
64 | 63 |
65 int number_of_transitions = 0; | 64 int number_of_transitions = 0; |
(...skipping 10 matching lines...) Expand all Loading... |
76 number_of_transitions = array->number_of_transitions(); | 75 number_of_transitions = array->number_of_transitions(); |
77 new_nof = number_of_transitions; | 76 new_nof = number_of_transitions; |
78 | 77 |
79 int index = | 78 int index = |
80 is_special_transition | 79 is_special_transition |
81 ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) | 80 ? array->SearchSpecial(Symbol::cast(*name), &insertion_index) |
82 : array->Search(details.kind(), *name, details.attributes(), | 81 : array->Search(details.kind(), *name, details.attributes(), |
83 &insertion_index); | 82 &insertion_index); |
84 // If an existing entry was found, overwrite it and return. | 83 // If an existing entry was found, overwrite it and return. |
85 if (index != kNotFound) { | 84 if (index != kNotFound) { |
86 array->SetTarget(index, *target); | 85 array->SetTargetCell(index, *cell); |
87 return; | 86 return; |
88 } | 87 } |
89 | 88 |
90 ++new_nof; | 89 ++new_nof; |
91 CHECK(new_nof <= kMaxNumberOfTransitions); | 90 CHECK(new_nof <= kMaxNumberOfTransitions); |
92 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); | 91 DCHECK(insertion_index >= 0 && insertion_index <= number_of_transitions); |
93 | 92 |
94 // If there is enough capacity, insert new entry into the existing array. | 93 // If there is enough capacity, insert new entry into the existing array. |
95 if (new_nof <= Capacity(array)) { | 94 if (new_nof <= Capacity(array)) { |
96 array->SetNumberOfTransitions(new_nof); | 95 array->SetNumberOfTransitions(new_nof); |
97 for (index = number_of_transitions; index > insertion_index; --index) { | 96 for (index = number_of_transitions; index > insertion_index; --index) { |
98 array->SetKey(index, array->GetKey(index - 1)); | 97 array->SetKey(index, array->GetKey(index - 1)); |
99 array->SetTarget(index, array->GetTarget(index - 1)); | 98 array->SetTargetCell(index, array->GetTargetCell(index - 1)); |
100 } | 99 } |
101 array->SetKey(index, *name); | 100 array->SetKey(index, *name); |
102 array->SetTarget(index, *target); | 101 array->SetTargetCell(index, *cell); |
103 SLOW_DCHECK(array->IsSortedNoDuplicates()); | 102 SLOW_DCHECK(array->IsSortedNoDuplicates()); |
104 return; | 103 return; |
105 } | 104 } |
106 } | 105 } |
107 | 106 |
108 // We're gonna need a bigger TransitionArray. | 107 // We're gonna need a bigger TransitionArray. |
109 Handle<TransitionArray> result = Allocate( | 108 Handle<TransitionArray> result = Allocate( |
110 map->GetIsolate(), new_nof, | 109 map->GetIsolate(), new_nof, |
111 Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); | 110 Map::SlackForArraySize(number_of_transitions, kMaxNumberOfTransitions)); |
112 | 111 |
(...skipping 25 matching lines...) Expand all Loading... |
138 result->Shrink(ToKeyIndex(new_nof)); | 137 result->Shrink(ToKeyIndex(new_nof)); |
139 result->SetNumberOfTransitions(new_nof); | 138 result->SetNumberOfTransitions(new_nof); |
140 } | 139 } |
141 | 140 |
142 if (array->HasPrototypeTransitions()) { | 141 if (array->HasPrototypeTransitions()) { |
143 result->SetPrototypeTransitions(array->GetPrototypeTransitions()); | 142 result->SetPrototypeTransitions(array->GetPrototypeTransitions()); |
144 } | 143 } |
145 | 144 |
146 DCHECK_NE(kNotFound, insertion_index); | 145 DCHECK_NE(kNotFound, insertion_index); |
147 for (int i = 0; i < insertion_index; ++i) { | 146 for (int i = 0; i < insertion_index; ++i) { |
148 result->NoIncrementalWriteBarrierCopyFrom(array, i, i); | 147 result->CopyFrom(array, i, i); |
149 } | 148 } |
150 result->NoIncrementalWriteBarrierSet(insertion_index, *name, *target); | 149 result->Set(insertion_index, *name, *cell); |
151 for (int i = insertion_index; i < number_of_transitions; ++i) { | 150 for (int i = insertion_index; i < number_of_transitions; ++i) { |
152 result->NoIncrementalWriteBarrierCopyFrom(array, i, i + 1); | 151 result->CopyFrom(array, i, i + 1); |
153 } | 152 } |
154 | 153 |
155 SLOW_DCHECK(result->IsSortedNoDuplicates()); | 154 SLOW_DCHECK(result->IsSortedNoDuplicates()); |
156 ReplaceTransitions(map, *result); | 155 ReplaceTransitions(map, *result); |
157 } | 156 } |
158 | 157 |
159 | 158 |
160 // static | 159 // static |
161 Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name, | 160 Map* TransitionArray::SearchTransition(Map* map, PropertyKind kind, Name* name, |
162 PropertyAttributes attributes) { | 161 PropertyAttributes attributes) { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 int number_of_transitions, | 341 int number_of_transitions, |
343 int slack) { | 342 int slack) { |
344 Handle<FixedArray> array = isolate->factory()->NewFixedArray( | 343 Handle<FixedArray> array = isolate->factory()->NewFixedArray( |
345 LengthFor(number_of_transitions + slack)); | 344 LengthFor(number_of_transitions + slack)); |
346 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); | 345 array->set(kPrototypeTransitionsIndex, Smi::FromInt(0)); |
347 array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); | 346 array->set(kTransitionLengthIndex, Smi::FromInt(number_of_transitions)); |
348 return Handle<TransitionArray>::cast(array); | 347 return Handle<TransitionArray>::cast(array); |
349 } | 348 } |
350 | 349 |
351 | 350 |
352 void TransitionArray::NoIncrementalWriteBarrierCopyFrom(TransitionArray* origin, | 351 void TransitionArray::CopyFrom(TransitionArray* origin, int origin_transition, |
353 int origin_transition, | 352 int target_transition) { |
354 int target_transition) { | 353 Set(target_transition, origin->GetKey(origin_transition), |
355 NoIncrementalWriteBarrierSet(target_transition, | 354 origin->GetTargetCell(origin_transition)); |
356 origin->GetKey(origin_transition), | |
357 origin->GetTarget(origin_transition)); | |
358 } | 355 } |
359 | 356 |
360 | 357 |
361 static void ZapTransitionArray(TransitionArray* transitions) { | 358 static void ZapTransitionArray(TransitionArray* transitions) { |
362 MemsetPointer(transitions->data_start(), | 359 MemsetPointer(transitions->data_start(), |
363 transitions->GetHeap()->the_hole_value(), | 360 transitions->GetHeap()->the_hole_value(), |
364 transitions->length()); | 361 transitions->length()); |
365 } | 362 } |
366 | 363 |
367 | 364 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); | 412 Handle<TransitionArray> result = Allocate(map->GetIsolate(), nof); |
416 DisallowHeapAllocation no_gc; | 413 DisallowHeapAllocation no_gc; |
417 // Reload pointer after the allocation that just happened. | 414 // Reload pointer after the allocation that just happened. |
418 raw_transitions = map->raw_transitions(); | 415 raw_transitions = map->raw_transitions(); |
419 int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0; | 416 int new_nof = IsSimpleTransition(raw_transitions) ? 1 : 0; |
420 if (new_nof != nof) { | 417 if (new_nof != nof) { |
421 DCHECK(new_nof == 0); | 418 DCHECK(new_nof == 0); |
422 result->Shrink(ToKeyIndex(0)); | 419 result->Shrink(ToKeyIndex(0)); |
423 result->SetNumberOfTransitions(0); | 420 result->SetNumberOfTransitions(0); |
424 } else if (nof == 1) { | 421 } else if (nof == 1) { |
425 Map* target = GetSimpleTransition(raw_transitions); | 422 WeakCell* target_cell = GetSimpleTransitionCell(raw_transitions); |
426 Name* key = GetSimpleTransitionKey(target); | 423 Name* key = GetSimpleTransitionKey(Map::cast(target_cell->value())); |
427 result->NoIncrementalWriteBarrierSet(0, key, target); | 424 result->Set(0, key, target_cell); |
428 } | 425 } |
429 ReplaceTransitions(map, *result); | 426 ReplaceTransitions(map, *result); |
430 } | 427 } |
431 | 428 |
432 | 429 |
433 void TransitionArray::TraverseTransitionTreeInternal(Map* map, | 430 void TransitionArray::TraverseTransitionTreeInternal(Map* map, |
434 TraverseCallback callback, | 431 TraverseCallback callback, |
435 void* data) { | 432 void* data) { |
436 Object* raw_transitions = map->raw_transitions(); | 433 Object* raw_transitions = map->raw_transitions(); |
437 if (IsFullTransitionArray(raw_transitions)) { | 434 if (IsFullTransitionArray(raw_transitions)) { |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 PropertyAttributes attributes, | 510 PropertyAttributes attributes, |
514 int* out_insertion_index) { | 511 int* out_insertion_index) { |
515 int transition = SearchName(name, out_insertion_index); | 512 int transition = SearchName(name, out_insertion_index); |
516 if (transition == kNotFound) { | 513 if (transition == kNotFound) { |
517 return kNotFound; | 514 return kNotFound; |
518 } | 515 } |
519 return SearchDetails(transition, kind, attributes, out_insertion_index); | 516 return SearchDetails(transition, kind, attributes, out_insertion_index); |
520 } | 517 } |
521 } // namespace internal | 518 } // namespace internal |
522 } // namespace v8 | 519 } // namespace v8 |
OLD | NEW |