| 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/block_scheduler.h" | 10 #include "vm/block_scheduler.h" |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 "Print the deopt-id to ICData map in optimizing compiler."); | 58 "Print the deopt-id to ICData map in optimizing compiler."); |
| 59 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); | 59 DEFINE_FLAG(bool, range_analysis, true, "Enable range analysis"); |
| 60 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); | 60 DEFINE_FLAG(bool, reorder_basic_blocks, true, "Enable basic-block reordering."); |
| 61 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); | 61 DEFINE_FLAG(bool, trace_compiler, false, "Trace compiler operations."); |
| 62 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); | 62 DEFINE_FLAG(bool, trace_bailout, false, "Print bailout from ssa compiler."); |
| 63 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); | 63 DEFINE_FLAG(bool, use_inlining, true, "Enable call-site inlining"); |
| 64 DEFINE_FLAG(bool, verify_compiler, false, | 64 DEFINE_FLAG(bool, verify_compiler, false, |
| 65 "Enable compiler verification assertions"); | 65 "Enable compiler verification assertions"); |
| 66 | 66 |
| 67 DECLARE_FLAG(bool, trace_failed_optimization_attempts); | 67 DECLARE_FLAG(bool, trace_failed_optimization_attempts); |
| 68 DECLARE_FLAG(bool, trace_inlining_intervals); |
| 69 DECLARE_FLAG(bool, trace_irregexp); |
| 68 DECLARE_FLAG(bool, trace_patching); | 70 DECLARE_FLAG(bool, trace_patching); |
| 69 DECLARE_FLAG(bool, trace_irregexp); | |
| 70 | 71 |
| 71 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove | 72 // TODO(zerny): Factor out unoptimizing/optimizing pipelines and remove |
| 72 // separate helpers functions & `optimizing` args. | 73 // separate helpers functions & `optimizing` args. |
| 73 class CompilationPipeline : public ZoneAllocated { | 74 class CompilationPipeline : public ZoneAllocated { |
| 74 public: | 75 public: |
| 75 static CompilationPipeline* New(Isolate* isolate, const Function& function); | 76 static CompilationPipeline* New(Isolate* isolate, const Function& function); |
| 76 | 77 |
| 77 virtual void ParseFunction(ParsedFunction* parsed_function) = 0; | 78 virtual void ParseFunction(ParsedFunction* parsed_function) = 0; |
| 78 virtual FlowGraph* BuildFlowGraph( | 79 virtual FlowGraph* BuildFlowGraph( |
| 79 ParsedFunction* parsed_function, | 80 ParsedFunction* parsed_function, |
| (...skipping 374 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 454 flow_graph->ComputeSSA(0, NULL); | 455 flow_graph->ComputeSSA(0, NULL); |
| 455 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 456 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 456 if (print_flow_graph) { | 457 if (print_flow_graph) { |
| 457 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 458 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
| 458 } | 459 } |
| 459 } | 460 } |
| 460 | 461 |
| 461 // Maps inline_id_to_function[inline_id] -> function. Top scope | 462 // Maps inline_id_to_function[inline_id] -> function. Top scope |
| 462 // function has inline_id 0. The map is populated by the inliner. | 463 // function has inline_id 0. The map is populated by the inliner. |
| 463 GrowableArray<const Function*> inline_id_to_function; | 464 GrowableArray<const Function*> inline_id_to_function; |
| 465 // For a given inlining-id(index) specifies the caller's inlining-id. |
| 466 GrowableArray<intptr_t> caller_inline_id; |
| 464 inline_id_to_function.Add(&function); | 467 inline_id_to_function.Add(&function); |
| 468 // Top scope function has no caller (-1). |
| 469 caller_inline_id.Add(-1); |
| 465 // Collect all instance fields that are loaded in the graph and | 470 // Collect all instance fields that are loaded in the graph and |
| 466 // have non-generic type feedback attached to them that can | 471 // have non-generic type feedback attached to them that can |
| 467 // potentially affect optimizations. | 472 // potentially affect optimizations. |
| 468 if (optimized) { | 473 if (optimized) { |
| 469 TimerScope timer(FLAG_compiler_stats, | 474 TimerScope timer(FLAG_compiler_stats, |
| 470 &CompilerStats::graphoptimizer_timer, | 475 &CompilerStats::graphoptimizer_timer, |
| 471 isolate); | 476 isolate); |
| 472 | 477 |
| 473 FlowGraphOptimizer optimizer(flow_graph); | 478 FlowGraphOptimizer optimizer(flow_graph); |
| 474 optimizer.ApplyICData(); | 479 optimizer.ApplyICData(); |
| 475 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 480 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 476 | 481 |
| 477 // Optimize (a << b) & c patterns, merge operations. | 482 // Optimize (a << b) & c patterns, merge operations. |
| 478 // Run early in order to have more opportunity to optimize left shifts. | 483 // Run early in order to have more opportunity to optimize left shifts. |
| 479 optimizer.TryOptimizePatterns(); | 484 optimizer.TryOptimizePatterns(); |
| 480 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 485 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 481 | 486 |
| 482 FlowGraphInliner::SetInliningId(*flow_graph, 0); | 487 FlowGraphInliner::SetInliningId(flow_graph, 0); |
| 483 | 488 |
| 484 // Inlining (mutates the flow graph) | 489 // Inlining (mutates the flow graph) |
| 485 if (FLAG_use_inlining) { | 490 if (FLAG_use_inlining) { |
| 486 TimerScope timer(FLAG_compiler_stats, | 491 TimerScope timer(FLAG_compiler_stats, |
| 487 &CompilerStats::graphinliner_timer); | 492 &CompilerStats::graphinliner_timer); |
| 488 // Propagate types to create more inlining opportunities. | 493 // Propagate types to create more inlining opportunities. |
| 489 FlowGraphTypePropagator::Propagate(flow_graph); | 494 FlowGraphTypePropagator::Propagate(flow_graph); |
| 490 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 495 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 491 | 496 |
| 492 // Use propagated class-ids to create more inlining opportunities. | 497 // Use propagated class-ids to create more inlining opportunities. |
| 493 optimizer.ApplyClassIds(); | 498 optimizer.ApplyClassIds(); |
| 494 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 499 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 495 | 500 |
| 496 FlowGraphInliner inliner(flow_graph, &inline_id_to_function); | 501 FlowGraphInliner inliner(flow_graph, |
| 502 &inline_id_to_function, |
| 503 &caller_inline_id); |
| 497 inliner.Inline(); | 504 inliner.Inline(); |
| 498 // Use lists are maintained and validated by the inliner. | 505 // Use lists are maintained and validated by the inliner. |
| 499 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 506 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 500 } | 507 } |
| 501 | 508 |
| 502 // Propagate types and eliminate more type tests. | 509 // Propagate types and eliminate more type tests. |
| 503 FlowGraphTypePropagator::Propagate(flow_graph); | 510 FlowGraphTypePropagator::Propagate(flow_graph); |
| 504 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 511 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 505 | 512 |
| 506 // Use propagated class-ids to optimize further. | 513 // Use propagated class-ids to optimize further. |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 // Perform register allocation on the SSA graph. | 686 // Perform register allocation on the SSA graph. |
| 680 FlowGraphAllocator allocator(*flow_graph); | 687 FlowGraphAllocator allocator(*flow_graph); |
| 681 allocator.AllocateRegisters(); | 688 allocator.AllocateRegisters(); |
| 682 if (reorder_blocks) block_scheduler.ReorderBlocks(); | 689 if (reorder_blocks) block_scheduler.ReorderBlocks(); |
| 683 | 690 |
| 684 if (print_flow_graph) { | 691 if (print_flow_graph) { |
| 685 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 692 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
| 686 } | 693 } |
| 687 } | 694 } |
| 688 | 695 |
| 696 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
| 689 Assembler assembler(use_far_branches); | 697 Assembler assembler(use_far_branches); |
| 690 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 698 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
| 691 *parsed_function, optimized, | 699 *parsed_function, optimized, |
| 692 inline_id_to_function); | 700 inline_id_to_function, |
| 701 caller_inline_id); |
| 693 { | 702 { |
| 694 TimerScope timer(FLAG_compiler_stats, | 703 TimerScope timer(FLAG_compiler_stats, |
| 695 &CompilerStats::graphcompiler_timer, | 704 &CompilerStats::graphcompiler_timer, |
| 696 isolate); | 705 isolate); |
| 697 graph_compiler.CompileGraph(); | 706 graph_compiler.CompileGraph(); |
| 698 pipeline->FinalizeCompilation(); | 707 pipeline->FinalizeCompilation(); |
| 699 } | 708 } |
| 700 { | 709 { |
| 701 TimerScope timer(FLAG_compiler_stats, | 710 TimerScope timer(FLAG_compiler_stats, |
| 702 &CompilerStats::codefinalizer_timer, | 711 &CompilerStats::codefinalizer_timer, |
| 703 isolate); | 712 isolate); |
| 704 const Code& code = Code::Handle( | 713 const Code& code = Code::Handle( |
| 705 Code::FinalizeCode(function, &assembler, optimized)); | 714 Code::FinalizeCode(function, &assembler, optimized)); |
| 706 code.set_is_optimized(optimized); | 715 code.set_is_optimized(optimized); |
| 707 code.set_inlined_intervals(graph_compiler.inlined_code_intervals()); | 716 code.set_inlined_intervals(graph_compiler.inlined_code_intervals()); |
| 717 code.set_inlined_id_to_function( |
| 718 Array::Handle(graph_compiler.InliningIdToFunction())); |
| 708 graph_compiler.FinalizePcDescriptors(code); | 719 graph_compiler.FinalizePcDescriptors(code); |
| 709 graph_compiler.FinalizeDeoptInfo(code); | 720 graph_compiler.FinalizeDeoptInfo(code); |
| 710 graph_compiler.FinalizeStackmaps(code); | 721 graph_compiler.FinalizeStackmaps(code); |
| 711 graph_compiler.FinalizeVarDescriptors(code); | 722 graph_compiler.FinalizeVarDescriptors(code); |
| 712 graph_compiler.FinalizeExceptionHandlers(code); | 723 graph_compiler.FinalizeExceptionHandlers(code); |
| 713 graph_compiler.FinalizeStaticCallTargetsTable(code); | 724 graph_compiler.FinalizeStaticCallTargetsTable(code); |
| 714 | 725 |
| 715 if (optimized) { | 726 if (optimized) { |
| 716 if (osr_id == Isolate::kNoDeoptId) { | 727 if (osr_id == Isolate::kNoDeoptId) { |
| 717 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); | 728 CodePatcher::PatchEntry(Code::Handle(function.CurrentCode())); |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 930 code.raw()); | 941 code.raw()); |
| 931 } else { | 942 } else { |
| 932 ISL_Print(" 0x%" Px ": %s, %p\n", | 943 ISL_Print(" 0x%" Px ": %s, %p\n", |
| 933 start + offset.Value(), | 944 start + offset.Value(), |
| 934 function.ToFullyQualifiedCString(), | 945 function.ToFullyQualifiedCString(), |
| 935 code.raw()); | 946 code.raw()); |
| 936 } | 947 } |
| 937 } | 948 } |
| 938 ISL_Print("}\n"); | 949 ISL_Print("}\n"); |
| 939 } | 950 } |
| 951 if (optimized && FLAG_trace_inlining_intervals) { |
| 952 code.DumpInlinedIntervals(); |
| 953 } |
| 940 } | 954 } |
| 941 | 955 |
| 942 | 956 |
| 943 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, | 957 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, |
| 944 const Function& function, | 958 const Function& function, |
| 945 bool optimized, | 959 bool optimized, |
| 946 intptr_t osr_id) { | 960 intptr_t osr_id) { |
| 947 Thread* thread = Thread::Current(); | 961 Thread* thread = Thread::Current(); |
| 948 Isolate* isolate = thread->isolate(); | 962 Isolate* isolate = thread->isolate(); |
| 949 StackZone stack_zone(isolate); | 963 StackZone stack_zone(isolate); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1003 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { | 1017 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { |
| 1004 DisassembleCode(function, optimized); | 1018 DisassembleCode(function, optimized); |
| 1005 } else if (FLAG_disassemble_optimized && | 1019 } else if (FLAG_disassemble_optimized && |
| 1006 optimized && | 1020 optimized && |
| 1007 FlowGraphPrinter::ShouldPrint(function)) { | 1021 FlowGraphPrinter::ShouldPrint(function)) { |
| 1008 // TODO(fschneider): Print unoptimized code along with the optimized code. | 1022 // TODO(fschneider): Print unoptimized code along with the optimized code. |
| 1009 ISL_Print("*** BEGIN CODE\n"); | 1023 ISL_Print("*** BEGIN CODE\n"); |
| 1010 DisassembleCode(function, true); | 1024 DisassembleCode(function, true); |
| 1011 ISL_Print("*** END CODE\n"); | 1025 ISL_Print("*** END CODE\n"); |
| 1012 } | 1026 } |
| 1013 | |
| 1014 return Error::null(); | 1027 return Error::null(); |
| 1015 } else { | 1028 } else { |
| 1016 Error& error = Error::Handle(); | 1029 Error& error = Error::Handle(); |
| 1017 // We got an error during compilation. | 1030 // We got an error during compilation. |
| 1018 error = isolate->object_store()->sticky_error(); | 1031 error = isolate->object_store()->sticky_error(); |
| 1019 isolate->object_store()->clear_sticky_error(); | 1032 isolate->object_store()->clear_sticky_error(); |
| 1020 return error.raw(); | 1033 return error.raw(); |
| 1021 } | 1034 } |
| 1022 UNREACHABLE(); | 1035 UNREACHABLE(); |
| 1023 return Error::null(); | 1036 return Error::null(); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1209 const Object& result = | 1222 const Object& result = |
| 1210 PassiveObject::Handle(isolate->object_store()->sticky_error()); | 1223 PassiveObject::Handle(isolate->object_store()->sticky_error()); |
| 1211 isolate->object_store()->clear_sticky_error(); | 1224 isolate->object_store()->clear_sticky_error(); |
| 1212 return result.raw(); | 1225 return result.raw(); |
| 1213 } | 1226 } |
| 1214 UNREACHABLE(); | 1227 UNREACHABLE(); |
| 1215 return Object::null(); | 1228 return Object::null(); |
| 1216 } | 1229 } |
| 1217 | 1230 |
| 1218 } // namespace dart | 1231 } // namespace dart |
| OLD | NEW |