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.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 Object& value = Object::ZoneHandle(base[-i]); | |
|
srdjan
2014/01/07 18:51:20
const Object&
Florian Schneider
2014/01/08 10:48:03
Done.
| |
| 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()); | |
|
Kevin Millikin (Google)
2014/01/07 14:09:19
I know you've already thought of this, but here yo
Florian Schneider
2014/01/08 10:48:03
Good point. I'll do this in a separate CL since ad
| |
| 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 intptr_t count = num_non_copied_params(); | |
|
Kevin Millikin (Google)
2014/01/07 14:09:19
I guess there should be a comment here that it's i
Florian Schneider
2014/01/08 10:48:03
Done.
| |
| 729 RawObject** base = reinterpret_cast<RawObject**>(frame->fp()) | |
| 730 + kParamEndSlotFromFp // One past the last parameter. | |
| 731 + count; | |
| 732 InitializeOsrLocalRange(env, base, count); | |
| 733 | |
| 734 count = num_copied_params() + num_stack_locals(); | |
| 735 base = reinterpret_cast<RawObject**>(frame->fp()) + kFirstLocalSlotFromFp; | |
| 736 InitializeOsrLocalRange(env, base, count); | |
| 737 } | |
| 738 | |
| 739 | |
| 698 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, | 740 void FlowGraph::Rename(GrowableArray<PhiInstr*>* live_phis, |
| 699 VariableLivenessAnalysis* variable_liveness, | 741 VariableLivenessAnalysis* variable_liveness, |
| 700 ZoneGrowableArray<Definition*>* inlining_parameters) { | 742 ZoneGrowableArray<Definition*>* inlining_parameters) { |
| 701 GraphEntryInstr* entry = graph_entry(); | 743 GraphEntryInstr* entry = graph_entry(); |
| 702 if (!FLAG_optimize_try_catch && (entry->SuccessorCount() > 1)) { | 744 if (!FLAG_optimize_try_catch && (entry->SuccessorCount() > 1)) { |
| 703 Bailout("Catch-entry support in SSA."); | 745 Bailout("Catch-entry support in SSA."); |
| 704 } | 746 } |
| 705 | 747 |
| 706 // Initial renaming environment. | 748 // Initial renaming environment. |
| 707 GrowableArray<Definition*> env(variable_count()); | 749 GrowableArray<Definition*> env(variable_count()); |
| 708 | 750 |
| 709 // Add global constants to the initial definitions. | 751 // Add global constants to the initial definitions. |
| 710 constant_null_ = GetConstant(Object::ZoneHandle()); | 752 constant_null_ = GetConstant(Object::ZoneHandle()); |
| 711 constant_dead_ = GetConstant(Symbols::OptimizedOut()); | 753 constant_dead_ = GetConstant(Symbols::OptimizedOut()); |
| 712 | 754 |
| 713 // Add parameters to the initial definitions and renaming environment. | 755 // Add parameters to the initial definitions and renaming environment. |
| 714 if (inlining_parameters != NULL) { | 756 if (inlining_parameters != NULL) { |
| 715 // Use known parameters. | 757 // When inlining, use the known parameter definitions. |
| 716 ASSERT(parameter_count() == inlining_parameters->length()); | 758 ASSERT(parameter_count() == inlining_parameters->length()); |
| 717 for (intptr_t i = 0; i < parameter_count(); ++i) { | 759 for (intptr_t i = 0; i < parameter_count(); ++i) { |
| 718 Definition* defn = (*inlining_parameters)[i]; | 760 Definition* defn = (*inlining_parameters)[i]; |
| 719 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 761 defn->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 720 AddToInitialDefinitions(defn); | 762 AddToInitialDefinitions(defn); |
| 721 env.Add(defn); | 763 env.Add(defn); |
| 722 } | 764 } |
| 765 } else if (IsCompiledForOsr()) { | |
| 766 // For functions compiled for OSR, use the constants found in the | |
| 767 // unoptimized frame. | |
| 768 InitializeOsrLocals(&env); | |
| 723 } else { | 769 } else { |
| 724 // Create new parameters. For functions compiled for OSR, the locals | 770 // Create fresh (unknown) parameters. |
| 725 // are unknown and so treated like parameters. | 771 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); | 772 ParameterInstr* param = new ParameterInstr(i, entry); |
| 729 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. | 773 param->set_ssa_temp_index(alloc_ssa_temp_index()); // New SSA temp. |
| 730 AddToInitialDefinitions(param); | 774 AddToInitialDefinitions(param); |
| 731 env.Add(param); | 775 env.Add(param); |
| 732 } | 776 } |
| 733 } | 777 } |
| 734 | 778 |
| 735 // Initialize all locals with #null in the renaming environment. For OSR, | 779 // Initialize all locals with #null in the renaming environment. For OSR, |
| 736 // the locals have already been handled as parameters. | 780 // the locals have already been handled as parameters. |
| 737 if (!IsCompiledForOsr()) { | 781 if (!IsCompiledForOsr()) { |
| 738 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { | 782 for (intptr_t i = parameter_count(); i < variable_count(); ++i) { |
| 739 env.Add(constant_null()); | 783 env.Add(constant_null()); |
| 740 } | 784 } |
| 741 } | 785 } |
| 742 | 786 |
| 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); | 787 RenameRecursive(entry, &env, live_phis, variable_liveness); |
| 750 } | 788 } |
| 751 | 789 |
| 752 | 790 |
| 753 void FlowGraph::AttachEnvironment(Instruction* instr, | 791 void FlowGraph::AttachEnvironment(Instruction* instr, |
| 754 GrowableArray<Definition*>* env) { | 792 GrowableArray<Definition*>* env) { |
| 755 Environment* deopt_env = | 793 Environment* deopt_env = |
| 756 Environment::From(*env, | 794 Environment::From(*env, |
| 757 num_non_copied_params_, | 795 num_non_copied_params_, |
| 758 Code::Handle(parsed_function_.code())); | 796 Code::Handle(parsed_function_.code())); |
| (...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1198 } | 1236 } |
| 1199 | 1237 |
| 1200 | 1238 |
| 1201 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, | 1239 bool BlockEffects::IsSideEffectFreePath(BlockEntryInstr* from, |
| 1202 BlockEntryInstr* to) const { | 1240 BlockEntryInstr* to) const { |
| 1203 return available_at_[to->postorder_number()]->Contains( | 1241 return available_at_[to->postorder_number()]->Contains( |
| 1204 from->postorder_number()); | 1242 from->postorder_number()); |
| 1205 } | 1243 } |
| 1206 | 1244 |
| 1207 } // namespace dart | 1245 } // namespace dart |
| OLD | NEW |