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 |