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