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

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

Issue 10377104: Compute assigned variables and dominance frontiers. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 7 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
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_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/code_descriptors.h" 9 #include "vm/code_descriptors.h"
9 #include "vm/dart_entry.h" 10 #include "vm/dart_entry.h"
10 #include "vm/flags.h" 11 #include "vm/flags.h"
11 #include "vm/intermediate_language.h" 12 #include "vm/intermediate_language.h"
12 #include "vm/longjump.h" 13 #include "vm/longjump.h"
13 #include "vm/object_store.h" 14 #include "vm/object_store.h"
14 #include "vm/os.h" 15 #include "vm/os.h"
15 #include "vm/parser.h" 16 #include "vm/parser.h"
16 #include "vm/resolver.h" 17 #include "vm/resolver.h"
17 #include "vm/stub_code.h" 18 #include "vm/stub_code.h"
18 19
19 namespace dart { 20 namespace dart {
20 21
21 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph."); 22 DEFINE_FLAG(bool, print_flow_graph, false, "Print the IR flow graph.");
22 DECLARE_FLAG(bool, enable_type_checks); 23 DECLARE_FLAG(bool, enable_type_checks);
23 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree."); 24 DEFINE_FLAG(bool, print_ast, false, "Print abstract syntax tree.");
24 25
25 26
26 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) 27 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function)
27 : parsed_function_(parsed_function), 28 : parsed_function_(parsed_function),
28 preorder_block_entries_(), 29 preorder_block_entries_(),
29 postorder_block_entries_(), 30 postorder_block_entries_(),
30 context_level_(0), 31 context_level_(0),
31 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), 32 last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
32 try_index_(CatchClauseNode::kInvalidTryIndex), 33 try_index_(CatchClauseNode::kInvalidTryIndex),
33 catch_entries_() {} 34 catch_entries_() { }
34 35
35 36
36 void FlowGraphBuilder::AddCatchEntry(intptr_t try_index, Instruction* entry) { 37 void FlowGraphBuilder::AddCatchEntry(intptr_t try_index, Instruction* entry) {
37 catch_entries_.Add(entry); 38 catch_entries_.Add(entry);
38 } 39 }
39 40
40 41
41 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { 42 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
42 ASSERT(is_open()); 43 ASSERT(is_open());
43 if (other_fragment.is_empty()) return; 44 if (other_fragment.is_empty()) return;
(...skipping 2440 matching lines...) Expand 10 before | Expand all | Expand 10 after
2484 Isolate* isolate = Isolate::Current(); 2485 Isolate* isolate = Isolate::Current();
2485 const intptr_t prev_cid = isolate->computation_id(); 2486 const intptr_t prev_cid = isolate->computation_id();
2486 isolate->set_computation_id(0); 2487 isolate->set_computation_id(0);
2487 const Function& function = parsed_function().function(); 2488 const Function& function = parsed_function().function();
2488 EffectGraphVisitor for_effect(this, 0); 2489 EffectGraphVisitor for_effect(this, 0);
2489 for_effect.AddInstruction(new TargetEntryInstr()); 2490 for_effect.AddInstruction(new TargetEntryInstr());
2490 parsed_function().node_sequence()->Visit(&for_effect); 2491 parsed_function().node_sequence()->Visit(&for_effect);
2491 // Check that the graph is properly terminated. 2492 // Check that the graph is properly terminated.
2492 ASSERT(!for_effect.is_open()); 2493 ASSERT(!for_effect.is_open());
2493 GrowableArray<intptr_t> parent; 2494 GrowableArray<intptr_t> parent;
2495 GrowableArray<BitVector*> assigned_vars;
2496 intptr_t variable_count = parsed_function_.function().num_fixed_parameters() +
2497 parsed_function_.copied_parameter_count() +
2498 parsed_function_.stack_local_count();
2499 GrowableArray<BitVector*> dominance_frontier;
2494 for (intptr_t i = 0; i < catch_entries_.length(); i++) { 2500 for (intptr_t i = 0; i < catch_entries_.length(); i++) {
2495 Instruction* entry = catch_entries_[i]; 2501 Instruction* entry = catch_entries_[i];
2496 entry->DiscoverBlocks(NULL, // Entry block predecessor. 2502 entry->DiscoverBlocks(NULL, // Entry block predecessor.
2497 &preorder_block_entries_, 2503 &preorder_block_entries_,
2498 &postorder_block_entries_, 2504 &postorder_block_entries_,
2499 &parent); 2505 &parent,
2506 &assigned_vars,
2507 variable_count);
2500 if (for_optimized) { 2508 if (for_optimized) {
2501 ComputeDominators(&preorder_block_entries_, &parent); 2509 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier);
2502 } 2510 }
2503 } 2511 }
2504 if (for_effect.entry() != NULL) { 2512 if (for_effect.entry() != NULL) {
2505 // Perform a depth-first traversal of the graph to build preorder and 2513 // Perform a depth-first traversal of the graph to build preorder and
2506 // postorder block orders. 2514 // postorder block orders.
2507 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor. 2515 for_effect.entry()->DiscoverBlocks(NULL, // Entry block predecessor.
2508 &preorder_block_entries_, 2516 &preorder_block_entries_,
2509 &postorder_block_entries_, 2517 &postorder_block_entries_,
2510 &parent); 2518 &parent,
2519 &assigned_vars,
2520 variable_count);
2511 if (for_optimized) { 2521 if (for_optimized) {
2512 ComputeDominators(&preorder_block_entries_, &parent); 2522 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier);
2513 } 2523 }
2514 } 2524 }
2515 isolate->set_computation_id(prev_cid); 2525 isolate->set_computation_id(prev_cid);
2516 if (FLAG_print_flow_graph) { 2526 if (FLAG_print_flow_graph) {
2517 intptr_t length = postorder_block_entries_.length(); 2527 intptr_t length = postorder_block_entries_.length();
2518 GrowableArray<BlockEntryInstr*> reverse_postorder(length); 2528 GrowableArray<BlockEntryInstr*> reverse_postorder(length);
2519 for (intptr_t i = length - 1; i >= 0; --i) { 2529 for (intptr_t i = length - 1; i >= 0; --i) {
2520 reverse_postorder.Add(postorder_block_entries_[i]); 2530 reverse_postorder.Add(postorder_block_entries_[i]);
2521 } 2531 }
2522 FlowGraphPrinter printer(function, reverse_postorder); 2532 FlowGraphPrinter printer(function, reverse_postorder);
2523 printer.VisitBlocks(); 2533 printer.VisitBlocks();
2524 } 2534 }
2525 } 2535 }
2526 2536
2527 2537
2528 void FlowGraphBuilder::ComputeDominators( 2538 void FlowGraphBuilder::ComputeDominators(
2529 GrowableArray<BlockEntryInstr*>* preorder, 2539 GrowableArray<BlockEntryInstr*>* preorder,
2530 GrowableArray<intptr_t>* parent) { 2540 GrowableArray<intptr_t>* parent,
2541 GrowableArray<BitVector*>* dominance_frontier) {
srdjan 2012/05/12 00:00:55 Maybe add in comment what is the content of parent
Kevin Millikin (Google) 2012/05/15 11:51:44 Done.
2531 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass 2542 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
2532 // version of the Lengauer-Tarjan algorithm (LT is normally three passes) 2543 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
2533 // that eliminates a pass by using nearest-common ancestor (NCA) to 2544 // that eliminates a pass by using nearest-common ancestor (NCA) to
2534 // compute immediate dominators from semidominators. It also removes a 2545 // compute immediate dominators from semidominators. It also removes a
2535 // level of indirection in the link-eval forest data structure. 2546 // level of indirection in the link-eval forest data structure.
2536 // 2547 //
2537 // The algorithm is described in Georgiadis, Tarjan, and Werneck's 2548 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
2538 // "Finding Dominators in Practice". 2549 // "Finding Dominators in Practice".
2539 // See http://www.cs.princeton.edu/~rwerneck/dominators/ . 2550 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
2540 2551
2541 // All arrays are maps between preorder basic-block numbers. 2552 // All arrays are maps between preorder basic-block numbers.
2542 intptr_t size = parent->length(); 2553 intptr_t size = parent->length();
2543 GrowableArray<intptr_t> idom(size); // Immediate dominator. 2554 GrowableArray<intptr_t> idom(size); // Immediate dominator.
2544 GrowableArray<intptr_t> semi(size); // Semidominator. 2555 GrowableArray<intptr_t> semi(size); // Semidominator.
2545 GrowableArray<intptr_t> label(size); // Label for link-eval forest. 2556 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
2546 2557
2547 // 1. First pass: compute semidominators as in Lengauer-Tarjan. 2558 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
2548 // Semidominators are computed from a depth-first spanning tree and are an 2559 // Semidominators are computed from a depth-first spanning tree and are an
2549 // approximation of immediate dominators. 2560 // approximation of immediate dominators.
2550 2561
2551 // Use a link-eval data structure with path compression. Implement path 2562 // Use a link-eval data structure with path compression. Implement path
2552 // compression in place by mutating the parent array. Each block has a 2563 // compression in place by mutating the parent array. Each block has a
2553 // label, which is the minimum block number on the compressed path. 2564 // label, which is the minimum block number on the compressed path.
2554 2565
2555 // Initialize idom, semi, and label. 2566 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
2567 // dominance frontier output array.
2556 for (intptr_t i = 0; i < size; ++i) { 2568 for (intptr_t i = 0; i < size; ++i) {
2557 idom.Add((*parent)[i]); 2569 idom.Add((*parent)[i]);
2558 semi.Add(i); 2570 semi.Add(i);
2559 label.Add(i); 2571 label.Add(i);
2572 dominance_frontier->Add(new BitVector(size,
2573 Isolate::Current()->current_zone()));
Florian Schneider 2012/05/11 13:19:37 Maybe it would be useful to have a Zone* zone_ sto
srdjan 2012/05/12 00:00:55 That would premature optimization, IMHO. At some p
Kevin Millikin (Google) 2012/05/15 11:51:44 I've eliminated the parameter, but I disagree that
srdjan 2012/05/15 22:05:32 In the VM we do not pass isolates/zones for perfor
2560 } 2574 }
2561 2575
2562 // Loop over the blocks in reverse preorder (not including the graph 2576 // Loop over the blocks in reverse preorder (not including the graph
2563 // entry). 2577 // entry).
2564 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) { 2578 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
2565 // Loop over the predecessors. 2579 // Loop over the predecessors.
2566 BlockEntryInstr* block = (*preorder)[block_index]; 2580 BlockEntryInstr* block = (*preorder)[block_index];
2567 for (intptr_t i = 0; i < block->PredecessorCount(); ++i) { 2581 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
2568 BlockEntryInstr* pred = block->PredecessorAt(i); 2582 BlockEntryInstr* pred = block->PredecessorAt(i);
2569 ASSERT(pred != NULL); 2583 ASSERT(pred != NULL);
2570 2584
2571 // Look for the semidominator by ascending the semidominator path 2585 // Look for the semidominator by ascending the semidominator path
2572 // starting from pred. 2586 // starting from pred.
2573 intptr_t pred_index = pred->preorder_number(); 2587 intptr_t pred_index = pred->preorder_number();
2574 intptr_t best = pred_index; 2588 intptr_t best = pred_index;
2575 if (pred_index > block_index) { 2589 if (pred_index > block_index) {
2576 CompressPath(block_index, pred_index, parent, &label); 2590 CompressPath(block_index, pred_index, parent, &label);
2577 best = label[pred_index]; 2591 best = label[pred_index];
2578 } 2592 }
2579 2593
2580 // Update the semidominator if we've found a better one. 2594 // Update the semidominator if we've found a better one.
2581 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]); 2595 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
2582 } 2596 }
2583 2597
2584 // Now use label for the semidominator. 2598 // Now use label for the semidominator.
2585 label[block_index] = semi[block_index]; 2599 label[block_index] = semi[block_index];
2586 } 2600 }
2587 2601
2588 // 2. Compute the immediate dominators as the nearest common ancestor of 2602 // 2. Compute the immediate dominators as the nearest common ancestor of
2589 // spanning tree parent and semidominator, for all nodes except the entry. 2603 // spanning tree parent and semidominator, for all blocks except the entry.
2590 for (intptr_t block_index = 1; block_index < size; ++block_index) { 2604 for (intptr_t block_index = 1; block_index < size; ++block_index) {
2591 intptr_t dom_index = idom[block_index]; 2605 intptr_t dom_index = idom[block_index];
2592 while (dom_index > semi[block_index]) { 2606 while (dom_index > semi[block_index]) {
2593 dom_index = idom[dom_index]; 2607 dom_index = idom[dom_index];
2594 } 2608 }
2595 idom[block_index] = dom_index; 2609 idom[block_index] = dom_index;
2596 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]); 2610 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]);
2597 } 2611 }
2612
2613 // 3. Compute the dominance frontier for all blocks. This is algorithm in
2614 // "A Simple, Fast Dominance Algorithm" (Figure 5), which is attributed to
2615 // a paper by Ferrante et al. There is no bookkeeping required to avoid
2616 // adding a block twice to the same block's dominance frontier because we
2617 // use a set to represent the dominance frontier.
2618 for (intptr_t block_index = 0; block_index < size; ++block_index) {
2619 BlockEntryInstr* block = (*preorder)[block_index];
2620 intptr_t count = block->PredecessorCount();
2621 if (count <= 1) continue;
2622 for (intptr_t i = 0; i < count; ++i) {
2623 BlockEntryInstr* runner = block->PredecessorAt(i);
2624 while (runner != block->dominator()) {
2625 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
2626 runner = runner->dominator();
2627 }
2628 }
2629 }
2598 } 2630 }
2599 2631
2600 2632
2601 void FlowGraphBuilder::CompressPath(intptr_t start_index, 2633 void FlowGraphBuilder::CompressPath(intptr_t start_index,
2602 intptr_t current_index, 2634 intptr_t current_index,
2603 GrowableArray<intptr_t>* parent, 2635 GrowableArray<intptr_t>* parent,
2604 GrowableArray<intptr_t>* label) { 2636 GrowableArray<intptr_t>* label) {
2605 intptr_t next_index = (*parent)[current_index]; 2637 intptr_t next_index = (*parent)[current_index];
2606 if (next_index > start_index) { 2638 if (next_index > start_index) {
2607 CompressPath(start_index, next_index, parent, label); 2639 CompressPath(start_index, next_index, parent, label);
(...skipping 11 matching lines...) Expand all
2619 char* chars = reinterpret_cast<char*>( 2651 char* chars = reinterpret_cast<char*>(
2620 Isolate::Current()->current_zone()->Allocate(len)); 2652 Isolate::Current()->current_zone()->Allocate(len));
2621 OS::SNPrint(chars, len, kFormat, function_name, reason); 2653 OS::SNPrint(chars, len, kFormat, function_name, reason);
2622 const Error& error = Error::Handle( 2654 const Error& error = Error::Handle(
2623 LanguageError::New(String::Handle(String::New(chars)))); 2655 LanguageError::New(String::Handle(String::New(chars))));
2624 Isolate::Current()->long_jump_base()->Jump(1, error); 2656 Isolate::Current()->long_jump_base()->Jump(1, error);
2625 } 2657 }
2626 2658
2627 2659
2628 } // namespace dart 2660 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698