| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/flow_graph_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
| 6 | 6 |
| 7 #include "vm/flow_graph_builder.h" | 7 #include "vm/flow_graph_builder.h" |
| 8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
| 9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
| 10 #include "vm/parser.h" | 10 #include "vm/parser.h" |
| (...skipping 731 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 742 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { | 742 for (intptr_t i = 0; i < join_entry->phis()->length(); ++i) { |
| 743 PhiInstr* phi = (*join_entry->phis())[i]; | 743 PhiInstr* phi = (*join_entry->phis())[i]; |
| 744 if (phi != NULL) { | 744 if (phi != NULL) { |
| 745 VisitPhi(phi); | 745 VisitPhi(phi); |
| 746 } | 746 } |
| 747 } | 747 } |
| 748 } | 748 } |
| 749 } | 749 } |
| 750 | 750 |
| 751 | 751 |
| 752 // TODO(srdjan): Investigate if the propagated cid should be more specific. |
| 753 void FlowGraphTypePropagator::VisitPushArgument(PushArgumentInstr* push) { |
| 754 if (!push->has_propagated_cid()) push->SetPropagatedCid(kDynamicCid); |
| 755 } |
| 756 |
| 757 |
| 752 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { | 758 void FlowGraphTypePropagator::VisitBind(BindInstr* bind) { |
| 753 // No need to propagate the input types of the bound computation, as long as | 759 // No need to propagate the input types of the bound computation, as long as |
| 754 // PhiInstr's are handled as part of JoinEntryInstr. | 760 // PhiInstr's are handled as part of JoinEntryInstr. |
| 755 // Visit computation and possibly eliminate type check. | 761 // Visit computation and possibly eliminate type check. |
| 756 bind->computation()->Accept(this, bind); | 762 bind->computation()->Accept(this, bind); |
| 757 // The current bind may have been removed from the graph. | 763 // The current bind may have been removed from the graph. |
| 758 if (current_iterator()->Current() == bind) { | 764 if (current_iterator()->Current() == bind) { |
| 759 // Current bind was not removed. | 765 // Current bind was not removed. |
| 760 // Cache propagated computation type. | 766 // Cache propagated computation type. |
| 761 AbstractType& computation_type = | 767 AbstractType& computation_type = |
| 762 AbstractType::Handle(bind->computation()->CompileType()); | 768 AbstractType::Handle(bind->computation()->CompileType()); |
| 763 bool changed = bind->SetPropagatedType(computation_type); | 769 bool changed = bind->SetPropagatedType(computation_type); |
| 764 if (changed) { | 770 if (changed) { |
| 765 still_changing_ = true; | 771 still_changing_ = true; |
| 766 } | 772 } |
| 773 // Propagate class ids. |
| 774 intptr_t cid = bind->computation()->ResultCid(); |
| 775 changed = bind->SetPropagatedCid(cid); |
| 776 if (changed) { |
| 777 still_changing_ = true; |
| 778 } |
| 767 } | 779 } |
| 768 } | 780 } |
| 769 | 781 |
| 770 | 782 |
| 771 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { | 783 void FlowGraphTypePropagator::VisitPhi(PhiInstr* phi) { |
| 772 // We could set the propagated type of the phi to the least upper bound of its | 784 // We could set the propagated type of the phi to the least upper bound of its |
| 773 // input propagated types. However, keeping all propagated types allows us to | 785 // input propagated types. However, keeping all propagated types allows us to |
| 774 // optimize method dispatch. | 786 // optimize method dispatch. |
| 775 // TODO(regis): Support a set of propagated types. For now, we compute the | 787 // TODO(regis): Support a set of propagated types. For now, we compute the |
| 776 // least specific of the input propagated types. | 788 // least specific of the input propagated types. |
| 777 AbstractType& type = AbstractType::Handle(phi->LeastSpecificInputType()); | 789 AbstractType& type = AbstractType::Handle(phi->LeastSpecificInputType()); |
| 778 bool changed = phi->SetPropagatedType(type); | 790 bool changed = phi->SetPropagatedType(type); |
| 779 if (changed) { | 791 if (changed) { |
| 780 still_changing_ = true; | 792 still_changing_ = true; |
| 781 } | 793 } |
| 794 |
| 795 // Merge class ids: if any two inputs have different class ids then result |
| 796 // is kDynamicCid. |
| 797 intptr_t merged_cid = kIllegalCid; |
| 798 for (intptr_t i = 0; i < phi->InputCount(); i++) { |
| 799 // Result cid of UseVal can be kIllegalCid if the referred definition |
| 800 // has not been visited yet. |
| 801 intptr_t cid = phi->InputAt(i)->ResultCid(); |
| 802 if (cid == kIllegalCid) { |
| 803 still_changing_ = true; |
| 804 continue; |
| 805 } |
| 806 if (merged_cid == kIllegalCid) { |
| 807 // First time set. |
| 808 merged_cid = cid; |
| 809 } else if (merged_cid != cid) { |
| 810 merged_cid = kDynamicCid; |
| 811 } |
| 812 } |
| 813 if (merged_cid == kIllegalCid) { |
| 814 merged_cid = kDynamicCid; |
| 815 } |
| 816 changed = phi->SetPropagatedCid(merged_cid); |
| 817 if (changed) { |
| 818 still_changing_ = true; |
| 819 } |
| 782 } | 820 } |
| 783 | 821 |
| 784 | 822 |
| 785 void FlowGraphTypePropagator::VisitParameter(ParameterInstr* param) { | 823 void FlowGraphTypePropagator::VisitParameter(ParameterInstr* param) { |
| 786 // TODO(regis): Once we inline functions, the propagated type of the formal | 824 // TODO(regis): Once we inline functions, the propagated type of the formal |
| 787 // parameter will reflect the compile type of the passed-in argument. | 825 // parameter will reflect the compile type of the passed-in argument. |
| 788 // For now, we do not know anything about the argument type and therefore set | 826 // For now, we do not know anything about the argument type and therefore set |
| 789 // it to the DynamicType, unless the argument is a compiler generated value, | 827 // it to the DynamicType, unless the argument is a compiler generated value, |
| 790 // i.e. the receiver argument or the constructor phase argument. | 828 // i.e. the receiver argument or the constructor phase argument. |
| 791 AbstractType& param_type = AbstractType::Handle(Type::DynamicType()); | 829 AbstractType& param_type = AbstractType::Handle(Type::DynamicType()); |
| 792 if (param->index() < 2) { | 830 if (param->index() < 2) { |
| 793 const Function& function = parsed_function().function(); | 831 const Function& function = parsed_function().function(); |
| 794 if (((param->index() == 0) && function.IsDynamicFunction()) || | 832 if (((param->index() == 0) && function.IsDynamicFunction()) || |
| 795 ((param->index() == 1) && function.IsConstructor())) { | 833 ((param->index() == 1) && function.IsConstructor())) { |
| 796 // Parameter is the receiver or the constructor phase. | 834 // Parameter is the receiver or the constructor phase. |
| 797 LocalScope* scope = parsed_function().node_sequence()->scope(); | 835 LocalScope* scope = parsed_function().node_sequence()->scope(); |
| 798 param_type = scope->VariableAt(param->index())->type().raw(); | 836 param_type = scope->VariableAt(param->index())->type().raw(); |
| 799 } | 837 } |
| 800 } | 838 } |
| 801 bool changed = param->SetPropagatedType(param_type); | 839 bool changed = param->SetPropagatedType(param_type); |
| 802 if (changed) { | 840 if (changed) { |
| 803 still_changing_ = true; | 841 still_changing_ = true; |
| 804 } | 842 } |
| 843 param->SetPropagatedCid(kDynamicCid); |
| 805 } | 844 } |
| 806 | 845 |
| 807 | 846 |
| 808 void FlowGraphTypePropagator::PropagateTypes() { | 847 void FlowGraphTypePropagator::PropagateTypes() { |
| 809 // TODO(regis): Is there a way to make this more efficient, e.g. by visiting | 848 // TODO(regis): Is there a way to make this more efficient, e.g. by visiting |
| 810 // only blocks depending on blocks that have changed and not the whole graph. | 849 // only blocks depending on blocks that have changed and not the whole graph. |
| 811 do { | 850 do { |
| 812 still_changing_ = false; | 851 still_changing_ = false; |
| 813 VisitBlocks(); | 852 VisitBlocks(); |
| 814 } while (still_changing_); | 853 } while (still_changing_); |
| 815 } | 854 } |
| 816 | 855 |
| 817 | 856 |
| 818 void FlowGraphAnalyzer::Analyze() { | 857 void FlowGraphAnalyzer::Analyze() { |
| 819 is_leaf_ = true; | 858 is_leaf_ = true; |
| 820 for (intptr_t i = 0; i < blocks_.length(); ++i) { | 859 for (intptr_t i = 0; i < blocks_.length(); ++i) { |
| 821 BlockEntryInstr* entry = blocks_[i]; | 860 BlockEntryInstr* entry = blocks_[i]; |
| 822 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 861 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
| 823 LocationSummary* locs = it.Current()->locs(); | 862 LocationSummary* locs = it.Current()->locs(); |
| 824 if ((locs != NULL) && locs->can_call()) { | 863 if ((locs != NULL) && locs->can_call()) { |
| 825 is_leaf_ = false; | 864 is_leaf_ = false; |
| 826 return; | 865 return; |
| 827 } | 866 } |
| 828 } | 867 } |
| 829 } | 868 } |
| 830 } | 869 } |
| 831 | 870 |
| 832 } // namespace dart | 871 } // namespace dart |
| OLD | NEW |