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