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 #include "vm/ast_printer.h" | 8 #include "vm/ast_printer.h" |
| 9 #include "vm/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 27 #include "vm/scanner.h" | 27 #include "vm/scanner.h" |
| 28 #include "vm/symbols.h" | 28 #include "vm/symbols.h" |
| 29 #include "vm/timer.h" | 29 #include "vm/timer.h" |
| 30 | 30 |
| 31 namespace dart { | 31 namespace dart { |
| 32 | 32 |
| 33 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); | 33 DEFINE_FLAG(bool, disassemble, false, "Disassemble dart code."); |
| 34 DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code."); | 34 DEFINE_FLAG(bool, disassemble_optimized, false, "Disassemble optimized code."); |
| 35 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); | 35 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
| 36 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 36 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
| 37 DEFINE_FLAG(bool, use_ssa, true, "Use SSA form"); | |
| 38 DEFINE_FLAG(bool, local_cse, true, "Do local subexpression elimination."); | 37 DEFINE_FLAG(bool, local_cse, true, "Do local subexpression elimination."); |
| 39 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, | 38 DEFINE_FLAG(int, deoptimization_counter_threshold, 5, |
| 40 "How many times we allow deoptimization before we disallow" | 39 "How many times we allow deoptimization before we disallow" |
| 41 " certain optimizations"); | 40 " certain optimizations"); |
| 42 DECLARE_FLAG(bool, print_flow_graph); | 41 DECLARE_FLAG(bool, print_flow_graph); |
| 43 | 42 |
| 44 | 43 |
| 45 // Compile a function. Should call only if the function has not been compiled. | 44 // Compile a function. Should call only if the function has not been compiled. |
| 46 // Arg0: function object. | 45 // Arg0: function object. |
| 47 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { | 46 DEFINE_RUNTIME_ENTRY(CompileFunction, 1) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 115 function.SetCode(Code::Handle(function.unoptimized_code())); | 114 function.SetCode(Code::Handle(function.unoptimized_code())); |
| 116 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); | 115 CodePatcher::RestoreEntry(Code::Handle(function.unoptimized_code())); |
| 117 if (FLAG_trace_compiler) { | 116 if (FLAG_trace_compiler) { |
| 118 OS::Print("--> restoring entry at 0x%x\n", | 117 OS::Print("--> restoring entry at 0x%x\n", |
| 119 Code::Handle(function.unoptimized_code()).EntryPoint()); | 118 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 120 } | 119 } |
| 121 } | 120 } |
| 122 | 121 |
| 123 | 122 |
| 124 // Return false if bailed out. | 123 // Return false if bailed out. |
| 125 static bool CompileParsedFunctionHelper( | 124 static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function, |
| 126 const ParsedFunction& parsed_function, bool optimized, bool use_ssa) { | 125 bool optimized) { |
| 127 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 126 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
| 128 bool is_compiled = false; | 127 bool is_compiled = false; |
| 129 Isolate* isolate = Isolate::Current(); | 128 Isolate* isolate = Isolate::Current(); |
| 130 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null. | 129 ASSERT(isolate->ic_data_array() == Array::null()); // Must be reset to null. |
| 131 const intptr_t prev_deopt_id = isolate->deopt_id(); | 130 const intptr_t prev_deopt_id = isolate->deopt_id(); |
| 132 isolate->set_deopt_id(0); | 131 isolate->set_deopt_id(0); |
| 133 LongJump* old_base = isolate->long_jump_base(); | 132 LongJump* old_base = isolate->long_jump_base(); |
| 134 LongJump bailout_jump; | 133 LongJump bailout_jump; |
| 135 isolate->set_long_jump_base(&bailout_jump); | 134 isolate->set_long_jump_base(&bailout_jump); |
| 136 if (setjmp(*bailout_jump.Set()) == 0) { | 135 if (setjmp(*bailout_jump.Set()) == 0) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 157 isolate->set_ic_data_array( | 156 isolate->set_ic_data_array( |
| 158 ExtractTypeFeedbackArray(unoptimized_code)); | 157 ExtractTypeFeedbackArray(unoptimized_code)); |
| 159 } | 158 } |
| 160 } | 159 } |
| 161 | 160 |
| 162 // Build the flow graph. | 161 // Build the flow graph. |
| 163 FlowGraphBuilder builder(parsed_function); | 162 FlowGraphBuilder builder(parsed_function); |
| 164 flow_graph = builder.BuildGraph(); | 163 flow_graph = builder.BuildGraph(); |
| 165 | 164 |
| 166 // Transform to SSA. | 165 // Transform to SSA. |
| 167 if (optimized && use_ssa) flow_graph->ComputeSSA(); | 166 if (optimized) { |
| 167 flow_graph->ComputeSSA(); | |
| 168 } | |
| 168 | 169 |
| 169 if (FLAG_print_flow_graph) { | 170 if (FLAG_print_flow_graph) { |
| 170 OS::Print("Before Optimizations\n"); | 171 OS::Print("Before Optimizations\n"); |
| 171 FlowGraphPrinter printer(*flow_graph); | 172 FlowGraphPrinter printer(*flow_graph); |
| 172 printer.PrintBlocks(); | 173 printer.PrintBlocks(); |
| 173 } | 174 } |
| 174 if (Dart::flow_graph_writer() != NULL) { | 175 if (Dart::flow_graph_writer() != NULL) { |
| 175 // Write flow graph to file. | 176 // Write flow graph to file. |
| 176 FlowGraphVisualizer printer(*flow_graph); | 177 FlowGraphVisualizer printer(*flow_graph); |
| 177 printer.PrintFunction(); | 178 printer.PrintFunction(); |
| 178 } | 179 } |
| 179 | 180 |
| 180 if (optimized) { | 181 if (optimized) { |
| 181 FlowGraphOptimizer optimizer(*flow_graph, use_ssa); | 182 FlowGraphOptimizer optimizer(*flow_graph); |
| 182 optimizer.ApplyICData(); | 183 optimizer.ApplyICData(); |
| 183 | 184 |
| 184 // Propagate types and eliminate more type tests. | 185 // Propagate types and eliminate more type tests. |
| 185 FlowGraphTypePropagator propagator(*flow_graph, optimized && use_ssa); | 186 FlowGraphTypePropagator propagator(*flow_graph); |
| 186 propagator.PropagateTypes(); | 187 propagator.PropagateTypes(); |
| 187 | 188 |
| 188 | 189 |
| 189 if (use_ssa) { | 190 // Do optimizations that depend on the propagated type information. |
| 190 // Do optimizations that depend on the propagated type information. | 191 optimizer.OptimizeComputations(); |
| 191 optimizer.OptimizeComputations(); | |
| 192 | 192 |
| 193 if (FLAG_local_cse) { | 193 if (FLAG_local_cse) { |
| 194 LocalCSE local_cse(*flow_graph); | 194 LocalCSE local_cse(*flow_graph); |
| 195 local_cse.Optimize(); | 195 local_cse.Optimize(); |
| 196 } | 196 } |
| 197 | 197 |
| 198 // Perform register allocation on the SSA graph. | 198 // Perform register allocation on the SSA graph. |
| 199 FlowGraphAllocator allocator(*flow_graph); | 199 FlowGraphAllocator allocator(*flow_graph); |
| 200 allocator.AllocateRegisters(); | 200 allocator.AllocateRegisters(); |
| 201 } | |
| 202 | 201 |
| 203 if (FLAG_print_flow_graph) { | 202 if (FLAG_print_flow_graph) { |
| 204 OS::Print("After Optimizations:\n"); | 203 OS::Print("After Optimizations:\n"); |
| 205 FlowGraphPrinter printer(*flow_graph); | 204 FlowGraphPrinter printer(*flow_graph); |
| 206 printer.PrintBlocks(); | 205 printer.PrintBlocks(); |
| 207 } | 206 } |
| 208 } | 207 } |
| 209 } | 208 } |
| 210 | 209 |
| 211 bool is_leaf = false; | 210 bool is_leaf = false; |
| 212 if (optimized) { | 211 if (optimized) { |
| 213 FlowGraphAnalyzer analyzer(*flow_graph); | 212 FlowGraphAnalyzer analyzer(*flow_graph); |
| 214 analyzer.Analyze(); | 213 analyzer.Analyze(); |
| 215 is_leaf = analyzer.is_leaf(); | 214 is_leaf = analyzer.is_leaf(); |
| 216 } | 215 } |
| 217 Assembler assembler; | 216 Assembler assembler; |
| 218 FlowGraphCompiler graph_compiler(&assembler, | 217 FlowGraphCompiler graph_compiler(&assembler, |
| 219 *flow_graph, | 218 *flow_graph, |
| 220 optimized, | 219 optimized, |
| 221 optimized && use_ssa, | |
| 222 is_leaf); | 220 is_leaf); |
| 223 { | 221 { |
| 224 TimerScope timer(FLAG_compiler_stats, | 222 TimerScope timer(FLAG_compiler_stats, |
| 225 &CompilerStats::graphcompiler_timer, | 223 &CompilerStats::graphcompiler_timer, |
| 226 isolate); | 224 isolate); |
| 227 graph_compiler.CompileGraph(); | 225 graph_compiler.CompileGraph(); |
| 228 } | 226 } |
| 229 { | 227 { |
| 230 TimerScope timer(FLAG_compiler_stats, | 228 TimerScope timer(FLAG_compiler_stats, |
| 231 &CompilerStats::codefinalizer_timer, | 229 &CompilerStats::codefinalizer_timer, |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 255 is_compiled = true; | 253 is_compiled = true; |
| 256 } else { | 254 } else { |
| 257 // We bailed out. | 255 // We bailed out. |
| 258 Error& bailout_error = Error::Handle( | 256 Error& bailout_error = Error::Handle( |
| 259 isolate->object_store()->sticky_error()); | 257 isolate->object_store()->sticky_error()); |
| 260 isolate->object_store()->clear_sticky_error(); | 258 isolate->object_store()->clear_sticky_error(); |
| 261 if (FLAG_trace_bailout) { | 259 if (FLAG_trace_bailout) { |
| 262 OS::Print("%s\n", bailout_error.ToErrorCString()); | 260 OS::Print("%s\n", bailout_error.ToErrorCString()); |
| 263 } | 261 } |
| 264 // We only bail out from generating ssa code. | 262 // We only bail out from generating ssa code. |
| 265 ASSERT(optimized && use_ssa); | 263 ASSERT(optimized); |
| 266 is_compiled = false; | 264 is_compiled = false; |
| 267 } | 265 } |
| 268 // Reset global isolate state. | 266 // Reset global isolate state. |
| 269 isolate->set_ic_data_array(Array::null()); | 267 isolate->set_ic_data_array(Array::null()); |
| 270 isolate->set_long_jump_base(old_base); | 268 isolate->set_long_jump_base(old_base); |
| 271 isolate->set_deopt_id(prev_deopt_id); | 269 isolate->set_deopt_id(prev_deopt_id); |
| 272 return is_compiled; | 270 return is_compiled; |
| 273 } | 271 } |
| 274 | 272 |
| 275 | 273 |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 390 ParsedFunction parsed_function(function); | 388 ParsedFunction parsed_function(function); |
| 391 if (FLAG_trace_compiler) { | 389 if (FLAG_trace_compiler) { |
| 392 OS::Print("Compiling %sfunction: '%s' @ token %d\n", | 390 OS::Print("Compiling %sfunction: '%s' @ token %d\n", |
| 393 (optimized ? "optimized " : ""), | 391 (optimized ? "optimized " : ""), |
| 394 function.ToFullyQualifiedCString(), | 392 function.ToFullyQualifiedCString(), |
| 395 function.token_pos()); | 393 function.token_pos()); |
| 396 } | 394 } |
| 397 Parser::ParseFunction(&parsed_function); | 395 Parser::ParseFunction(&parsed_function); |
| 398 parsed_function.AllocateVariables(); | 396 parsed_function.AllocateVariables(); |
| 399 | 397 |
| 400 if (!CompileParsedFunctionHelper(parsed_function, | 398 CompileParsedFunctionHelper(parsed_function, optimized); |
|
Florian Schneider
2012/08/21 12:50:01
When bailing out, we should mark the function as n
| |
| 401 optimized, | |
| 402 FLAG_use_ssa)) { | |
| 403 // Compile again using non-ssa code generation. | |
| 404 // Re-parse because of side-effects to the AST during compilation. | |
| 405 ParsedFunction parsed_function(function); | |
| 406 Parser::ParseFunction(&parsed_function); | |
| 407 parsed_function.AllocateVariables(); | |
| 408 CompileParsedFunctionHelper(parsed_function, optimized, false); | |
| 409 } | |
| 410 | 399 |
| 411 if (FLAG_trace_compiler) { | 400 if (FLAG_trace_compiler) { |
| 412 OS::Print("--> '%s' entry: 0x%x\n", | 401 OS::Print("--> '%s' entry: 0x%x\n", |
| 413 function.ToFullyQualifiedCString(), | 402 function.ToFullyQualifiedCString(), |
| 414 Code::Handle(function.CurrentCode()).EntryPoint()); | 403 Code::Handle(function.CurrentCode()).EntryPoint()); |
| 415 } | 404 } |
| 416 if (Isolate::Current()->debugger()->IsActive()) { | 405 if (Isolate::Current()->debugger()->IsActive()) { |
| 417 Isolate::Current()->debugger()->NotifyCompilation(function); | 406 Isolate::Current()->debugger()->NotifyCompilation(function); |
| 418 } | 407 } |
| 419 if (FLAG_disassemble) { | 408 if (FLAG_disassemble) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 447 } | 436 } |
| 448 | 437 |
| 449 | 438 |
| 450 RawError* Compiler::CompileParsedFunction( | 439 RawError* Compiler::CompileParsedFunction( |
| 451 const ParsedFunction& parsed_function) { | 440 const ParsedFunction& parsed_function) { |
| 452 Isolate* isolate = Isolate::Current(); | 441 Isolate* isolate = Isolate::Current(); |
| 453 LongJump* base = isolate->long_jump_base(); | 442 LongJump* base = isolate->long_jump_base(); |
| 454 LongJump jump; | 443 LongJump jump; |
| 455 isolate->set_long_jump_base(&jump); | 444 isolate->set_long_jump_base(&jump); |
| 456 if (setjmp(*jump.Set()) == 0) { | 445 if (setjmp(*jump.Set()) == 0) { |
| 457 // Non-optimized, non-ssa code generator. | 446 // Non-optimized code generator. |
| 458 CompileParsedFunctionHelper(parsed_function, false, false); | 447 CompileParsedFunctionHelper(parsed_function, false); |
| 459 isolate->set_long_jump_base(base); | 448 isolate->set_long_jump_base(base); |
| 460 return Error::null(); | 449 return Error::null(); |
| 461 } else { | 450 } else { |
| 462 Error& error = Error::Handle(); | 451 Error& error = Error::Handle(); |
| 463 // We got an error during compilation. | 452 // We got an error during compilation. |
| 464 error = isolate->object_store()->sticky_error(); | 453 error = isolate->object_store()->sticky_error(); |
| 465 isolate->object_store()->clear_sticky_error(); | 454 isolate->object_store()->clear_sticky_error(); |
| 466 isolate->set_long_jump_base(base); | 455 isolate->set_long_jump_base(base); |
| 467 return error.raw(); | 456 return error.raw(); |
| 468 } | 457 } |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 524 // would compile func automatically. We are checking fewer invariants | 513 // would compile func automatically. We are checking fewer invariants |
| 525 // here. | 514 // here. |
| 526 ParsedFunction parsed_function(func); | 515 ParsedFunction parsed_function(func); |
| 527 parsed_function.SetNodeSequence(fragment); | 516 parsed_function.SetNodeSequence(fragment); |
| 528 parsed_function.set_default_parameter_values(Array::Handle()); | 517 parsed_function.set_default_parameter_values(Array::Handle()); |
| 529 parsed_function.set_expression_temp_var( | 518 parsed_function.set_expression_temp_var( |
| 530 ParsedFunction::CreateExpressionTempVar(0)); | 519 ParsedFunction::CreateExpressionTempVar(0)); |
| 531 fragment->scope()->AddVariable(parsed_function.expression_temp_var()); | 520 fragment->scope()->AddVariable(parsed_function.expression_temp_var()); |
| 532 parsed_function.AllocateVariables(); | 521 parsed_function.AllocateVariables(); |
| 533 | 522 |
| 534 // Non-optimized, non-ssa code generator. | 523 // Non-optimized code generator. |
| 535 CompileParsedFunctionHelper(parsed_function, false, false); | 524 CompileParsedFunctionHelper(parsed_function, false); |
| 536 | 525 |
| 537 GrowableArray<const Object*> arguments; // no arguments. | 526 GrowableArray<const Object*> arguments; // no arguments. |
| 538 const Array& kNoArgumentNames = Array::Handle(); | 527 const Array& kNoArgumentNames = Array::Handle(); |
| 539 Object& result = Object::Handle(); | 528 Object& result = Object::Handle(); |
| 540 result = DartEntry::InvokeStatic(func, | 529 result = DartEntry::InvokeStatic(func, |
| 541 arguments, | 530 arguments, |
| 542 kNoArgumentNames); | 531 kNoArgumentNames); |
| 543 isolate->set_long_jump_base(base); | 532 isolate->set_long_jump_base(base); |
| 544 return result.raw(); | 533 return result.raw(); |
| 545 } else { | 534 } else { |
| 546 Object& result = Object::Handle(); | 535 Object& result = Object::Handle(); |
| 547 result = isolate->object_store()->sticky_error(); | 536 result = isolate->object_store()->sticky_error(); |
| 548 isolate->object_store()->clear_sticky_error(); | 537 isolate->object_store()->clear_sticky_error(); |
| 549 isolate->set_long_jump_base(base); | 538 isolate->set_long_jump_base(base); |
| 550 return result.raw(); | 539 return result.raw(); |
| 551 } | 540 } |
| 552 UNREACHABLE(); | 541 UNREACHABLE(); |
| 553 return Object::null(); | 542 return Object::null(); |
| 554 } | 543 } |
| 555 | 544 |
| 556 } // namespace dart | 545 } // namespace dart |
| OLD | NEW |