Chromium Code Reviews| 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.h" | 5 #include "vm/flow_graph.h" |
| 6 | 6 |
| 7 #include "vm/bit_vector.h" | 7 #include "vm/bit_vector.h" |
| 8 #include "vm/cha.h" | 8 #include "vm/cha.h" |
| 9 #include "vm/flow_graph_builder.h" | 9 #include "vm/flow_graph_builder.h" |
| 10 #include "vm/flow_graph_compiler.h" | 10 #include "vm/flow_graph_compiler.h" |
| (...skipping 662 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 673 | 673 |
| 674 return assigned_vars_; | 674 return assigned_vars_; |
| 675 } | 675 } |
| 676 | 676 |
| 677 // Returns true if the value set by the given store reaches any load from the | 677 // Returns true if the value set by the given store reaches any load from the |
| 678 // same local variable. | 678 // same local variable. |
| 679 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) { | 679 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) { |
| 680 if (store->local().Equals(*flow_graph_->CurrentContextVar())) { | 680 if (store->local().Equals(*flow_graph_->CurrentContextVar())) { |
| 681 return true; | 681 return true; |
| 682 } | 682 } |
| 683 if ((flow_graph_->FunctionTypeArgsVar() != NULL) && | |
|
Vyacheslav Egorov (Google)
2017/05/22 11:23:21
Is this a mutable variable?
I thought it's just
regis
2017/05/22 17:51:08
It is invariable with one exception: if the generi
regis
2017/05/22 18:02:42
I suppose I could use the SpecialParameterInstr on
Vyacheslav Egorov (Google)
2017/05/22 18:39:43
I think there is no problem. I think the best way
| |
| 684 store->local().Equals(*flow_graph_->FunctionTypeArgsVar())) { | |
| 685 return true; | |
| 686 } | |
| 683 | 687 |
| 684 if (store->is_dead()) { | 688 if (store->is_dead()) { |
| 685 return false; | 689 return false; |
| 686 } | 690 } |
| 687 if (store->is_last()) { | 691 if (store->is_last()) { |
| 688 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_); | 692 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_); |
| 689 return GetLiveOutSet(block)->Contains(index); | 693 return GetLiveOutSet(block)->Contains(index); |
| 690 } | 694 } |
| 691 | 695 |
| 692 return true; | 696 return true; |
| 693 } | 697 } |
| 694 | 698 |
| 695 // Returns true if the given load is the last for the local and the value | 699 // Returns true if the given load is the last for the local and the value |
| 696 // of the local will not flow into another one. | 700 // of the local will not flow into another one. |
| 697 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) { | 701 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) { |
| 698 if (load->local().Equals(*flow_graph_->CurrentContextVar())) { | 702 if (load->local().Equals(*flow_graph_->CurrentContextVar())) { |
| 699 return false; | 703 return false; |
| 700 } | 704 } |
| 705 if ((flow_graph_->FunctionTypeArgsVar() != NULL) && | |
| 706 load->local().Equals(*flow_graph_->FunctionTypeArgsVar())) { | |
| 707 return false; | |
| 708 } | |
| 701 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_); | 709 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_); |
| 702 return load->is_last() && !GetLiveOutSet(block)->Contains(index); | 710 return load->is_last() && !GetLiveOutSet(block)->Contains(index); |
| 703 } | 711 } |
| 704 | 712 |
| 705 private: | 713 private: |
| 706 virtual void ComputeInitialSets(); | 714 virtual void ComputeInitialSets(); |
| 707 | 715 |
| 708 const FlowGraph* flow_graph_; | 716 const FlowGraph* flow_graph_; |
| 709 const intptr_t num_non_copied_params_; | 717 const intptr_t num_non_copied_params_; |
| 710 GrowableArray<BitVector*> assigned_vars_; | 718 GrowableArray<BitVector*> assigned_vars_; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 765 kill->Add(index); | 773 kill->Add(index); |
| 766 } | 774 } |
| 767 live_in->Remove(index); | 775 live_in->Remove(index); |
| 768 continue; | 776 continue; |
| 769 } | 777 } |
| 770 } | 778 } |
| 771 } | 779 } |
| 772 } | 780 } |
| 773 | 781 |
| 774 | 782 |
| 775 void FlowGraph::ComputeSSA( | 783 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, |
| 776 intptr_t next_virtual_register_number, | 784 ZoneGrowableArray<Definition*>* inlining_parameters, |
| 777 ZoneGrowableArray<Definition*>* inlining_parameters) { | 785 Definition* inlining_type_args) { |
| 778 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); | 786 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); |
| 779 current_ssa_temp_index_ = next_virtual_register_number; | 787 current_ssa_temp_index_ = next_virtual_register_number; |
| 780 GrowableArray<BitVector*> dominance_frontier; | 788 GrowableArray<BitVector*> dominance_frontier; |
| 781 ComputeDominators(&dominance_frontier); | 789 ComputeDominators(&dominance_frontier); |
| 782 | 790 |
| 783 VariableLivenessAnalysis variable_liveness(this); | 791 VariableLivenessAnalysis variable_liveness(this); |
| 784 variable_liveness.Analyze(); | 792 variable_liveness.Analyze(); |
| 785 | 793 |
| 786 GrowableArray<PhiInstr*> live_phis; | 794 GrowableArray<PhiInstr*> live_phis; |
| 787 | 795 |
| 788 InsertPhis(preorder_, variable_liveness.ComputeAssignedVars(), | 796 InsertPhis(preorder_, variable_liveness.ComputeAssignedVars(), |
| 789 dominance_frontier, &live_phis); | 797 dominance_frontier, &live_phis); |
| 790 | 798 |
| 791 | 799 |
| 792 // Rename uses to reference inserted phis where appropriate. | 800 // Rename uses to reference inserted phis where appropriate. |
| 793 // Collect phis that reach a non-environment use. | 801 // Collect phis that reach a non-environment use. |
| 794 Rename(&live_phis, &variable_liveness, inlining_parameters); | 802 Rename(&live_phis, &variable_liveness, inlining_parameters, |
| 803 inlining_type_args); | |
| 795 | 804 |
| 796 // Propagate alive mark transitively from alive phis and then remove | 805 // Propagate alive mark transitively from alive phis and then remove |
| 797 // non-live ones. | 806 // non-live ones. |
| 798 RemoveDeadPhis(&live_phis); | 807 RemoveDeadPhis(&live_phis); |
| 799 } | 808 } |
| 800 | 809 |
| 801 | 810 |
| 802 // Compute immediate dominators and the dominance frontier for each basic | 811 // Compute immediate dominators and the dominance frontier for each basic |
| 803 // block. As a side effect of the algorithm, sets the immediate dominator | 812 // block. As a side effect of the algorithm, sets the immediate dominator |
| 804 // of each basic block. | 813 // of each basic block. |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 972 } | 981 } |
| 973 } | 982 } |
| 974 } | 983 } |
| 975 } | 984 } |
| 976 } | 985 } |
| 977 } | 986 } |
| 978 | 987 |
| 979 | 988 |
| 980 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, | 989 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, |
| 981 VariableLivenessAnalysis* variable_liveness, | 990 VariableLivenessAnalysis* variable_liveness, |
| 982 ZoneGrowableArray<Definition*>* inlining_parameters) { | 991 ZoneGrowableArray<Definition*>* inlining_parameters, |
| 992 Definition* inlining_type_args) { | |
| 983 GraphEntryInstr* entry = graph_entry(); | 993 GraphEntryInstr* entry = graph_entry(); |
| 984 | 994 |
| 985 // Initial renaming environment. | 995 // Initial renaming environment. |
| 986 GrowableArray<Definition*> env(variable_count()); | 996 GrowableArray<Definition*> env(variable_count()); |
| 987 | 997 |
| 988 // Add global constants to the initial definitions. | 998 // Add global constants to the initial definitions. |
| 989 constant_null_ = GetConstant(Object::ZoneHandle()); | 999 constant_null_ = GetConstant(Object::ZoneHandle()); |
| 990 constant_dead_ = GetConstant(Symbols::OptimizedOut()); | 1000 constant_dead_ = GetConstant(Symbols::OptimizedOut()); |
| 991 constant_empty_context_ = GetConstant(Object::empty_context()); | 1001 constant_empty_context_ = GetConstant(Object::empty_context()); |
| 992 | 1002 |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1008 ParameterInstr* param = new (zone()) ParameterInstr(i, entry); | 1018 ParameterInstr* param = new (zone()) ParameterInstr(i, entry); |
| 1009 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 1019 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 1010 AddToInitialDefinitions(param); | 1020 AddToInitialDefinitions(param); |
| 1011 env.Add(param); | 1021 env.Add(param); |
| 1012 } | 1022 } |
| 1013 } | 1023 } |
| 1014 | 1024 |
| 1015 // Initialize all locals in the renaming environment For OSR, the locals have | 1025 // Initialize all locals in the renaming environment For OSR, the locals have |
| 1016 // already been handled as parameters. | 1026 // already been handled as parameters. |
| 1017 if (!IsCompiledForOsr()) { | 1027 if (!IsCompiledForOsr()) { |
| 1028 const intptr_t type_args_env_index = | |
| 1029 (FunctionTypeArgsVar() != NULL) ? FunctionTypeArgsEnvIndex() : -1; | |
| 1018 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { | 1030 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { |
| 1019 if (i == CurrentContextEnvIndex()) { | 1031 if (i == type_args_env_index) { |
|
Vyacheslav Egorov (Google)
2017/05/22 11:23:21
I think a better way would be to mimic what we do
regis
2017/05/22 17:51:08
Thank you for the suggestion. Let me try that.
| |
| 1032 if (inlining_type_args != NULL) { | |
| 1033 AllocateSSAIndexes(inlining_type_args); | |
| 1034 AddToInitialDefinitions(inlining_type_args); | |
| 1035 env.Add(inlining_type_args); | |
| 1036 } else { | |
| 1037 // TODO(regis): For now, initialize local variable to null. | |
| 1038 // Where do we check for a passed type args? If not passed in, must | |
| 1039 // set to vector of dynamic of the proper length. | |
| 1040 // Do we need a FunctionTypeArgsInstr? | |
| 1041 env.Add(constant_null()); | |
| 1042 } | |
| 1043 } else if (i == CurrentContextEnvIndex()) { | |
| 1020 if (function().IsClosureFunction()) { | 1044 if (function().IsClosureFunction()) { |
| 1021 CurrentContextInstr* context = new CurrentContextInstr(); | 1045 CurrentContextInstr* context = new CurrentContextInstr(); |
| 1022 context->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 1046 context->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 1023 AddToInitialDefinitions(context); | 1047 AddToInitialDefinitions(context); |
| 1024 env.Add(context); | 1048 env.Add(context); |
| 1025 } else { | 1049 } else { |
| 1026 env.Add(constant_empty_context()); | 1050 env.Add(constant_empty_context()); |
| 1027 } | 1051 } |
| 1028 } else { | 1052 } else { |
| 1029 env.Add(constant_null()); | 1053 env.Add(constant_null()); |
| (...skipping 1282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2312 Representation rep, | 2336 Representation rep, |
| 2313 intptr_t cid) { | 2337 intptr_t cid) { |
| 2314 ExtractNthOutputInstr* extract = | 2338 ExtractNthOutputInstr* extract = |
| 2315 new (Z) ExtractNthOutputInstr(new (Z) Value(instr), index, rep, cid); | 2339 new (Z) ExtractNthOutputInstr(new (Z) Value(instr), index, rep, cid); |
| 2316 instr->ReplaceUsesWith(extract); | 2340 instr->ReplaceUsesWith(extract); |
| 2317 InsertAfter(instr, extract, NULL, FlowGraph::kValue); | 2341 InsertAfter(instr, extract, NULL, FlowGraph::kValue); |
| 2318 } | 2342 } |
| 2319 | 2343 |
| 2320 | 2344 |
| 2321 } // namespace dart | 2345 } // namespace dart |
| OLD | NEW |