| 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 // Transform to SSA (virtual register 0 and no inlining arguments). | 160 // Transform to SSA (virtual register 0 and no inlining arguments). |
| 161 flow_graph->ComputeSSA(0, NULL); | 161 flow_graph->ComputeSSA(0, NULL); |
| 162 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 162 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 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 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 167 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
| 168 } | 168 } |
| 169 | 169 |
| 170 const ZoneGrowableArray<Field*>* guarded_fields = NULL; |
| 171 |
| 170 if (optimized) { | 172 if (optimized) { |
| 171 TimerScope timer(FLAG_compiler_stats, | 173 TimerScope timer(FLAG_compiler_stats, |
| 172 &CompilerStats::graphoptimizer_timer, | 174 &CompilerStats::graphoptimizer_timer, |
| 173 isolate); | 175 isolate); |
| 174 | 176 |
| 175 FlowGraphOptimizer optimizer(flow_graph); | 177 FlowGraphOptimizer optimizer(flow_graph); |
| 176 optimizer.ApplyICData(); | 178 optimizer.ApplyICData(); |
| 177 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 179 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 178 | 180 |
| 179 // Optimize (a << b) & c patterns. Must occur before | 181 // Optimize (a << b) & c patterns. Must occur before |
| 180 // 'SelectRepresentations' which inserts conversion nodes. | 182 // 'SelectRepresentations' which inserts conversion nodes. |
| 181 // TODO(srdjan): Moved before inlining until environment use list can | 183 // TODO(srdjan): Moved before inlining until environment use list can |
| 182 // be used to detect when shift-left is outside the scope of bit-and. | 184 // be used to detect when shift-left is outside the scope of bit-and. |
| 183 optimizer.TryOptimizeLeftShiftWithBitAndPattern(); | 185 optimizer.TryOptimizeLeftShiftWithBitAndPattern(); |
| 184 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 186 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 185 | 187 |
| 186 // Inlining (mutates the flow graph) | 188 // Inlining (mutates the flow graph) |
| 187 if (FLAG_use_inlining) { | 189 if (FLAG_use_inlining) { |
| 188 TimerScope timer(FLAG_compiler_stats, | 190 TimerScope timer(FLAG_compiler_stats, |
| 189 &CompilerStats::graphinliner_timer); | 191 &CompilerStats::graphinliner_timer); |
| 190 FlowGraphInliner inliner(flow_graph); | 192 FlowGraphInliner inliner(flow_graph); |
| 191 inliner.Inline(); | 193 inliner.Inline(); |
| 192 // Use lists are maintained and validated by the inliner. | 194 // Use lists are maintained and validated by the inliner. |
| 193 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 195 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 194 } | 196 } |
| 195 | 197 |
| 198 guarded_fields = flow_graph->FieldDependencies(); |
| 199 |
| 196 // Propagate types and eliminate more type tests. | 200 // Propagate types and eliminate more type tests. |
| 197 if (FLAG_propagate_types) { | 201 if (FLAG_propagate_types) { |
| 198 FlowGraphTypePropagator propagator(flow_graph); | 202 FlowGraphTypePropagator propagator(flow_graph); |
| 199 propagator.Propagate(); | 203 propagator.Propagate(); |
| 200 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 204 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 201 } | 205 } |
| 202 | 206 |
| 203 // Use propagated class-ids to optimize further. | 207 // Use propagated class-ids to optimize further. |
| 204 optimizer.ApplyClassIds(); | 208 optimizer.ApplyClassIds(); |
| 205 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 209 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 206 | 210 |
| 207 // Do optimizations that depend on the propagated type information. | 211 // Do optimizations that depend on the propagated type information. |
| 208 optimizer.Canonicalize(); | 212 optimizer.Canonicalize(); |
| 209 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 213 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 210 | 214 |
| 211 BranchSimplifier::Simplify(flow_graph); | 215 BranchSimplifier::Simplify(flow_graph); |
| 212 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 216 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 213 | 217 |
| 214 if (FLAG_constant_propagation) { | 218 if (FLAG_constant_propagation) { |
| 215 ConstantPropagator::Optimize(flow_graph); | 219 ConstantPropagator::Optimize(flow_graph); |
| 216 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 220 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 217 // A canonicalization pass to remove e.g. smi checks on smi constants. | 221 // A canonicalization pass to remove e.g. smi checks on smi constants. |
| 218 optimizer.Canonicalize(); | 222 optimizer.Canonicalize(); |
| 219 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 223 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 220 } | 224 } |
| 221 | 225 |
| 222 // Propagate types and eliminate even more type tests. | 226 // Propagate types and eliminate even more type tests. |
| 223 if (FLAG_propagate_types) { | 227 if (FLAG_propagate_types) { |
| 228 // Recompute types after constant propagation to infer more precise |
| 229 // types for uses that were previously reached by now eliminated phis. |
| 224 FlowGraphTypePropagator propagator(flow_graph); | 230 FlowGraphTypePropagator propagator(flow_graph); |
| 225 propagator.Propagate(); | 231 propagator.Propagate(); |
| 226 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 232 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 227 } | 233 } |
| 228 | 234 |
| 229 // Unbox doubles. Performed after constant propagation to minimize | 235 // Unbox doubles. Performed after constant propagation to minimize |
| 230 // interference from phis merging double values and tagged | 236 // interference from phis merging double values and tagged |
| 231 // values comming from dead paths. | 237 // values comming from dead paths. |
| 232 optimizer.SelectRepresentations(); | 238 optimizer.SelectRepresentations(); |
| 233 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 239 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 252 | 258 |
| 253 if (FLAG_range_analysis) { | 259 if (FLAG_range_analysis) { |
| 254 // We have to perform range analysis after LICM because it | 260 // We have to perform range analysis after LICM because it |
| 255 // optimistically moves CheckSmi through phis into loop preheaders | 261 // optimistically moves CheckSmi through phis into loop preheaders |
| 256 // making some phis smi. | 262 // making some phis smi. |
| 257 optimizer.InferSmiRanges(); | 263 optimizer.InferSmiRanges(); |
| 258 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 264 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 259 } | 265 } |
| 260 | 266 |
| 261 // The final canonicalization pass before the code generation. | 267 // The final canonicalization pass before the code generation. |
| 268 if (FLAG_propagate_types) { |
| 269 // Propagate types one more time after code movement phases. |
| 270 // This recomputes types of values that became dominated by |
| 271 // hoisted checks. |
| 272 FlowGraphTypePropagator propagator(flow_graph); |
| 273 propagator.Propagate(); |
| 274 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 275 } |
| 262 optimizer.Canonicalize(); | 276 optimizer.Canonicalize(); |
| 263 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 277 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 264 | 278 |
| 265 // Perform register allocation on the SSA graph. | 279 // Perform register allocation on the SSA graph. |
| 266 FlowGraphAllocator allocator(*flow_graph); | 280 FlowGraphAllocator allocator(*flow_graph); |
| 267 allocator.AllocateRegisters(); | 281 allocator.AllocateRegisters(); |
| 268 | 282 |
| 269 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 283 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
| 270 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 284 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
| 271 } | 285 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 289 const Code& code = Code::Handle( | 303 const Code& code = Code::Handle( |
| 290 Code::FinalizeCode(function, &assembler, optimized)); | 304 Code::FinalizeCode(function, &assembler, optimized)); |
| 291 code.set_is_optimized(optimized); | 305 code.set_is_optimized(optimized); |
| 292 graph_compiler.FinalizePcDescriptors(code); | 306 graph_compiler.FinalizePcDescriptors(code); |
| 293 graph_compiler.FinalizeDeoptInfo(code); | 307 graph_compiler.FinalizeDeoptInfo(code); |
| 294 graph_compiler.FinalizeStackmaps(code); | 308 graph_compiler.FinalizeStackmaps(code); |
| 295 graph_compiler.FinalizeVarDescriptors(code); | 309 graph_compiler.FinalizeVarDescriptors(code); |
| 296 graph_compiler.FinalizeExceptionHandlers(code); | 310 graph_compiler.FinalizeExceptionHandlers(code); |
| 297 graph_compiler.FinalizeComments(code); | 311 graph_compiler.FinalizeComments(code); |
| 298 graph_compiler.FinalizeStaticCallTargetsTable(code); | 312 graph_compiler.FinalizeStaticCallTargetsTable(code); |
| 313 |
| 299 if (optimized) { | 314 if (optimized) { |
| 300 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 315 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
| 301 function.SetCode(code); | 316 function.SetCode(code); |
| 302 if (FLAG_trace_compiler) { | 317 if (FLAG_trace_compiler) { |
| 303 OS::Print("--> patching entry %#"Px"\n", | 318 OS::Print("--> patching entry %#"Px"\n", |
| 304 Code::Handle(function.unoptimized_code()).EntryPoint()); | 319 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 305 } | 320 } |
| 321 |
| 322 for (intptr_t i = 0; i < guarded_fields->length(); i++) { |
| 323 const Field& field = *(*guarded_fields)[i]; |
| 324 field.RegisterDependentCode(code); |
| 325 } |
| 306 } else { | 326 } else { |
| 307 function.set_unoptimized_code(code); | 327 function.set_unoptimized_code(code); |
| 308 function.SetCode(code); | 328 function.SetCode(code); |
| 309 ASSERT(CodePatcher::CodeIsPatchable(code)); | 329 ASSERT(CodePatcher::CodeIsPatchable(code)); |
| 310 } | 330 } |
| 311 } | 331 } |
| 312 is_compiled = true; | 332 is_compiled = true; |
| 313 } else { | 333 } else { |
| 314 // We bailed out. | 334 // We bailed out. |
| 315 Error& bailout_error = Error::Handle( | 335 Error& bailout_error = Error::Handle( |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 661 Object::Handle(isolate->object_store()->sticky_error()); | 681 Object::Handle(isolate->object_store()->sticky_error()); |
| 662 isolate->object_store()->clear_sticky_error(); | 682 isolate->object_store()->clear_sticky_error(); |
| 663 isolate->set_long_jump_base(base); | 683 isolate->set_long_jump_base(base); |
| 664 return result.raw(); | 684 return result.raw(); |
| 665 } | 685 } |
| 666 UNREACHABLE(); | 686 UNREACHABLE(); |
| 667 return Object::null(); | 687 return Object::null(); |
| 668 } | 688 } |
| 669 | 689 |
| 670 } // namespace dart | 690 } // namespace dart |
| OLD | NEW |