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/flow_graph_builder.h" | 8 #include "vm/flow_graph_builder.h" |
9 #include "vm/intermediate_language.h" | 9 #include "vm/intermediate_language.h" |
10 #include "vm/longjump.h" | 10 #include "vm/longjump.h" |
(...skipping 10 matching lines...) Expand all Loading... |
21 : parent_(), | 21 : parent_(), |
22 current_ssa_temp_index_(0), | 22 current_ssa_temp_index_(0), |
23 max_block_id_(max_block_id), | 23 max_block_id_(max_block_id), |
24 parsed_function_(builder.parsed_function()), | 24 parsed_function_(builder.parsed_function()), |
25 num_copied_params_(builder.num_copied_params()), | 25 num_copied_params_(builder.num_copied_params()), |
26 num_non_copied_params_(builder.num_non_copied_params()), | 26 num_non_copied_params_(builder.num_non_copied_params()), |
27 num_stack_locals_(builder.num_stack_locals()), | 27 num_stack_locals_(builder.num_stack_locals()), |
28 graph_entry_(graph_entry), | 28 graph_entry_(graph_entry), |
29 preorder_(), | 29 preorder_(), |
30 postorder_(), | 30 postorder_(), |
31 reverse_postorder_() { | 31 reverse_postorder_(), |
| 32 block_effects_(NULL) { |
32 DiscoverBlocks(); | 33 DiscoverBlocks(); |
33 } | 34 } |
34 | 35 |
35 | 36 |
36 ConstantInstr* FlowGraph::AddConstantToInitialDefinitions( | 37 ConstantInstr* FlowGraph::AddConstantToInitialDefinitions( |
37 const Object& object) { | 38 const Object& object) { |
38 // Check if the constant is already in the pool. | 39 // Check if the constant is already in the pool. |
39 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { | 40 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { |
40 ConstantInstr* constant = | 41 ConstantInstr* constant = |
41 (*graph_entry_->initial_definitions())[i]->AsConstant(); | 42 (*graph_entry_->initial_definitions())[i]->AsConstant(); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
92 &preorder_, | 93 &preorder_, |
93 &postorder_, | 94 &postorder_, |
94 &parent_, | 95 &parent_, |
95 variable_count(), | 96 variable_count(), |
96 num_non_copied_params()); | 97 num_non_copied_params()); |
97 // Create an array of blocks in reverse postorder. | 98 // Create an array of blocks in reverse postorder. |
98 intptr_t block_count = postorder_.length(); | 99 intptr_t block_count = postorder_.length(); |
99 for (intptr_t i = 0; i < block_count; ++i) { | 100 for (intptr_t i = 0; i < block_count; ++i) { |
100 reverse_postorder_.Add(postorder_[block_count - i - 1]); | 101 reverse_postorder_.Add(postorder_[block_count - i - 1]); |
101 } | 102 } |
| 103 |
| 104 // Block effects are using postorder numbering. Discard computed information. |
| 105 block_effects_ = NULL; |
102 } | 106 } |
103 | 107 |
104 | 108 |
105 #ifdef DEBUG | 109 #ifdef DEBUG |
106 // Debugging code to verify the construction of use lists. | 110 // Debugging code to verify the construction of use lists. |
107 | 111 |
108 static intptr_t MembershipCount(Value* use, Value* list) { | 112 static intptr_t MembershipCount(Value* use, Value* list) { |
109 intptr_t count = 0; | 113 intptr_t count = 0; |
110 while (list != NULL) { | 114 while (list != NULL) { |
111 if (list == use) ++count; | 115 if (list == use) ++count; |
(...skipping 804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
916 for (intptr_t i = 1; i < preorder_.length(); ++i) { | 920 for (intptr_t i = 1; i < preorder_.length(); ++i) { |
917 for (ForwardInstructionIterator it(preorder_[i]); | 921 for (ForwardInstructionIterator it(preorder_[i]); |
918 !it.Done(); | 922 !it.Done(); |
919 it.Advance()) { | 923 it.Advance()) { |
920 ++size; | 924 ++size; |
921 } | 925 } |
922 } | 926 } |
923 return size; | 927 return size; |
924 } | 928 } |
925 | 929 |
| 930 |
| 931 void FlowGraph::ComputeBlockEffects() { |
| 932 block_effects_ = new BlockEffects(this); |
| 933 } |
| 934 |
| 935 |
| 936 BlockEffects::BlockEffects(FlowGraph* flow_graph) |
| 937 : available_at_(flow_graph->postorder().length()) { |
| 938 // We are tracking a single effect. |
| 939 ASSERT(EffectSet::kLastEffect == 1); |
| 940 |
| 941 const intptr_t block_count = flow_graph->postorder().length(); |
| 942 |
| 943 // Set of blocks that contain side-effects. |
| 944 BitVector* kill = new BitVector(block_count); |
| 945 |
| 946 // Per block available-after sets. Block A is available after the block B if |
| 947 // and only if A is either equal to B or A is available at B and B contains no |
| 948 // side-effects. Initially we consider all blocks available after all other |
| 949 // blocks. |
| 950 GrowableArray<BitVector*> available_after(block_count); |
| 951 |
| 952 // Discover all blocks with side-effects. |
| 953 for (BlockIterator it = flow_graph->postorder_iterator(); |
| 954 !it.Done(); |
| 955 it.Advance()) { |
| 956 available_at_.Add(NULL); |
| 957 available_after.Add(NULL); |
| 958 |
| 959 BlockEntryInstr* block = it.Current(); |
| 960 for (ForwardInstructionIterator it(block); |
| 961 !it.Done(); |
| 962 it.Advance()) { |
| 963 if (!it.Current()->Effects().IsNone()) { |
| 964 kill->Add(block->postorder_number()); |
| 965 break; |
| 966 } |
| 967 } |
| 968 } |
| 969 |
| 970 BitVector* temp = new BitVector(block_count); |
| 971 |
| 972 // Recompute available-at based on predecessors' available-after until the fix |
| 973 // point is reached. |
| 974 bool changed; |
| 975 do { |
| 976 changed = false; |
| 977 |
| 978 for (BlockIterator it = flow_graph->reverse_postorder_iterator(); |
| 979 !it.Done(); |
| 980 it.Advance()) { |
| 981 BlockEntryInstr* block = it.Current(); |
| 982 const intptr_t block_num = block->postorder_number(); |
| 983 |
| 984 if (block->IsGraphEntry()) { |
| 985 temp->Clear(); // Nothing is live-in into graph entry. |
| 986 } else { |
| 987 // Available-at is an intersection of all predecessors' available-after |
| 988 // sets. |
| 989 temp->SetAll(); |
| 990 for (intptr_t i = 0; i < block->PredecessorCount(); i++) { |
| 991 const intptr_t pred = block->PredecessorAt(i)->postorder_number(); |
| 992 if (available_after[pred] != NULL) { |
| 993 temp->Intersect(available_after[pred]); |
| 994 } |
| 995 } |
| 996 } |
| 997 |
| 998 BitVector* current = available_at_[block_num]; |
| 999 if ((current == NULL) || !current->Equals(*temp)) { |
| 1000 // Available-at changed: update it and recompute available-after. |
| 1001 if (available_at_[block_num] == NULL) { |
| 1002 current = available_at_[block_num] = new BitVector(block_count); |
| 1003 available_after[block_num] = new BitVector(block_count); |
| 1004 // Block is always available after itself. |
| 1005 available_after[block_num]->Add(block_num); |
| 1006 } |
| 1007 current->CopyFrom(temp); |
| 1008 if (!kill->Contains(block_num)) { |
| 1009 available_after[block_num]->CopyFrom(temp); |
| 1010 // Block is always available after itself. |
| 1011 available_after[block_num]->Add(block_num); |
| 1012 } |
| 1013 changed = true; |
| 1014 } |
| 1015 } |
| 1016 } while (changed); |
| 1017 } |
| 1018 |
| 1019 |
| 1020 bool BlockEffects::IsAvailableAt(Instruction* instr, |
| 1021 BlockEntryInstr* block) const { |
| 1022 return (instr->Dependencies().IsNone()) || |
| 1023 IsSideEffectFreePath(instr->GetBlock(), block); |
| 1024 } |
| 1025 |
| 1026 |
| 1027 bool BlockEffects::CanBeMovedTo(Instruction* instr, |
| 1028 BlockEntryInstr* block) const { |
| 1029 return (instr->Dependencies().IsNone()) || |
| 1030 IsSideEffectFreePath(block, instr->GetBlock()); |
| 1031 } |
| 1032 |
| 1033 |
| 1034 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, |
| 1035 BlockEntryInstr* to) const { |
| 1036 return available_at_[to->postorder_number()]->Contains( |
| 1037 from->postorder_number()); |
| 1038 } |
| 1039 |
926 } // namespace dart | 1040 } // namespace dart |
OLD | NEW |