| 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.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" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 num_stack_locals_(builder.num_stack_locals()), | 27 num_stack_locals_(builder.num_stack_locals()), |
| 28 graph_entry_(graph_entry), | 28 graph_entry_(graph_entry), |
| 29 preorder_(), | 29 preorder_(), |
| 30 postorder_(), | 30 postorder_(), |
| 31 reverse_postorder_(), | 31 reverse_postorder_(), |
| 32 block_effects_(NULL) { | 32 block_effects_(NULL) { |
| 33 DiscoverBlocks(); | 33 DiscoverBlocks(); |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 ConstantInstr* FlowGraph::AddConstantToInitialDefinitions( | 37 ConstantInstr* FlowGraph::GetConstant(const Object& object) { |
| 38 const Object& object) { | |
| 39 // Check if the constant is already in the pool. | 38 // Check if the constant is already in the pool. |
| 40 for (intptr_t i = 0; i < graph_entry_->initial_definitions()->length(); ++i) { | 39 GrowableArray<Definition*>* pool = graph_entry_->initial_definitions(); |
| 41 ConstantInstr* constant = | 40 for (intptr_t i = 0; i < pool->length(); ++i) { |
| 42 (*graph_entry_->initial_definitions())[i]->AsConstant(); | 41 ConstantInstr* constant = (*pool)[i]->AsConstant(); |
| 43 if ((constant != NULL) && (constant->value().raw() == object.raw())) { | 42 if ((constant != NULL) && (constant->value().raw() == object.raw())) { |
| 44 return constant; | 43 return constant; |
| 45 } | 44 } |
| 46 } | 45 } |
| 47 // Otherwise, allocate and add it to the pool. | 46 // Otherwise, allocate and add it to the pool. |
| 48 ConstantInstr* constant = new ConstantInstr(object); | 47 ConstantInstr* constant = new ConstantInstr(object); |
| 49 constant->set_ssa_temp_index(alloc_ssa_temp_index()); | 48 constant->set_ssa_temp_index(alloc_ssa_temp_index()); |
| 50 AddToInitialDefinitions(constant); | 49 AddToInitialDefinitions(constant); |
| 51 return constant; | 50 return constant; |
| 52 } | 51 } |
| 53 | 52 |
| 53 |
| 54 void FlowGraph::AddToInitialDefinitions(Definition* defn) { | 54 void FlowGraph::AddToInitialDefinitions(Definition* defn) { |
| 55 // TODO(zerny): Set previous to the graph entry so it is accessible by | 55 // TODO(zerny): Set previous to the graph entry so it is accessible by |
| 56 // GetBlock. Remove this once there is a direct pointer to the block. | 56 // GetBlock. Remove this once there is a direct pointer to the block. |
| 57 defn->set_previous(graph_entry_); | 57 defn->set_previous(graph_entry_); |
| 58 graph_entry_->initial_definitions()->Add(defn); | 58 graph_entry_->initial_definitions()->Add(defn); |
| 59 } | 59 } |
| 60 | 60 |
| 61 | 61 |
| 62 void FlowGraph::InsertBefore(Instruction* next, | 62 void FlowGraph::InsertBefore(Instruction* next, |
| 63 Instruction* instr, | 63 Instruction* instr, |
| (...skipping 554 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 ZoneGrowableArray<Definition*>* inlining_parameters) { | 618 ZoneGrowableArray<Definition*>* inlining_parameters) { |
| 619 // TODO(fschneider): Support catch-entry. | 619 // TODO(fschneider): Support catch-entry. |
| 620 if (graph_entry_->SuccessorCount() > 1) { | 620 if (graph_entry_->SuccessorCount() > 1) { |
| 621 Bailout("Catch-entry support in SSA."); | 621 Bailout("Catch-entry support in SSA."); |
| 622 } | 622 } |
| 623 | 623 |
| 624 // Initial renaming environment. | 624 // Initial renaming environment. |
| 625 GrowableArray<Definition*> env(variable_count()); | 625 GrowableArray<Definition*> env(variable_count()); |
| 626 | 626 |
| 627 // Add global constants to the initial definitions. | 627 // Add global constants to the initial definitions. |
| 628 constant_null_ = | 628 constant_null_ = GetConstant(Object::ZoneHandle()); |
| 629 AddConstantToInitialDefinitions(Object::ZoneHandle()); | |
| 630 | 629 |
| 631 // Add parameters to the initial definitions and renaming environment. | 630 // Add parameters to the initial definitions and renaming environment. |
| 632 if (inlining_parameters != NULL) { | 631 if (inlining_parameters != NULL) { |
| 633 // Use known parameters. | 632 // Use known parameters. |
| 634 ASSERT(parameter_count() == inlining_parameters->length()); | 633 ASSERT(parameter_count() == inlining_parameters->length()); |
| 635 for (intptr_t i = 0; i < parameter_count(); ++i) { | 634 for (intptr_t i = 0; i < parameter_count(); ++i) { |
| 636 Definition* defn = (*inlining_parameters)[i]; | 635 Definition* defn = (*inlining_parameters)[i]; |
| 637 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 636 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 638 AddToInitialDefinitions(defn); | 637 AddToInitialDefinitions(defn); |
| 639 env.Add(defn); | 638 env.Add(defn); |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 691 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 690 phi->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 692 } | 691 } |
| 693 } | 692 } |
| 694 } | 693 } |
| 695 } | 694 } |
| 696 | 695 |
| 697 // Attach environment to the block entry. | 696 // Attach environment to the block entry. |
| 698 AttachEnvironment(block_entry, env); | 697 AttachEnvironment(block_entry, env); |
| 699 | 698 |
| 700 // 2. Process normal instructions. | 699 // 2. Process normal instructions. |
| 701 | |
| 702 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { | 700 for (ForwardInstructionIterator it(block_entry); !it.Done(); it.Advance()) { |
| 703 Instruction* current = it.Current(); | 701 Instruction* current = it.Current(); |
| 704 | 702 |
| 705 // Attach current environment to the instructions that need it. | 703 // Attach current environment to the instructions that need it. |
| 706 if (current->NeedsEnvironment()) { | 704 if (current->NeedsEnvironment()) { |
| 707 AttachEnvironment(current, env); | 705 AttachEnvironment(current, env); |
| 708 } | 706 } |
| 709 | 707 |
| 710 // 2a. Handle uses: | 708 // 2a. Handle uses: |
| 711 // Update expression stack environment for each use. | 709 // Update the expression stack renaming environment for each use by |
| 712 // For each use of a LoadLocal or StoreLocal: Replace it with the value | 710 // removing the renamed value. |
| 713 // from the environment. | 711 // For each use of a LoadLocal, StoreLocal, or Constant: Replace it with |
| 712 // the renamed value. |
| 714 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { | 713 for (intptr_t i = current->InputCount() - 1; i >= 0; --i) { |
| 715 Value* v = current->InputAt(i); | 714 Value* v = current->InputAt(i); |
| 716 // Update expression stack. | 715 // Update expression stack. |
| 717 ASSERT(env->length() > variable_count()); | 716 ASSERT(env->length() > variable_count()); |
| 718 | 717 |
| 719 Definition* reaching_defn = env->RemoveLast(); | 718 Definition* reaching_defn = env->RemoveLast(); |
| 720 | |
| 721 Definition* input_defn = v->definition(); | 719 Definition* input_defn = v->definition(); |
| 722 if (input_defn->IsLoadLocal() || input_defn->IsStoreLocal()) { | 720 if (input_defn->IsLoadLocal() || |
| 721 input_defn->IsStoreLocal() || |
| 722 input_defn->IsConstant()) { |
| 723 // Remove the load/store from the graph. | 723 // Remove the load/store from the graph. |
| 724 input_defn->RemoveFromGraph(); | 724 input_defn->RemoveFromGraph(); |
| 725 // Assert we are not referencing nulls in the initial environment. | 725 // Assert we are not referencing nulls in the initial environment. |
| 726 ASSERT(reaching_defn->ssa_temp_index() != -1); | 726 ASSERT(reaching_defn->ssa_temp_index() != -1); |
| 727 v->set_definition(reaching_defn); | 727 v->set_definition(reaching_defn); |
| 728 input_defn = reaching_defn; | 728 input_defn = reaching_defn; |
| 729 } | 729 } |
| 730 input_defn->AddInputUse(v); | 730 input_defn->AddInputUse(v); |
| 731 } | 731 } |
| 732 | 732 |
| 733 // Drop pushed arguments for calls. | 733 // Drop pushed arguments for calls. |
| 734 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { | 734 for (intptr_t j = 0; j < current->ArgumentCount(); j++) { |
| 735 env->RemoveLast(); | 735 env->RemoveLast(); |
| 736 } | 736 } |
| 737 | 737 |
| 738 // 2b. Handle LoadLocal and StoreLocal. | 738 // 2b. Handle LoadLocal, StoreLocal, and Constant. |
| 739 // For each LoadLocal: Remove it from the graph. | |
| 740 // For each StoreLocal: Remove it from the graph and update the environment. | |
| 741 Definition* definition = current->AsDefinition(); | 739 Definition* definition = current->AsDefinition(); |
| 742 if (definition != NULL) { | 740 if (definition != NULL) { |
| 743 LoadLocalInstr* load = definition->AsLoadLocal(); | 741 LoadLocalInstr* load = definition->AsLoadLocal(); |
| 744 StoreLocalInstr* store = definition->AsStoreLocal(); | 742 StoreLocalInstr* store = definition->AsStoreLocal(); |
| 745 if ((load != NULL) || (store != NULL)) { | 743 ConstantInstr* constant = definition->AsConstant(); |
| 744 if ((load != NULL) || (store != NULL) || (constant != NULL)) { |
| 746 intptr_t index; | 745 intptr_t index; |
| 747 Definition* result; | 746 Definition* result; |
| 748 if (store != NULL) { | 747 if (store != NULL) { |
| 749 // Update renaming environment. | 748 // Update renaming environment. |
| 750 index = store->local().BitIndexIn(num_non_copied_params_); | 749 index = store->local().BitIndexIn(num_non_copied_params_); |
| 751 result = store->value()->definition(); | 750 result = store->value()->definition(); |
| 752 | 751 |
| 753 if (variable_liveness->IsStoreAlive(block_entry, store)) { | 752 if (variable_liveness->IsStoreAlive(block_entry, store)) { |
| 754 (*env)[index] = result; | 753 (*env)[index] = result; |
| 755 } else { | 754 } else { |
| 756 (*env)[index] = constant_null(); | 755 (*env)[index] = constant_null(); |
| 757 } | 756 } |
| 758 } else { | 757 } else if (load != NULL) { |
| 759 // The graph construction ensures we do not have an unused LoadLocal | 758 // The graph construction ensures we do not have an unused LoadLocal |
| 760 // computation. | 759 // computation. |
| 761 ASSERT(definition->is_used()); | 760 ASSERT(definition->is_used()); |
| 762 index = load->local().BitIndexIn(num_non_copied_params_); | 761 index = load->local().BitIndexIn(num_non_copied_params_); |
| 763 result = (*env)[index]; | 762 result = (*env)[index]; |
| 764 | 763 |
| 765 PhiInstr* phi = result->AsPhi(); | 764 PhiInstr* phi = result->AsPhi(); |
| 766 if ((phi != NULL) && !phi->is_alive()) { | 765 if ((phi != NULL) && !phi->is_alive()) { |
| 767 phi->mark_alive(); | 766 phi->mark_alive(); |
| 768 live_phis->Add(phi); | 767 live_phis->Add(phi); |
| 769 } | 768 } |
| 770 | 769 |
| 771 if (variable_liveness->IsLastLoad(block_entry, load)) { | 770 if (variable_liveness->IsLastLoad(block_entry, load)) { |
| 772 (*env)[index] = constant_null(); | 771 (*env)[index] = constant_null(); |
| 773 } | 772 } |
| 773 } else { |
| 774 ASSERT(definition->is_used()); |
| 775 result = GetConstant(constant->value()); |
| 774 } | 776 } |
| 775 // Update expression stack or remove from graph. | 777 // Update expression stack or remove from graph. |
| 776 if (definition->is_used()) { | 778 if (definition->is_used()) { |
| 779 ASSERT(result != NULL); |
| 777 env->Add(result); | 780 env->Add(result); |
| 778 // We remove load/store instructions when we find their use in 2a. | 781 // We remove load/store/constant instructions when we find their |
| 782 // use in 2a. |
| 779 } else { | 783 } else { |
| 780 it.RemoveCurrentFromGraph(); | 784 it.RemoveCurrentFromGraph(); |
| 781 } | 785 } |
| 782 } else { | 786 } else { |
| 783 // Not a load or store. | 787 // Not a load, store, or constant. |
| 784 if (definition->is_used()) { | 788 if (definition->is_used()) { |
| 785 // Assign fresh SSA temporary and update expression stack. | 789 // Assign fresh SSA temporary and update expression stack. |
| 786 definition->set_ssa_temp_index(alloc_ssa_temp_index()); | 790 definition->set_ssa_temp_index(alloc_ssa_temp_index()); |
| 787 env->Add(definition); | 791 env->Add(definition); |
| 788 } | 792 } |
| 789 } | 793 } |
| 790 } | 794 } |
| 791 | 795 |
| 792 // 2c. Handle pushed argument. | 796 // 2c. Handle pushed argument. |
| 793 PushArgumentInstr* push = current->AsPushArgument(); | 797 PushArgumentInstr* push = current->AsPushArgument(); |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1052 } | 1056 } |
| 1053 | 1057 |
| 1054 | 1058 |
| 1055 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, | 1059 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, |
| 1056 BlockEntryInstr* to) const { | 1060 BlockEntryInstr* to) const { |
| 1057 return available_at_[to->postorder_number()]->Contains( | 1061 return available_at_[to->postorder_number()]->Contains( |
| 1058 from->postorder_number()); | 1062 from->postorder_number()); |
| 1059 } | 1063 } |
| 1060 | 1064 |
| 1061 } // namespace dart | 1065 } // namespace dart |
| OLD | NEW |