| 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/compiler.h" | 5 #include "vm/compiler.h" |
| 6 | 6 |
| 7 #include "vm/assembler.h" | 7 #include "vm/assembler.h" |
| 8 | 8 |
| 9 #include "vm/ast_printer.h" | 9 #include "vm/ast_printer.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 DEFINE_FLAG(bool, propagate_types, true, "Do static type propagation."); | 47 DEFINE_FLAG(bool, propagate_types, true, "Do static type propagation."); |
| 48 DEFINE_FLAG(int, deoptimization_counter_threshold, 16, | 48 DEFINE_FLAG(int, deoptimization_counter_threshold, 16, |
| 49 "How many times we allow deoptimization before we disallow optimization."); | 49 "How many times we allow deoptimization before we disallow optimization."); |
| 50 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); | 50 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
| 51 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); | 51 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); |
| 52 DEFINE_FLAG(bool, verify_compiler, false, | 52 DEFINE_FLAG(bool, verify_compiler, false, |
| 53 "Enable compiler verification assertions"); | 53 "Enable compiler verification assertions"); |
| 54 DECLARE_FLAG(bool, print_flow_graph); | 54 DECLARE_FLAG(bool, print_flow_graph); |
| 55 DECLARE_FLAG(bool, print_flow_graph_optimized); | 55 DECLARE_FLAG(bool, print_flow_graph_optimized); |
| 56 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 56 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
| 57 DECLARE_FLAG(bool, trace_type_propagation); | |
| 58 | 57 |
| 59 // Compile a function. Should call only if the function has not been compiled. | 58 // Compile a function. Should call only if the function has not been compiled. |
| 60 // Arg0: function object. | 59 // Arg0: function object. |
| 61 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 60 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
| 62 ASSERT(arguments.ArgCount() == kCompileFunctionRuntimeEntry.argument_count()); | 61 ASSERT(arguments.ArgCount() == kCompileFunctionRuntimeEntry.argument_count()); |
| 63 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); | 62 const Function& function = Function::CheckedHandle(arguments.ArgAt(0)); |
| 64 ASSERT(!function.HasCode()); | 63 ASSERT(!function.HasCode()); |
| 65 const Error& error = Error::Handle(Compiler::CompileFunction(function)); | 64 const Error& error = Error::Handle(Compiler::CompileFunction(function)); |
| 66 if (!error.IsNull()) { | 65 if (!error.IsNull()) { |
| 67 Exceptions::PropagateError(error); | 66 Exceptions::PropagateError(error); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 FlowGraphBuilder builder(parsed_function, NULL); // NULL = not inlining. | 152 FlowGraphBuilder builder(parsed_function, NULL); // NULL = not inlining. |
| 154 flow_graph = builder.BuildGraph(); | 153 flow_graph = builder.BuildGraph(); |
| 155 } | 154 } |
| 156 | 155 |
| 157 if (optimized) { | 156 if (optimized) { |
| 158 TimerScope timer(FLAG_compiler_stats, | 157 TimerScope timer(FLAG_compiler_stats, |
| 159 &CompilerStats::ssa_timer, | 158 &CompilerStats::ssa_timer, |
| 160 isolate); | 159 isolate); |
| 161 // Transform to SSA (virtual register 0 and no inlining arguments). | 160 // Transform to SSA (virtual register 0 and no inlining arguments). |
| 162 flow_graph->ComputeSSA(0, NULL); | 161 flow_graph->ComputeSSA(0, NULL); |
| 162 flow_graph->ComputeUseLists(); |
| 163 } | 163 } |
| 164 | 164 |
| 165 if (FLAG_print_flow_graph || | 165 if (FLAG_print_flow_graph || |
| 166 (optimized && FLAG_print_flow_graph_optimized)) { | 166 (optimized && FLAG_print_flow_graph_optimized)) { |
| 167 OS::Print("Before Optimizations\n"); | 167 OS::Print("Before Optimizations\n"); |
| 168 FlowGraphPrinter printer(*flow_graph); | 168 FlowGraphPrinter printer(*flow_graph); |
| 169 printer.PrintBlocks(); | 169 printer.PrintBlocks(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 if (optimized) { | 172 if (optimized) { |
| 173 TimerScope timer(FLAG_compiler_stats, | 173 TimerScope timer(FLAG_compiler_stats, |
| 174 &CompilerStats::graphoptimizer_timer, | 174 &CompilerStats::graphoptimizer_timer, |
| 175 isolate); | 175 isolate); |
| 176 | 176 |
| 177 flow_graph->ComputeUseLists(); | |
| 178 | |
| 179 FlowGraphOptimizer optimizer(flow_graph); | 177 FlowGraphOptimizer optimizer(flow_graph); |
| 180 optimizer.ApplyICData(); | 178 optimizer.ApplyICData(); |
| 179 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 181 | 180 |
| 182 // Inlining (mutates the flow graph) | 181 // Inlining (mutates the flow graph) |
| 183 if (FLAG_use_inlining) { | 182 if (FLAG_use_inlining) { |
| 184 TimerScope timer(FLAG_compiler_stats, | 183 TimerScope timer(FLAG_compiler_stats, |
| 185 &CompilerStats::graphinliner_timer); | 184 &CompilerStats::graphinliner_timer); |
| 186 FlowGraphInliner inliner(flow_graph); | 185 FlowGraphInliner inliner(flow_graph); |
| 187 inliner.Inline(); | 186 inliner.Inline(); |
| 188 // Use lists are maintained and validated by the inliner. | 187 // Use lists are maintained and validated by the inliner. |
| 189 } | 188 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 190 | |
| 191 if (FLAG_trace_type_propagation) { | |
| 192 OS::Print("Before type propagation:\n"); | |
| 193 FlowGraphPrinter printer(*flow_graph); | |
| 194 printer.PrintBlocks(); | |
| 195 } | 189 } |
| 196 | 190 |
| 197 // Propagate types and eliminate more type tests. | 191 // Propagate types and eliminate more type tests. |
| 198 if (FLAG_propagate_types) { | 192 if (FLAG_propagate_types) { |
| 199 FlowGraphTypePropagator propagator(flow_graph); | 193 FlowGraphTypePropagator propagator(flow_graph); |
| 200 propagator.Propagate(); | 194 propagator.Propagate(); |
| 195 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 201 } | 196 } |
| 202 | 197 |
| 203 if (FLAG_trace_type_propagation) { | |
| 204 OS::Print("After type propagation:\n"); | |
| 205 FlowGraphPrinter printer(*flow_graph); | |
| 206 printer.PrintBlocks(); | |
| 207 } | |
| 208 | |
| 209 flow_graph->ComputeUseLists(); | |
| 210 | |
| 211 // Use propagated class-ids to optimize further. | 198 // Use propagated class-ids to optimize further. |
| 212 optimizer.ApplyClassIds(); | 199 optimizer.ApplyClassIds(); |
| 200 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 213 | 201 |
| 214 // Do optimizations that depend on the propagated type information. | 202 // Do optimizations that depend on the propagated type information. |
| 215 optimizer.Canonicalize(); | 203 optimizer.Canonicalize(); |
| 204 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 216 | 205 |
| 217 if (FLAG_constant_propagation) { | 206 if (FLAG_constant_propagation) { |
| 218 ConstantPropagator::Optimize(flow_graph); | 207 ConstantPropagator::Optimize(flow_graph); |
| 208 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 219 // A canonicalization pass to remove e.g. smi checks on smi constants. | 209 // A canonicalization pass to remove e.g. smi checks on smi constants. |
| 220 optimizer.Canonicalize(); | 210 optimizer.Canonicalize(); |
| 211 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 221 } | 212 } |
| 222 | 213 |
| 223 // Unbox doubles. Performed after constant propagation to minimize | 214 // Unbox doubles. Performed after constant propagation to minimize |
| 224 // interference from phis merging double values and tagged | 215 // interference from phis merging double values and tagged |
| 225 // values comming from dead paths. | 216 // values comming from dead paths. |
| 226 optimizer.SelectRepresentations(); | 217 optimizer.SelectRepresentations(); |
| 218 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 227 | 219 |
| 228 if (FLAG_common_subexpression_elimination) { | 220 if (FLAG_common_subexpression_elimination) { |
| 229 if (DominatorBasedCSE::Optimize(flow_graph)) { | 221 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 222 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 230 // Do another round of CSE to take secondary effects into account: | 223 // Do another round of CSE to take secondary effects into account: |
| 231 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) | 224 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
| 232 // TODO(fschneider): Change to a one-pass optimization pass. | 225 // TODO(fschneider): Change to a one-pass optimization pass. |
| 233 DominatorBasedCSE::Optimize(flow_graph); | 226 DominatorBasedCSE::Optimize(flow_graph); |
| 227 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 234 } | 228 } |
| 235 } | 229 } |
| 236 if (FLAG_loop_invariant_code_motion && | 230 if (FLAG_loop_invariant_code_motion && |
| 237 (parsed_function.function().deoptimization_counter() < | 231 (parsed_function.function().deoptimization_counter() < |
| 238 (FLAG_deoptimization_counter_threshold - 1))) { | 232 (FLAG_deoptimization_counter_threshold - 1))) { |
| 239 LICM::Optimize(flow_graph); | 233 LICM::Optimize(flow_graph); |
| 234 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 240 } | 235 } |
| 241 | 236 |
| 242 if (FLAG_range_analysis) { | 237 if (FLAG_range_analysis) { |
| 243 // We have to perform range analysis after LICM because it | 238 // We have to perform range analysis after LICM because it |
| 244 // optimistically moves CheckSmi through phis into loop preheaders | 239 // optimistically moves CheckSmi through phis into loop preheaders |
| 245 // making some phis smi. | 240 // making some phis smi. |
| 246 optimizer.InferSmiRanges(); | 241 optimizer.InferSmiRanges(); |
| 242 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 247 } | 243 } |
| 248 | 244 |
| 249 // The final canonicalization pass before the code generation. | 245 // The final canonicalization pass before the code generation. |
| 250 optimizer.Canonicalize(); | 246 optimizer.Canonicalize(); |
| 247 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 251 | 248 |
| 252 // Perform register allocation on the SSA graph. | 249 // Perform register allocation on the SSA graph. |
| 253 FlowGraphAllocator allocator(*flow_graph); | 250 FlowGraphAllocator allocator(*flow_graph); |
| 254 allocator.AllocateRegisters(); | 251 allocator.AllocateRegisters(); |
| 255 | 252 |
| 256 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 253 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
| 257 OS::Print("After Optimizations:\n"); | 254 OS::Print("After Optimizations:\n"); |
| 258 FlowGraphPrinter printer(*flow_graph); | 255 FlowGraphPrinter printer(*flow_graph); |
| 259 printer.PrintBlocks(); | 256 printer.PrintBlocks(); |
| 260 } | 257 } |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 645 Object::Handle(isolate->object_store()->sticky_error()); | 642 Object::Handle(isolate->object_store()->sticky_error()); |
| 646 isolate->object_store()->clear_sticky_error(); | 643 isolate->object_store()->clear_sticky_error(); |
| 647 isolate->set_long_jump_base(base); | 644 isolate->set_long_jump_base(base); |
| 648 return result.raw(); | 645 return result.raw(); |
| 649 } | 646 } |
| 650 UNREACHABLE(); | 647 UNREACHABLE(); |
| 651 return Object::null(); | 648 return Object::null(); |
| 652 } | 649 } |
| 653 | 650 |
| 654 } // namespace dart | 651 } // namespace dart |
| OLD | NEW |