Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Side by Side Diff: runtime/vm/flow_graph_compiler.cc

Issue 23766021: Fix a bug in block reordering/block compaction. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_compiler.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/globals.h" // Needed here to get TARGET_ARCH_XXX. 5 #include "vm/globals.h" // Needed here to get TARGET_ARCH_XXX.
6 6
7 #include "vm/flow_graph_compiler.h" 7 #include "vm/flow_graph_compiler.h"
8 8
9 #include "vm/cha.h" 9 #include "vm/cha.h"
10 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
173 static bool IsEmptyBlock(BlockEntryInstr* block) { 173 static bool IsEmptyBlock(BlockEntryInstr* block) {
174 return !block->HasParallelMove() && 174 return !block->HasParallelMove() &&
175 block->next()->IsGoto() && 175 block->next()->IsGoto() &&
176 !block->next()->AsGoto()->HasParallelMove(); 176 !block->next()->AsGoto()->HasParallelMove();
177 } 177 }
178 178
179 179
180 void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) { 180 void FlowGraphCompiler::CompactBlock(BlockEntryInstr* block) {
181 BlockInfo* block_info = block_info_[block->postorder_number()]; 181 BlockInfo* block_info = block_info_[block->postorder_number()];
182 182
183 // Break out of cycles in the control flow graph.
183 if (block_info->is_marked()) { 184 if (block_info->is_marked()) {
184 return; 185 return;
185 } 186 }
186 block_info->mark(); 187 block_info->mark();
187 188
188 if (IsEmptyBlock(block)) { 189 if (IsEmptyBlock(block)) {
190 // For empty blocks, record a corresponding nonempty target as their
191 // jump label.
189 BlockEntryInstr* target = block->next()->AsGoto()->successor(); 192 BlockEntryInstr* target = block->next()->AsGoto()->successor();
190 CompactBlock(target); 193 CompactBlock(target);
191 block_info->set_jump_label(GetJumpLabel(target)); 194 block_info->set_jump_label(GetJumpLabel(target));
192 } 195 }
193 } 196 }
194 197
195 198
196 void FlowGraphCompiler::CompactBlocks() { 199 void FlowGraphCompiler::CompactBlocks() {
197 Label* fallthrough_label = NULL; 200 // This algorithm does not garbage collect blocks in place, but merely
201 // records forwarding label information. In this way it avoids having to
202 // change join and target entries.
203 Label* nonempty_label = NULL;
198 for (intptr_t i = block_order().length() - 1; i >= 1; --i) { 204 for (intptr_t i = block_order().length() - 1; i >= 1; --i) {
199 BlockEntryInstr* block = block_order()[i]; 205 BlockEntryInstr* block = block_order()[i];
200 206
201 // Unoptimized code must emit all possible deoptimization points. 207 // Unoptimized code must emit all possible deoptimization points.
202 if (is_optimizing()) { 208 if (is_optimizing()) {
203 CompactBlock(block); 209 CompactBlock(block);
204 } 210 }
205 211
212 // For nonempty blocks, record the next nonempty block in the block
213 // order. Since no code is emitted for empty blocks, control flow is
214 // eligible to fall through to the next nonempty one.
206 if (!WasCompacted(block)) { 215 if (!WasCompacted(block)) {
207 BlockInfo* block_info = block_info_[block->postorder_number()]; 216 BlockInfo* block_info = block_info_[block->postorder_number()];
208 block_info->set_fallthrough_label(fallthrough_label); 217 block_info->set_next_nonempty_label(nonempty_label);
209 fallthrough_label = GetJumpLabel(block); 218 nonempty_label = GetJumpLabel(block);
210 } 219 }
211 } 220 }
212 221
213 ASSERT(block_order()[0]->IsGraphEntry()); 222 ASSERT(block_order()[0]->IsGraphEntry());
214 BlockInfo* block_info = block_info_[block_order()[0]->postorder_number()]; 223 BlockInfo* block_info = block_info_[block_order()[0]->postorder_number()];
215 block_info->set_fallthrough_label(fallthrough_label); 224 block_info->set_next_nonempty_label(nonempty_label);
216 } 225 }
217 226
218 227
219 void FlowGraphCompiler::VisitBlocks() { 228 void FlowGraphCompiler::VisitBlocks() {
220 CompactBlocks(); 229 CompactBlocks();
221 230
222 for (intptr_t i = 0; i < block_order().length(); ++i) { 231 for (intptr_t i = 0; i < block_order().length(); ++i) {
223 // Compile the block entry. 232 // Compile the block entry.
224 BlockEntryInstr* entry = block_order()[i]; 233 BlockEntryInstr* entry = block_order()[i];
225 assembler()->Comment("B%" Pd "", entry->block_id()); 234 assembler()->Comment("B%" Pd "", entry->block_id());
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
282 291
283 bool FlowGraphCompiler::WasCompacted( 292 bool FlowGraphCompiler::WasCompacted(
284 BlockEntryInstr* block_entry) const { 293 BlockEntryInstr* block_entry) const {
285 const intptr_t block_index = block_entry->postorder_number(); 294 const intptr_t block_index = block_entry->postorder_number();
286 return block_info_[block_index]->WasCompacted(); 295 return block_info_[block_index]->WasCompacted();
287 } 296 }
288 297
289 298
290 bool FlowGraphCompiler::CanFallThroughTo(BlockEntryInstr* block_entry) const { 299 bool FlowGraphCompiler::CanFallThroughTo(BlockEntryInstr* block_entry) const {
291 const intptr_t current_index = current_block()->postorder_number(); 300 const intptr_t current_index = current_block()->postorder_number();
292 Label* fallthrough_label = block_info_[current_index]->fallthrough_label(); 301 Label* next_nonempty = block_info_[current_index]->next_nonempty_label();
293 return fallthrough_label == GetJumpLabel(block_entry); 302 return next_nonempty == GetJumpLabel(block_entry);
294 } 303 }
295 304
296 305
297 void FlowGraphCompiler::AddSlowPathCode(SlowPathCode* code) { 306 void FlowGraphCompiler::AddSlowPathCode(SlowPathCode* code) {
298 slow_path_code_.Add(code); 307 slow_path_code_.Add(code);
299 } 308 }
300 309
301 310
302 void FlowGraphCompiler::GenerateDeferredCode() { 311 void FlowGraphCompiler::GenerateDeferredCode() {
303 for (intptr_t i = 0; i < slow_path_code_.length(); i++) { 312 for (intptr_t i = 0; i < slow_path_code_.length(); i++) {
(...skipping 796 matching lines...) Expand 10 before | Expand all | Expand 10 after
1100 1109
1101 for (int i = 0; i < len; i++) { 1110 for (int i = 0; i < len; i++) {
1102 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i), 1111 sorted->Add(CidTarget(ic_data.GetReceiverClassIdAt(i),
1103 &Function::ZoneHandle(ic_data.GetTargetAt(i)), 1112 &Function::ZoneHandle(ic_data.GetTargetAt(i)),
1104 ic_data.GetCountAt(i))); 1113 ic_data.GetCountAt(i)));
1105 } 1114 }
1106 sorted->Sort(HighestCountFirst); 1115 sorted->Sort(HighestCountFirst);
1107 } 1116 }
1108 1117
1109 } // namespace dart 1118 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_compiler.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698