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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 if (location == kField) { | 78 if (location == kField) { |
79 return handle(descriptors->GetFieldType(descriptor), isolate_); | 79 return handle(descriptors->GetFieldType(descriptor), isolate_); |
80 } else { | 80 } else { |
81 return descriptors->GetValue(descriptor) | 81 return descriptors->GetValue(descriptor) |
82 ->OptimalType(isolate_, representation); | 82 ->OptimalType(isolate_, representation); |
83 } | 83 } |
84 } | 84 } |
85 | 85 |
86 Handle<Map> MapUpdater::ReconfigureToDataField(int descriptor, | 86 Handle<Map> MapUpdater::ReconfigureToDataField(int descriptor, |
87 PropertyAttributes attributes, | 87 PropertyAttributes attributes, |
| 88 PropertyConstness constness, |
88 Representation representation, | 89 Representation representation, |
89 Handle<FieldType> field_type) { | 90 Handle<FieldType> field_type) { |
90 DCHECK_EQ(kInitialized, state_); | 91 DCHECK_EQ(kInitialized, state_); |
91 DCHECK_LE(0, descriptor); | 92 DCHECK_LE(0, descriptor); |
92 DCHECK(!old_map_->is_dictionary_map()); | 93 DCHECK(!old_map_->is_dictionary_map()); |
93 modified_descriptor_ = descriptor; | 94 modified_descriptor_ = descriptor; |
94 new_kind_ = kData; | 95 new_kind_ = kData; |
95 new_attributes_ = attributes; | 96 new_attributes_ = attributes; |
96 new_location_ = kField; | 97 new_location_ = kField; |
97 | 98 |
98 PropertyDetails old_details = | 99 PropertyDetails old_details = |
99 old_descriptors_->GetDetails(modified_descriptor_); | 100 old_descriptors_->GetDetails(modified_descriptor_); |
100 | 101 |
101 // If property kind is not reconfigured merge the result with | 102 // If property kind is not reconfigured merge the result with |
102 // representation/field type from the old descriptor. | 103 // representation/field type from the old descriptor. |
103 if (old_details.kind() == new_kind_) { | 104 if (old_details.kind() == new_kind_) { |
104 new_constness_ = kMutable; | 105 new_constness_ = GeneralizeConstness(constness, old_details.constness()); |
105 | 106 |
106 Representation old_representation = old_details.representation(); | 107 Representation old_representation = old_details.representation(); |
107 new_representation_ = representation.generalize(old_representation); | 108 new_representation_ = representation.generalize(old_representation); |
108 | 109 |
109 Handle<FieldType> old_field_type = | 110 Handle<FieldType> old_field_type = |
110 GetOrComputeFieldType(old_descriptors_, modified_descriptor_, | 111 GetOrComputeFieldType(old_descriptors_, modified_descriptor_, |
111 old_details.location(), new_representation_); | 112 old_details.location(), new_representation_); |
112 | 113 |
113 new_field_type_ = | 114 new_field_type_ = |
114 Map::GeneralizeFieldType(old_representation, old_field_type, | 115 Map::GeneralizeFieldType(old_representation, old_field_type, |
(...skipping 30 matching lines...) Expand all Loading... |
145 DCHECK_EQ(kInitialized, state_); | 146 DCHECK_EQ(kInitialized, state_); |
146 DCHECK(old_map_->is_deprecated()); | 147 DCHECK(old_map_->is_deprecated()); |
147 | 148 |
148 if (FindRootMap() == kEnd) return result_map_; | 149 if (FindRootMap() == kEnd) return result_map_; |
149 if (FindTargetMap() == kEnd) return result_map_; | 150 if (FindTargetMap() == kEnd) return result_map_; |
150 ConstructNewMap(); | 151 ConstructNewMap(); |
151 DCHECK_EQ(kEnd, state_); | 152 DCHECK_EQ(kEnd, state_); |
152 return result_map_; | 153 return result_map_; |
153 } | 154 } |
154 | 155 |
| 156 void MapUpdater::GeneralizeField(Handle<Map> map, int modify_index, |
| 157 PropertyConstness new_constness, |
| 158 Representation new_representation, |
| 159 Handle<FieldType> new_field_type) { |
| 160 Map::GeneralizeField(map, modify_index, new_constness, new_representation, |
| 161 new_field_type); |
| 162 |
| 163 DCHECK_EQ(*old_descriptors_, old_map_->instance_descriptors()); |
| 164 } |
| 165 |
155 MapUpdater::State MapUpdater::CopyGeneralizeAllFields(const char* reason) { | 166 MapUpdater::State MapUpdater::CopyGeneralizeAllFields(const char* reason) { |
156 result_map_ = Map::CopyGeneralizeAllFields(old_map_, new_elements_kind_, | 167 result_map_ = Map::CopyGeneralizeAllFields(old_map_, new_elements_kind_, |
157 modified_descriptor_, new_kind_, | 168 modified_descriptor_, new_kind_, |
158 new_attributes_, reason); | 169 new_attributes_, reason); |
159 state_ = kEnd; | 170 state_ = kEnd; |
160 return state_; // Done. | 171 return state_; // Done. |
161 } | 172 } |
162 | 173 |
163 MapUpdater::State MapUpdater::TryRecofigureToDataFieldInplace() { | 174 MapUpdater::State MapUpdater::TryRecofigureToDataFieldInplace() { |
164 // If it's just a representation generalization case (i.e. property kind and | 175 // If it's just a representation generalization case (i.e. property kind and |
(...skipping 18 matching lines...) Expand all Loading... |
183 if (FLAG_trace_generalization) { | 194 if (FLAG_trace_generalization) { |
184 old_map_->PrintGeneralization( | 195 old_map_->PrintGeneralization( |
185 stdout, "uninitialized field", modified_descriptor_, old_nof_, old_nof_, | 196 stdout, "uninitialized field", modified_descriptor_, old_nof_, old_nof_, |
186 false, old_representation, new_representation_, | 197 false, old_representation, new_representation_, |
187 handle(old_descriptors_->GetFieldType(modified_descriptor_), isolate_), | 198 handle(old_descriptors_->GetFieldType(modified_descriptor_), isolate_), |
188 MaybeHandle<Object>(), new_field_type_, MaybeHandle<Object>()); | 199 MaybeHandle<Object>(), new_field_type_, MaybeHandle<Object>()); |
189 } | 200 } |
190 Handle<Map> field_owner(old_map_->FindFieldOwner(modified_descriptor_), | 201 Handle<Map> field_owner(old_map_->FindFieldOwner(modified_descriptor_), |
191 isolate_); | 202 isolate_); |
192 | 203 |
193 Map::GeneralizeField(field_owner, modified_descriptor_, new_representation_, | 204 GeneralizeField(field_owner, modified_descriptor_, new_constness_, |
194 new_field_type_); | 205 new_representation_, new_field_type_); |
195 // Check that the descriptor array was updated. | 206 // Check that the descriptor array was updated. |
196 DCHECK(old_descriptors_->GetDetails(modified_descriptor_) | 207 DCHECK(old_descriptors_->GetDetails(modified_descriptor_) |
197 .representation() | 208 .representation() |
198 .Equals(new_representation_)); | 209 .Equals(new_representation_)); |
199 DCHECK(old_descriptors_->GetFieldType(modified_descriptor_) | 210 DCHECK(old_descriptors_->GetFieldType(modified_descriptor_) |
200 ->NowIs(new_field_type_)); | 211 ->NowIs(new_field_type_)); |
201 | 212 |
202 result_map_ = old_map_; | 213 result_map_ = old_map_; |
203 state_ = kEnd; | 214 state_ = kEnd; |
204 return state_; // Done. | 215 return state_; // Done. |
(...skipping 22 matching lines...) Expand all Loading... |
227 if (modified_descriptor_ >= 0 && modified_descriptor_ < root_nof) { | 238 if (modified_descriptor_ >= 0 && modified_descriptor_ < root_nof) { |
228 PropertyDetails old_details = | 239 PropertyDetails old_details = |
229 old_descriptors_->GetDetails(modified_descriptor_); | 240 old_descriptors_->GetDetails(modified_descriptor_); |
230 if (old_details.kind() != new_kind_ || | 241 if (old_details.kind() != new_kind_ || |
231 old_details.attributes() != new_attributes_) { | 242 old_details.attributes() != new_attributes_) { |
232 return CopyGeneralizeAllFields("GenAll_RootModification1"); | 243 return CopyGeneralizeAllFields("GenAll_RootModification1"); |
233 } | 244 } |
234 if (old_details.location() != kField) { | 245 if (old_details.location() != kField) { |
235 return CopyGeneralizeAllFields("GenAll_RootModification2"); | 246 return CopyGeneralizeAllFields("GenAll_RootModification2"); |
236 } | 247 } |
237 DCHECK_EQ(kMutable, old_details.constness()); | 248 if (new_constness_ != old_details.constness()) { |
238 if (!new_representation_.fits_into(old_details.representation())) { | |
239 return CopyGeneralizeAllFields("GenAll_RootModification3"); | 249 return CopyGeneralizeAllFields("GenAll_RootModification3"); |
240 } | 250 } |
| 251 if (!new_representation_.fits_into(old_details.representation())) { |
| 252 return CopyGeneralizeAllFields("GenAll_RootModification4"); |
| 253 } |
| 254 |
241 DCHECK_EQ(kData, old_details.kind()); | 255 DCHECK_EQ(kData, old_details.kind()); |
242 DCHECK_EQ(kData, new_kind_); | 256 DCHECK_EQ(kData, new_kind_); |
243 DCHECK_EQ(kField, new_location_); | 257 DCHECK_EQ(kField, new_location_); |
244 FieldType* old_field_type = | 258 FieldType* old_field_type = |
245 old_descriptors_->GetFieldType(modified_descriptor_); | 259 old_descriptors_->GetFieldType(modified_descriptor_); |
246 if (!new_field_type_->NowIs(old_field_type)) { | 260 if (!new_field_type_->NowIs(old_field_type)) { |
247 return CopyGeneralizeAllFields("GenAll_RootModification4"); | 261 return CopyGeneralizeAllFields("GenAll_RootModification5"); |
248 } | 262 } |
249 } | 263 } |
250 | 264 |
251 // From here on, use the map with correct elements kind as root map. | 265 // From here on, use the map with correct elements kind as root map. |
252 if (from_kind != to_kind) { | 266 if (from_kind != to_kind) { |
253 root_map_ = Map::AsElementsKind(root_map_, to_kind); | 267 root_map_ = Map::AsElementsKind(root_map_, to_kind); |
254 } | 268 } |
255 state_ = kAtRootMap; | 269 state_ = kAtRootMap; |
256 return state_; // Not done yet. | 270 return state_; // Not done yet. |
257 } | 271 } |
(...skipping 15 matching lines...) Expand all Loading... |
273 | 287 |
274 // Check if target map is incompatible. | 288 // Check if target map is incompatible. |
275 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); | 289 PropertyDetails tmp_details = tmp_descriptors->GetDetails(i); |
276 DCHECK_EQ(old_details.kind(), tmp_details.kind()); | 290 DCHECK_EQ(old_details.kind(), tmp_details.kind()); |
277 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); | 291 DCHECK_EQ(old_details.attributes(), tmp_details.attributes()); |
278 if (old_details.kind() == kAccessor && | 292 if (old_details.kind() == kAccessor && |
279 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { | 293 !EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { |
280 // TODO(ishell): mutable accessors are not implemented yet. | 294 // TODO(ishell): mutable accessors are not implemented yet. |
281 return CopyGeneralizeAllFields("GenAll_Incompatible"); | 295 return CopyGeneralizeAllFields("GenAll_Incompatible"); |
282 } | 296 } |
283 // Check if old constness fits into tmp constness. | 297 PropertyConstness tmp_constness = tmp_details.constness(); |
284 if (!IsGeneralizableTo(old_details.constness(), tmp_details.constness())) { | 298 if (!IsGeneralizableTo(old_details.constness(), tmp_constness)) { |
285 break; | 299 break; |
286 } | 300 } |
287 // Check if old location fits into tmp location. | |
288 if (!IsGeneralizableTo(old_details.location(), tmp_details.location())) { | 301 if (!IsGeneralizableTo(old_details.location(), tmp_details.location())) { |
289 break; | 302 break; |
290 } | 303 } |
291 | |
292 // Check if old representation fits into tmp representation. | |
293 Representation tmp_representation = tmp_details.representation(); | 304 Representation tmp_representation = tmp_details.representation(); |
294 if (!old_details.representation().fits_into(tmp_representation)) { | 305 if (!old_details.representation().fits_into(tmp_representation)) { |
295 break; | 306 break; |
296 } | 307 } |
297 | 308 |
298 if (tmp_details.location() == kField) { | 309 if (tmp_details.location() == kField) { |
299 Handle<FieldType> old_field_type = | 310 Handle<FieldType> old_field_type = |
300 GetOrComputeFieldType(i, old_details.location(), tmp_representation); | 311 GetOrComputeFieldType(i, old_details.location(), tmp_representation); |
301 Map::GeneralizeField(tmp_map, i, tmp_representation, old_field_type); | 312 GeneralizeField(tmp_map, i, tmp_constness, tmp_representation, |
| 313 old_field_type); |
302 } else { | 314 } else { |
303 // kDescriptor: Check that the value matches. | 315 // kDescriptor: Check that the value matches. |
304 if (!EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { | 316 if (!EqualImmutableValues(GetValue(i), tmp_descriptors->GetValue(i))) { |
305 break; | 317 break; |
306 } | 318 } |
307 } | 319 } |
308 DCHECK(!tmp_map->is_deprecated()); | 320 DCHECK(!tmp_map->is_deprecated()); |
309 target_map_ = tmp_map; | 321 target_map_ = tmp_map; |
310 } | 322 } |
311 | 323 |
312 // Directly change the map if the target map is more general. | 324 // Directly change the map if the target map is more general. |
313 int target_nof = target_map_->NumberOfOwnDescriptors(); | 325 int target_nof = target_map_->NumberOfOwnDescriptors(); |
314 if (target_nof == old_nof_) { | 326 if (target_nof == old_nof_) { |
315 #ifdef DEBUG | 327 #ifdef DEBUG |
316 if (modified_descriptor_ >= 0) { | 328 if (modified_descriptor_ >= 0) { |
317 DescriptorArray* target_descriptors = target_map_->instance_descriptors(); | 329 DescriptorArray* target_descriptors = target_map_->instance_descriptors(); |
318 PropertyDetails details = | 330 PropertyDetails details = |
319 target_descriptors->GetDetails(modified_descriptor_); | 331 target_descriptors->GetDetails(modified_descriptor_); |
320 DCHECK_EQ(new_kind_, details.kind()); | 332 DCHECK_EQ(new_kind_, details.kind()); |
321 DCHECK_EQ(new_attributes_, details.attributes()); | 333 DCHECK_EQ(new_attributes_, details.attributes()); |
| 334 DCHECK(IsGeneralizableTo(new_constness_, details.constness())); |
322 DCHECK_EQ(new_location_, details.location()); | 335 DCHECK_EQ(new_location_, details.location()); |
323 DCHECK(new_representation_.fits_into(details.representation())); | 336 DCHECK(new_representation_.fits_into(details.representation())); |
324 if (new_location_ == kField) { | 337 if (new_location_ == kField) { |
325 DCHECK_EQ(kField, details.location()); | 338 DCHECK_EQ(kField, details.location()); |
326 DCHECK(new_field_type_->NowIs( | 339 DCHECK(new_field_type_->NowIs( |
327 target_descriptors->GetFieldType(modified_descriptor_))); | 340 target_descriptors->GetFieldType(modified_descriptor_))); |
328 } else { | 341 } else { |
329 DCHECK(details.location() == kField || | 342 DCHECK(details.location() == kField || |
330 EqualImmutableValues(*new_value_, target_descriptors->GetValue( | 343 EqualImmutableValues(*new_value_, target_descriptors->GetValue( |
331 modified_descriptor_))); | 344 modified_descriptor_))); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 // Note: failed values equality check does not invalidate per-object | 433 // Note: failed values equality check does not invalidate per-object |
421 // property constness. | 434 // property constness. |
422 PropertyLocation next_location = | 435 PropertyLocation next_location = |
423 old_details.location() == kField || | 436 old_details.location() == kField || |
424 target_details.location() == kField || | 437 target_details.location() == kField || |
425 !EqualImmutableValues(target_descriptors->GetValue(i), | 438 !EqualImmutableValues(target_descriptors->GetValue(i), |
426 GetValue(i)) | 439 GetValue(i)) |
427 ? kField | 440 ? kField |
428 : kDescriptor; | 441 : kDescriptor; |
429 | 442 |
430 // TODO(ishell): remove once constant field tracking is done. | 443 if (!FLAG_track_constant_fields && next_location == kField) { |
431 if (next_location == kField) next_constness = kMutable; | 444 next_constness = kMutable; |
| 445 } |
432 // Ensure that mutable values are stored in fields. | 446 // Ensure that mutable values are stored in fields. |
433 DCHECK_IMPLIES(next_constness == kMutable, next_location == kField); | 447 DCHECK_IMPLIES(next_constness == kMutable, next_location == kField); |
434 | 448 |
435 Representation next_representation = | 449 Representation next_representation = |
436 old_details.representation().generalize( | 450 old_details.representation().generalize( |
437 target_details.representation()); | 451 target_details.representation()); |
438 | 452 |
439 if (next_location == kField) { | 453 if (next_location == kField) { |
440 Handle<FieldType> old_field_type = | 454 Handle<FieldType> old_field_type = |
441 GetOrComputeFieldType(i, old_details.location(), next_representation); | 455 GetOrComputeFieldType(i, old_details.location(), next_representation); |
(...skipping 18 matching lines...) Expand all Loading... |
460 } | 474 } |
461 current_offset += d.GetDetails().field_width_in_words(); | 475 current_offset += d.GetDetails().field_width_in_words(); |
462 new_descriptors->Set(i, &d); | 476 new_descriptors->Set(i, &d); |
463 } else { | 477 } else { |
464 DCHECK_EQ(kDescriptor, next_location); | 478 DCHECK_EQ(kDescriptor, next_location); |
465 DCHECK_EQ(kConst, next_constness); | 479 DCHECK_EQ(kConst, next_constness); |
466 | 480 |
467 Handle<Object> value(GetValue(i), isolate_); | 481 Handle<Object> value(GetValue(i), isolate_); |
468 Descriptor d; | 482 Descriptor d; |
469 if (next_kind == kData) { | 483 if (next_kind == kData) { |
| 484 DCHECK(!FLAG_track_constant_fields); |
470 d = Descriptor::DataConstant(key, value, next_attributes); | 485 d = Descriptor::DataConstant(key, value, next_attributes); |
471 } else { | 486 } else { |
472 DCHECK_EQ(kAccessor, next_kind); | 487 DCHECK_EQ(kAccessor, next_kind); |
473 d = Descriptor::AccessorConstant(key, value, next_attributes); | 488 d = Descriptor::AccessorConstant(key, value, next_attributes); |
474 } | 489 } |
475 new_descriptors->Set(i, &d); | 490 new_descriptors->Set(i, &d); |
476 } | 491 } |
477 } | 492 } |
478 | 493 |
479 // Take "updated" old_descriptor entries. | 494 // Take "updated" old_descriptor entries. |
480 // |target_nof| -> |old_nof| | 495 // |target_nof| -> |old_nof| |
481 for (int i = target_nof; i < old_nof_; ++i) { | 496 for (int i = target_nof; i < old_nof_; ++i) { |
482 PropertyDetails old_details = GetDetails(i); | 497 PropertyDetails old_details = GetDetails(i); |
483 Handle<Name> key(GetKey(i), isolate_); | 498 Handle<Name> key(GetKey(i), isolate_); |
484 | 499 |
485 PropertyKind next_kind = old_details.kind(); | 500 PropertyKind next_kind = old_details.kind(); |
486 PropertyAttributes next_attributes = old_details.attributes(); | 501 PropertyAttributes next_attributes = old_details.attributes(); |
487 PropertyConstness next_constness = old_details.constness(); | 502 PropertyConstness next_constness = old_details.constness(); |
488 PropertyLocation next_location = old_details.location(); | 503 PropertyLocation next_location = old_details.location(); |
489 Representation next_representation = old_details.representation(); | 504 Representation next_representation = old_details.representation(); |
490 | 505 |
491 Descriptor d; | 506 Descriptor d; |
492 if (next_location == kField) { | 507 if (next_location == kField) { |
493 DCHECK_EQ(kMutable, next_constness); | |
494 Handle<FieldType> old_field_type = | 508 Handle<FieldType> old_field_type = |
495 GetOrComputeFieldType(i, old_details.location(), next_representation); | 509 GetOrComputeFieldType(i, old_details.location(), next_representation); |
496 | 510 |
497 Handle<Object> wrapped_type(Map::WrapFieldType(old_field_type)); | 511 Handle<Object> wrapped_type(Map::WrapFieldType(old_field_type)); |
498 Descriptor d; | 512 Descriptor d; |
499 if (next_kind == kData) { | 513 if (next_kind == kData) { |
| 514 DCHECK_IMPLIES(!FLAG_track_constant_fields, next_constness == kMutable); |
500 d = Descriptor::DataField(key, current_offset, next_attributes, | 515 d = Descriptor::DataField(key, current_offset, next_attributes, |
501 next_constness, next_representation, | 516 next_constness, next_representation, |
502 wrapped_type); | 517 wrapped_type); |
503 } else { | 518 } else { |
504 // TODO(ishell): mutable accessors are not implemented yet. | 519 // TODO(ishell): mutable accessors are not implemented yet. |
505 UNIMPLEMENTED(); | 520 UNIMPLEMENTED(); |
506 } | 521 } |
507 current_offset += d.GetDetails().field_width_in_words(); | 522 current_offset += d.GetDetails().field_width_in_words(); |
508 new_descriptors->Set(i, &d); | 523 new_descriptors->Set(i, &d); |
509 } else { | 524 } else { |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
630 // the new descriptors to maintain descriptors sharing invariant. | 645 // the new descriptors to maintain descriptors sharing invariant. |
631 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor); | 646 split_map->ReplaceDescriptors(*new_descriptors, *new_layout_descriptor); |
632 | 647 |
633 result_map_ = new_map; | 648 result_map_ = new_map; |
634 state_ = kEnd; | 649 state_ = kEnd; |
635 return state_; // Done. | 650 return state_; // Done. |
636 } | 651 } |
637 | 652 |
638 } // namespace internal | 653 } // namespace internal |
639 } // namespace v8 | 654 } // namespace v8 |
OLD | NEW |