| OLD | NEW |
| 1 // Copyright 2017 the V8 project authors. All rights reserved. | 1 // Copyright 2017 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/map-updater.h" | 5 #include "src/map-updater.h" |
| 6 | 6 |
| 7 #include "src/field-type.h" | 7 #include "src/field-type.h" |
| 8 #include "src/handles.h" | 8 #include "src/handles.h" |
| 9 #include "src/isolate.h" | 9 #include "src/isolate.h" |
| 10 #include "src/objects-inl.h" | 10 #include "src/objects-inl.h" |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 DCHECK_EQ(kInitialized, state_); | 142 DCHECK_EQ(kInitialized, state_); |
| 143 DCHECK(old_map_->is_deprecated()); | 143 DCHECK(old_map_->is_deprecated()); |
| 144 | 144 |
| 145 if (FindRootMap() == kEnd) return result_map_; | 145 if (FindRootMap() == kEnd) return result_map_; |
| 146 if (FindTargetMap() == kEnd) return result_map_; | 146 if (FindTargetMap() == kEnd) return result_map_; |
| 147 ConstructNewMap(); | 147 ConstructNewMap(); |
| 148 DCHECK_EQ(kEnd, state_); | 148 DCHECK_EQ(kEnd, state_); |
| 149 return result_map_; | 149 return result_map_; |
| 150 } | 150 } |
| 151 | 151 |
| 152 MapUpdater::State MapUpdater::CopyGeneralizeAllRepresentations( | 152 MapUpdater::State MapUpdater::CopyGeneralizeAllFields(const char* reason) { |
| 153 const char* reason) { | |
| 154 StoreMode store_mode = | 153 StoreMode store_mode = |
| 155 modified_descriptor_ >= 0 ? FORCE_FIELD : ALLOW_IN_DESCRIPTOR; | 154 modified_descriptor_ >= 0 ? FORCE_FIELD : ALLOW_IN_DESCRIPTOR; |
| 156 result_map_ = Map::CopyGeneralizeAllRepresentations( | 155 result_map_ = Map::CopyGeneralizeAllFields( |
| 157 old_map_, new_elements_kind_, modified_descriptor_, store_mode, new_kind_, | 156 old_map_, new_elements_kind_, modified_descriptor_, store_mode, new_kind_, |
| 158 new_attributes_, reason); | 157 new_attributes_, reason); |
| 159 state_ = kEnd; | 158 state_ = kEnd; |
| 160 return state_; // Done. | 159 return state_; // Done. |
| 161 } | 160 } |
| 162 | 161 |
| 163 MapUpdater::State MapUpdater::TryRecofigureToDataFieldInplace() { | 162 MapUpdater::State MapUpdater::TryRecofigureToDataFieldInplace() { |
| 164 // If it's just a representation generalization case (i.e. property kind and | 163 // If it's just a representation generalization case (i.e. property kind and |
| 165 // attributes stays unchanged) it's fine to transition from None to anything | 164 // attributes stays unchanged) it's fine to transition from None to anything |
| 166 // but double without any modification to the object, because the default | 165 // but double without any modification to the object, because the default |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 state_ = kEnd; | 202 state_ = kEnd; |
| 204 return state_; // Done. | 203 return state_; // Done. |
| 205 } | 204 } |
| 206 | 205 |
| 207 MapUpdater::State MapUpdater::FindRootMap() { | 206 MapUpdater::State MapUpdater::FindRootMap() { |
| 208 DCHECK_EQ(kInitialized, state_); | 207 DCHECK_EQ(kInitialized, state_); |
| 209 // Check the state of the root map. | 208 // Check the state of the root map. |
| 210 root_map_ = handle(old_map_->FindRootMap(), isolate_); | 209 root_map_ = handle(old_map_->FindRootMap(), isolate_); |
| 211 int root_nof = root_map_->NumberOfOwnDescriptors(); | 210 int root_nof = root_map_->NumberOfOwnDescriptors(); |
| 212 if (!old_map_->EquivalentToForTransition(*root_map_)) { | 211 if (!old_map_->EquivalentToForTransition(*root_map_)) { |
| 213 return CopyGeneralizeAllRepresentations("GenAll_NotEquivalent"); | 212 return CopyGeneralizeAllFields("GenAll_NotEquivalent"); |
| 214 } | 213 } |
| 215 | 214 |
| 216 ElementsKind from_kind = root_map_->elements_kind(); | 215 ElementsKind from_kind = root_map_->elements_kind(); |
| 217 ElementsKind to_kind = new_elements_kind_; | 216 ElementsKind to_kind = new_elements_kind_; |
| 218 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. | 217 // TODO(ishell): Add a test for SLOW_SLOPPY_ARGUMENTS_ELEMENTS. |
| 219 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && | 218 if (from_kind != to_kind && to_kind != DICTIONARY_ELEMENTS && |
| 220 to_kind != SLOW_STRING_WRAPPER_ELEMENTS && | 219 to_kind != SLOW_STRING_WRAPPER_ELEMENTS && |
| 221 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && | 220 to_kind != SLOW_SLOPPY_ARGUMENTS_ELEMENTS && |
| 222 !(IsTransitionableFastElementsKind(from_kind) && | 221 !(IsTransitionableFastElementsKind(from_kind) && |
| 223 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { | 222 IsMoreGeneralElementsKindTransition(from_kind, to_kind))) { |
| 224 return CopyGeneralizeAllRepresentations("GenAll_InvalidElementsTransition"); | 223 return CopyGeneralizeAllFields("GenAll_InvalidElementsTransition"); |
| 225 } | 224 } |
| 226 | 225 |
| 227 if (modified_descriptor_ >= 0 && modified_descriptor_ < root_nof) { | 226 if (modified_descriptor_ >= 0 && modified_descriptor_ < root_nof) { |
| 228 PropertyDetails old_details = | 227 PropertyDetails old_details = |
| 229 old_descriptors_->GetDetails(modified_descriptor_); | 228 old_descriptors_->GetDetails(modified_descriptor_); |
| 230 if (old_details.kind() != new_kind_ || | 229 if (old_details.kind() != new_kind_ || |
| 231 old_details.attributes() != new_attributes_) { | 230 old_details.attributes() != new_attributes_) { |
| 232 return CopyGeneralizeAllRepresentations("GenAll_RootModification1"); | 231 return CopyGeneralizeAllFields("GenAll_RootModification1"); |
| 233 } | 232 } |
| 234 if (!new_representation_.fits_into(old_details.representation())) { | 233 if (!new_representation_.fits_into(old_details.representation())) { |
| 235 return CopyGeneralizeAllRepresentations("GenAll_RootModification2"); | 234 return CopyGeneralizeAllFields("GenAll_RootModification2"); |
| 236 } | 235 } |
| 237 if (old_details.location() != kField) { | 236 if (old_details.location() != kField) { |
| 238 return CopyGeneralizeAllRepresentations("GenAll_RootModification3"); | 237 return CopyGeneralizeAllFields("GenAll_RootModification3"); |
| 239 } | 238 } |
| 240 DCHECK_EQ(kData, old_details.kind()); | 239 DCHECK_EQ(kData, old_details.kind()); |
| 241 DCHECK_EQ(kData, new_kind_); | 240 DCHECK_EQ(kData, new_kind_); |
| 242 DCHECK_EQ(kField, new_location_); | 241 DCHECK_EQ(kField, new_location_); |
| 243 FieldType* old_field_type = | 242 FieldType* old_field_type = |
| 244 old_descriptors_->GetFieldType(modified_descriptor_); | 243 old_descriptors_->GetFieldType(modified_descriptor_); |
| 245 if (!new_field_type_->NowIs(old_field_type)) { | 244 if (!new_field_type_->NowIs(old_field_type)) { |
| 246 return CopyGeneralizeAllRepresentations("GenAll_RootModification4"); | 245 return CopyGeneralizeAllFields("GenAll_RootModification4"); |
| 247 } | 246 } |
| 248 } | 247 } |
| 249 | 248 |
| 250 // From here on, use the map with correct elements kind as root map. | 249 // From here on, use the map with correct elements kind as root map. |
| 251 if (from_kind != to_kind) { | 250 if (from_kind != to_kind) { |
| 252 root_map_ = Map::AsElementsKind(root_map_, to_kind); | 251 root_map_ = Map::AsElementsKind(root_map_, to_kind); |
| 253 } | 252 } |
| 254 state_ = kAtRootMap; | 253 state_ = kAtRootMap; |
| 255 return state_; // Not done yet. | 254 return state_; // Not done yet. |
| 256 } | 255 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 270 Handle<DescriptorArray> tmp_descriptors(tmp_map->instance_descriptors(), | 269 Handle<DescriptorArray> tmp_descriptors(tmp_map->instance_descriptors(), |
| 271 isolate_); | 270 isolate_); |
| 272 | 271 |
| 273 // Check if target map is incompatible. | 272 // Check if target map is incompatible. |
| 274 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 273 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 275 DCHECK_EQ(old_details.kind(), tmp_details.kind()); | 274 DCHECK_EQ(old_details.kind(), tmp_details.kind()); |
| 276 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 275 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
| 277 if (old_details.kind() == kAccessor && | 276 if (old_details.kind() == kAccessor && |
| 278 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { | 277 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { |
| 279 // TODO(ishell): mutable accessors are not implemented yet. | 278 // TODO(ishell): mutable accessors are not implemented yet. |
| 280 return CopyGeneralizeAllRepresentations("GenAll_Incompatible"); | 279 return CopyGeneralizeAllFields("GenAll_Incompatible"); |
| 281 } | 280 } |
| 282 // Check if old location fits into tmp location. | 281 // Check if old location fits into tmp location. |
| 283 if (!LocationFitsInto(old_details.location(), tmp_details.location())) { | 282 if (!LocationFitsInto(old_details.location(), tmp_details.location())) { |
| 284 break; | 283 break; |
| 285 } | 284 } |
| 286 | 285 |
| 287 // Check if old representation fits into tmp representation. | 286 // Check if old representation fits into tmp representation. |
| 288 Representation tmp_representation = tmp_details.representation(); | 287 Representation tmp_representation = tmp_details.representation(); |
| 289 if (!old_details.representation().fits_into(tmp_representation)) { | 288 if (!old_details.representation().fits_into(tmp_representation)) { |
| 290 break; | 289 break; |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 346 isolate_); | 345 isolate_); |
| 347 | 346 |
| 348 #ifdef DEBUG | 347 #ifdef DEBUG |
| 349 // Check that target map is compatible. | 348 // Check that target map is compatible. |
| 350 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 349 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
| 351 DCHECK_EQ(old_details.kind(), tmp_details.kind()); | 350 DCHECK_EQ(old_details.kind(), tmp_details.kind()); |
| 352 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 351 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
| 353 #endif | 352 #endif |
| 354 if (old_details.kind() == kAccessor && | 353 if (old_details.kind() == kAccessor && |
| 355 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { | 354 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { |
| 356 return CopyGeneralizeAllRepresentations("GenAll_Incompatible"); | 355 return CopyGeneralizeAllFields("GenAll_Incompatible"); |
| 357 } | 356 } |
| 358 DCHECK(!tmp_map->is_deprecated()); | 357 DCHECK(!tmp_map->is_deprecated()); |
| 359 target_map_ = tmp_map; | 358 target_map_ = tmp_map; |
| 360 } | 359 } |
| 361 | 360 |
| 362 state_ = kAtTargetMap; | 361 state_ = kAtTargetMap; |
| 363 return state_; // Not done yet. | 362 return state_; // Not done yet. |
| 364 } | 363 } |
| 365 | 364 |
| 366 Handle<DescriptorArray> MapUpdater::BuildDescriptorArray() { | 365 Handle<DescriptorArray> MapUpdater::BuildDescriptorArray() { |
| (...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 555 split_details.attributes()); | 554 split_details.attributes()); |
| 556 if (maybe_transition != NULL) { | 555 if (maybe_transition != NULL) { |
| 557 maybe_transition->DeprecateTransitionTree(); | 556 maybe_transition->DeprecateTransitionTree(); |
| 558 } | 557 } |
| 559 | 558 |
| 560 // If |maybe_transition| is not NULL then the transition array already | 559 // If |maybe_transition| is not NULL then the transition array already |
| 561 // contains entry for given descriptor. This means that the transition | 560 // contains entry for given descriptor. This means that the transition |
| 562 // could be inserted regardless of whether transitions array is full or not. | 561 // could be inserted regardless of whether transitions array is full or not. |
| 563 if (maybe_transition == NULL && | 562 if (maybe_transition == NULL && |
| 564 !TransitionArray::CanHaveMoreTransitions(split_map)) { | 563 !TransitionArray::CanHaveMoreTransitions(split_map)) { |
| 565 return CopyGeneralizeAllRepresentations("GenAll_CantHaveMoreTransitions"); | 564 return CopyGeneralizeAllFields("GenAll_CantHaveMoreTransitions"); |
| 566 } | 565 } |
| 567 | 566 |
| 568 old_map_->NotifyLeafMapLayoutChange(); | 567 old_map_->NotifyLeafMapLayoutChange(); |
| 569 | 568 |
| 570 if (FLAG_trace_generalization && modified_descriptor_ >= 0) { | 569 if (FLAG_trace_generalization && modified_descriptor_ >= 0) { |
| 571 PropertyDetails old_details = | 570 PropertyDetails old_details = |
| 572 old_descriptors_->GetDetails(modified_descriptor_); | 571 old_descriptors_->GetDetails(modified_descriptor_); |
| 573 PropertyDetails new_details = | 572 PropertyDetails new_details = |
| 574 new_descriptors->GetDetails(modified_descriptor_); | 573 new_descriptors->GetDetails(modified_descriptor_); |
| 575 MaybeHandle<FieldType> old_field_type; | 574 MaybeHandle<FieldType> old_field_type; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 // the new descriptors to maintain descriptors sharing invariant. | 608 // the new descriptors to maintain descriptors sharing invariant. |
| 610 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor); | 609 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor); |
| 611 | 610 |
| 612 result_map_ = new_map; | 611 result_map_ = new_map; |
| 613 state_ = kEnd; | 612 state_ = kEnd; |
| 614 return state_; // Done. | 613 return state_; // Done. |
| 615 } | 614 } |
| 616 | 615 |
| 617 } // namespace internal | 616 } // namespace internal |
| 618 } // namespace v8 | 617 } // namespace v8 |
| OLD | NEW |