| 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 2324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2335 } | 2335 } |
| 2336 } | 2336 } |
| 2337 } | 2337 } |
| 2338 | 2338 |
| 2339 if (for_optimized && use_ssa) { | 2339 if (for_optimized && use_ssa) { |
| 2340 GrowableArray<BitVector*> dominance_frontier; | 2340 GrowableArray<BitVector*> dominance_frontier; |
| 2341 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); | 2341 ComputeDominators(&preorder_block_entries_, &parent, &dominance_frontier); |
| 2342 InsertPhis(preorder_block_entries_, | 2342 InsertPhis(preorder_block_entries_, |
| 2343 assigned_vars, | 2343 assigned_vars, |
| 2344 dominance_frontier); | 2344 dominance_frontier); |
| 2345 Rename(); | 2345 |
| 2346 GrowableArray<PhiInstr*> live_phis; |
| 2347 |
| 2348 // Rename uses to reference inserted phis where appropriate. |
| 2349 // Collect phis that reach a non-environment use. |
| 2350 Rename(&live_phis); |
| 2351 |
| 2352 // Propagate alive mark transitively from alive phis. |
| 2353 MarkLivePhis(&live_phis); |
| 2346 } | 2354 } |
| 2347 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { | 2355 if (FLAG_print_flow_graph || (Dart::flow_graph_writer() != NULL)) { |
| 2348 intptr_t length = postorder_block_entries_.length(); | 2356 intptr_t length = postorder_block_entries_.length(); |
| 2349 GrowableArray<BlockEntryInstr*> reverse_postorder(length); | 2357 GrowableArray<BlockEntryInstr*> reverse_postorder(length); |
| 2350 for (intptr_t i = length - 1; i >= 0; --i) { | 2358 for (intptr_t i = length - 1; i >= 0; --i) { |
| 2351 reverse_postorder.Add(postorder_block_entries_[i]); | 2359 reverse_postorder.Add(postorder_block_entries_[i]); |
| 2352 } | 2360 } |
| 2353 if (FLAG_print_flow_graph) { | 2361 if (FLAG_print_flow_graph) { |
| 2354 // Print flow graph to stdout. | 2362 // Print flow graph to stdout. |
| 2355 FlowGraphPrinter printer(function, reverse_postorder); | 2363 FlowGraphPrinter printer(function, reverse_postorder); |
| (...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2536 work[index] = var_index; | 2544 work[index] = var_index; |
| 2537 worklist.Add(block); | 2545 worklist.Add(block); |
| 2538 } | 2546 } |
| 2539 } | 2547 } |
| 2540 } | 2548 } |
| 2541 } | 2549 } |
| 2542 } | 2550 } |
| 2543 } | 2551 } |
| 2544 | 2552 |
| 2545 | 2553 |
| 2546 void FlowGraphBuilder::Rename() { | 2554 void FlowGraphBuilder::Rename(GrowableArray<PhiInstr*>* live_phis) { |
| 2547 // TODO(fschneider): Support catch-entry. | 2555 // TODO(fschneider): Support catch-entry. |
| 2548 if (graph_entry_->SuccessorCount() > 1) { | 2556 if (graph_entry_->SuccessorCount() > 1) { |
| 2549 Bailout("Catch-entry support in SSA."); | 2557 Bailout("Catch-entry support in SSA."); |
| 2550 } | 2558 } |
| 2551 | 2559 |
| 2552 // Initialize start environment. | 2560 // Initialize start environment. |
| 2553 GrowableArray<Value*> start_env(variable_count()); | 2561 GrowableArray<Value*> start_env(variable_count()); |
| 2554 for (intptr_t i = 0; i < parameter_count(); ++i) { | 2562 for (intptr_t i = 0; i < parameter_count(); ++i) { |
| 2555 ParameterInstr* param = new ParameterInstr(i); | 2563 ParameterInstr* param = new ParameterInstr(i); |
| 2556 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 2564 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 2557 start_env.Add(new UseVal(param)); | 2565 start_env.Add(new UseVal(param)); |
| 2558 } | 2566 } |
| 2559 | 2567 |
| 2560 // All locals are initialized with #null. | 2568 // All locals are initialized with #null. |
| 2561 Value* null_value = new ConstantVal(Object::ZoneHandle()); | 2569 Value* null_value = new ConstantVal(Object::ZoneHandle()); |
| 2562 while (start_env.length() < variable_count()) { | 2570 while (start_env.length() < variable_count()) { |
| 2563 start_env.Add(null_value); | 2571 start_env.Add(null_value); |
| 2564 } | 2572 } |
| 2565 graph_entry_->set_start_env( | 2573 graph_entry_->set_start_env( |
| 2566 new Environment(start_env, non_copied_parameter_count_)); | 2574 new Environment(start_env, non_copied_parameter_count_)); |
| 2567 | 2575 |
| 2568 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); | 2576 BlockEntryInstr* normal_entry = graph_entry_->SuccessorAt(0); |
| 2569 ASSERT(normal_entry != NULL); // Must have entry. | 2577 ASSERT(normal_entry != NULL); // Must have entry. |
| 2570 GrowableArray<Value*> env(variable_count()); | 2578 GrowableArray<Value*> env(variable_count()); |
| 2571 env.AddArray(start_env); | 2579 env.AddArray(start_env); |
| 2572 RenameRecursive(normal_entry, &env); | 2580 RenameRecursive(normal_entry, &env, live_phis); |
| 2573 } | 2581 } |
| 2574 | 2582 |
| 2575 | 2583 |
| 2576 // Helper to a copy a value iff it is a UseVal. | 2584 // Helper to a copy a value iff it is a UseVal. |
| 2577 static Value* CopyValue(Value* value) { | 2585 static Value* CopyValue(Value* value) { |
| 2578 return value->IsUse() | 2586 return value->IsUse() |
| 2579 ? new UseVal(value->AsUse()->definition()) | 2587 ? new UseVal(value->AsUse()->definition()) |
| 2580 : value; | 2588 : value; |
| 2581 } | 2589 } |
| 2582 | 2590 |
| 2583 | 2591 |
| 2584 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, | 2592 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, |
| 2585 GrowableArray<Value*>* env) { | 2593 GrowableArray<Value*>* env, |
| 2594 GrowableArray<PhiInstr*>* live_phis) { |
| 2586 // 1. Process phis first. | 2595 // 1. Process phis first. |
| 2587 if (block_entry->IsJoinEntry()) { | 2596 if (block_entry->IsJoinEntry()) { |
| 2588 JoinEntryInstr* join = block_entry->AsJoinEntry(); | 2597 JoinEntryInstr* join = block_entry->AsJoinEntry(); |
| 2589 if (join->phis() != NULL) { | 2598 if (join->phis() != NULL) { |
| 2590 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 2599 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
| 2591 PhiInstr* phi = (*join->phis())[i]; | 2600 PhiInstr* phi = (*join->phis())[i]; |
| 2592 if (phi != NULL) { | 2601 if (phi != NULL) { |
| 2593 (*env)[i] = new UseVal(phi); | 2602 (*env)[i] = new UseVal(phi); |
| 2594 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 2603 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 2595 } | 2604 } |
| 2596 } | 2605 } |
| 2597 } | 2606 } |
| 2598 } | 2607 } |
| 2599 | 2608 |
| 2600 // 2. Process normal instructions. | 2609 // 2. Process normal instructions. |
| 2601 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { | 2610 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { |
| 2602 Instruction* current = it.Current(); | 2611 Instruction* current = it.Current(); |
| 2603 // Attach current environment to the instruction. First, each instruction | 2612 // Attach current environment to the instruction. First, each instruction |
| 2604 // gets a full copy of the environment. Later we optimize this by | 2613 // gets a full copy of the environment. Later we optimize this by |
| 2605 // eliminating unnecessary environments. | 2614 // eliminating unnecessary environments. |
| 2606 current->set_env(new Environment(*env, non_copied_parameter_count_)); | 2615 current->set_env(new Environment(*env, non_copied_parameter_count_)); |
| 2607 | 2616 |
| 2608 // 2a. Handle uses: | 2617 // 2a. Handle uses: |
| 2609 // Update expression stack environment for each use. | 2618 // Update expression stack environment for each use. |
| 2610 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 2619 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
| 2611 // from the environment. | 2620 // from the environment. |
| 2612 for (intptr_t i = 0; i < current->InputCount(); ++i) { | 2621 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { |
| 2613 Value* v = current->InputAt(i); | 2622 Value* v = current->InputAt(i); |
| 2614 if (!v->IsUse()) continue; | 2623 if (!v->IsUse()) continue; |
| 2615 // Update expression stack. | 2624 // Update expression stack. |
| 2616 ASSERT(env->length() > variable_count()); | 2625 ASSERT(env->length() > variable_count()); |
| 2626 |
| 2627 Value* input_value = env->Last(); |
| 2628 ASSERT(input_value->IsUse()); |
| 2617 env->RemoveLast(); | 2629 env->RemoveLast(); |
| 2630 |
| 2618 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); | 2631 BindInstr* as_bind = v->AsUse()->definition()->AsBind(); |
| 2619 if ((as_bind != NULL) && as_bind->computation()->IsLoadLocal()) { | 2632 if ((as_bind != NULL) && |
| 2620 Computation* comp = as_bind->computation(); | 2633 (as_bind->computation()->IsLoadLocal() || |
| 2621 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn( | 2634 as_bind->computation()->IsStoreLocal())) { |
| 2622 non_copied_parameter_count_); | 2635 current->SetInputAt(i, CopyValue(input_value)); |
| 2623 current->SetInputAt(i, CopyValue((*env)[index])); | |
| 2624 } | |
| 2625 if ((as_bind != NULL) && as_bind->computation()->IsStoreLocal()) { | |
| 2626 // For each use of a StoreLocal: Replace it with the value from the | |
| 2627 // environment. | |
| 2628 Computation* comp = as_bind->computation(); | |
| 2629 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn( | |
| 2630 non_copied_parameter_count_); | |
| 2631 current->SetInputAt(i, CopyValue((*env)[index])); | |
| 2632 } | 2636 } |
| 2633 } | 2637 } |
| 2634 | 2638 |
| 2635 // Drop pushed arguments for calls. | 2639 // Drop pushed arguments for calls. |
| 2636 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { | 2640 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { |
| 2637 env->RemoveLast(); | 2641 env->RemoveLast(); |
| 2638 } | 2642 } |
| 2639 | 2643 |
| 2640 // 2b. Handle LoadLocal and StoreLocal. | 2644 // 2b. Handle LoadLocal and StoreLocal. |
| 2641 // For each LoadLocal: Remove it from the graph. | 2645 // For each LoadLocal: Remove it from the graph. |
| 2642 // For each StoreLocal: Remove it from the graph and update the environment. | 2646 // For each StoreLocal: Remove it from the graph and update the environment. |
| 2643 BindInstr* bind = current->AsBind(); | 2647 BindInstr* bind = current->AsBind(); |
| 2644 if (bind != NULL) { | 2648 if (bind != NULL) { |
| 2645 LoadLocalComp* load = bind->computation()->AsLoadLocal(); | 2649 LoadLocalComp* load = bind->computation()->AsLoadLocal(); |
| 2646 StoreLocalComp* store = bind->computation()->AsStoreLocal(); | 2650 StoreLocalComp* store = bind->computation()->AsStoreLocal(); |
| 2647 if ((load != NULL) || (store != NULL)) { | 2651 if ((load != NULL) || (store != NULL)) { |
| 2648 intptr_t index; | 2652 intptr_t index; |
| 2649 if (store != NULL) { | 2653 if (store != NULL) { |
| 2650 index = store->local().BitIndexIn(non_copied_parameter_count_); | 2654 index = store->local().BitIndexIn(non_copied_parameter_count_); |
| 2651 // Update renaming environment. | 2655 // Update renaming environment. |
| 2652 (*env)[index] = store->value(); | 2656 (*env)[index] = store->value(); |
| 2653 } else { | 2657 } else { |
| 2654 // The graph construction ensures we do not have an unused LoadLocal | 2658 // The graph construction ensures we do not have an unused LoadLocal |
| 2655 // computation. | 2659 // computation. |
| 2656 ASSERT(bind->is_used()); | 2660 ASSERT(bind->is_used()); |
| 2657 index = load->local().BitIndexIn(non_copied_parameter_count_); | 2661 index = load->local().BitIndexIn(non_copied_parameter_count_); |
| 2662 |
| 2663 Value* value = (*env)[index]; |
| 2664 if (value->IsUse()) { |
| 2665 PhiInstr* phi = value->AsUse()->definition()->AsPhi(); |
| 2666 if ((phi != NULL) && !phi->is_alive()) { |
| 2667 phi->mark_alive(); |
| 2668 live_phis->Add(phi); |
| 2669 } |
| 2670 } |
| 2658 } | 2671 } |
| 2659 // Update expression stack and remove from graph. | 2672 // Update expression stack and remove from graph. |
| 2660 if (bind->is_used()) { | 2673 if (bind->is_used()) { |
| 2661 env->Add(CopyValue((*env)[index])); | 2674 env->Add(CopyValue((*env)[index])); |
| 2662 } | 2675 } |
| 2663 it.RemoveCurrentFromGraph(); | 2676 it.RemoveCurrentFromGraph(); |
| 2664 } else { | 2677 } else { |
| 2665 // Not a load or store. | 2678 // Not a load or store. |
| 2666 if (bind->is_used()) { | 2679 if (bind->is_used()) { |
| 2667 // Assign fresh SSA temporary and update expression stack. | 2680 // Assign fresh SSA temporary and update expression stack. |
| 2668 bind->set_ssa_temp_index(alloc_ssa_temp_index()); | 2681 bind->set_ssa_temp_index(alloc_ssa_temp_index()); |
| 2669 env->Add(new UseVal(bind)); | 2682 env->Add(new UseVal(bind)); |
| 2670 } | 2683 } |
| 2671 } | 2684 } |
| 2672 } | 2685 } |
| 2673 | 2686 |
| 2674 // 2c. Handle pushed argument. | 2687 // 2c. Handle pushed argument. |
| 2675 PushArgumentInstr* push = current->AsPushArgument(); | 2688 PushArgumentInstr* push = current->AsPushArgument(); |
| 2676 if (push != NULL) { | 2689 if (push != NULL) { |
| 2677 env->Add(push->value()); | 2690 env->Add(push->value()); |
| 2678 } | 2691 } |
| 2679 } | 2692 } |
| 2680 | 2693 |
| 2681 // 3. Process dominated blocks. | 2694 // 3. Process dominated blocks. |
| 2682 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { | 2695 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { |
| 2683 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; | 2696 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; |
| 2684 GrowableArray<Value*> new_env(env->length()); | 2697 GrowableArray<Value*> new_env(env->length()); |
| 2685 new_env.AddArray(*env); | 2698 new_env.AddArray(*env); |
| 2686 RenameRecursive(block, &new_env); | 2699 RenameRecursive(block, &new_env, live_phis); |
| 2687 } | 2700 } |
| 2688 | 2701 |
| 2689 // 4. Process successor block. We have edge-split form, so that only blocks | 2702 // 4. Process successor block. We have edge-split form, so that only blocks |
| 2690 // with one successor can have a join block as successor. | 2703 // with one successor can have a join block as successor. |
| 2691 if ((block_entry->last_instruction()->SuccessorCount() == 1) && | 2704 if ((block_entry->last_instruction()->SuccessorCount() == 1) && |
| 2692 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { | 2705 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { |
| 2693 JoinEntryInstr* successor = | 2706 JoinEntryInstr* successor = |
| 2694 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); | 2707 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); |
| 2695 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); | 2708 intptr_t pred_index = successor->IndexOfPredecessor(block_entry); |
| 2696 ASSERT(pred_index >= 0); | 2709 ASSERT(pred_index >= 0); |
| 2697 if (successor->phis() != NULL) { | 2710 if (successor->phis() != NULL) { |
| 2698 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { | 2711 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { |
| 2699 PhiInstr* phi = (*successor->phis())[i]; | 2712 PhiInstr* phi = (*successor->phis())[i]; |
| 2700 if (phi != NULL) { | 2713 if (phi != NULL) { |
| 2701 // Rename input operand and make a copy if it is a UseVal. | 2714 // Rename input operand and make a copy if it is a UseVal. |
| 2702 Value* new_val = (*env)[i]->IsUse() | 2715 Value* new_val = (*env)[i]->IsUse() |
| 2703 ? new UseVal((*env)[i]->AsUse()->definition()) | 2716 ? new UseVal((*env)[i]->AsUse()->definition()) |
| 2704 : (*env)[i]; | 2717 : (*env)[i]; |
| 2705 phi->SetInputAt(pred_index, new_val); | 2718 phi->SetInputAt(pred_index, new_val); |
| 2706 } | 2719 } |
| 2707 } | 2720 } |
| 2708 } | 2721 } |
| 2709 } | 2722 } |
| 2710 } | 2723 } |
| 2711 | 2724 |
| 2712 | 2725 |
| 2726 void FlowGraphBuilder::MarkLivePhis(GrowableArray<PhiInstr*>* live_phis) { |
| 2727 while (!live_phis->is_empty()) { |
| 2728 PhiInstr* phi = live_phis->Last(); |
| 2729 live_phis->RemoveLast(); |
| 2730 for (intptr_t i = 0; i < phi->InputCount(); i++) { |
| 2731 Value* val = phi->InputAt(i); |
| 2732 if (!val->IsUse()) continue; |
| 2733 PhiInstr* used_phi = val->AsUse()->definition()->AsPhi(); |
| 2734 if ((used_phi != NULL) && !used_phi->is_alive()) { |
| 2735 used_phi->mark_alive(); |
| 2736 live_phis->Add(used_phi); |
| 2737 } |
| 2738 } |
| 2739 } |
| 2740 } |
| 2741 |
| 2713 void FlowGraphBuilder::Bailout(const char* reason) { | 2742 void FlowGraphBuilder::Bailout(const char* reason) { |
| 2714 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 2743 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 2715 const char* function_name = parsed_function_.function().ToCString(); | 2744 const char* function_name = parsed_function_.function().ToCString(); |
| 2716 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2745 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 2717 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 2746 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 2718 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2747 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2719 const Error& error = Error::Handle( | 2748 const Error& error = Error::Handle( |
| 2720 LanguageError::New(String::Handle(String::New(chars)))); | 2749 LanguageError::New(String::Handle(String::New(chars)))); |
| 2721 Isolate::Current()->long_jump_base()->Jump(1, error); | 2750 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2722 } | 2751 } |
| 2723 | 2752 |
| 2724 | 2753 |
| 2725 } // namespace dart | 2754 } // namespace dart |
| OLD | NEW |