| 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 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 208 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 208 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 209 receiver, effect, control); | 209 receiver, effect, control); |
| 210 | 210 |
| 211 // Generate code for the various different property access patterns. | 211 // Generate code for the various different property access patterns. |
| 212 Node* fallthrough_control = control; | 212 Node* fallthrough_control = control; |
| 213 for (size_t j = 0; j < access_infos.size(); ++j) { | 213 for (size_t j = 0; j < access_infos.size(); ++j) { |
| 214 PropertyAccessInfo const& access_info = access_infos[j]; | 214 PropertyAccessInfo const& access_info = access_infos[j]; |
| 215 Node* this_value = value; | 215 Node* this_value = value; |
| 216 Node* this_receiver = receiver; | 216 Node* this_receiver = receiver; |
| 217 Node* this_effect = effect; | 217 Node* this_effect = effect; |
| 218 Node* this_control; | 218 Node* this_control = fallthrough_control; |
| 219 | 219 |
| 220 // Perform map check on {receiver}. | 220 // Perform map check on {receiver}. |
| 221 MapList const& receiver_maps = access_info.receiver_maps(); | 221 MapList const& receiver_maps = access_info.receiver_maps(); |
| 222 { | 222 { |
| 223 // Emit a (sequence of) map checks for other {receiver}s. | 223 // Emit a (sequence of) map checks for other {receiver}s. |
| 224 ZoneVector<Node*> this_controls(zone()); | 224 ZoneVector<Node*> this_controls(zone()); |
| 225 ZoneVector<Node*> this_effects(zone()); | 225 ZoneVector<Node*> this_effects(zone()); |
| 226 size_t num_classes = receiver_maps.size(); | 226 if (j == access_infos.size() - 1) { |
| 227 for (auto map : receiver_maps) { | 227 // Last map check on the fallthrough control path, do a |
| 228 DCHECK_LT(0u, num_classes); | 228 // conditional eager deoptimization exit here. |
| 229 Node* check = | 229 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
| 230 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, | 230 receiver_maps); |
| 231 jsgraph()->Constant(map)); | 231 this_effects.push_back(this_effect); |
| 232 if (--num_classes == 0 && j == access_infos.size() - 1) { | 232 this_controls.push_back(fallthrough_control); |
| 233 check = graph()->NewNode(simplified()->CheckIf(), check, | 233 fallthrough_control = nullptr; |
| 234 this_effect, fallthrough_control); | 234 } else { |
| 235 this_controls.push_back(fallthrough_control); | 235 for (auto map : receiver_maps) { |
| 236 this_effects.push_back(check); | 236 Node* check = |
| 237 fallthrough_control = nullptr; | 237 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, |
| 238 } else { | 238 jsgraph()->Constant(map)); |
| 239 Node* branch = graph()->NewNode(common()->Branch(), check, | 239 Node* branch = graph()->NewNode(common()->Branch(), check, |
| 240 fallthrough_control); | 240 fallthrough_control); |
| 241 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 241 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 242 this_controls.push_back( | 242 this_controls.push_back( |
| 243 graph()->NewNode(common()->IfTrue(), branch)); | 243 graph()->NewNode(common()->IfTrue(), branch)); |
| 244 this_effects.push_back(this_effect); | 244 this_effects.push_back(this_effect); |
| 245 } | 245 } |
| 246 } | 246 } |
| 247 | 247 |
| 248 // The Number case requires special treatment to also deal with Smis. | 248 // The Number case requires special treatment to also deal with Smis. |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 572 this_control); | 572 this_control); |
| 573 } | 573 } |
| 574 | 574 |
| 575 // Load the {receiver} map. | 575 // Load the {receiver} map. |
| 576 Node* receiver_map = this_effect = | 576 Node* receiver_map = this_effect = |
| 577 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), | 577 graph()->NewNode(simplified()->LoadField(AccessBuilder::ForMap()), |
| 578 receiver, this_effect, this_control); | 578 receiver, this_effect, this_control); |
| 579 | 579 |
| 580 // Perform map check(s) on {receiver}. | 580 // Perform map check(s) on {receiver}. |
| 581 MapList const& receiver_maps = access_info.receiver_maps(); | 581 MapList const& receiver_maps = access_info.receiver_maps(); |
| 582 { | 582 if (j == access_infos.size() - 1) { |
| 583 // Last map check on the fallthrough control path, do a |
| 584 // conditional eager deoptimization exit here. |
| 585 this_effect = BuildCheckMaps(receiver, this_effect, this_control, |
| 586 receiver_maps); |
| 587 fallthrough_control = nullptr; |
| 588 } else { |
| 583 ZoneVector<Node*> this_controls(zone()); | 589 ZoneVector<Node*> this_controls(zone()); |
| 584 ZoneVector<Node*> this_effects(zone()); | 590 ZoneVector<Node*> this_effects(zone()); |
| 585 size_t num_classes = receiver_maps.size(); | |
| 586 for (Handle<Map> map : receiver_maps) { | 591 for (Handle<Map> map : receiver_maps) { |
| 587 DCHECK_LT(0u, num_classes); | |
| 588 Node* check = | 592 Node* check = |
| 589 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, | 593 graph()->NewNode(simplified()->ReferenceEqual(), receiver_map, |
| 590 jsgraph()->Constant(map)); | 594 jsgraph()->Constant(map)); |
| 591 if (--num_classes == 0 && j == access_infos.size() - 1) { | 595 Node* branch = graph()->NewNode(common()->Branch(), check, |
| 592 // Last map check on the fallthrough control path, do a | 596 fallthrough_control); |
| 593 // conditional eager deoptimization exit here. | 597 this_controls.push_back( |
| 594 // TODO(turbofan): This is ugly as hell! We should probably | 598 graph()->NewNode(common()->IfTrue(), branch)); |
| 595 // introduce macro-ish operators for property access that | 599 this_effects.push_back(this_effect); |
| 596 // encapsulate this whole mess. | 600 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 597 check = graph()->NewNode(simplified()->CheckIf(), check, | |
| 598 this_effect, this_control); | |
| 599 this_controls.push_back(this_control); | |
| 600 this_effects.push_back(check); | |
| 601 fallthrough_control = nullptr; | |
| 602 } else { | |
| 603 Node* branch = graph()->NewNode(common()->Branch(), check, | |
| 604 fallthrough_control); | |
| 605 this_controls.push_back( | |
| 606 graph()->NewNode(common()->IfTrue(), branch)); | |
| 607 this_effects.push_back(this_effect); | |
| 608 fallthrough_control = | |
| 609 graph()->NewNode(common()->IfFalse(), branch); | |
| 610 } | |
| 611 } | 601 } |
| 612 | 602 |
| 613 // Create single chokepoint for the control. | 603 // Create single chokepoint for the control. |
| 614 int const this_control_count = static_cast<int>(this_controls.size()); | 604 int const this_control_count = static_cast<int>(this_controls.size()); |
| 615 if (this_control_count == 1) { | 605 if (this_control_count == 1) { |
| 616 this_control = this_controls.front(); | 606 this_control = this_controls.front(); |
| 617 this_effect = this_effects.front(); | 607 this_effect = this_effects.front(); |
| 618 } else { | 608 } else { |
| 619 this_control = | 609 this_control = |
| 620 graph()->NewNode(common()->Merge(this_control_count), | 610 graph()->NewNode(common()->Merge(this_control_count), |
| (...skipping 882 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1503 return jsgraph()->javascript(); | 1493 return jsgraph()->javascript(); |
| 1504 } | 1494 } |
| 1505 | 1495 |
| 1506 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 1496 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 1507 return jsgraph()->simplified(); | 1497 return jsgraph()->simplified(); |
| 1508 } | 1498 } |
| 1509 | 1499 |
| 1510 } // namespace compiler | 1500 } // namespace compiler |
| 1511 } // namespace internal | 1501 } // namespace internal |
| 1512 } // namespace v8 | 1502 } // namespace v8 |
| OLD | NEW |