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

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

Issue 10857016: Refactored FlowGraphBuilder into a separate FlowGraph representation. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Revision based on Kevin's review. Created 8 years, 4 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_builder.h ('k') | runtime/vm/flow_graph_compiler.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) 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"
9 #include "vm/code_descriptors.h" 8 #include "vm/code_descriptors.h"
10 #include "vm/dart_entry.h" 9 #include "vm/dart_entry.h"
11 #include "vm/flags.h" 10 #include "vm/flags.h"
12 #include "vm/il_printer.h" 11 #include "vm/il_printer.h"
13 #include "vm/intermediate_language.h" 12 #include "vm/intermediate_language.h"
14 #include "vm/longjump.h" 13 #include "vm/longjump.h"
15 #include "vm/object_store.h" 14 #include "vm/object_store.h"
16 #include "vm/os.h" 15 #include "vm/os.h"
17 #include "vm/parser.h" 16 #include "vm/parser.h"
18 #include "vm/resolver.h" 17 #include "vm/resolver.h"
(...skipping 13 matching lines...) Expand all
32 31
33 32
34 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function) 33 FlowGraphBuilder::FlowGraphBuilder(const ParsedFunction& parsed_function)
35 : parsed_function_(parsed_function), 34 : parsed_function_(parsed_function),
36 copied_parameter_count_(parsed_function.copied_parameter_count()), 35 copied_parameter_count_(parsed_function.copied_parameter_count()),
37 // All parameters are copied if any parameter is. 36 // All parameters are copied if any parameter is.
38 non_copied_parameter_count_((copied_parameter_count_ == 0) 37 non_copied_parameter_count_((copied_parameter_count_ == 0)
39 ? parsed_function.function().num_fixed_parameters() 38 ? parsed_function.function().num_fixed_parameters()
40 : 0), 39 : 0),
41 stack_local_count_(parsed_function.stack_local_count()), 40 stack_local_count_(parsed_function.stack_local_count()),
42 preorder_block_entries_(),
43 postorder_block_entries_(),
44 context_level_(0), 41 context_level_(0),
45 last_used_try_index_(CatchClauseNode::kInvalidTryIndex), 42 last_used_try_index_(CatchClauseNode::kInvalidTryIndex),
46 try_index_(CatchClauseNode::kInvalidTryIndex), 43 try_index_(CatchClauseNode::kInvalidTryIndex),
47 graph_entry_(NULL), 44 graph_entry_(NULL) { }
48 current_ssa_temp_index_(0) { }
49 45
50 46
51 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) { 47 void FlowGraphBuilder::AddCatchEntry(TargetEntryInstr* entry) {
52 graph_entry_->AddCatchEntry(entry); 48 graph_entry_->AddCatchEntry(entry);
53 } 49 }
54 50
55 51
56 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) { 52 void EffectGraphVisitor::Append(const EffectGraphVisitor& other_fragment) {
57 ASSERT(is_open()); 53 ASSERT(is_open());
58 if (other_fragment.is_empty()) return; 54 if (other_fragment.is_empty()) return;
(...skipping 2323 matching lines...) Expand 10 before | Expand all | Expand 10 after
2382 BuildLoadContext(node->context_var()); 2378 BuildLoadContext(node->context_var());
2383 EffectGraphVisitor for_finally_block(owner(), temp_index()); 2379 EffectGraphVisitor for_finally_block(owner(), temp_index());
2384 node->finally_block()->Visit(&for_finally_block); 2380 node->finally_block()->Visit(&for_finally_block);
2385 Append(for_finally_block); 2381 Append(for_finally_block);
2386 if (try_index >= 0) { 2382 if (try_index >= 0) {
2387 owner()->set_try_index(try_index); 2383 owner()->set_try_index(try_index);
2388 } 2384 }
2389 } 2385 }
2390 2386
2391 2387
2392 void FlowGraphBuilder::BuildGraph(bool for_optimized, bool use_ssa) { 2388 FlowGraph* FlowGraphBuilder::BuildGraph() {
2393 if (FLAG_print_ast) { 2389 if (FLAG_print_ast) {
2394 // Print the function ast before IL generation. 2390 // Print the function ast before IL generation.
2395 AstPrinter::PrintFunctionNodes(parsed_function()); 2391 AstPrinter::PrintFunctionNodes(parsed_function());
2396 } 2392 }
2397 // Compilation can be nested, preserve the computation-id. 2393 // Compilation can be nested, preserve the computation-id.
2398 const Function& function = parsed_function().function(); 2394 const Function& function = parsed_function().function();
2399 TargetEntryInstr* normal_entry = new TargetEntryInstr(); 2395 TargetEntryInstr* normal_entry = new TargetEntryInstr();
2400 graph_entry_ = new GraphEntryInstr(normal_entry); 2396 graph_entry_ = new GraphEntryInstr(normal_entry);
2401 EffectGraphVisitor for_effect(this, 0); 2397 EffectGraphVisitor for_effect(this, 0);
2402 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the 2398 // TODO(kmillikin): We can eliminate stack checks in some cases (e.g., the
2403 // stack check on entry for leaf routines). 2399 // stack check on entry for leaf routines).
2404 for_effect.Do(new CheckStackOverflowComp(function.token_pos(), 2400 for_effect.Do(new CheckStackOverflowComp(function.token_pos(),
2405 CatchClauseNode::kInvalidTryIndex)); 2401 CatchClauseNode::kInvalidTryIndex));
2406 parsed_function().node_sequence()->Visit(&for_effect); 2402 parsed_function().node_sequence()->Visit(&for_effect);
2407 AppendFragment(normal_entry, for_effect); 2403 AppendFragment(normal_entry, for_effect);
2408 // Check that the graph is properly terminated. 2404 // Check that the graph is properly terminated.
2409 ASSERT(!for_effect.is_open()); 2405 ASSERT(!for_effect.is_open());
2410 GrowableArray<intptr_t> parent; 2406 return new FlowGraph(*this, graph_entry_);
2411 GrowableArray<BitVector*> assigned_vars;
2412
2413 // Perform a depth-first traversal of the graph to build preorder and
2414 // postorder block orders.
2415 graph_entry_->DiscoverBlocks(NULL, // Entry block predecessor.
2416 &preorder_block_entries_,
2417 &postorder_block_entries_,
2418 &parent,
2419 &assigned_vars,
2420 variable_count(),
2421 non_copied_parameter_count_);
2422 // Number blocks in reverse postorder.
2423 intptr_t block_count = postorder_block_entries_.length();
2424 for (intptr_t i = 0; i < block_count; ++i) {
2425 postorder_block_entries_[i]->set_block_id(block_count - i - 1);
2426 }
2427
2428 if (for_optimized) {
2429 // Link instructions backwards for optimized compilation.
2430 for (intptr_t i = 0; i < block_count; ++i) {
2431 BlockEntryInstr* entry = postorder_block_entries_[i];
2432 Instruction* previous = entry;
2433 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) {
2434 Instruction* current = it.Current();
2435 current->set_previous(previous);
2436 previous = current;
2437 }
2438 }
2439 }
2440
2441 if (for_optimized && use_ssa) {
2442 GrowableArray<BitVector*> dominance_frontier;
2443 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier);
2444 InsertPhis(preorder_block_entries_,
2445 assigned_vars,
2446 dominance_frontier);
2447
2448 GrowableArray<PhiInstr*> live_phis;
2449
2450 // Rename uses to reference inserted phis where appropriate.
2451 // Collect phis that reach a non-environment use.
2452 Rename(&live_phis);
2453
2454 // Propagate alive mark transitively from alive phis.
2455 MarkLivePhis(&live_phis);
2456 }
2457 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) {
2458 intptr_t length = postorder_block_entries_.length();
2459 GrowableArray<BlockEntryInstr*> reverse_postorder(length);
2460 for (intptr_t i = length - 1; i >= 0; --i) {
2461 reverse_postorder.Add(postorder_block_entries_[i]);
2462 }
2463 if (FLAG_print_flow_graph) {
2464 // Print flow graph to stdout.
2465 FlowGraphPrinter printer(function, reverse_postorder);
2466 printer.PrintBlocks();
2467 }
2468 if (Dart::flow_graph_writer() != NULL) {
2469 // Write flow graph to file.
2470 FlowGraphVisualizer printer(function, reverse_postorder);
2471 printer.PrintFunction();
2472 }
2473 }
2474 } 2407 }
2475 2408
2476 2409
2477 // Compute immediate dominators and the dominance frontier for each basic
2478 // block. As a side effect of the algorithm, sets the immediate dominator
2479 // of each basic block.
2480 //
2481 // preorder: an input list of basic block entries in preorder. The
2482 // algorithm relies on the block ordering.
2483 //
2484 // parent: an input parameter encoding a depth-first spanning tree of
2485 // the control flow graph. The array maps the preorder block
2486 // number of a block to the preorder block number of its spanning
2487 // tree parent.
2488 //
2489 // dominance_frontier: an output parameter encoding the dominance frontier.
2490 // The array maps the preorder block number of a block to the set of
2491 // (preorder block numbers of) blocks in the dominance frontier.
2492 void FlowGraphBuilder::ComputeDominators(
2493 GrowableArray<BlockEntryInstr*>* preorder,
2494 GrowableArray<intptr_t>* parent,
2495 GrowableArray<BitVector*>* dominance_frontier) {
2496 // Use the SEMI-NCA algorithm to compute dominators. This is a two-pass
2497 // version of the Lengauer-Tarjan algorithm (LT is normally three passes)
2498 // that eliminates a pass by using nearest-common ancestor (NCA) to
2499 // compute immediate dominators from semidominators. It also removes a
2500 // level of indirection in the link-eval forest data structure.
2501 //
2502 // The algorithm is described in Georgiadis, Tarjan, and Werneck's
2503 // "Finding Dominators in Practice".
2504 // See http://www.cs.princeton.edu/~rwerneck/dominators/ .
2505
2506 // All arrays are maps between preorder basic-block numbers.
2507 intptr_t size = parent->length();
2508 GrowableArray<intptr_t> idom(size); // Immediate dominator.
2509 GrowableArray<intptr_t> semi(size); // Semidominator.
2510 GrowableArray<intptr_t> label(size); // Label for link-eval forest.
2511
2512 // 1. First pass: compute semidominators as in Lengauer-Tarjan.
2513 // Semidominators are computed from a depth-first spanning tree and are an
2514 // approximation of immediate dominators.
2515
2516 // Use a link-eval data structure with path compression. Implement path
2517 // compression in place by mutating the parent array. Each block has a
2518 // label, which is the minimum block number on the compressed path.
2519
2520 // Initialize idom, semi, and label used by SEMI-NCA. Initialize the
2521 // dominance frontier output array.
2522 for (intptr_t i = 0; i < size; ++i) {
2523 idom.Add((*parent)[i]);
2524 semi.Add(i);
2525 label.Add(i);
2526 dominance_frontier->Add(new BitVector(size));
2527 }
2528
2529 // Loop over the blocks in reverse preorder (not including the graph
2530 // entry).
2531 for (intptr_t block_index = size - 1; block_index >= 1; --block_index) {
2532 // Loop over the predecessors.
2533 BlockEntryInstr* block = (*preorder)[block_index];
2534 for (intptr_t i = 0, count = block->PredecessorCount(); i < count; ++i) {
2535 BlockEntryInstr* pred = block->PredecessorAt(i);
2536 ASSERT(pred != NULL);
2537
2538 // Look for the semidominator by ascending the semidominator path
2539 // starting from pred.
2540 intptr_t pred_index = pred->preorder_number();
2541 intptr_t best = pred_index;
2542 if (pred_index > block_index) {
2543 CompressPath(block_index, pred_index, parent, &label);
2544 best = label[pred_index];
2545 }
2546
2547 // Update the semidominator if we've found a better one.
2548 semi[block_index] = Utils::Minimum(semi[block_index], semi[best]);
2549 }
2550
2551 // Now use label for the semidominator.
2552 label[block_index] = semi[block_index];
2553 }
2554
2555 // 2. Compute the immediate dominators as the nearest common ancestor of
2556 // spanning tree parent and semidominator, for all blocks except the entry.
2557 for (intptr_t block_index = 1; block_index < size; ++block_index) {
2558 intptr_t dom_index = idom[block_index];
2559 while (dom_index > semi[block_index]) {
2560 dom_index = idom[dom_index];
2561 }
2562 idom[block_index] = dom_index;
2563 (*preorder)[block_index]->set_dominator((*preorder)[dom_index]);
2564 (*preorder)[dom_index]->AddDominatedBlock((*preorder)[block_index]);
2565 }
2566
2567 // 3. Now compute the dominance frontier for all blocks. This is
2568 // algorithm in "A Simple, Fast Dominance Algorithm" (Figure 5), which is
2569 // attributed to a paper by Ferrante et al. There is no bookkeeping
2570 // required to avoid adding a block twice to the same block's dominance
2571 // frontier because we use a set to represent the dominance frontier.
2572 for (intptr_t block_index = 0; block_index < size; ++block_index) {
2573 BlockEntryInstr* block = (*preorder)[block_index];
2574 intptr_t count = block->PredecessorCount();
2575 if (count <= 1) continue;
2576 for (intptr_t i = 0; i < count; ++i) {
2577 BlockEntryInstr* runner = block->PredecessorAt(i);
2578 while (runner != block->dominator()) {
2579 (*dominance_frontier)[runner->preorder_number()]->Add(block_index);
2580 runner = runner->dominator();
2581 }
2582 }
2583 }
2584 }
2585
2586
2587 void FlowGraphBuilder::CompressPath(intptr_t start_index,
2588 intptr_t current_index,
2589 GrowableArray<intptr_t>* parent,
2590 GrowableArray<intptr_t>* label) {
2591 intptr_t next_index = (*parent)[current_index];
2592 if (next_index > start_index) {
2593 CompressPath(start_index, next_index, parent, label);
2594 (*label)[current_index] =
2595 Utils::Minimum((*label)[current_index], (*label)[next_index]);
2596 (*parent)[current_index] = (*parent)[next_index];
2597 }
2598 }
2599
2600
2601 void FlowGraphBuilder::InsertPhis(
2602 const GrowableArray<BlockEntryInstr*>& preorder,
2603 const GrowableArray<BitVector*>& assigned_vars,
2604 const GrowableArray<BitVector*>& dom_frontier) {
2605 const intptr_t block_count = preorder.length();
2606 // Map preorder block number to the highest variable index that has a phi
2607 // in that block. Use it to avoid inserting multiple phis for the same
2608 // variable.
2609 GrowableArray<intptr_t> has_already(block_count);
2610 // Map preorder block number to the highest variable index for which the
2611 // block went on the worklist. Use it to avoid adding the same block to
2612 // the worklist more than once for the same variable.
2613 GrowableArray<intptr_t> work(block_count);
2614
2615 // Initialize has_already and work.
2616 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
2617 has_already.Add(-1);
2618 work.Add(-1);
2619 }
2620
2621 // Insert phis for each variable in turn.
2622 GrowableArray<BlockEntryInstr*> worklist;
2623 for (intptr_t var_index = 0; var_index < variable_count(); ++var_index) {
2624 // Add to the worklist each block containing an assignment.
2625 for (intptr_t block_index = 0; block_index < block_count; ++block_index) {
2626 if (assigned_vars[block_index]->Contains(var_index)) {
2627 work[block_index] = var_index;
2628 worklist.Add(preorder[block_index]);
2629 }
2630 }
2631
2632 while (!worklist.is_empty()) {
2633 BlockEntryInstr* current = worklist.Last();
2634 worklist.RemoveLast();
2635 // Ensure a phi for each block in the dominance frontier of current.
2636 for (BitVector::Iterator it(dom_frontier[current->preorder_number()]);
2637 !it.Done();
2638 it.Advance()) {
2639 int index = it.Current();
2640 if (has_already[index] < var_index) {
2641 BlockEntryInstr* block = preorder[index];
2642 ASSERT(block->IsJoinEntry());
2643 block->AsJoinEntry()->InsertPhi(var_index, variable_count());
2644 has_already[index] = var_index;
2645 if (work[index] < var_index) {
2646 work[index] = var_index;
2647 worklist.Add(block);
2648 }
2649 }
2650 }
2651 }
2652 }
2653 }
2654
2655
2656 void FlowGraphBuilder::Rename(GrowableArray<PhiInstr*>* live_phis) {
2657 // TODO(fschneider): Support catch-entry.
2658 if (graph_entry_->SuccessorCount() > 1) {
2659 Bailout("Catch-entry support in SSA.");
2660 }
2661
2662 // Initialize start environment.
2663 GrowableArray<Value*> start_env(variable_count());
2664 for (intptr_t i = 0; i < parameter_count(); ++i) {
2665 ParameterInstr* param = new ParameterInstr(i);
2666 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2667 start_env.Add(new UseVal(param));
2668 }
2669
2670 // All locals are initialized with #null.
2671 Value* null_value = new ConstantVal(Object::ZoneHandle());
2672 while (start_env.length() < variable_count()) {
2673 start_env.Add(null_value);
2674 }
2675 graph_entry_->set_start_env(
2676 new Environment(start_env, non_copied_parameter_count_));
2677
2678 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0);
2679 ASSERT(normal_entry != NULL); // Must have entry.
2680 GrowableArray<Value*> env(variable_count());
2681 env.AddArray(start_env);
2682 RenameRecursive(normal_entry, &env, live_phis);
2683 }
2684
2685
2686 // Helper to a copy a value iff it is a UseVal.
2687 static Value* CopyValue(Value* value) {
2688 return value->IsUse()
2689 ? new UseVal(value->AsUse()->definition())
2690 : value;
2691 }
2692
2693
2694 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry,
2695 GrowableArray<Value*>* env,
2696 GrowableArray<PhiInstr*>* live_phis) {
2697 // 1. Process phis first.
2698 if (block_entry->IsJoinEntry()) {
2699 JoinEntryInstr* join = block_entry->AsJoinEntry();
2700 if (join->phis() != NULL) {
2701 for (intptr_t i = 0; i < join->phis()->length(); ++i) {
2702 PhiInstr* phi = (*join->phis())[i];
2703 if (phi != NULL) {
2704 (*env)[i] = new UseVal(phi);
2705 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp.
2706 }
2707 }
2708 }
2709 }
2710
2711 // 2. Process normal instructions.
2712 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) {
2713 Instruction* current = it.Current();
2714 // Attach current environment to the instruction. First, each instruction
2715 // gets a full copy of the environment. Later we optimize this by
2716 // eliminating unnecessary environments.
2717 current->set_env(new Environment(*env, non_copied_parameter_count_));
2718
2719 // 2a. Handle uses:
2720 // Update expression stack environment for each use.
2721 // For each use of a LoadLocal or StoreLocal: Replace it with the value
2722 // from the environment.
2723 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) {
2724 Value* v = current->InputAt(i);
2725 if (!v->IsUse()) continue;
2726 // Update expression stack.
2727 ASSERT(env->length() > variable_count());
2728
2729 Value* input_value = env->Last();
2730 ASSERT(input_value->IsUse());
2731 env->RemoveLast();
2732
2733 BindInstr* as_bind = v->AsUse()->definition()->AsBind();
2734 if ((as_bind != NULL) &&
2735 (as_bind->computation()->IsLoadLocal() ||
2736 as_bind->computation()->IsStoreLocal())) {
2737 current->SetInputAt(i, CopyValue(input_value));
2738 }
2739 }
2740
2741 // Drop pushed arguments for calls.
2742 for (intptr_t j = 0; j < current->ArgumentCount(); j++) {
2743 env->RemoveLast();
2744 }
2745
2746 // 2b. Handle LoadLocal and StoreLocal.
2747 // For each LoadLocal: Remove it from the graph.
2748 // For each StoreLocal: Remove it from the graph and update the environment.
2749 BindInstr* bind = current->AsBind();
2750 if (bind != NULL) {
2751 LoadLocalComp* load = bind->computation()->AsLoadLocal();
2752 StoreLocalComp* store = bind->computation()->AsStoreLocal();
2753 if ((load != NULL) || (store != NULL)) {
2754 intptr_t index;
2755 if (store != NULL) {
2756 index = store->local().BitIndexIn(non_copied_parameter_count_);
2757 // Update renaming environment.
2758 (*env)[index] = store->value();
2759 } else {
2760 // The graph construction ensures we do not have an unused LoadLocal
2761 // computation.
2762 ASSERT(bind->is_used());
2763 index = load->local().BitIndexIn(non_copied_parameter_count_);
2764
2765 Value* value = (*env)[index];
2766 if (value->IsUse()) {
2767 PhiInstr* phi = value->AsUse()->definition()->AsPhi();
2768 if ((phi != NULL) && !phi->is_alive()) {
2769 phi->mark_alive();
2770 live_phis->Add(phi);
2771 }
2772 }
2773 }
2774 // Update expression stack and remove from graph.
2775 if (bind->is_used()) {
2776 env->Add(CopyValue((*env)[index]));
2777 }
2778 it.RemoveCurrentFromGraph();
2779 } else {
2780 // Not a load or store.
2781 if (bind->is_used()) {
2782 // Assign fresh SSA temporary and update expression stack.
2783 bind->set_ssa_temp_index(alloc_ssa_temp_index());
2784 env->Add(new UseVal(bind));
2785 }
2786 }
2787 }
2788
2789 // 2c. Handle pushed argument.
2790 PushArgumentInstr* push = current->AsPushArgument();
2791 if (push != NULL) {
2792 env->Add(new UseVal(push));
2793 }
2794 }
2795
2796 // 3. Process dominated blocks.
2797 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) {
2798 BlockEntryInstr* block = block_entry->dominated_blocks()[i];
2799 GrowableArray<Value*> new_env(env->length());
2800 new_env.AddArray(*env);
2801 RenameRecursive(block, &new_env, live_phis);
2802 }
2803
2804 // 4. Process successor block. We have edge-split form, so that only blocks
2805 // with one successor can have a join block as successor.
2806 if ((block_entry->last_instruction()->SuccessorCount() == 1) &&
2807 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) {
2808 JoinEntryInstr* successor =
2809 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry();
2810 intptr_t pred_index = successor->IndexOfPredecessor(block_entry);
2811 ASSERT(pred_index >= 0);
2812 if (successor->phis() != NULL) {
2813 for (intptr_t i = 0; i < successor->phis()->length(); ++i) {
2814 PhiInstr* phi = (*successor->phis())[i];
2815 if (phi != NULL) {
2816 // Rename input operand and make a copy if it is a UseVal.
2817 Value* new_val = (*env)[i]->IsUse()
2818 ? new UseVal((*env)[i]->AsUse()->definition())
2819 : (*env)[i];
2820 phi->SetInputAt(pred_index, new_val);
2821 }
2822 }
2823 }
2824 }
2825 }
2826
2827
2828 void FlowGraphBuilder::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) {
2829 while (!live_phis->is_empty()) {
2830 PhiInstr* phi = live_phis->Last();
2831 live_phis->RemoveLast();
2832 for (intptr_t i = 0; i < phi->InputCount(); i++) {
2833 Value* val = phi->InputAt(i);
2834 if (!val->IsUse()) continue;
2835 PhiInstr* used_phi = val->AsUse()->definition()->AsPhi();
2836 if ((used_phi != NULL) && !used_phi->is_alive()) {
2837 used_phi->mark_alive();
2838 live_phis->Add(used_phi);
2839 }
2840 }
2841 }
2842 }
2843
2844 void FlowGraphBuilder::Bailout(const char* reason) { 2410 void FlowGraphBuilder::Bailout(const char* reason) {
2845 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; 2411 const char* kFormat = "FlowGraphBuilder Bailout: %s %s";
2846 const char* function_name = parsed_function_.function().ToCString(); 2412 const char* function_name = parsed_function_.function().ToCString();
2847 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; 2413 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1;
2848 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); 2414 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
2849 OS::SNPrint(chars, len, kFormat, function_name, reason); 2415 OS::SNPrint(chars, len, kFormat, function_name, reason);
2850 const Error& error = Error::Handle( 2416 const Error& error = Error::Handle(
2851 LanguageError::New(String::Handle(String::New(chars)))); 2417 LanguageError::New(String::Handle(String::New(chars))));
2852 Isolate::Current()->long_jump_base()->Jump(1, error); 2418 Isolate::Current()->long_jump_base()->Jump(1, error);
2853 } 2419 }
2854 2420
2855 2421
2856 } // namespace dart 2422 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_builder.h ('k') | runtime/vm/flow_graph_compiler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698