| 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/growable_array.h" |
| 9 #include "vm/intermediate_language.h" | 10 #include "vm/intermediate_language.h" |
| 10 #include "vm/longjump.h" | 11 #include "vm/longjump.h" |
| 11 #include "vm/growable_array.h" | 12 #include "vm/stack_frame.h" |
| 12 | 13 |
| 13 namespace dart { | 14 namespace dart { |
| 14 | 15 |
| 15 DECLARE_FLAG(bool, reorder_basic_blocks); | 16 DECLARE_FLAG(bool, reorder_basic_blocks); |
| 16 DECLARE_FLAG(bool, trace_optimization); | 17 DECLARE_FLAG(bool, trace_optimization); |
| 17 DECLARE_FLAG(bool, verify_compiler); | 18 DECLARE_FLAG(bool, verify_compiler); |
| 18 DEFINE_FLAG(bool, optimize_try_catch, true, "Optimization of try-catch"); | 19 DEFINE_FLAG(bool, optimize_try_catch, true, "Optimization of try-catch"); |
| 19 | 20 |
| 20 | 21 |
| 21 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, | 22 FlowGraph::FlowGraph(const FlowGraphBuilder& builder, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 70 | 71 |
| 71 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder( | 72 GrowableArray<BlockEntryInstr*>* FlowGraph::CodegenBlockOrder( |
| 72 bool is_optimized) { | 73 bool is_optimized) { |
| 73 return ShouldReorderBlocks(parsed_function().function(), is_optimized) | 74 return ShouldReorderBlocks(parsed_function().function(), is_optimized) |
| 74 ? &optimized_block_order_ | 75 ? &optimized_block_order_ |
| 75 : &reverse_postorder_; | 76 : &reverse_postorder_; |
| 76 } | 77 } |
| 77 | 78 |
| 78 | 79 |
| 79 ConstantInstr* FlowGraph::GetConstant(const Object& object) { | 80 ConstantInstr* FlowGraph::GetConstant(const Object& object) { |
| 81 // Not all objects can be embedded in code. |
| 82 ASSERT(object.IsSmi() || object.InVMHeap() || object.IsOld()); |
| 80 // Check if the constant is already in the pool. | 83 // Check if the constant is already in the pool. |
| 81 GrowableArray<Definition*>* pool = graph_entry_->initial_definitions(); | 84 GrowableArray<Definition*>* pool = graph_entry_->initial_definitions(); |
| 82 for (intptr_t i = 0; i < pool->length(); ++i) { | 85 for (intptr_t i = 0; i < pool->length(); ++i) { |
| 83 ConstantInstr* constant = (*pool)[i]->AsConstant(); | 86 ConstantInstr* constant = (*pool)[i]->AsConstant(); |
| 84 if ((constant != NULL) && (constant->value().raw() == object.raw())) { | 87 if ((constant != NULL) && (constant->value().raw() == object.raw())) { |
| 85 return constant; | 88 return constant; |
| 86 } | 89 } |
| 87 } | 90 } |
| 88 // Otherwise, allocate and add it to the pool. | 91 // Otherwise, allocate and add it to the pool. |
| 89 ConstantInstr* constant = new ConstantInstr(object); | 92 ConstantInstr* constant = new ConstantInstr(object); |
| (...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 688 work[index] = var_index; | 691 work[index] = var_index; |
| 689 worklist.Add(block); | 692 worklist.Add(block); |
| 690 } | 693 } |
| 691 } | 694 } |
| 692 } | 695 } |
| 693 } | 696 } |
| 694 } | 697 } |
| 695 } | 698 } |
| 696 | 699 |
| 697 | 700 |
| 701 void FlowGraph::InitializeOsrLocalRange(GrowableArray<Definition*>* env, |
| 702 RawObject** base, |
| 703 intptr_t count) { |
| 704 for (intptr_t i = 0; i < count; ++i) { |
| 705 // Variables go from high to low addresses as they go from left to |
| 706 // right. |
| 707 const Object& value = Object::ZoneHandle(base[-i]); |
| 708 Definition* definition = NULL; |
| 709 if (value.IsSmi() || value.InVMHeap() || value.IsOld()) { |
| 710 definition = GetConstant(value); |
| 711 } else { |
| 712 definition = new ParameterInstr(env->length(), graph_entry()); |
| 713 definition->set_ssa_temp_index(alloc_ssa_temp_index()); |
| 714 AddToInitialDefinitions(definition); |
| 715 } |
| 716 env->Add(definition); |
| 717 } |
| 718 } |
| 719 |
| 720 |
| 721 void FlowGraph::InitializeOsrLocals(GrowableArray<Definition*>* env) { |
| 722 DartFrameIterator iterator; |
| 723 StackFrame* frame = iterator.NextFrame(); |
| 724 const Code& code = Code::Handle(frame->LookupDartCode()); |
| 725 ASSERT(!code.is_optimized()); |
| 726 ASSERT(frame->LookupDartFunction() == parsed_function().function().raw()); |
| 727 |
| 728 // Initialize parameters and locals in the order they appear in the |
| 729 // environment (left-to-right, parameters first). |
| 730 intptr_t count = num_non_copied_params(); |
| 731 RawObject** base = reinterpret_cast<RawObject**>(frame->fp()) |
| 732 + kParamEndSlotFromFp // One past the last parameter. |
| 733 + count; |
| 734 InitializeOsrLocalRange(env, base, count); |
| 735 |
| 736 count = num_copied_params() + num_stack_locals(); |
| 737 base = reinterpret_cast<RawObject**>(frame->fp()) + kFirstLocalSlotFromFp; |
| 738 InitializeOsrLocalRange(env, base, count); |
| 739 } |
| 740 |
| 741 |
| 698 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, | 742 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, |
| 699 VariableLivenessAnalysis* variable_liveness, | 743 VariableLivenessAnalysis* variable_liveness, |
| 700 ZoneGrowableArray<Definition*>* inlining_parameters) { | 744 ZoneGrowableArray<Definition*>* inlining_parameters) { |
| 701 GraphEntryInstr* entry = graph_entry(); | 745 GraphEntryInstr* entry = graph_entry(); |
| 702 if (!FLAG_optimize_try_catch && (entry->SuccessorCount() > 1)) { | 746 if (!FLAG_optimize_try_catch && (entry->SuccessorCount() > 1)) { |
| 703 Bailout("Catch-entry support in SSA."); | 747 Bailout("Catch-entry support in SSA."); |
| 704 } | 748 } |
| 705 | 749 |
| 706 // Initial renaming environment. | 750 // Initial renaming environment. |
| 707 GrowableArray<Definition*> env(variable_count()); | 751 GrowableArray<Definition*> env(variable_count()); |
| 708 | 752 |
| 709 // Add global constants to the initial definitions. | 753 // Add global constants to the initial definitions. |
| 710 constant_null_ = GetConstant(Object::ZoneHandle()); | 754 constant_null_ = GetConstant(Object::ZoneHandle()); |
| 711 constant_dead_ = GetConstant(Symbols::OptimizedOut()); | 755 constant_dead_ = GetConstant(Symbols::OptimizedOut()); |
| 712 | 756 |
| 713 // Add parameters to the initial definitions and renaming environment. | 757 // Add parameters to the initial definitions and renaming environment. |
| 714 if (inlining_parameters != NULL) { | 758 if (inlining_parameters != NULL) { |
| 715 // Use known parameters. | 759 // When inlining, use the known parameter definitions. |
| 716 ASSERT(parameter_count() == inlining_parameters->length()); | 760 ASSERT(parameter_count() == inlining_parameters->length()); |
| 717 for (intptr_t i = 0; i < parameter_count(); ++i) { | 761 for (intptr_t i = 0; i < parameter_count(); ++i) { |
| 718 Definition* defn = (*inlining_parameters)[i]; | 762 Definition* defn = (*inlining_parameters)[i]; |
| 719 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 763 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 720 AddToInitialDefinitions(defn); | 764 AddToInitialDefinitions(defn); |
| 721 env.Add(defn); | 765 env.Add(defn); |
| 722 } | 766 } |
| 767 } else if (IsCompiledForOsr()) { |
| 768 // For functions compiled for OSR, use the constants found in the |
| 769 // unoptimized frame. |
| 770 InitializeOsrLocals(&env); |
| 723 } else { | 771 } else { |
| 724 // Create new parameters. For functions compiled for OSR, the locals | 772 // Create fresh (unknown) parameters. |
| 725 // are unknown and so treated like parameters. | 773 for (intptr_t i = 0; i < parameter_count(); ++i) { |
| 726 intptr_t count = IsCompiledForOsr() ? variable_count() : parameter_count(); | |
| 727 for (intptr_t i = 0; i < count; ++i) { | |
| 728 ParameterInstr* param = new ParameterInstr(i, entry); | 774 ParameterInstr* param = new ParameterInstr(i, entry); |
| 729 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 775 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 730 AddToInitialDefinitions(param); | 776 AddToInitialDefinitions(param); |
| 731 env.Add(param); | 777 env.Add(param); |
| 732 } | 778 } |
| 733 } | 779 } |
| 734 | 780 |
| 735 // Initialize all locals with #null in the renaming environment. For OSR, | 781 // Initialize all locals with #null in the renaming environment. For OSR, |
| 736 // the locals have already been handled as parameters. | 782 // the locals have already been handled as parameters. |
| 737 if (!IsCompiledForOsr()) { | 783 if (!IsCompiledForOsr()) { |
| 738 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { | 784 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { |
| 739 env.Add(constant_null()); | 785 env.Add(constant_null()); |
| 740 } | 786 } |
| 741 } | 787 } |
| 742 | 788 |
| 743 if (entry->SuccessorCount() > 1) { | |
| 744 // Functions with try-catch have a fixed area of stack slots reserved | |
| 745 // so that all local variables are stored at a known location when | |
| 746 // on entry to the catch. | |
| 747 entry->set_fixed_slot_count(num_stack_locals() + num_copied_params()); | |
| 748 } | |
| 749 RenameRecursive(entry, &env, live_phis, variable_liveness); | 789 RenameRecursive(entry, &env, live_phis, variable_liveness); |
| 750 } | 790 } |
| 751 | 791 |
| 752 | 792 |
| 753 void FlowGraph::AttachEnvironment(Instruction* instr, | 793 void FlowGraph::AttachEnvironment(Instruction* instr, |
| 754 GrowableArray<Definition*>* env) { | 794 GrowableArray<Definition*>* env) { |
| 755 Environment* deopt_env = | 795 Environment* deopt_env = |
| 756 Environment::From(*env, | 796 Environment::From(*env, |
| 757 num_non_copied_params_, | 797 num_non_copied_params_, |
| 758 Code::Handle(parsed_function_.code())); | 798 Code::Handle(parsed_function_.code())); |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1198 } | 1238 } |
| 1199 | 1239 |
| 1200 | 1240 |
| 1201 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, | 1241 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, |
| 1202 BlockEntryInstr* to) const { | 1242 BlockEntryInstr* to) const { |
| 1203 return available_at_[to->postorder_number()]->Contains( | 1243 return available_at_[to->postorder_number()]->Contains( |
| 1204 from->postorder_number()); | 1244 from->postorder_number()); |
| 1205 } | 1245 } |
| 1206 | 1246 |
| 1207 } // namespace dart | 1247 } // namespace dart |
| OLD | NEW |