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_builder.h" | 5 #include "vm/flow_graph_builder.h" |
6 | 6 |
7 #include "vm/ast_printer.h" | 7 #include "vm/ast_printer.h" |
8 #include "vm/bit_vector.h" | 8 #include "vm/bit_vector.h" |
9 #include "vm/code_descriptors.h" | 9 #include "vm/code_descriptors.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
66 } | 66 } |
67 if (is_empty()) { | 67 if (is_empty()) { |
68 entry_ = exit_ = instruction; | 68 entry_ = exit_ = instruction; |
69 } else { | 69 } else { |
70 exit()->SetSuccessor(instruction); | 70 exit()->SetSuccessor(instruction); |
71 exit_ = instruction; | 71 exit_ = instruction; |
72 } | 72 } |
73 } | 73 } |
74 | 74 |
75 | 75 |
76 // Appends a graph fragment to a block entry instruction and returns the exit | |
77 // of the resulting graph fragment. | |
78 static Instruction* AppendFragment(BlockEntryInstr* entry, | |
79 const EffectGraphVisitor& fragment) { | |
80 if (fragment.is_empty()) return entry; | |
81 entry->SetSuccessor(fragment.entry()); | |
82 return fragment.exit(); | |
83 } | |
srdjan
2012/06/25 15:57:16
I like it a lot that we factor out the knowledge o
| |
84 | |
85 | |
76 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, | 86 void EffectGraphVisitor::Join(const TestGraphVisitor& test_fragment, |
77 const EffectGraphVisitor& true_fragment, | 87 const EffectGraphVisitor& true_fragment, |
78 const EffectGraphVisitor& false_fragment) { | 88 const EffectGraphVisitor& false_fragment) { |
79 // We have: a test graph fragment with zero, one, or two available exits; | 89 // We have: a test graph fragment with zero, one, or two available exits; |
80 // and a pair of effect graph fragments with zero or one available exits. | 90 // and a pair of effect graph fragments with zero or one available exits. |
81 // We want to append the branch and (if necessary) a join node to this | 91 // We want to append the branch and (if necessary) a join node to this |
82 // graph fragment. | 92 // graph fragment. |
83 ASSERT(is_open()); | 93 ASSERT(is_open()); |
84 | 94 |
85 // 1. Connect the test to this graph. | 95 // 1. Connect the test to this graph. |
86 Append(test_fragment); | 96 Append(test_fragment); |
87 | 97 |
88 // 2. Connect the true and false bodies to the test and record their exits | 98 // 2. Connect the true and false bodies to the test and record their exits |
89 // (if any). | 99 // (if any). |
90 Instruction* true_exit = NULL; | |
91 Instruction* false_exit = NULL; | |
92 TargetEntryInstr* true_entry = new TargetEntryInstr(); | 100 TargetEntryInstr* true_entry = new TargetEntryInstr(); |
93 *test_fragment.true_successor_address() = true_entry; | 101 *test_fragment.true_successor_address() = true_entry; |
94 true_entry->SetSuccessor(true_fragment.entry()); | 102 Instruction* true_exit = AppendFragment(true_entry, true_fragment); |
95 true_exit = true_fragment.is_empty() ? true_entry : true_fragment.exit(); | |
96 | 103 |
97 TargetEntryInstr* false_entry = new TargetEntryInstr(); | 104 TargetEntryInstr* false_entry = new TargetEntryInstr(); |
98 *test_fragment.false_successor_address() = false_entry; | 105 *test_fragment.false_successor_address() = false_entry; |
99 false_entry->SetSuccessor(false_fragment.entry()); | 106 Instruction* false_exit = AppendFragment(false_entry, false_fragment); |
100 false_exit = false_fragment.is_empty() ? false_entry : false_fragment.exit(); | |
101 | 107 |
102 // 3. Add a join or select one (or neither) of the arms as exit. | 108 // 3. Add a join or select one (or neither) of the arms as exit. |
103 if (true_exit == NULL) { | 109 if (true_exit == NULL) { |
104 exit_ = false_exit; // May be NULL. | 110 exit_ = false_exit; // May be NULL. |
105 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); | 111 if (false_exit != NULL) temp_index_ = false_fragment.temp_index(); |
106 } else if (false_exit == NULL) { | 112 } else if (false_exit == NULL) { |
107 exit_ = true_exit; | 113 exit_ = true_exit; |
108 temp_index_ = true_fragment.temp_index(); | 114 temp_index_ = true_fragment.temp_index(); |
109 } else { | 115 } else { |
110 exit_ = new JoinEntryInstr(); | 116 exit_ = new JoinEntryInstr(); |
111 true_exit->SetSuccessor(exit_); | 117 true_exit->SetSuccessor(exit_); |
112 false_exit->SetSuccessor(exit_); | 118 false_exit->SetSuccessor(exit_); |
113 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); | 119 ASSERT(true_fragment.temp_index() == false_fragment.temp_index()); |
114 temp_index_ = true_fragment.temp_index(); | 120 temp_index_ = true_fragment.temp_index(); |
115 } | 121 } |
116 } | 122 } |
117 | 123 |
118 | 124 |
119 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, | 125 void EffectGraphVisitor::TieLoop(const TestGraphVisitor& test_fragment, |
120 const EffectGraphVisitor& body_fragment) { | 126 const EffectGraphVisitor& body_fragment) { |
121 // We have: a test graph fragment with zero, one, or two available exits; | 127 // We have: a test graph fragment with zero, one, or two available exits; |
122 // and an effect graph fragment with zero or one available exits. We want | 128 // and an effect graph fragment with zero or one available exits. We want |
123 // to append the 'while loop' consisting of the test graph fragment as | 129 // to append the 'while loop' consisting of the test graph fragment as |
124 // condition and the effect graph fragment as body. | 130 // condition and the effect graph fragment as body. |
125 ASSERT(is_open()); | 131 ASSERT(is_open()); |
126 | 132 |
127 // 1. Connect the body to the test if it is reachable, and if so record | 133 // 1. Connect the body to the test if it is reachable, and if so record |
128 // its exit (if any). | 134 // its exit (if any). |
129 Instruction* body_exit = NULL; | |
130 TargetEntryInstr* body_entry = new TargetEntryInstr(); | 135 TargetEntryInstr* body_entry = new TargetEntryInstr(); |
131 *test_fragment.true_successor_address() = body_entry; | 136 *test_fragment.true_successor_address() = body_entry; |
132 body_entry->SetSuccessor(body_fragment.entry()); | 137 Instruction* body_exit = AppendFragment(body_entry, body_fragment); |
133 body_exit = body_fragment.is_empty() ? body_entry : body_fragment.exit(); | |
134 | 138 |
135 // 2. Connect the test to this graph, including the body if reachable and | 139 // 2. Connect the test to this graph, including the body if reachable and |
136 // using a fresh join node if the body is reachable and has an open exit. | 140 // using a fresh join node if the body is reachable and has an open exit. |
137 if (body_exit == NULL) { | 141 if (body_exit == NULL) { |
138 Append(test_fragment); | 142 Append(test_fragment); |
139 } else { | 143 } else { |
140 JoinEntryInstr* join = new JoinEntryInstr(); | 144 JoinEntryInstr* join = new JoinEntryInstr(); |
141 AddInstruction(join); | 145 AddInstruction(join); |
142 join->SetSuccessor(test_fragment.entry()); | 146 join->SetSuccessor(test_fragment.entry()); |
143 body_exit->SetSuccessor(join); | 147 body_exit->SetSuccessor(join); |
(...skipping 974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1118 | 1122 |
1119 TestGraphVisitor for_test(owner(), | 1123 TestGraphVisitor for_test(owner(), |
1120 temp_index(), | 1124 temp_index(), |
1121 node->condition()->token_pos()); | 1125 node->condition()->token_pos()); |
1122 node->condition()->Visit(&for_test); | 1126 node->condition()->Visit(&for_test); |
1123 ASSERT(is_open()); | 1127 ASSERT(is_open()); |
1124 | 1128 |
1125 // Tie do-while loop (test is after the body). | 1129 // Tie do-while loop (test is after the body). |
1126 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); | 1130 JoinEntryInstr* body_entry_join = new JoinEntryInstr(); |
1127 AddInstruction(body_entry_join); | 1131 AddInstruction(body_entry_join); |
1128 body_entry_join->SetSuccessor(for_body.entry()); | 1132 Instruction* body_exit = AppendFragment(body_entry_join, for_body); |
1129 Instruction* body_exit = | |
1130 for_body.is_empty() ? body_entry_join : for_body.exit(); | |
1131 | 1133 |
1132 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { | 1134 if (for_body.is_open() || (node->label()->join_for_continue() != NULL)) { |
1133 BlockEntryInstr* test_entry = NULL; | 1135 BlockEntryInstr* test_entry = NULL; |
1134 if (node->label()->join_for_continue() == NULL) { | 1136 if (node->label()->join_for_continue() == NULL) { |
1135 test_entry = new TargetEntryInstr(); | 1137 test_entry = new TargetEntryInstr(); |
1136 } else { | 1138 } else { |
1137 test_entry = node->label()->join_for_continue(); | 1139 test_entry = node->label()->join_for_continue(); |
1138 } | 1140 } |
1139 test_entry->SetSuccessor(for_test.entry()); | 1141 test_entry->SetSuccessor(for_test.entry()); |
1140 if (body_exit != NULL) { | 1142 if (body_exit != NULL) { |
(...skipping 1201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2342 &preorder_block_entries_, | 2344 &preorder_block_entries_, |
2343 &postorder_block_entries_, | 2345 &postorder_block_entries_, |
2344 &parent, | 2346 &parent, |
2345 &assigned_vars, | 2347 &assigned_vars, |
2346 variable_count); | 2348 variable_count); |
2347 // Number blocks in reverse postorder. | 2349 // Number blocks in reverse postorder. |
2348 intptr_t block_count = postorder_block_entries_.length(); | 2350 intptr_t block_count = postorder_block_entries_.length(); |
2349 for (intptr_t i = 0; i < block_count; ++i) { | 2351 for (intptr_t i = 0; i < block_count; ++i) { |
2350 postorder_block_entries_[i]->set_block_id(block_count - i - 1); | 2352 postorder_block_entries_[i]->set_block_id(block_count - i - 1); |
2351 } | 2353 } |
2352 if (for_optimized && FLAG_use_ssa) { | 2354 if (for_optimized) { |
2353 GrowableArray<BitVector*> dominance_frontier; | 2355 // Link instructions backwards for optimized compilation. |
2354 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); | 2356 for (intptr_t i = 0; i < block_count; ++i) { |
2355 InsertPhis(preorder_block_entries_, | 2357 Instruction* prev = postorder_block_entries_[i]; |
2356 assigned_vars, | 2358 Instruction* current = prev->StraightLineSuccessor(); |
2357 variable_count, | 2359 while (current != NULL && !current->IsBlockEntry()) { |
2358 dominance_frontier); | 2360 current->SetPrevious(prev); |
2359 Rename(variable_count); | 2361 prev = current; |
2362 current = current->StraightLineSuccessor(); | |
2363 } | |
2364 } | |
2365 | |
2366 // Construct SSA form. | |
2367 if (FLAG_use_ssa) { | |
2368 GrowableArray<BitVector*> dominance_frontier; | |
2369 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); | |
2370 InsertPhis(preorder_block_entries_, | |
2371 assigned_vars, | |
2372 variable_count, | |
2373 dominance_frontier); | |
2374 Rename(variable_count); | |
2375 } | |
2360 } | 2376 } |
2361 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { | 2377 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { |
2362 intptr_t length = postorder_block_entries_.length(); | 2378 intptr_t length = postorder_block_entries_.length(); |
2363 GrowableArray<BlockEntryInstr*> reverse_postorder(length); | 2379 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
2364 for (intptr_t i = length - 1; i >= 0; --i) { | 2380 for (intptr_t i = length - 1; i >= 0; --i) { |
2365 reverse_postorder.Add(postorder_block_entries_[i]); | 2381 reverse_postorder.Add(postorder_block_entries_[i]); |
2366 } | 2382 } |
2367 if (FLAG_print_flow_graph) { | 2383 if (FLAG_print_flow_graph) { |
2368 // Print flow graph to stdout. | 2384 // Print flow graph to stdout. |
2369 FlowGraphPrinter printer(function, reverse_postorder); | 2385 FlowGraphPrinter printer(function, reverse_postorder); |
(...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2611 if (phi != NULL) { | 2627 if (phi != NULL) { |
2612 (*env)[i] = new UseVal(phi); | 2628 (*env)[i] = new UseVal(phi); |
2613 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. | 2629 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. |
2614 } | 2630 } |
2615 } | 2631 } |
2616 } | 2632 } |
2617 } | 2633 } |
2618 | 2634 |
2619 // 2. Process normal instructions. | 2635 // 2. Process normal instructions. |
2620 Instruction* current = block_entry->StraightLineSuccessor(); | 2636 Instruction* current = block_entry->StraightLineSuccessor(); |
2621 Instruction* prev = block_entry; | |
2622 while ((current != NULL) && !current->IsBlockEntry()) { | 2637 while ((current != NULL) && !current->IsBlockEntry()) { |
2623 // 2a. Handle uses of LoadLocal / StoreLocal | 2638 // 2a. Handle uses of LoadLocal / StoreLocal |
2624 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 2639 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
2625 // from the environment. | 2640 // from the environment. |
2626 for (intptr_t i = 0; i < current->InputCount(); ++i) { | 2641 for (intptr_t i = 0; i < current->InputCount(); ++i) { |
2627 Value* v = current->InputAt(i); | 2642 Value* v = current->InputAt(i); |
2628 if (v->IsUse() && | 2643 if (v->IsUse() && |
2629 v->AsUse()->definition()->IsBind() && | 2644 v->AsUse()->definition()->IsBind() && |
2630 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { | 2645 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { |
2631 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2646 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2667 if (current->IsDo() && | 2682 if (current->IsDo() && |
2668 current->AsDo()->computation()->IsStoreLocal()) { | 2683 current->AsDo()->computation()->IsStoreLocal()) { |
2669 store = current->AsDo()->computation()->AsStoreLocal(); | 2684 store = current->AsDo()->computation()->AsStoreLocal(); |
2670 } else if (current->IsBind() && | 2685 } else if (current->IsBind() && |
2671 current->AsBind()->computation()->IsStoreLocal()) { | 2686 current->AsBind()->computation()->IsStoreLocal()) { |
2672 store = current->AsBind()->computation()->AsStoreLocal(); | 2687 store = current->AsBind()->computation()->AsStoreLocal(); |
2673 } | 2688 } |
2674 | 2689 |
2675 if (load != NULL) { | 2690 if (load != NULL) { |
2676 // Remove instruction. | 2691 // Remove instruction. |
2677 prev->SetSuccessor(current->StraightLineSuccessor()); | 2692 current->RemoveFromGraph(); |
2678 } else if (store != NULL) { | 2693 } else if (store != NULL) { |
2679 // Remove instruction and update renaming environment. | 2694 // Remove instruction and update renaming environment. |
2680 prev->SetSuccessor(current->StraightLineSuccessor()); | 2695 current->RemoveFromGraph(); |
2681 (*env)[store->local().BitIndexIn(var_count)] = store->value(); | 2696 (*env)[store->local().BitIndexIn(var_count)] = store->value(); |
2682 } else { | 2697 } else if (current->IsBind()) { |
2683 // Assign new SSA temporary. | 2698 // Assign new SSA temporary. |
2684 if (current->IsBind()) { | 2699 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); |
2685 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); | |
2686 } | |
2687 // Update previous only if no instruction was removed from the graph. | |
2688 prev = current; | |
2689 } | 2700 } |
2690 current = current->StraightLineSuccessor(); | 2701 current = current->StraightLineSuccessor(); |
2691 } | 2702 } |
2692 | 2703 |
2693 // 3. Process dominated blocks. | 2704 // 3. Process dominated blocks. |
2694 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { | 2705 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { |
2695 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; | 2706 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; |
2696 ZoneGrowableArray<Value*>* new_env = | 2707 ZoneGrowableArray<Value*>* new_env = |
2697 new ZoneGrowableArray<Value*>(var_count); | 2708 new ZoneGrowableArray<Value*>(var_count); |
2698 new_env->AddArray(*env); | 2709 new_env->AddArray(*env); |
(...skipping 30 matching lines...) Expand all Loading... | |
2729 char* chars = reinterpret_cast<char*>( | 2740 char* chars = reinterpret_cast<char*>( |
2730 Isolate::Current()->current_zone()->Allocate(len)); | 2741 Isolate::Current()->current_zone()->Allocate(len)); |
2731 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2742 OS::SNPrint(chars, len, kFormat, function_name, reason); |
2732 const Error& error = Error::Handle( | 2743 const Error& error = Error::Handle( |
2733 LanguageError::New(String::Handle(String::New(chars)))); | 2744 LanguageError::New(String::Handle(String::New(chars)))); |
2734 Isolate::Current()->long_jump_base()->Jump(1, error); | 2745 Isolate::Current()->long_jump_base()->Jump(1, error); |
2735 } | 2746 } |
2736 | 2747 |
2737 | 2748 |
2738 } // namespace dart | 2749 } // namespace dart |
OLD | NEW |