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

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

Issue 14215006: Re-apply r20377. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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.h ('k') | runtime/vm/flow_graph_allocator.h » ('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) 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"
11 #include "vm/growable_array.h" 11 #include "vm/growable_array.h"
12 12
13 namespace dart { 13 namespace dart {
14 14
15 DECLARE_FLAG(bool, trace_optimization); 15 DECLARE_FLAG(bool, trace_optimization);
16 DECLARE_FLAG(bool, verify_compiler); 16 DECLARE_FLAG(bool, verify_compiler);
17 17
18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, 18 FlowGraph::FlowGraph(const FlowGraphBuilder& builder,
19 GraphEntryInstr* graph_entry, 19 GraphEntryInstr* graph_entry,
20 intptr_t max_block_id) 20 intptr_t max_block_id)
21 : parent_(), 21 : parent_(),
22 assigned_vars_(),
23 current_ssa_temp_index_(0), 22 current_ssa_temp_index_(0),
24 max_block_id_(max_block_id), 23 max_block_id_(max_block_id),
25 parsed_function_(builder.parsed_function()), 24 parsed_function_(builder.parsed_function()),
26 num_copied_params_(builder.num_copied_params()), 25 num_copied_params_(builder.num_copied_params()),
27 num_non_copied_params_(builder.num_non_copied_params()), 26 num_non_copied_params_(builder.num_non_copied_params()),
28 num_stack_locals_(builder.num_stack_locals()), 27 num_stack_locals_(builder.num_stack_locals()),
29 graph_entry_(graph_entry), 28 graph_entry_(graph_entry),
30 preorder_(), 29 preorder_(),
31 postorder_(), 30 postorder_(),
32 reverse_postorder_(), 31 reverse_postorder_(),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 if (env != NULL) env->DeepCopyTo(instr); 80 if (env != NULL) env->DeepCopyTo(instr);
82 } 81 }
83 82
84 83
85 void FlowGraph::DiscoverBlocks() { 84 void FlowGraph::DiscoverBlocks() {
86 // Initialize state. 85 // Initialize state.
87 preorder_.Clear(); 86 preorder_.Clear();
88 postorder_.Clear(); 87 postorder_.Clear();
89 reverse_postorder_.Clear(); 88 reverse_postorder_.Clear();
90 parent_.Clear(); 89 parent_.Clear();
91 assigned_vars_.Clear();
92 // Perform a depth-first traversal of the graph to build preorder and 90 // Perform a depth-first traversal of the graph to build preorder and
93 // postorder block orders. 91 // postorder block orders.
94 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor. 92 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
95 &preorder_, 93 &preorder_,
96 &postorder_, 94 &postorder_,
97 &parent_, 95 &parent_,
98 &assigned_vars_,
99 variable_count(), 96 variable_count(),
100 num_non_copied_params()); 97 num_non_copied_params());
101 // Create an array of blocks in reverse postorder. 98 // Create an array of blocks in reverse postorder.
102 intptr_t block_count = postorder_.length(); 99 intptr_t block_count = postorder_.length();
103 for (intptr_t i = 0; i < block_count; ++i) { 100 for (intptr_t i = 0; i < block_count; ++i) {
104 reverse_postorder_.Add(postorder_[block_count - i - 1]); 101 reverse_postorder_.Add(postorder_[block_count - i - 1]);
105 } 102 }
106 } 103 }
107 104
108 105
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 } 199 }
203 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { 200 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
204 VerifyUseListsInInstruction(it.Current()); 201 VerifyUseListsInInstruction(it.Current());
205 } 202 }
206 } 203 }
207 return true; // Return true so we can ASSERT validation. 204 return true; // Return true so we can ASSERT validation.
208 } 205 }
209 #endif // DEBUG 206 #endif // DEBUG
210 207
211 208
209 LivenessAnalysis::LivenessAnalysis(
210 intptr_t variable_count,
211 const GrowableArray<BlockEntryInstr*>& postorder)
212 : variable_count_(variable_count),
213 postorder_(postorder),
214 live_out_(postorder.length()),
215 kill_(postorder.length()),
216 live_in_(postorder.length()) {
217 }
218
219
220 bool LivenessAnalysis::UpdateLiveOut(const BlockEntryInstr& block) {
221 BitVector* live_out = live_out_[block.postorder_number()];
222 bool changed = false;
223 Instruction* last = block.last_instruction();
224 ASSERT(last != NULL);
225 for (intptr_t i = 0; i < last->SuccessorCount(); i++) {
226 BlockEntryInstr* succ = last->SuccessorAt(i);
227 ASSERT(succ != NULL);
228 if (live_out->AddAll(live_in_[succ->postorder_number()])) {
229 changed = true;
230 }
231 }
232 return changed;
233 }
234
235
236 bool LivenessAnalysis::UpdateLiveIn(const BlockEntryInstr& block) {
237 BitVector* live_out = live_out_[block.postorder_number()];
238 BitVector* kill = kill_[block.postorder_number()];
239 BitVector* live_in = live_in_[block.postorder_number()];
240 return live_in->KillAndAdd(kill, live_out);
241 }
242
243
244 void LivenessAnalysis::ComputeLiveInAndLiveOutSets() {
245 const intptr_t block_count = postorder_.length();
246 bool changed;
247 do {
248 changed = false;
249
250 for (intptr_t i = 0; i < block_count; i++) {
251 const BlockEntryInstr& block = *postorder_[i];
252
253 // Live-in set depends only on kill set which does not
254 // change in this loop and live-out set. If live-out
255 // set does not change there is no need to recompute
256 // live-in set.
257 if (UpdateLiveOut(block) && UpdateLiveIn(block)) {
258 changed = true;
259 }
260 }
261 } while (changed);
262 }
263
264
265 void LivenessAnalysis::Analyze() {
266 const intptr_t block_count = postorder_.length();
267 for (intptr_t i = 0; i < block_count; i++) {
268 live_out_.Add(new BitVector(variable_count_));
269 kill_.Add(new BitVector(variable_count_));
270 live_in_.Add(new BitVector(variable_count_));
271 }
272
273 ComputeInitialSets();
274 ComputeLiveInAndLiveOutSets();
275 }
276
277
278 static void PrintBitVector(const char* tag, BitVector* v) {
279 OS::Print("%s:", tag);
280 for (BitVector::Iterator it(v); !it.Done(); it.Advance()) {
281 OS::Print(" %"Pd"", it.Current());
282 }
283 OS::Print("\n");
284 }
285
286
287 void LivenessAnalysis::Dump() {
288 const intptr_t block_count = postorder_.length();
289 for (intptr_t i = 0; i < block_count; i++) {
290 BlockEntryInstr* block = postorder_[i];
291 OS::Print("block @%"Pd" -> ", block->block_id());
292
293 Instruction* last = block->last_instruction();
294 for (intptr_t j = 0; j < last->SuccessorCount(); j++) {
295 BlockEntryInstr* succ = last->SuccessorAt(j);
296 OS::Print(" @%"Pd"", succ->block_id());
297 }
298 OS::Print("\n");
299
300 PrintBitVector(" live out", live_out_[i]);
301 PrintBitVector(" kill", kill_[i]);
302 PrintBitVector(" live in", live_in_[i]);
303 }
304 }
305
306
307 // Computes liveness information for local variables.
308 class VariableLivenessAnalysis : public LivenessAnalysis {
309 public:
310 explicit VariableLivenessAnalysis(FlowGraph* flow_graph)
311 : LivenessAnalysis(flow_graph->variable_count(), flow_graph->postorder()),
312 flow_graph_(flow_graph),
313 num_non_copied_params_(flow_graph->num_non_copied_params()),
314 assigned_vars_() { }
315
316 // For every block (in preorder) compute and return set of variables that
317 // have new assigned values flowing out of that block.
318 const GrowableArray<BitVector*>& ComputeAssignedVars() {
319 // We can't directly return kill_ because it uses postorder numbering while
320 // SSA construction uses preorder numbering internally.
321 // We have to permute postorder into preorder.
322 assigned_vars_.Clear();
323
324 const intptr_t block_count = flow_graph_->preorder().length();
325 for (intptr_t i = 0; i < block_count; i++) {
326 BlockEntryInstr* block = flow_graph_->preorder()[i];
327 BitVector* kill = GetKillSet(block);
328 kill->Intersect(GetLiveOutSet(block));
329 assigned_vars_.Add(kill);
330 }
331
332 return assigned_vars_;
333 }
334
335 // Returns true if the value set by the given store reaches any load from the
336 // same local variable.
337 bool IsStoreAlive(BlockEntryInstr* block, StoreLocalInstr* store) {
338 if (store->is_dead()) {
339 return false;
340 }
341
342 if (store->is_last()) {
343 const intptr_t index = store->local().BitIndexIn(num_non_copied_params_);
344 return GetLiveOutSet(block)->Contains(index);
345 }
346
347 return true;
348 }
349
350 // Returns true if the given load is the last for the local and the value
351 // of the local will not flow into another one.
352 bool IsLastLoad(BlockEntryInstr* block, LoadLocalInstr* load) {
353 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
354 return load->is_last() && !GetLiveOutSet(block)->Contains(index);
355 }
356
357 private:
358 virtual void ComputeInitialSets();
359
360 const FlowGraph* flow_graph_;
361 const intptr_t num_non_copied_params_;
362 GrowableArray<BitVector*> assigned_vars_;
363 };
364
365
366 void VariableLivenessAnalysis::ComputeInitialSets() {
367 const intptr_t block_count = postorder_.length();
368
369 BitVector* last_loads = new BitVector(variable_count_);
370 for (intptr_t i = 0; i < block_count; i++) {
371 BlockEntryInstr* block = postorder_[i];
372
373 BitVector* kill = kill_[i];
374 BitVector* live_in = live_in_[i];
375 last_loads->Clear();
376
377 // Iterate backwards starting at the last instruction.
378 for (BackwardInstructionIterator it(block); !it.Done(); it.Advance()) {
379 Instruction* current = it.Current();
380
381 LoadLocalInstr* load = current->AsLoadLocal();
382 if (load != NULL) {
383 const intptr_t index = load->local().BitIndexIn(num_non_copied_params_);
384 live_in->Add(index);
385
Florian Schneider 2013/04/15 10:45:09 Make empty lines consistent with the StoreLocal ca
386 if (!last_loads->Contains(index)) {
387 last_loads->Add(index);
388 load->mark_last();
389 }
390
391 continue;
392 }
393
394 StoreLocalInstr* store = current->AsStoreLocal();
395 if (store != NULL) {
396 const intptr_t index =
397 store->local().BitIndexIn(num_non_copied_params_);
398 if (kill->Contains(index)) {
399 if (!live_in->Contains(index)) {
400 store->mark_dead();
401 }
402 } else {
403 if (!live_in->Contains(index)) {
404 store->mark_last();
405 }
406 kill->Add(index);
407 }
408 live_in->Remove(index);
409 continue;
410 }
411 }
412 }
413 }
414
415
212 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number, 416 void FlowGraph::ComputeSSA(intptr_t next_virtual_register_number,
213 GrowableArray<Definition*>* inlining_parameters) { 417 GrowableArray<Definition*>* inlining_parameters) {
214 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL)); 418 ASSERT((next_virtual_register_number == 0) || (inlining_parameters != NULL));
215 current_ssa_temp_index_ = next_virtual_register_number; 419 current_ssa_temp_index_ = next_virtual_register_number;
216 GrowableArray<BitVector*> dominance_frontier; 420 GrowableArray<BitVector*> dominance_frontier;
217 ComputeDominators(&dominance_frontier); 421 ComputeDominators(&dominance_frontier);
218 InsertPhis(preorder_, assigned_vars_, dominance_frontier); 422
423 VariableLivenessAnalysis variable_liveness(this);
424 variable_liveness.Analyze();
425
426 InsertPhis(preorder_,
427 variable_liveness.ComputeAssignedVars(),
428 dominance_frontier);
429
219 GrowableArray<PhiInstr*> live_phis; 430 GrowableArray<PhiInstr*> live_phis;
431
220 // Rename uses to reference inserted phis where appropriate. 432 // Rename uses to reference inserted phis where appropriate.
221 // Collect phis that reach a non-environment use. 433 // Collect phis that reach a non-environment use.
222 Rename(&live_phis, inlining_parameters); 434 Rename(&live_phis, &variable_liveness, inlining_parameters);
435
223 // Propagate alive mark transitively from alive phis and then remove 436 // Propagate alive mark transitively from alive phis and then remove
224 // non-live ones. 437 // non-live ones.
225 RemoveDeadPhis(&live_phis); 438 RemoveDeadPhis(&live_phis);
226 } 439 }
227 440
228 441
229 // Compute immediate dominators and the dominance frontier for each basic 442 // Compute immediate dominators and the dominance frontier for each basic
230 // block. As a side effect of the algorithm, sets the immediate dominator 443 // block. As a side effect of the algorithm, sets the immediate dominator
231 // of each basic block. 444 // of each basic block.
232 // 445 //
(...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 worklist.Add(block); 607 worklist.Add(block);
395 } 608 }
396 } 609 }
397 } 610 }
398 } 611 }
399 } 612 }
400 } 613 }
401 614
402 615
403 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, 616 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis,
617 VariableLivenessAnalysis* variable_liveness,
404 GrowableArray<Definition*>* inlining_parameters) { 618 GrowableArray<Definition*>* inlining_parameters) {
405 // TODO(fschneider): Support catch-entry. 619 // TODO(fschneider): Support catch-entry.
406 if (graph_entry_->SuccessorCount() > 1) { 620 if (graph_entry_->SuccessorCount() > 1) {
407 Bailout("Catch-entry support in SSA."); 621 Bailout("Catch-entry support in SSA.");
408 } 622 }
409 623
410 // Initial renaming environment. 624 // Initial renaming environment.
411 GrowableArray<Definition*> env(variable_count()); 625 GrowableArray<Definition*> env(variable_count());
412 626
413 // Add global constants to the initial definitions. 627 // Add global constants to the initial definitions.
(...skipping 20 matching lines...) Expand all
434 } 648 }
435 } 649 }
436 650
437 // Initialize all locals with #null in the renaming environment. 651 // Initialize all locals with #null in the renaming environment.
438 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { 652 for (intptr_t i = parameter_count(); i < variable_count(); ++i) {
439 env.Add(constant_null()); 653 env.Add(constant_null());
440 } 654 }
441 655
442 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); 656 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
443 ASSERT(normal_entry != NULL); // Must have entry. 657 ASSERT(normal_entry != NULL); // Must have entry.
444 RenameRecursive(normal_entry, &env, live_phis); 658 RenameRecursive(normal_entry, &env, live_phis, variable_liveness);
445 } 659 }
446 660
447 661
448 void FlowGraph::AttachEnvironment(Instruction* instr, 662 void FlowGraph::AttachEnvironment(Instruction* instr,
449 GrowableArray<Definition*>* env) { 663 GrowableArray<Definition*>* env) {
450 Environment* deopt_env = 664 Environment* deopt_env =
451 Environment::From(*env, 665 Environment::From(*env,
452 num_non_copied_params_, 666 num_non_copied_params_,
453 parsed_function_.function()); 667 parsed_function_.function());
454 instr->SetEnvironment(deopt_env); 668 instr->SetEnvironment(deopt_env);
455 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) { 669 for (Environment::DeepIterator it(deopt_env); !it.Done(); it.Advance()) {
456 Value* use = it.CurrentValue(); 670 Value* use = it.CurrentValue();
457 use->definition()->AddEnvUse(use); 671 use->definition()->AddEnvUse(use);
458 } 672 }
459 if (instr->CanDeoptimize()) { 673 if (instr->CanDeoptimize()) {
460 instr->env()->set_deopt_id(instr->deopt_id()); 674 instr->env()->set_deopt_id(instr->deopt_id());
461 } 675 }
462 } 676 }
463 677
464 678
465 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry, 679 void FlowGraph::RenameRecursive(BlockEntryInstr* block_entry,
466 GrowableArray<Definition*>* env, 680 GrowableArray<Definition*>* env,
467 GrowableArray<PhiInstr*>* live_phis) { 681 GrowableArray<PhiInstr*>* live_phis,
682 VariableLivenessAnalysis* variable_liveness) {
468 // 1. Process phis first. 683 // 1. Process phis first.
469 if (block_entry->IsJoinEntry()) { 684 if (block_entry->IsJoinEntry()) {
470 JoinEntryInstr* join = block_entry->AsJoinEntry(); 685 JoinEntryInstr* join = block_entry->AsJoinEntry();
471 if (join->phis() != NULL) { 686 if (join->phis() != NULL) {
472 for (intptr_t i = 0; i < join->phis()->length(); ++i) { 687 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
473 PhiInstr* phi = (*join->phis())[i]; 688 PhiInstr* phi = (*join->phis())[i];
474 if (phi != NULL) { 689 if (phi != NULL) {
475 (*env)[i] = phi; 690 (*env)[i] = phi;
476 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. 691 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
477 } 692 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 737
523 // 2b. Handle LoadLocal and StoreLocal. 738 // 2b. Handle LoadLocal and StoreLocal.
524 // For each LoadLocal: Remove it from the graph. 739 // For each LoadLocal: Remove it from the graph.
525 // For each StoreLocal: Remove it from the graph and update the environment. 740 // For each StoreLocal: Remove it from the graph and update the environment.
526 Definition* definition = current->AsDefinition(); 741 Definition* definition = current->AsDefinition();
527 if (definition != NULL) { 742 if (definition != NULL) {
528 LoadLocalInstr* load = definition->AsLoadLocal(); 743 LoadLocalInstr* load = definition->AsLoadLocal();
529 StoreLocalInstr* store = definition->AsStoreLocal(); 744 StoreLocalInstr* store = definition->AsStoreLocal();
530 if ((load != NULL) || (store != NULL)) { 745 if ((load != NULL) || (store != NULL)) {
531 intptr_t index; 746 intptr_t index;
747 Definition* result;
532 if (store != NULL) { 748 if (store != NULL) {
749 // Update renaming environment.
533 index = store->local().BitIndexIn(num_non_copied_params_); 750 index = store->local().BitIndexIn(num_non_copied_params_);
534 // Update renaming environment. 751 result = store->value()->definition();
535 (*env)[index] = store->value()->definition(); 752
753 if (variable_liveness->IsStoreAlive(block_entry, store)) {
754 (*env)[index] = result;
755 } else {
756 (*env)[index] = constant_null();
757 }
536 } else { 758 } else {
537 // The graph construction ensures we do not have an unused LoadLocal 759 // The graph construction ensures we do not have an unused LoadLocal
538 // computation. 760 // computation.
539 ASSERT(definition->is_used()); 761 ASSERT(definition->is_used());
540 index = load->local().BitIndexIn(num_non_copied_params_); 762 index = load->local().BitIndexIn(num_non_copied_params_);
763 result = (*env)[index];
541 764
542 PhiInstr* phi = (*env)[index]->AsPhi(); 765 PhiInstr* phi = result->AsPhi();
543 if ((phi != NULL) && !phi->is_alive()) { 766 if ((phi != NULL) && !phi->is_alive()) {
544 phi->mark_alive(); 767 phi->mark_alive();
545 live_phis->Add(phi); 768 live_phis->Add(phi);
546 } 769 }
770
771 if (variable_liveness->IsLastLoad(block_entry, load)) {
772 (*env)[index] = constant_null();
773 }
547 } 774 }
548 // Update expression stack or remove from graph. 775 // Update expression stack or remove from graph.
549 if (definition->is_used()) { 776 if (definition->is_used()) {
550 env->Add((*env)[index]); 777 env->Add(result);
551 // We remove load/store instructions when we find their use in 2a. 778 // We remove load/store instructions when we find their use in 2a.
552 } else { 779 } else {
553 it.RemoveCurrentFromGraph(); 780 it.RemoveCurrentFromGraph();
554 } 781 }
555 } else { 782 } else {
556 // Not a load or store. 783 // Not a load or store.
557 if (definition->is_used()) { 784 if (definition->is_used()) {
558 // Assign fresh SSA temporary and update expression stack. 785 // Assign fresh SSA temporary and update expression stack.
559 definition->set_ssa_temp_index(alloc_ssa_temp_index()); 786 definition->set_ssa_temp_index(alloc_ssa_temp_index());
560 env->Add(definition); 787 env->Add(definition);
561 } 788 }
562 } 789 }
563 } 790 }
564 791
565 // 2c. Handle pushed argument. 792 // 2c. Handle pushed argument.
566 PushArgumentInstr* push = current->AsPushArgument(); 793 PushArgumentInstr* push = current->AsPushArgument();
567 if (push != NULL) { 794 if (push != NULL) {
568 env->Add(push); 795 env->Add(push);
569 } 796 }
570 } 797 }
571 798
572 // 3. Process dominated blocks. 799 // 3. Process dominated blocks.
573 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { 800 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
574 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; 801 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
575 GrowableArray<Definition*> new_env(env->length()); 802 GrowableArray<Definition*> new_env(env->length());
576 new_env.AddArray(*env); 803 new_env.AddArray(*env);
577 RenameRecursive(block, &new_env, live_phis); 804 RenameRecursive(block, &new_env, live_phis, variable_liveness);
578 } 805 }
579 806
580 // 4. Process successor block. We have edge-split form, so that only blocks 807 // 4. Process successor block. We have edge-split form, so that only blocks
581 // with one successor can have a join block as successor. 808 // with one successor can have a join block as successor.
582 if ((block_entry->last_instruction()->SuccessorCount() == 1) && 809 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
583 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { 810 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
584 JoinEntryInstr* successor = 811 JoinEntryInstr* successor =
585 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); 812 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
586 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); 813 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
587 ASSERT(pred_index >= 0); 814 ASSERT(pred_index >= 0);
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
702 for (ForwardInstructionIterator it(preorder_[i]); 929 for (ForwardInstructionIterator it(preorder_[i]);
703 !it.Done(); 930 !it.Done();
704 it.Advance()) { 931 it.Advance()) {
705 ++size; 932 ++size;
706 } 933 }
707 } 934 }
708 return size; 935 return size;
709 } 936 }
710 937
711 } // namespace dart 938 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph.h ('k') | runtime/vm/flow_graph_allocator.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698