| 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 |