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