| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/js-native-context-specialization.h" | 5 #include "src/compiler/js-native-context-specialization.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/access-builder.h" | 10 #include "src/compiler/access-builder.h" |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 // Check if {receiver} may be a number. | 118 // Check if {receiver} may be a number. |
| 119 bool receiverissmi_possible = false; | 119 bool receiverissmi_possible = false; |
| 120 for (PropertyAccessInfo const& access_info : access_infos) { | 120 for (PropertyAccessInfo const& access_info : access_infos) { |
| 121 if (access_info.receiver_type()->Is(Type::Number())) { | 121 if (access_info.receiver_type()->Is(Type::Number())) { |
| 122 receiverissmi_possible = true; | 122 receiverissmi_possible = true; |
| 123 break; | 123 break; |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 | 126 |
| 127 // Ensure that {receiver} is a heap object. | 127 // Ensure that {receiver} is a heap object. |
| 128 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | |
| 129 Node* receiverissmi_control = nullptr; | 128 Node* receiverissmi_control = nullptr; |
| 130 Node* receiverissmi_effect = effect; | 129 Node* receiverissmi_effect = effect; |
| 131 if (receiverissmi_possible) { | 130 if (receiverissmi_possible) { |
| 131 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); |
| 132 Node* branch = graph()->NewNode(common()->Branch(), check, control); | 132 Node* branch = graph()->NewNode(common()->Branch(), check, control); |
| 133 control = graph()->NewNode(common()->IfFalse(), branch); | 133 control = graph()->NewNode(common()->IfFalse(), branch); |
| 134 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); | 134 receiverissmi_control = graph()->NewNode(common()->IfTrue(), branch); |
| 135 receiverissmi_effect = effect; | 135 receiverissmi_effect = effect; |
| 136 } else { | 136 } else { |
| 137 control = effect = graph()->NewNode(common()->DeoptimizeIf(), check, | 137 receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(), |
| 138 frame_state, effect, control); | 138 receiver, effect, control); |
| 139 } | 139 } |
| 140 | 140 |
| 141 // Load the {receiver} map. The resulting effect is the dominating effect for | 141 // Load the {receiver} map. The resulting effect is the dominating effect for |
| 142 // all (polymorphic) branches. | 142 // all (polymorphic) branches. |
| 143 Node* receiver_map = effect = | 143 Node* receiver_map = effect = |
| 144 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 144 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 145 receiver, effect, control); | 145 receiver, effect, control); |
| 146 | 146 |
| 147 // Generate code for the various different property access patterns. | 147 // Generate code for the various different property access patterns. |
| 148 Node* fallthrough_control = control; | 148 Node* fallthrough_control = control; |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 this_control = this_effect = | 281 this_control = this_effect = |
| 282 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, | 282 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, |
| 283 this_effect, this_control); | 283 this_effect, this_control); |
| 284 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), | 284 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), |
| 285 this_value, this_control); | 285 this_value, this_control); |
| 286 | 286 |
| 287 if (!field_index.is_inobject() || field_index.is_hidden_field() || | 287 if (!field_index.is_inobject() || field_index.is_hidden_field() || |
| 288 !FLAG_unbox_double_fields) { | 288 !FLAG_unbox_double_fields) { |
| 289 if (access_info.HasTransitionMap()) { | 289 if (access_info.HasTransitionMap()) { |
| 290 // Allocate a MutableHeapNumber for the new property. | 290 // Allocate a MutableHeapNumber for the new property. |
| 291 this_effect = | 291 this_effect = graph()->NewNode( |
| 292 graph()->NewNode(common()->BeginRegion(), this_effect); | 292 common()->BeginRegion(RegionObservability::kNotObservable), |
| 293 this_effect); |
| 293 Node* this_box = this_effect = | 294 Node* this_box = this_effect = |
| 294 graph()->NewNode(simplified()->Allocate(NOT_TENURED), | 295 graph()->NewNode(simplified()->Allocate(NOT_TENURED), |
| 295 jsgraph()->Constant(HeapNumber::kSize), | 296 jsgraph()->Constant(HeapNumber::kSize), |
| 296 this_effect, this_control); | 297 this_effect, this_control); |
| 297 this_effect = graph()->NewNode( | 298 this_effect = graph()->NewNode( |
| 298 simplified()->StoreField(AccessBuilder::ForMap()), this_box, | 299 simplified()->StoreField(AccessBuilder::ForMap()), this_box, |
| 299 jsgraph()->HeapConstant(factory()->mutable_heap_number_map()), | 300 jsgraph()->HeapConstant(factory()->mutable_heap_number_map()), |
| 300 this_effect, this_control); | 301 this_effect, this_control); |
| 301 this_effect = graph()->NewNode( | 302 this_effect = graph()->NewNode( |
| 302 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), | 303 simplified()->StoreField(AccessBuilder::ForHeapNumberValue()), |
| 303 this_box, this_value, this_effect, this_control); | 304 this_box, this_value, this_effect, this_control); |
| 304 this_value = this_effect = graph()->NewNode( | 305 this_value = this_effect = graph()->NewNode( |
| 305 common()->FinishRegion(), this_box, this_effect); | 306 common()->FinishRegion(), this_box, this_effect); |
| 306 | 307 |
| 307 field_access.type = Type::TaggedPointer(); | 308 field_access.type = Type::TaggedPointer(); |
| 308 } else { | 309 } else { |
| 309 // We just store directly to the MutableHeapNumber. | 310 // We just store directly to the MutableHeapNumber. |
| 310 this_storage = this_effect = | 311 this_storage = this_effect = |
| 311 graph()->NewNode(simplified()->LoadField(field_access), | 312 graph()->NewNode(simplified()->LoadField(field_access), |
| 312 this_storage, this_effect, this_control); | 313 this_storage, this_effect, this_control); |
| 313 field_access.offset = HeapNumber::kValueOffset; | 314 field_access.offset = HeapNumber::kValueOffset; |
| 314 field_access.name = MaybeHandle<Name>(); | 315 field_access.name = MaybeHandle<Name>(); |
| 315 field_access.machine_type = MachineType::Float64(); | 316 field_access.machine_type = MachineType::Float64(); |
| 316 } | 317 } |
| 317 } else { | 318 } else { |
| 318 // Unboxed double field, we store directly to the field. | 319 // Unboxed double field, we store directly to the field. |
| 319 field_access.machine_type = MachineType::Float64(); | 320 field_access.machine_type = MachineType::Float64(); |
| 320 } | 321 } |
| 321 } else if (field_type->Is(Type::TaggedSigned())) { | 322 } else if (field_type->Is(Type::TaggedSigned())) { |
| 322 Node* check = | 323 this_value = this_effect = |
| 323 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); | 324 graph()->NewNode(simplified()->CheckTaggedSigned(), this_value, |
| 324 this_control = this_effect = | |
| 325 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, | |
| 326 this_effect, this_control); | 325 this_effect, this_control); |
| 327 this_value = | |
| 328 graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), | |
| 329 this_value, this_control); | |
| 330 } else if (field_type->Is(Type::TaggedPointer())) { | 326 } else if (field_type->Is(Type::TaggedPointer())) { |
| 331 Node* check = | 327 this_value = this_effect = |
| 332 graph()->NewNode(simplified()->ObjectIsSmi(), this_value); | 328 graph()->NewNode(simplified()->CheckTaggedPointer(), this_value, |
| 333 this_control = this_effect = | |
| 334 graph()->NewNode(common()->DeoptimizeIf(), check, frame_state, | |
| 335 this_effect, this_control); | 329 this_effect, this_control); |
| 336 if (field_type->NumClasses() == 1) { | 330 if (field_type->NumClasses() == 1) { |
| 337 // Emit a map check for the value. | 331 // Emit a map check for the value. |
| 338 Node* this_value_map = this_effect = graph()->NewNode( | 332 Node* this_value_map = this_effect = graph()->NewNode( |
| 339 simplified()->LoadField(AccessBuilder::ForMap()), this_value, | 333 simplified()->LoadField(AccessBuilder::ForMap()), this_value, |
| 340 this_effect, this_control); | 334 this_effect, this_control); |
| 341 Node* check = graph()->NewNode( | 335 Node* check = graph()->NewNode( |
| 342 simplified()->ReferenceEqual(Type::Internal()), this_value_map, | 336 simplified()->ReferenceEqual(Type::Internal()), this_value_map, |
| 343 jsgraph()->Constant(field_type->Classes().Current())); | 337 jsgraph()->Constant(field_type->Classes().Current())); |
| 344 this_control = this_effect = | 338 this_control = this_effect = |
| 345 graph()->NewNode(common()->DeoptimizeUnless(), check, | 339 graph()->NewNode(common()->DeoptimizeUnless(), check, |
| 346 frame_state, this_effect, this_control); | 340 frame_state, this_effect, this_control); |
| 347 } else { | 341 } else { |
| 348 DCHECK_EQ(0, field_type->NumClasses()); | 342 DCHECK_EQ(0, field_type->NumClasses()); |
| 349 } | 343 } |
| 350 } else { | 344 } else { |
| 351 DCHECK(field_type->Is(Type::Tagged())); | 345 DCHECK(field_type->Is(Type::Tagged())); |
| 352 } | 346 } |
| 353 Handle<Map> transition_map; | 347 Handle<Map> transition_map; |
| 354 if (access_info.transition_map().ToHandle(&transition_map)) { | 348 if (access_info.transition_map().ToHandle(&transition_map)) { |
| 355 this_effect = graph()->NewNode(common()->BeginRegion(), this_effect); | 349 this_effect = graph()->NewNode( |
| 350 common()->BeginRegion(RegionObservability::kObservable), |
| 351 this_effect); |
| 356 this_effect = graph()->NewNode( | 352 this_effect = graph()->NewNode( |
| 357 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver, | 353 simplified()->StoreField(AccessBuilder::ForMap()), this_receiver, |
| 358 jsgraph()->Constant(transition_map), this_effect, this_control); | 354 jsgraph()->Constant(transition_map), this_effect, this_control); |
| 359 } | 355 } |
| 360 this_effect = graph()->NewNode(simplified()->StoreField(field_access), | 356 this_effect = graph()->NewNode(simplified()->StoreField(field_access), |
| 361 this_storage, this_value, this_effect, | 357 this_storage, this_value, this_effect, |
| 362 this_control); | 358 this_control); |
| 363 if (access_info.HasTransitionMap()) { | 359 if (access_info.HasTransitionMap()) { |
| 364 this_effect = | 360 this_effect = |
| 365 graph()->NewNode(common()->FinishRegion(), | 361 graph()->NewNode(common()->FinishRegion(), |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 524 // Nothing to do if we have no non-deprecated maps. | 520 // Nothing to do if we have no non-deprecated maps. |
| 525 if (access_infos.empty()) return NoChange(); | 521 if (access_infos.empty()) return NoChange(); |
| 526 | 522 |
| 527 // The final states for every polymorphic branch. We join them with | 523 // The final states for every polymorphic branch. We join them with |
| 528 // Merge+Phi+EffectPhi at the bottom. | 524 // Merge+Phi+EffectPhi at the bottom. |
| 529 ZoneVector<Node*> values(zone()); | 525 ZoneVector<Node*> values(zone()); |
| 530 ZoneVector<Node*> effects(zone()); | 526 ZoneVector<Node*> effects(zone()); |
| 531 ZoneVector<Node*> controls(zone()); | 527 ZoneVector<Node*> controls(zone()); |
| 532 | 528 |
| 533 // Ensure that {receiver} is a heap object. | 529 // Ensure that {receiver} is a heap object. |
| 534 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), receiver); | 530 receiver = effect = graph()->NewNode(simplified()->CheckTaggedPointer(), |
| 535 control = effect = graph()->NewNode(common()->DeoptimizeIf(), check, | 531 receiver, effect, control); |
| 536 frame_state, effect, control); | |
| 537 | 532 |
| 538 // Load the {receiver} map. The resulting effect is the dominating effect for | 533 // Load the {receiver} map. The resulting effect is the dominating effect for |
| 539 // all (polymorphic) branches. | 534 // all (polymorphic) branches. |
| 540 Node* receiver_map = effect = | 535 Node* receiver_map = effect = |
| 541 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 536 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 542 receiver, effect, control); | 537 receiver, effect, control); |
| 543 | 538 |
| 544 // Generate code for the various different element access patterns. | 539 // Generate code for the various different element access patterns. |
| 545 Node* fallthrough_control = control; | 540 Node* fallthrough_control = control; |
| 546 for (size_t j = 0; j < access_infos.size(); ++j) { | 541 for (size_t j = 0; j < access_infos.size(); ++j) { |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 778 // Return the signaling NaN hole directly if all uses are truncating. | 773 // Return the signaling NaN hole directly if all uses are truncating. |
| 779 mode = CheckFloat64HoleMode::kAllowReturnHole; | 774 mode = CheckFloat64HoleMode::kAllowReturnHole; |
| 780 } | 775 } |
| 781 this_value = this_effect = | 776 this_value = this_effect = |
| 782 graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value, | 777 graph()->NewNode(simplified()->CheckFloat64Hole(mode), this_value, |
| 783 this_effect, this_control); | 778 this_effect, this_control); |
| 784 } | 779 } |
| 785 } else { | 780 } else { |
| 786 DCHECK_EQ(AccessMode::kStore, access_mode); | 781 DCHECK_EQ(AccessMode::kStore, access_mode); |
| 787 if (IsFastSmiElementsKind(elements_kind)) { | 782 if (IsFastSmiElementsKind(elements_kind)) { |
| 788 Node* check = graph()->NewNode(simplified()->ObjectIsSmi(), this_value); | 783 this_value = this_effect = |
| 789 this_control = this_effect = | 784 graph()->NewNode(simplified()->CheckTaggedSigned(), this_value, |
| 790 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, | |
| 791 this_effect, this_control); | 785 this_effect, this_control); |
| 792 this_value = graph()->NewNode(simplified()->TypeGuard(type_cache_.kSmi), | |
| 793 this_value, this_control); | |
| 794 } else if (IsFastDoubleElementsKind(elements_kind)) { | 786 } else if (IsFastDoubleElementsKind(elements_kind)) { |
| 795 Node* check = | 787 Node* check = |
| 796 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); | 788 graph()->NewNode(simplified()->ObjectIsNumber(), this_value); |
| 797 this_control = this_effect = | 789 this_control = this_effect = |
| 798 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, | 790 graph()->NewNode(common()->DeoptimizeUnless(), check, frame_state, |
| 799 this_effect, this_control); | 791 this_effect, this_control); |
| 800 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), | 792 this_value = graph()->NewNode(simplified()->TypeGuard(Type::Number()), |
| 801 this_value, this_control); | 793 this_value, this_control); |
| 802 // Make sure we do not store signalling NaNs into holey double arrays. | 794 // Make sure we do not store signalling NaNs into holey double arrays. |
| 803 if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { | 795 if (elements_kind == FAST_HOLEY_DOUBLE_ELEMENTS) { |
| (...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1091 } | 1083 } |
| 1092 | 1084 |
| 1093 | 1085 |
| 1094 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1086 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 1095 return jsgraph()->simplified(); | 1087 return jsgraph()->simplified(); |
| 1096 } | 1088 } |
| 1097 | 1089 |
| 1098 } // namespace compiler | 1090 } // namespace compiler |
| 1099 } // namespace internal | 1091 } // namespace internal |
| 1100 } // namespace v8 | 1092 } // namespace v8 |
| OLD | NEW |