Chromium Code Reviews| 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 2586 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2597 if (join_block->PredecessorAt(i) == predecessor) return i; | 2597 if (join_block->PredecessorAt(i) == predecessor) return i; |
| 2598 } | 2598 } |
| 2599 UNREACHABLE(); | 2599 UNREACHABLE(); |
| 2600 return -1; | 2600 return -1; |
| 2601 } | 2601 } |
| 2602 | 2602 |
| 2603 | 2603 |
| 2604 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, | 2604 void FlowGraphBuilder::RenameRecursive(BlockEntryInstr* block_entry, |
| 2605 ZoneGrowableArray<Value*>* env, | 2605 ZoneGrowableArray<Value*>* env, |
| 2606 intptr_t var_count) { | 2606 intptr_t var_count) { |
| 2607 // Iterate over instructions. | 2607 // 1. Process phis first. |
| 2608 // 1. Handle phis first. | |
| 2609 if (block_entry->IsJoinEntry()) { | 2608 if (block_entry->IsJoinEntry()) { |
| 2610 JoinEntryInstr* join = block_entry->AsJoinEntry(); | 2609 JoinEntryInstr* join = block_entry->AsJoinEntry(); |
| 2611 if (join->phis() != NULL) { | 2610 if (join->phis() != NULL) { |
| 2612 for (intptr_t i = 0; i < join->phis()->length(); ++i) { | 2611 for (intptr_t i = 0; i < join->phis()->length(); ++i) { |
| 2613 PhiInstr* phi = (*join->phis())[i]; | 2612 PhiInstr* phi = (*join->phis())[i]; |
| 2614 if (phi != NULL) { | 2613 if (phi != NULL) { |
| 2615 (*env)[i] = new UseVal(phi); | 2614 (*env)[i] = new UseVal(phi); |
| 2616 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. | 2615 phi->set_ssa_temp_index(current_ssa_temp_index_++); // New SSA temp. |
| 2617 } | 2616 } |
| 2618 } | 2617 } |
| 2619 } | 2618 } |
| 2620 } | 2619 } |
| 2621 | 2620 |
| 2622 // 2. Handle normal instructions. | 2621 // 2. Process normal instructions. |
| 2623 Instruction* current = block_entry->StraightLineSuccessor(); | 2622 Instruction* current = block_entry->StraightLineSuccessor(); |
| 2624 Instruction* prev = block_entry; | 2623 Instruction* prev = block_entry; |
| 2625 while ((current != NULL) && !current->IsBlockEntry()) { | 2624 while ((current != NULL) && !current->IsBlockEntry()) { |
| 2626 // 2a. Handle LoadLocal and StoreLocal. | 2625 // 2a. Handle uses of LoadLocal / StoreLocal |
| 2627 // LoadLocal should not be present in an effect context. | 2626 // For each use of a LoadLocal or StoreLocal: Replace it with the value |
| 2628 ASSERT(!current->IsDo() || | 2627 // from the environment. |
| 2629 !current->AsDo()->computation()->IsLoadLocal()); | |
| 2630 LoadLocalComp* load = NULL; | |
| 2631 if (current->IsBind() && | |
| 2632 current->AsBind()->computation()->IsLoadLocal()) { | |
| 2633 load = current->AsBind()->computation()->AsLoadLocal(); | |
| 2634 } | |
| 2635 StoreLocalComp* store = NULL; | |
| 2636 if (current->IsDo() && | |
| 2637 current->AsDo()->computation()->IsStoreLocal()) { | |
| 2638 store = current->AsDo()->computation()->AsStoreLocal(); | |
| 2639 } else if (current->IsBind() && | |
| 2640 current->AsBind()->computation()->IsStoreLocal()) { | |
| 2641 store = current->AsBind()->computation()->AsStoreLocal(); | |
| 2642 } | |
| 2643 | |
| 2644 if ((load != NULL) || (store != NULL)) { | |
| 2645 // Remove instruction with LoadLocal or StoreLocal. | |
| 2646 prev->SetSuccessor(current->StraightLineSuccessor()); | |
| 2647 // Update renaming environment for StoreLocal. | |
| 2648 if (store != NULL) { | |
| 2649 (*env)[store->local().BitIndexIn(var_count)] = store->value(); | |
| 2650 } | |
| 2651 } else { | |
| 2652 // Assign new SSA temporary. | |
| 2653 if (current->IsBind()) { | |
| 2654 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); | |
| 2655 } | |
| 2656 } | |
| 2657 | |
| 2658 // 2b. Handle uses of LoadLocal / StoreLocal | |
| 2659 for (intptr_t i = 0; i < current->InputCount(); ++i) { | 2628 for (intptr_t i = 0; i < current->InputCount(); ++i) { |
| 2660 // For each use of a LoadLocal/StoreLocal: Replace it with the definition | |
| 2661 // from the environment. | |
| 2662 Value* v = current->InputAt(i); | 2629 Value* v = current->InputAt(i); |
| 2663 if (v->IsUse() && | 2630 if (v->IsUse() && |
| 2664 v->AsUse()->definition()->IsBind() && | 2631 v->AsUse()->definition()->IsBind() && |
| 2665 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { | 2632 v->AsUse()->definition()->AsBind()->computation()->IsLoadLocal()) { |
| 2666 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2633 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); |
| 2667 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); | 2634 intptr_t index = comp->AsLoadLocal()->local().BitIndexIn(var_count); |
| 2668 Value* new_value = (*env)[index]; | 2635 Value* new_value = (*env)[index]; |
| 2669 // Make a copy if it is a UseVal. | 2636 // Make a copy if it is a UseVal. |
| 2670 if (new_value->IsUse()) { | 2637 if (new_value->IsUse()) { |
| 2671 new_value = new UseVal(new_value->AsUse()->definition()); | 2638 new_value = new UseVal(new_value->AsUse()->definition()); |
| 2672 } | 2639 } |
| 2673 current->SetInputAt(i, new_value); | 2640 current->SetInputAt(i, new_value); |
| 2674 } | 2641 } |
| 2675 if (v->IsUse() && | 2642 if (v->IsUse() && |
| 2676 v->AsUse()->definition()->IsBind() && | 2643 v->AsUse()->definition()->IsBind() && |
| 2677 v->AsUse()->definition()->AsBind()->computation()->IsStoreLocal()) { | 2644 v->AsUse()->definition()->AsBind()->computation()->IsStoreLocal()) { |
| 2678 // For each use of a LoadLocal: Replace LoadLocal with the definition | 2645 // For each use of a StoreLocal: Replace it with the value from the |
| 2679 // from the enviroment. | 2646 // enviroment. |
|
srdjan
2012/06/19 16:45:06
s/enviroment/environment/
Florian Schneider
2012/06/21 08:15:47
Done.
| |
| 2680 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); | 2647 Computation* comp = v->AsUse()->definition()->AsBind()->computation(); |
| 2681 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); | 2648 intptr_t index = comp->AsStoreLocal()->local().BitIndexIn(var_count); |
| 2682 Value* new_value = (*env)[index]; | 2649 Value* new_value = (*env)[index]; |
| 2683 // Make a copy if it is a UseVal. | 2650 // Make a copy if it is a UseVal. |
| 2684 if (new_value->IsUse()) { | 2651 if (new_value->IsUse()) { |
| 2685 new_value = new UseVal(new_value->AsUse()->definition()); | 2652 new_value = new UseVal(new_value->AsUse()->definition()); |
| 2686 } | 2653 } |
| 2687 current->SetInputAt(i, new_value); | 2654 current->SetInputAt(i, new_value); |
| 2688 } | 2655 } |
| 2689 } | 2656 } |
| 2690 | 2657 |
| 2691 // Update previous only if no instruction was removed from the graph. | 2658 // 2b. Handle LoadLocal and StoreLocal. |
| 2692 if ((load == NULL) && (store == NULL)) { | 2659 // For each LoadLocal: Remove it from the graph. |
| 2660 // For each StoreLocal: Remove it from the graph and update the environment. | |
| 2661 ASSERT(!current->IsDo() || | |
| 2662 !current->AsDo()->computation()->IsLoadLocal()); // Not possible. | |
| 2663 LoadLocalComp* load = NULL; | |
| 2664 if (current->IsBind() && | |
| 2665 current->AsBind()->computation()->IsLoadLocal()) { | |
| 2666 load = current->AsBind()->computation()->AsLoadLocal(); | |
| 2667 } | |
| 2668 StoreLocalComp* store = NULL; | |
| 2669 if (current->IsDo() && | |
| 2670 current->AsDo()->computation()->IsStoreLocal()) { | |
| 2671 store = current->AsDo()->computation()->AsStoreLocal(); | |
| 2672 } else if (current->IsBind() && | |
| 2673 current->AsBind()->computation()->IsStoreLocal()) { | |
| 2674 store = current->AsBind()->computation()->AsStoreLocal(); | |
| 2675 } | |
| 2676 | |
| 2677 if ((load != NULL) || (store != NULL)) { | |
|
srdjan
2012/06/19 16:45:06
I think it would be more readable if you split it
Florian Schneider
2012/06/21 08:15:47
Done.
| |
| 2678 // Remove instruction with LoadLocal or StoreLocal. | |
| 2679 prev->SetSuccessor(current->StraightLineSuccessor()); | |
| 2680 // Update renaming environment for StoreLocal. | |
| 2681 if (store != NULL) { | |
| 2682 (*env)[store->local().BitIndexIn(var_count)] = store->value(); | |
| 2683 } | |
| 2684 } else { | |
| 2685 // Assign new SSA temporary. | |
| 2686 if (current->IsBind()) { | |
| 2687 current->AsDefinition()->set_ssa_temp_index(current_ssa_temp_index_++); | |
| 2688 } | |
| 2689 // Update previous only if no instruction was removed from the graph. | |
| 2693 prev = current; | 2690 prev = current; |
| 2694 } | 2691 } |
| 2695 current = current->StraightLineSuccessor(); | 2692 current = current->StraightLineSuccessor(); |
| 2696 } | 2693 } |
| 2697 | 2694 |
| 2698 // 3. Process dominated blocks. | 2695 // 3. Process dominated blocks. |
| 2699 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { | 2696 for (intptr_t i = 0; i < block_entry->dominated_blocks().length(); ++i) { |
| 2700 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; | 2697 BlockEntryInstr* block = block_entry->dominated_blocks()[i]; |
| 2701 ZoneGrowableArray<Value*>* new_env = | 2698 ZoneGrowableArray<Value*>* new_env = |
| 2702 new ZoneGrowableArray<Value*>(var_count); | 2699 new ZoneGrowableArray<Value*>(var_count); |
| 2703 new_env->AddArray(*env); | 2700 new_env->AddArray(*env); |
| 2704 RenameRecursive(block, new_env, var_count); | 2701 RenameRecursive(block, new_env, var_count); |
| 2705 } | 2702 } |
| 2706 | 2703 |
| 2707 // 4. Process successor block. We have edge-split form, so that only blocks | 2704 // 4. Process successor block. We have edge-split form, so that only blocks |
| 2708 // with one successor can have a join block as successor. | 2705 // with one successor can have a join block as successor. |
| 2709 if ((block_entry->last_instruction()->SuccessorCount() == 1) && | 2706 if ((block_entry->last_instruction()->SuccessorCount() == 1) && |
| 2710 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { | 2707 block_entry->last_instruction()->SuccessorAt(0)->IsJoinEntry()) { |
| 2711 JoinEntryInstr* successor = | 2708 JoinEntryInstr* successor = |
| 2712 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); | 2709 block_entry->last_instruction()->SuccessorAt(0)->AsJoinEntry(); |
| 2713 intptr_t pred_index = WhichPred(block_entry, successor); | 2710 intptr_t pred_index = WhichPred(block_entry, successor); |
| 2714 if (successor->phis() != NULL) { | 2711 if (successor->phis() != NULL) { |
| 2715 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { | 2712 for (intptr_t i = 0; i < successor->phis()->length(); ++i) { |
| 2716 PhiInstr* phi = (*successor->phis())[i]; | 2713 PhiInstr* phi = (*successor->phis())[i]; |
| 2717 if (phi != NULL) phi->SetInputAt(pred_index, (*env)[i]); | 2714 if (phi != NULL) { |
| 2715 // Rename input operand and make a copy if it is a UseVal. | |
|
srdjan
2012/06/19 16:45:06
Indent comment
Florian Schneider
2012/06/21 08:15:47
Done.
| |
| 2716 Value* new_val = (*env)[i]->IsUse() | |
| 2717 ? new UseVal((*env)[i]->AsUse()->definition()) | |
| 2718 : (*env)[i]; | |
| 2719 phi->SetInputAt(pred_index, new_val); | |
| 2720 } | |
| 2718 } | 2721 } |
| 2719 } | 2722 } |
| 2720 } | 2723 } |
| 2721 } | 2724 } |
| 2722 | 2725 |
| 2723 | 2726 |
| 2724 void FlowGraphBuilder::Bailout(const char* reason) { | 2727 void FlowGraphBuilder::Bailout(const char* reason) { |
| 2725 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; | 2728 const char* kFormat = "FlowGraphBuilder Bailout: %s %s"; |
| 2726 const char* function_name = parsed_function_.function().ToCString(); | 2729 const char* function_name = parsed_function_.function().ToCString(); |
| 2727 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; | 2730 intptr_t len = OS::SNPrint(NULL, 0, kFormat, function_name, reason) + 1; |
| 2728 char* chars = reinterpret_cast<char*>( | 2731 char* chars = reinterpret_cast<char*>( |
| 2729 Isolate::Current()->current_zone()->Allocate(len)); | 2732 Isolate::Current()->current_zone()->Allocate(len)); |
| 2730 OS::SNPrint(chars, len, kFormat, function_name, reason); | 2733 OS::SNPrint(chars, len, kFormat, function_name, reason); |
| 2731 const Error& error = Error::Handle( | 2734 const Error& error = Error::Handle( |
| 2732 LanguageError::New(String::Handle(String::New(chars)))); | 2735 LanguageError::New(String::Handle(String::New(chars)))); |
| 2733 Isolate::Current()->long_jump_base()->Jump(1, error); | 2736 Isolate::Current()->long_jump_base()->Jump(1, error); |
| 2734 } | 2737 } |
| 2735 | 2738 |
| 2736 | 2739 |
| 2737 } // namespace dart | 2740 } // namespace dart |
| OLD | NEW |