Chromium Code Reviews| 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/compilation-dependencies.h" | 8 #include "src/compilation-dependencies.h" |
| 9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
| 10 #include "src/compiler/js-graph.h" | 10 #include "src/compiler/js-graph.h" |
| (...skipping 519 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 // Perform map check on {receiver}. | 530 // Perform map check on {receiver}. |
| 531 Type* receiver_type = access_info.receiver_type(); | 531 Type* receiver_type = access_info.receiver_type(); |
| 532 if (receiver_type->Is(Type::String())) { | 532 if (receiver_type->Is(Type::String())) { |
| 533 // Emit an instance type check for strings. | 533 // Emit an instance type check for strings. |
| 534 Node* receiver_instance_type = this_effect = graph()->NewNode( | 534 Node* receiver_instance_type = this_effect = graph()->NewNode( |
| 535 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | 535 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 536 receiver_map, this_effect, fallthrough_control); | 536 receiver_map, this_effect, fallthrough_control); |
| 537 Node* check = | 537 Node* check = |
| 538 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, | 538 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, |
| 539 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); | 539 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 540 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 540 Node* branch = |
| 541 check, fallthrough_control); | 541 graph()->NewNode(common()->Branch(), check, fallthrough_control); |
| 542 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 542 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 543 this_control = graph()->NewNode(common()->IfTrue(), branch); | 543 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 544 } else { | 544 } else { |
| 545 // Emit a (sequence of) map checks for other properties. | 545 // Emit a (sequence of) map checks for other properties. |
| 546 ZoneVector<Node*> this_controls(zone()); | 546 ZoneVector<Node*> this_controls(zone()); |
| 547 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); | 547 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); |
| 548 i.Advance()) { | 548 i.Advance()) { |
| 549 Handle<Map> map = i.Current(); | 549 Handle<Map> map = i.Current(); |
| 550 Node* check = | 550 Node* check = |
| 551 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), | 551 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), |
| 552 receiver_map, jsgraph()->Constant(map)); | 552 receiver_map, jsgraph()->Constant(map)); |
| 553 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 553 Node* branch = |
| 554 check, fallthrough_control); | 554 graph()->NewNode(common()->Branch(), check, fallthrough_control); |
| 555 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); | 555 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); |
| 556 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 556 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 557 } | 557 } |
| 558 int const this_control_count = static_cast<int>(this_controls.size()); | 558 int const this_control_count = static_cast<int>(this_controls.size()); |
| 559 this_control = | 559 this_control = |
| 560 (this_control_count == 1) | 560 (this_control_count == 1) |
| 561 ? this_controls.front() | 561 ? this_controls.front() |
| 562 : graph()->NewNode(common()->Merge(this_control_count), | 562 : graph()->NewNode(common()->Merge(this_control_count), |
| 563 this_control_count, &this_controls.front()); | 563 this_control_count, &this_controls.front()); |
| 564 } | 564 } |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 606 this_effect, this_control); | 606 this_effect, this_control); |
| 607 } | 607 } |
| 608 | 608 |
| 609 // Remember the final state for this property access. | 609 // Remember the final state for this property access. |
| 610 values.push_back(this_value); | 610 values.push_back(this_value); |
| 611 effects.push_back(this_effect); | 611 effects.push_back(this_effect); |
| 612 controls.push_back(this_control); | 612 controls.push_back(this_control); |
| 613 } | 613 } |
| 614 | 614 |
| 615 // Collect the fallthru control as final "exit" control. | 615 // Collect the fallthru control as final "exit" control. |
| 616 if (fallthrough_control != control) { | |
| 617 // Mark the last fallthru branch as deferred. | |
| 618 Node* branch = NodeProperties::GetControlInput(fallthrough_control); | |
| 619 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); | |
| 620 if (fallthrough_control->opcode() == IrOpcode::kIfTrue) { | |
| 621 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse)); | |
| 622 } else { | |
| 623 DCHECK_EQ(IrOpcode::kIfFalse, fallthrough_control->opcode()); | |
| 624 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue)); | |
| 625 } | |
| 626 } | |
| 616 exit_controls.push_back(fallthrough_control); | 627 exit_controls.push_back(fallthrough_control); |
| 617 | 628 |
| 618 // Generate the single "exit" point, where we get if either all map/instance | 629 // Generate the single "exit" point, where we get if either all map/instance |
| 619 // type checks failed, or one of the assumptions inside one of the cases | 630 // type checks failed, or one of the assumptions inside one of the cases |
| 620 // failes (i.e. failing prototype chain check). | 631 // failes (i.e. failing prototype chain check). |
| 621 // TODO(bmeurer): Consider falling back to IC here if deoptimization is | 632 // TODO(bmeurer): Consider falling back to IC here if deoptimization is |
| 622 // disabled. | 633 // disabled. |
| 623 int const exit_control_count = static_cast<int>(exit_controls.size()); | 634 int const exit_control_count = static_cast<int>(exit_controls.size()); |
| 624 Node* exit_control = | 635 Node* exit_control = |
| 625 (exit_control_count == 1) | 636 (exit_control_count == 1) |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 714 // Perform map check on {receiver}. | 725 // Perform map check on {receiver}. |
| 715 Type* receiver_type = access_info.receiver_type(); | 726 Type* receiver_type = access_info.receiver_type(); |
| 716 if (receiver_type->Is(Type::String())) { | 727 if (receiver_type->Is(Type::String())) { |
| 717 // Emit an instance type check for strings. | 728 // Emit an instance type check for strings. |
| 718 Node* receiver_instance_type = this_effect = graph()->NewNode( | 729 Node* receiver_instance_type = this_effect = graph()->NewNode( |
| 719 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), | 730 simplified()->LoadField(AccessBuilder::ForMapInstanceType()), |
| 720 receiver_map, this_effect, fallthrough_control); | 731 receiver_map, this_effect, fallthrough_control); |
| 721 Node* check = | 732 Node* check = |
| 722 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, | 733 graph()->NewNode(machine()->Uint32LessThan(), receiver_instance_type, |
| 723 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); | 734 jsgraph()->Uint32Constant(FIRST_NONSTRING_TYPE)); |
| 724 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 735 Node* branch = |
| 725 check, fallthrough_control); | 736 graph()->NewNode(common()->Branch(), check, fallthrough_control); |
| 726 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 737 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 727 this_control = graph()->NewNode(common()->IfTrue(), branch); | 738 this_control = graph()->NewNode(common()->IfTrue(), branch); |
| 728 } else { | 739 } else { |
| 729 // Emit a (sequence of) map checks for other properties. | 740 // Emit a (sequence of) map checks for other properties. |
| 730 ZoneVector<Node*> this_controls(zone()); | 741 ZoneVector<Node*> this_controls(zone()); |
| 731 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); | 742 for (auto i = access_info.receiver_type()->Classes(); !i.Done(); |
| 732 i.Advance()) { | 743 i.Advance()) { |
| 733 Handle<Map> map = i.Current(); | 744 Handle<Map> map = i.Current(); |
| 734 Node* check = | 745 Node* check = |
| 735 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), | 746 graph()->NewNode(simplified()->ReferenceEqual(Type::Internal()), |
| 736 receiver_map, jsgraph()->Constant(map)); | 747 receiver_map, jsgraph()->Constant(map)); |
| 737 Node* branch = graph()->NewNode(common()->Branch(BranchHint::kTrue), | 748 Node* branch = |
| 738 check, fallthrough_control); | 749 graph()->NewNode(common()->Branch(), check, fallthrough_control); |
| 739 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); | 750 this_controls.push_back(graph()->NewNode(common()->IfTrue(), branch)); |
| 740 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); | 751 fallthrough_control = graph()->NewNode(common()->IfFalse(), branch); |
| 741 } | 752 } |
| 742 int const this_control_count = static_cast<int>(this_controls.size()); | 753 int const this_control_count = static_cast<int>(this_controls.size()); |
| 743 this_control = | 754 this_control = |
| 744 (this_control_count == 1) | 755 (this_control_count == 1) |
| 745 ? this_controls.front() | 756 ? this_controls.front() |
| 746 : graph()->NewNode(common()->Merge(this_control_count), | 757 : graph()->NewNode(common()->Merge(this_control_count), |
| 747 this_control_count, &this_controls.front()); | 758 this_control_count, &this_controls.front()); |
| 748 } | 759 } |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 822 this_effect = | 833 this_effect = |
| 823 graph()->NewNode(simplified()->StoreField(field_access), | 834 graph()->NewNode(simplified()->StoreField(field_access), |
| 824 this_receiver, value, this_effect, this_control); | 835 this_receiver, value, this_effect, this_control); |
| 825 } | 836 } |
| 826 | 837 |
| 827 // Remember the final state for this property access. | 838 // Remember the final state for this property access. |
| 828 effects.push_back(this_effect); | 839 effects.push_back(this_effect); |
| 829 controls.push_back(this_control); | 840 controls.push_back(this_control); |
| 830 } | 841 } |
| 831 | 842 |
| 832 // Collect the fallthru control as final "exit" control. | 843 // Collect the fallthru control as final "exit" control. |
|
Jarin
2015/10/26 21:14:50
Why the funny spelling of fallthru? (Also in other
Benedikt Meurer
2015/10/28 10:20:50
Done. Refactored the whole thing into a single nam
| |
| 844 if (fallthrough_control != control) { | |
| 845 // Mark the last fallthru branch as deferred. | |
| 846 Node* branch = NodeProperties::GetControlInput(fallthrough_control); | |
| 847 DCHECK_EQ(IrOpcode::kBranch, branch->opcode()); | |
| 848 if (fallthrough_control->opcode() == IrOpcode::kIfTrue) { | |
| 849 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kFalse)); | |
| 850 } else { | |
| 851 DCHECK_EQ(IrOpcode::kIfFalse, fallthrough_control->opcode()); | |
| 852 NodeProperties::ChangeOp(branch, common()->Branch(BranchHint::kTrue)); | |
| 853 } | |
| 854 } | |
| 833 exit_controls.push_back(fallthrough_control); | 855 exit_controls.push_back(fallthrough_control); |
| 834 | 856 |
| 835 // Generate the single "exit" point, where we get if either all map/instance | 857 // Generate the single "exit" point, where we get if either all map/instance |
| 836 // type checks failed, or one of the assumptions inside one of the cases | 858 // type checks failed, or one of the assumptions inside one of the cases |
| 837 // failes (i.e. failing prototype chain check). | 859 // failes (i.e. failing prototype chain check). |
| 838 // TODO(bmeurer): Consider falling back to IC here if deoptimization is | 860 // TODO(bmeurer): Consider falling back to IC here if deoptimization is |
| 839 // disabled. | 861 // disabled. |
| 840 int const exit_control_count = static_cast<int>(exit_controls.size()); | 862 int const exit_control_count = static_cast<int>(exit_controls.size()); |
| 841 Node* exit_control = | 863 Node* exit_control = |
| 842 (exit_control_count == 1) | 864 (exit_control_count == 1) |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 938 } | 960 } |
| 939 | 961 |
| 940 | 962 |
| 941 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { | 963 SimplifiedOperatorBuilder* JSNativeContextSpecialization::simplified() const { |
| 942 return jsgraph()->simplified(); | 964 return jsgraph()->simplified(); |
| 943 } | 965 } |
| 944 | 966 |
| 945 } // namespace compiler | 967 } // namespace compiler |
| 946 } // namespace internal | 968 } // namespace internal |
| 947 } // namespace v8 | 969 } // namespace v8 |
| OLD | NEW |