| 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 222 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 } | 233 } |
| 234 function.SwitchToUnoptimizedCode(); | 234 function.SwitchToUnoptimizedCode(); |
| 235 if (FLAG_trace_compiler) { | 235 if (FLAG_trace_compiler) { |
| 236 OS::Print("--> restoring entry at %#"Px"\n", | 236 OS::Print("--> restoring entry at %#"Px"\n", |
| 237 Code::Handle(function.unoptimized_code()).EntryPoint()); | 237 Code::Handle(function.unoptimized_code()).EntryPoint()); |
| 238 } | 238 } |
| 239 } | 239 } |
| 240 | 240 |
| 241 | 241 |
| 242 // Return false if bailed out. | 242 // Return false if bailed out. |
| 243 static bool CompileParsedFunctionHelper(const ParsedFunction& parsed_function, | 243 static bool CompileParsedFunctionHelper(ParsedFunction* parsed_function, |
| 244 bool optimized) { | 244 bool optimized) { |
| 245 if (optimized && !parsed_function.function().is_optimizable()) { | 245 const Function& function = parsed_function->function(); |
| 246 if (optimized && !function.is_optimizable()) { |
| 246 return false; | 247 return false; |
| 247 } | 248 } |
| 248 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); | 249 TimerScope timer(FLAG_compiler_stats, &CompilerStats::codegen_timer); |
| 249 bool is_compiled = false; | 250 bool is_compiled = false; |
| 250 Isolate* isolate = Isolate::Current(); | 251 Isolate* isolate = Isolate::Current(); |
| 251 HANDLESCOPE(isolate); | 252 HANDLESCOPE(isolate); |
| 252 const intptr_t prev_deopt_id = isolate->deopt_id(); | 253 const intptr_t prev_deopt_id = isolate->deopt_id(); |
| 253 isolate->set_deopt_id(0); | 254 isolate->set_deopt_id(0); |
| 254 LongJump* old_base = isolate->long_jump_base(); | 255 LongJump* old_base = isolate->long_jump_base(); |
| 255 LongJump bailout_jump; | 256 LongJump bailout_jump; |
| 256 isolate->set_long_jump_base(&bailout_jump); | 257 isolate->set_long_jump_base(&bailout_jump); |
| 257 if (setjmp(*bailout_jump.Set()) == 0) { | 258 if (setjmp(*bailout_jump.Set()) == 0) { |
| 258 FlowGraph* flow_graph = NULL; | 259 FlowGraph* flow_graph = NULL; |
| 259 // TimerScope needs an isolate to be properly terminated in case of a | 260 // TimerScope needs an isolate to be properly terminated in case of a |
| 260 // LongJump. | 261 // LongJump. |
| 261 { | 262 { |
| 262 TimerScope timer(FLAG_compiler_stats, | 263 TimerScope timer(FLAG_compiler_stats, |
| 263 &CompilerStats::graphbuilder_timer, | 264 &CompilerStats::graphbuilder_timer, |
| 264 isolate); | 265 isolate); |
| 265 Array& ic_data_array = Array::Handle(); | 266 Array& ic_data_array = Array::Handle(); |
| 266 if (optimized) { | 267 if (optimized) { |
| 267 ASSERT(parsed_function.function().HasCode()); | 268 ASSERT(function.HasCode()); |
| 268 // Extract type feedback before the graph is built, as the graph | 269 // Extract type feedback before the graph is built, as the graph |
| 269 // builder uses it to attach it to nodes. | 270 // builder uses it to attach it to nodes. |
| 270 // Do not use type feedback to optimize a function that was | 271 // Do not use type feedback to optimize a function that was |
| 271 // deoptimized too often. | 272 // deoptimized too often. |
| 272 if (parsed_function.function().deoptimization_counter() < | 273 if (function.deoptimization_counter() < |
| 273 FLAG_deoptimization_counter_threshold) { | 274 FLAG_deoptimization_counter_threshold) { |
| 274 const Code& unoptimized_code = | 275 const Code& unoptimized_code = |
| 275 Code::Handle(parsed_function.function().unoptimized_code()); | 276 Code::Handle(function.unoptimized_code()); |
| 276 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); | 277 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); |
| 277 } | 278 } |
| 278 } | 279 } |
| 279 | 280 |
| 280 // Build the flow graph. | 281 // Build the flow graph. |
| 281 FlowGraphBuilder builder(parsed_function, | 282 FlowGraphBuilder builder(parsed_function, |
| 282 ic_data_array, | 283 ic_data_array, |
| 283 NULL); // NULL = not inlining. | 284 NULL); // NULL = not inlining. |
| 284 flow_graph = builder.BuildGraph(); | 285 flow_graph = builder.BuildGraph(); |
| 285 } | 286 } |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 389 if (DominatorBasedCSE::Optimize(flow_graph)) { | 390 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 390 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 391 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 391 // Do another round of CSE to take secondary effects into account: | 392 // Do another round of CSE to take secondary effects into account: |
| 392 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) | 393 // e.g. when eliminating dependent loads (a.x[0] + a.x[0]) |
| 393 // TODO(fschneider): Change to a one-pass optimization pass. | 394 // TODO(fschneider): Change to a one-pass optimization pass. |
| 394 DominatorBasedCSE::Optimize(flow_graph); | 395 DominatorBasedCSE::Optimize(flow_graph); |
| 395 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 396 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 396 } | 397 } |
| 397 } | 398 } |
| 398 if (FLAG_loop_invariant_code_motion && | 399 if (FLAG_loop_invariant_code_motion && |
| 399 (parsed_function.function().deoptimization_counter() < | 400 (function.deoptimization_counter() < |
| 400 (FLAG_deoptimization_counter_threshold - 1))) { | 401 (FLAG_deoptimization_counter_threshold - 1))) { |
| 401 LICM licm(flow_graph); | 402 LICM licm(flow_graph); |
| 402 licm.Optimize(); | 403 licm.Optimize(); |
| 403 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 404 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 404 } | 405 } |
| 405 flow_graph->RemoveRedefinitions(); | 406 flow_graph->RemoveRedefinitions(); |
| 406 | 407 |
| 407 if (FLAG_range_analysis) { | 408 if (FLAG_range_analysis) { |
| 408 // We have to perform range analysis after LICM because it | 409 // We have to perform range analysis after LICM because it |
| 409 // optimistically moves CheckSmi through phis into loop preheaders | 410 // optimistically moves CheckSmi through phis into loop preheaders |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 { | 479 { |
| 479 TimerScope timer(FLAG_compiler_stats, | 480 TimerScope timer(FLAG_compiler_stats, |
| 480 &CompilerStats::graphcompiler_timer, | 481 &CompilerStats::graphcompiler_timer, |
| 481 isolate); | 482 isolate); |
| 482 graph_compiler.CompileGraph(); | 483 graph_compiler.CompileGraph(); |
| 483 } | 484 } |
| 484 { | 485 { |
| 485 TimerScope timer(FLAG_compiler_stats, | 486 TimerScope timer(FLAG_compiler_stats, |
| 486 &CompilerStats::codefinalizer_timer, | 487 &CompilerStats::codefinalizer_timer, |
| 487 isolate); | 488 isolate); |
| 488 const Function& function = parsed_function.function(); | |
| 489 const Code& code = Code::Handle( | 489 const Code& code = Code::Handle( |
| 490 Code::FinalizeCode(function, &assembler, optimized)); | 490 Code::FinalizeCode(function, &assembler, optimized)); |
| 491 code.set_is_optimized(optimized); | 491 code.set_is_optimized(optimized); |
| 492 graph_compiler.FinalizePcDescriptors(code); | 492 graph_compiler.FinalizePcDescriptors(code); |
| 493 graph_compiler.FinalizeDeoptInfo(code); | 493 graph_compiler.FinalizeDeoptInfo(code); |
| 494 graph_compiler.FinalizeStackmaps(code); | 494 graph_compiler.FinalizeStackmaps(code); |
| 495 graph_compiler.FinalizeVarDescriptors(code); | 495 graph_compiler.FinalizeVarDescriptors(code); |
| 496 graph_compiler.FinalizeExceptionHandlers(code); | 496 graph_compiler.FinalizeExceptionHandlers(code); |
| 497 graph_compiler.FinalizeComments(code); | 497 graph_compiler.FinalizeComments(code); |
| 498 graph_compiler.FinalizeStaticCallTargetsTable(code); | 498 graph_compiler.FinalizeStaticCallTargetsTable(code); |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 693 function.token_pos(), | 693 function.token_pos(), |
| 694 (function.end_token_pos() - function.token_pos())); | 694 (function.end_token_pos() - function.token_pos())); |
| 695 } | 695 } |
| 696 { | 696 { |
| 697 HANDLESCOPE(isolate); | 697 HANDLESCOPE(isolate); |
| 698 Parser::ParseFunction(parsed_function); | 698 Parser::ParseFunction(parsed_function); |
| 699 parsed_function->AllocateVariables(); | 699 parsed_function->AllocateVariables(); |
| 700 } | 700 } |
| 701 | 701 |
| 702 const bool success = | 702 const bool success = |
| 703 CompileParsedFunctionHelper(*parsed_function, optimized); | 703 CompileParsedFunctionHelper(parsed_function, optimized); |
| 704 if (optimized && !success) { | 704 if (optimized && !success) { |
| 705 // Optimizer bailed out. Disable optimizations and to never try again. | 705 // Optimizer bailed out. Disable optimizations and to never try again. |
| 706 if (FLAG_trace_compiler) { | 706 if (FLAG_trace_compiler) { |
| 707 OS::Print("--> disabling optimizations for '%s'\n", | 707 OS::Print("--> disabling optimizations for '%s'\n", |
| 708 function.ToFullyQualifiedCString()); | 708 function.ToFullyQualifiedCString()); |
| 709 } else if (FLAG_trace_failed_optimization_attempts) { | 709 } else if (FLAG_trace_failed_optimization_attempts) { |
| 710 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); | 710 OS::Print("Cannot optimize: %s\n", function.ToFullyQualifiedCString()); |
| 711 } | 711 } |
| 712 function.set_is_optimizable(false); | 712 function.set_is_optimizable(false); |
| 713 isolate->set_long_jump_base(base); | 713 isolate->set_long_jump_base(base); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 755 return CompileFunctionHelper(function, false); // Non-optimized. | 755 return CompileFunctionHelper(function, false); // Non-optimized. |
| 756 } | 756 } |
| 757 | 757 |
| 758 | 758 |
| 759 RawError* Compiler::CompileOptimizedFunction(const Function& function) { | 759 RawError* Compiler::CompileOptimizedFunction(const Function& function) { |
| 760 return CompileFunctionHelper(function, true); // Optimized. | 760 return CompileFunctionHelper(function, true); // Optimized. |
| 761 } | 761 } |
| 762 | 762 |
| 763 | 763 |
| 764 RawError* Compiler::CompileParsedFunction( | 764 RawError* Compiler::CompileParsedFunction( |
| 765 const ParsedFunction& parsed_function) { | 765 ParsedFunction* parsed_function) { |
| 766 Isolate* isolate = Isolate::Current(); | 766 Isolate* isolate = Isolate::Current(); |
| 767 LongJump* base = isolate->long_jump_base(); | 767 LongJump* base = isolate->long_jump_base(); |
| 768 LongJump jump; | 768 LongJump jump; |
| 769 isolate->set_long_jump_base(&jump); | 769 isolate->set_long_jump_base(&jump); |
| 770 if (setjmp(*jump.Set()) == 0) { | 770 if (setjmp(*jump.Set()) == 0) { |
| 771 // Non-optimized code generator. | 771 // Non-optimized code generator. |
| 772 CompileParsedFunctionHelper(parsed_function, false); | 772 CompileParsedFunctionHelper(parsed_function, false); |
| 773 if (FLAG_disassemble) { | 773 if (FLAG_disassemble) { |
| 774 DisassembleCode(parsed_function.function(), false); | 774 DisassembleCode(parsed_function->function(), false); |
| 775 } | 775 } |
| 776 isolate->set_long_jump_base(base); | 776 isolate->set_long_jump_base(base); |
| 777 return Error::null(); | 777 return Error::null(); |
| 778 } else { | 778 } else { |
| 779 Error& error = Error::Handle(); | 779 Error& error = Error::Handle(); |
| 780 // We got an error during compilation. | 780 // We got an error during compilation. |
| 781 error = isolate->object_store()->sticky_error(); | 781 error = isolate->object_store()->sticky_error(); |
| 782 isolate->object_store()->clear_sticky_error(); | 782 isolate->object_store()->clear_sticky_error(); |
| 783 isolate->set_long_jump_base(base); | 783 isolate->set_long_jump_base(base); |
| 784 return error.raw(); | 784 return error.raw(); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 844 func.SetNumOptionalParameters(0, true); | 844 func.SetNumOptionalParameters(0, true); |
| 845 // Manually generated AST, do not recompile. | 845 // Manually generated AST, do not recompile. |
| 846 func.set_is_optimizable(false); | 846 func.set_is_optimizable(false); |
| 847 | 847 |
| 848 // We compile the function here, even though InvokeStatic() below | 848 // We compile the function here, even though InvokeStatic() below |
| 849 // would compile func automatically. We are checking fewer invariants | 849 // would compile func automatically. We are checking fewer invariants |
| 850 // here. | 850 // here. |
| 851 ParsedFunction* parsed_function = new ParsedFunction(func); | 851 ParsedFunction* parsed_function = new ParsedFunction(func); |
| 852 parsed_function->SetNodeSequence(fragment); | 852 parsed_function->SetNodeSequence(fragment); |
| 853 parsed_function->set_default_parameter_values(Array::ZoneHandle()); | 853 parsed_function->set_default_parameter_values(Array::ZoneHandle()); |
| 854 parsed_function->set_expression_temp_var( | 854 parsed_function->EnsureExpressionTemp(); |
| 855 ParsedFunction::CreateExpressionTempVar(0)); | |
| 856 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); | 855 fragment->scope()->AddVariable(parsed_function->expression_temp_var()); |
| 857 parsed_function->AllocateVariables(); | 856 parsed_function->AllocateVariables(); |
| 858 | 857 |
| 859 // Non-optimized code generator. | 858 // Non-optimized code generator. |
| 860 CompileParsedFunctionHelper(*parsed_function, false); | 859 CompileParsedFunctionHelper(parsed_function, false); |
| 861 | 860 |
| 862 const Object& result = Object::Handle( | 861 const Object& result = Object::Handle( |
| 863 DartEntry::InvokeFunction(func, Object::empty_array())); | 862 DartEntry::InvokeFunction(func, Object::empty_array())); |
| 864 isolate->set_long_jump_base(base); | 863 isolate->set_long_jump_base(base); |
| 865 return result.raw(); | 864 return result.raw(); |
| 866 } else { | 865 } else { |
| 867 const Object& result = | 866 const Object& result = |
| 868 Object::Handle(isolate->object_store()->sticky_error()); | 867 Object::Handle(isolate->object_store()->sticky_error()); |
| 869 isolate->object_store()->clear_sticky_error(); | 868 isolate->object_store()->clear_sticky_error(); |
| 870 isolate->set_long_jump_base(base); | 869 isolate->set_long_jump_base(base); |
| 871 return result.raw(); | 870 return result.raw(); |
| 872 } | 871 } |
| 873 UNREACHABLE(); | 872 UNREACHABLE(); |
| 874 return Object::null(); | 873 return Object::null(); |
| 875 } | 874 } |
| 876 | 875 |
| 877 } // namespace dart | 876 } // namespace dart |
| OLD | NEW |