| 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 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 Thread* thread = Thread::Current(); | 267 Thread* thread = Thread::Current(); |
| 268 Error& error = Error::Handle(thread->zone()); | 268 Error& error = Error::Handle(thread->zone()); |
| 269 error = thread->sticky_error(); | 269 error = thread->sticky_error(); |
| 270 thread->clear_sticky_error(); | 270 thread->clear_sticky_error(); |
| 271 return error.raw(); | 271 return error.raw(); |
| 272 } | 272 } |
| 273 } | 273 } |
| 274 | 274 |
| 275 Thread* const thread = Thread::Current(); | 275 Thread* const thread = Thread::Current(); |
| 276 StackZone zone(thread); | 276 StackZone zone(thread); |
| 277 // We remember all the classes that are being compiled in these lists. This | 277 #ifndef PRODUCT |
| 278 // also allows us to reset the marked_for_parsing state in case we see an | |
| 279 // error. | |
| 280 VMTagScope tagScope(thread, VMTag::kCompileClassTagId); | 278 VMTagScope tagScope(thread, VMTag::kCompileClassTagId); |
| 281 TimelineDurationScope tds(thread, | 279 TimelineDurationScope tds(thread, |
| 282 thread->isolate()->GetCompilerStream(), | 280 thread->isolate()->GetCompilerStream(), |
| 283 "CompileClass"); | 281 "CompileClass"); |
| 284 if (tds.enabled()) { | 282 if (tds.enabled()) { |
| 285 tds.SetNumArguments(1); | 283 tds.SetNumArguments(1); |
| 286 tds.CopyArgument(0, "class", cls.ToCString()); | 284 tds.CopyArgument(0, "class", cls.ToCString()); |
| 287 } | 285 } |
| 286 #endif // !PRODUCT |
| 288 | 287 |
| 288 // We remember all the classes that are being compiled in these lists. This |
| 289 // also allows us to reset the marked_for_parsing state in case we see an |
| 290 // error. |
| 289 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4); | 291 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4); |
| 290 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4); | 292 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4); |
| 291 | 293 |
| 292 // Parse the class and all the interfaces it implements and super classes. | 294 // Parse the class and all the interfaces it implements and super classes. |
| 293 LongJumpScope jump; | 295 LongJumpScope jump; |
| 294 if (setjmp(*jump.Set()) == 0) { | 296 if (setjmp(*jump.Set()) == 0) { |
| 295 if (FLAG_trace_compiler) { | 297 if (FLAG_trace_compiler) { |
| 296 THR_Print("Compiling Class '%s'\n", cls.ToCString()); | 298 THR_Print("Compiling Class '%s'\n", cls.ToCString()); |
| 297 } | 299 } |
| 298 | 300 |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 563 // If optimized_result_code is not NULL then it is caller's responsibility | 565 // If optimized_result_code is not NULL then it is caller's responsibility |
| 564 // to install code. | 566 // to install code. |
| 565 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { | 567 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { |
| 566 ASSERT(!FLAG_precompilation); | 568 ASSERT(!FLAG_precompilation); |
| 567 const Function& function = parsed_function()->function(); | 569 const Function& function = parsed_function()->function(); |
| 568 if (optimized() && !function.IsOptimizable()) { | 570 if (optimized() && !function.IsOptimizable()) { |
| 569 return false; | 571 return false; |
| 570 } | 572 } |
| 571 bool is_compiled = false; | 573 bool is_compiled = false; |
| 572 Zone* const zone = thread()->zone(); | 574 Zone* const zone = thread()->zone(); |
| 575 #ifndef PRODUCT |
| 573 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); | 576 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); |
| 577 #endif |
| 574 CSTAT_TIMER_SCOPE(thread(), codegen_timer); | 578 CSTAT_TIMER_SCOPE(thread(), codegen_timer); |
| 575 HANDLESCOPE(thread()); | 579 HANDLESCOPE(thread()); |
| 576 | 580 |
| 577 // We may reattempt compilation if the function needs to be assembled using | 581 // We may reattempt compilation if the function needs to be assembled using |
| 578 // far branches on ARM and MIPS. In the else branch of the setjmp call, | 582 // far branches on ARM and MIPS. In the else branch of the setjmp call, |
| 579 // done is set to false, and use_far_branches is set to true if there is a | 583 // done is set to false, and use_far_branches is set to true if there is a |
| 580 // longjmp from the ARM or MIPS assemblers. In all other paths through this | 584 // longjmp from the ARM or MIPS assemblers. In all other paths through this |
| 581 // while loop, done is set to true. use_far_branches is always false on ia32 | 585 // while loop, done is set to true. use_far_branches is always false on ia32 |
| 582 // and x64. | 586 // and x64. |
| 583 bool done = false; | 587 bool done = false; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 621 if (FLAG_print_ic_data_map) { | 625 if (FLAG_print_ic_data_map) { |
| 622 for (intptr_t i = 0; i < ic_data_array->length(); i++) { | 626 for (intptr_t i = 0; i < ic_data_array->length(); i++) { |
| 623 if ((*ic_data_array)[i] != NULL) { | 627 if ((*ic_data_array)[i] != NULL) { |
| 624 THR_Print("%" Pd " ", i); | 628 THR_Print("%" Pd " ", i); |
| 625 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); | 629 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); |
| 626 } | 630 } |
| 627 } | 631 } |
| 628 } | 632 } |
| 629 } | 633 } |
| 630 | 634 |
| 635 #ifndef PRODUCT |
| 631 TimelineDurationScope tds(thread(), | 636 TimelineDurationScope tds(thread(), |
| 632 compiler_timeline, | 637 compiler_timeline, |
| 633 "BuildFlowGraph"); | 638 "BuildFlowGraph"); |
| 639 #endif // !PRODUCT |
| 634 flow_graph = pipeline->BuildFlowGraph(zone, | 640 flow_graph = pipeline->BuildFlowGraph(zone, |
| 635 parsed_function(), | 641 parsed_function(), |
| 636 *ic_data_array, | 642 *ic_data_array, |
| 637 osr_id()); | 643 osr_id()); |
| 638 } | 644 } |
| 639 | 645 |
| 640 const bool print_flow_graph = | 646 const bool print_flow_graph = |
| 641 (FLAG_print_flow_graph || | 647 (FLAG_print_flow_graph || |
| 642 (optimized() && FLAG_print_flow_graph_optimized)) && | 648 (optimized() && FLAG_print_flow_graph_optimized)) && |
| 643 FlowGraphPrinter::ShouldPrint(function); | 649 FlowGraphPrinter::ShouldPrint(function); |
| 644 | 650 |
| 645 if (print_flow_graph) { | 651 if (print_flow_graph) { |
| 646 if (osr_id() == Compiler::kNoOSRDeoptId) { | 652 if (osr_id() == Compiler::kNoOSRDeoptId) { |
| 647 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); | 653 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); |
| 648 } else { | 654 } else { |
| 649 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); | 655 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); |
| 650 } | 656 } |
| 651 } | 657 } |
| 652 | 658 |
| 653 BlockScheduler block_scheduler(flow_graph); | 659 BlockScheduler block_scheduler(flow_graph); |
| 654 const bool reorder_blocks = | 660 const bool reorder_blocks = |
| 655 FlowGraph::ShouldReorderBlocks(function, optimized()); | 661 FlowGraph::ShouldReorderBlocks(function, optimized()); |
| 656 if (reorder_blocks) { | 662 if (reorder_blocks) { |
| 663 #ifndef PRODUCT |
| 657 TimelineDurationScope tds(thread(), | 664 TimelineDurationScope tds(thread(), |
| 658 compiler_timeline, | 665 compiler_timeline, |
| 659 "BlockScheduler::AssignEdgeWeights"); | 666 "BlockScheduler::AssignEdgeWeights"); |
| 667 #endif // !PRODUCT |
| 660 block_scheduler.AssignEdgeWeights(); | 668 block_scheduler.AssignEdgeWeights(); |
| 661 } | 669 } |
| 662 | 670 |
| 663 if (optimized()) { | 671 if (optimized()) { |
| 672 #ifndef PRODUCT |
| 664 TimelineDurationScope tds(thread(), | 673 TimelineDurationScope tds(thread(), |
| 665 compiler_timeline, | 674 compiler_timeline, |
| 666 "ComputeSSA"); | 675 "ComputeSSA"); |
| 676 #endif // !PRODUCT |
| 667 CSTAT_TIMER_SCOPE(thread(), ssa_timer); | 677 CSTAT_TIMER_SCOPE(thread(), ssa_timer); |
| 668 // Transform to SSA (virtual register 0 and no inlining arguments). | 678 // Transform to SSA (virtual register 0 and no inlining arguments). |
| 669 flow_graph->ComputeSSA(0, NULL); | 679 flow_graph->ComputeSSA(0, NULL); |
| 670 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 680 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 671 if (print_flow_graph) { | 681 if (print_flow_graph) { |
| 672 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); | 682 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); |
| 673 } | 683 } |
| 674 } | 684 } |
| 675 | 685 |
| 676 // Maps inline_id_to_function[inline_id] -> function. Top scope | 686 // Maps inline_id_to_function[inline_id] -> function. Top scope |
| 677 // function has inline_id 0. The map is populated by the inliner. | 687 // function has inline_id 0. The map is populated by the inliner. |
| 678 GrowableArray<const Function*> inline_id_to_function; | 688 GrowableArray<const Function*> inline_id_to_function; |
| 679 // For a given inlining-id(index) specifies the caller's inlining-id. | 689 // For a given inlining-id(index) specifies the caller's inlining-id. |
| 680 GrowableArray<intptr_t> caller_inline_id; | 690 GrowableArray<intptr_t> caller_inline_id; |
| 681 // Collect all instance fields that are loaded in the graph and | 691 // Collect all instance fields that are loaded in the graph and |
| 682 // have non-generic type feedback attached to them that can | 692 // have non-generic type feedback attached to them that can |
| 683 // potentially affect optimizations. | 693 // potentially affect optimizations. |
| 684 if (optimized()) { | 694 if (optimized()) { |
| 695 #ifndef PRODUCT |
| 685 TimelineDurationScope tds(thread(), | 696 TimelineDurationScope tds(thread(), |
| 686 compiler_timeline, | 697 compiler_timeline, |
| 687 "OptimizationPasses"); | 698 "OptimizationPasses"); |
| 699 #endif // !PRODUCT |
| 688 inline_id_to_function.Add(&function); | 700 inline_id_to_function.Add(&function); |
| 689 // Top scope function has no caller (-1). | 701 // Top scope function has no caller (-1). |
| 690 caller_inline_id.Add(-1); | 702 caller_inline_id.Add(-1); |
| 691 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); | 703 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); |
| 692 | 704 |
| 693 FlowGraphOptimizer optimizer(flow_graph, | 705 FlowGraphOptimizer optimizer(flow_graph, |
| 694 use_speculative_inlining, | 706 use_speculative_inlining, |
| 695 NULL); | 707 NULL); |
| 696 optimizer.ApplyICData(); | 708 optimizer.ApplyICData(); |
| 697 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 709 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 698 | 710 |
| 699 // Optimize (a << b) & c patterns, merge operations. | 711 // Optimize (a << b) & c patterns, merge operations. |
| 700 // Run early in order to have more opportunity to optimize left shifts. | 712 // Run early in order to have more opportunity to optimize left shifts. |
| 701 optimizer.TryOptimizePatterns(); | 713 optimizer.TryOptimizePatterns(); |
| 702 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 714 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 703 | 715 |
| 704 FlowGraphInliner::SetInliningId(flow_graph, 0); | 716 FlowGraphInliner::SetInliningId(flow_graph, 0); |
| 705 | 717 |
| 706 // Inlining (mutates the flow graph) | 718 // Inlining (mutates the flow graph) |
| 707 if (FLAG_use_inlining) { | 719 if (FLAG_use_inlining) { |
| 720 #ifndef PRODUCT |
| 708 TimelineDurationScope tds2(thread(), | 721 TimelineDurationScope tds2(thread(), |
| 709 compiler_timeline, | 722 compiler_timeline, |
| 710 "Inlining"); | 723 "Inlining"); |
| 724 #endif // !PRODUCT |
| 711 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); | 725 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); |
| 712 // Propagate types to create more inlining opportunities. | 726 // Propagate types to create more inlining opportunities. |
| 713 FlowGraphTypePropagator::Propagate(flow_graph); | 727 FlowGraphTypePropagator::Propagate(flow_graph); |
| 714 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 728 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 715 | 729 |
| 716 // Use propagated class-ids to create more inlining opportunities. | 730 // Use propagated class-ids to create more inlining opportunities. |
| 717 optimizer.ApplyClassIds(); | 731 optimizer.ApplyClassIds(); |
| 718 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 732 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 719 | 733 |
| 720 FlowGraphInliner inliner(flow_graph, | 734 FlowGraphInliner inliner(flow_graph, |
| 721 &inline_id_to_function, | 735 &inline_id_to_function, |
| 722 &caller_inline_id, | 736 &caller_inline_id, |
| 723 use_speculative_inlining, | 737 use_speculative_inlining, |
| 724 NULL); | 738 NULL); |
| 725 inliner.Inline(); | 739 inliner.Inline(); |
| 726 // Use lists are maintained and validated by the inliner. | 740 // Use lists are maintained and validated by the inliner. |
| 727 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 741 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 728 } | 742 } |
| 729 | 743 |
| 730 // Propagate types and eliminate more type tests. | 744 // Propagate types and eliminate more type tests. |
| 731 FlowGraphTypePropagator::Propagate(flow_graph); | 745 FlowGraphTypePropagator::Propagate(flow_graph); |
| 732 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 746 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 733 | 747 |
| 734 { | 748 { |
| 749 #ifndef PRODUCT |
| 735 TimelineDurationScope tds2(thread(), | 750 TimelineDurationScope tds2(thread(), |
| 736 compiler_timeline, | 751 compiler_timeline, |
| 737 "ApplyClassIds"); | 752 "ApplyClassIds"); |
| 753 #endif // !PRODUCT |
| 738 // Use propagated class-ids to optimize further. | 754 // Use propagated class-ids to optimize further. |
| 739 optimizer.ApplyClassIds(); | 755 optimizer.ApplyClassIds(); |
| 740 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 756 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 741 } | 757 } |
| 742 | 758 |
| 743 // Propagate types for potentially newly added instructions by | 759 // Propagate types for potentially newly added instructions by |
| 744 // ApplyClassIds(). Must occur before canonicalization. | 760 // ApplyClassIds(). Must occur before canonicalization. |
| 745 FlowGraphTypePropagator::Propagate(flow_graph); | 761 FlowGraphTypePropagator::Propagate(flow_graph); |
| 746 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 762 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 747 | 763 |
| 748 // Do optimizations that depend on the propagated type information. | 764 // Do optimizations that depend on the propagated type information. |
| 749 if (optimizer.Canonicalize()) { | 765 if (optimizer.Canonicalize()) { |
| 750 // Invoke Canonicalize twice in order to fully canonicalize patterns | 766 // Invoke Canonicalize twice in order to fully canonicalize patterns |
| 751 // like "if (a & const == 0) { }". | 767 // like "if (a & const == 0) { }". |
| 752 optimizer.Canonicalize(); | 768 optimizer.Canonicalize(); |
| 753 } | 769 } |
| 754 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 770 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 755 | 771 |
| 756 { | 772 { |
| 773 #ifndef PRODUCT |
| 757 TimelineDurationScope tds2(thread(), | 774 TimelineDurationScope tds2(thread(), |
| 758 compiler_timeline, | 775 compiler_timeline, |
| 759 "BranchSimplifier"); | 776 "BranchSimplifier"); |
| 777 #endif // !PRODUCT |
| 760 BranchSimplifier::Simplify(flow_graph); | 778 BranchSimplifier::Simplify(flow_graph); |
| 761 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 779 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 762 | 780 |
| 763 IfConverter::Simplify(flow_graph); | 781 IfConverter::Simplify(flow_graph); |
| 764 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 782 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 765 } | 783 } |
| 766 | 784 |
| 767 if (FLAG_constant_propagation) { | 785 if (FLAG_constant_propagation) { |
| 786 #ifndef PRODUCT |
| 768 TimelineDurationScope tds2(thread(), | 787 TimelineDurationScope tds2(thread(), |
| 769 compiler_timeline, | 788 compiler_timeline, |
| 770 "ConstantPropagation"); | 789 "ConstantPropagation"); |
| 790 #endif // !PRODUCT |
| 771 ConstantPropagator::Optimize(flow_graph); | 791 ConstantPropagator::Optimize(flow_graph); |
| 772 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 792 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 773 // A canonicalization pass to remove e.g. smi checks on smi constants. | 793 // A canonicalization pass to remove e.g. smi checks on smi constants. |
| 774 optimizer.Canonicalize(); | 794 optimizer.Canonicalize(); |
| 775 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 795 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 776 // Canonicalization introduced more opportunities for constant | 796 // Canonicalization introduced more opportunities for constant |
| 777 // propagation. | 797 // propagation. |
| 778 ConstantPropagator::Optimize(flow_graph); | 798 ConstantPropagator::Optimize(flow_graph); |
| 779 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 799 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 780 } | 800 } |
| 781 | 801 |
| 782 // Optimistically convert loop phis that have a single non-smi input | 802 // Optimistically convert loop phis that have a single non-smi input |
| 783 // coming from the loop pre-header into smi-phis. | 803 // coming from the loop pre-header into smi-phis. |
| 784 if (FLAG_loop_invariant_code_motion) { | 804 if (FLAG_loop_invariant_code_motion) { |
| 785 LICM licm(flow_graph); | 805 LICM licm(flow_graph); |
| 786 licm.OptimisticallySpecializeSmiPhis(); | 806 licm.OptimisticallySpecializeSmiPhis(); |
| 787 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 807 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 788 } | 808 } |
| 789 | 809 |
| 790 // Propagate types and eliminate even more type tests. | 810 // Propagate types and eliminate even more type tests. |
| 791 // Recompute types after constant propagation to infer more precise | 811 // Recompute types after constant propagation to infer more precise |
| 792 // types for uses that were previously reached by now eliminated phis. | 812 // types for uses that were previously reached by now eliminated phis. |
| 793 FlowGraphTypePropagator::Propagate(flow_graph); | 813 FlowGraphTypePropagator::Propagate(flow_graph); |
| 794 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 814 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 795 | 815 |
| 796 { | 816 { |
| 817 #ifndef PRODUCT |
| 797 TimelineDurationScope tds2(thread(), | 818 TimelineDurationScope tds2(thread(), |
| 798 compiler_timeline, | 819 compiler_timeline, |
| 799 "SelectRepresentations"); | 820 "SelectRepresentations"); |
| 821 #endif // !PRODUCT |
| 800 // Where beneficial convert Smi operations into Int32 operations. | 822 // Where beneficial convert Smi operations into Int32 operations. |
| 801 // Only meanigful for 32bit platforms right now. | 823 // Only meanigful for 32bit platforms right now. |
| 802 optimizer.WidenSmiToInt32(); | 824 optimizer.WidenSmiToInt32(); |
| 803 | 825 |
| 804 // Unbox doubles. Performed after constant propagation to minimize | 826 // Unbox doubles. Performed after constant propagation to minimize |
| 805 // interference from phis merging double values and tagged | 827 // interference from phis merging double values and tagged |
| 806 // values coming from dead paths. | 828 // values coming from dead paths. |
| 807 optimizer.SelectRepresentations(); | 829 optimizer.SelectRepresentations(); |
| 808 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 830 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 809 } | 831 } |
| 810 | 832 |
| 811 { | 833 { |
| 834 #ifndef PRODUCT |
| 812 TimelineDurationScope tds2(thread(), | 835 TimelineDurationScope tds2(thread(), |
| 813 compiler_timeline, | 836 compiler_timeline, |
| 814 "CommonSubexpressionElinination"); | 837 "CommonSubexpressionElinination"); |
| 838 #endif // !PRODUCT |
| 815 if (FLAG_common_subexpression_elimination || | 839 if (FLAG_common_subexpression_elimination || |
| 816 FLAG_loop_invariant_code_motion) { | 840 FLAG_loop_invariant_code_motion) { |
| 817 flow_graph->ComputeBlockEffects(); | 841 flow_graph->ComputeBlockEffects(); |
| 818 } | 842 } |
| 819 | 843 |
| 820 if (FLAG_common_subexpression_elimination) { | 844 if (FLAG_common_subexpression_elimination) { |
| 821 if (DominatorBasedCSE::Optimize(flow_graph)) { | 845 if (DominatorBasedCSE::Optimize(flow_graph)) { |
| 822 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 846 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 823 optimizer.Canonicalize(); | 847 optimizer.Canonicalize(); |
| 824 // Do another round of CSE to take secondary effects into account: | 848 // Do another round of CSE to take secondary effects into account: |
| (...skipping 17 matching lines...) Expand all Loading... |
| 842 flow_graph->RemoveRedefinitions(); | 866 flow_graph->RemoveRedefinitions(); |
| 843 } | 867 } |
| 844 | 868 |
| 845 // Optimize (a << b) & c patterns, merge operations. | 869 // Optimize (a << b) & c patterns, merge operations. |
| 846 // Run after CSE in order to have more opportunity to merge | 870 // Run after CSE in order to have more opportunity to merge |
| 847 // instructions that have same inputs. | 871 // instructions that have same inputs. |
| 848 optimizer.TryOptimizePatterns(); | 872 optimizer.TryOptimizePatterns(); |
| 849 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 873 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 850 | 874 |
| 851 { | 875 { |
| 876 #ifndef PRODUCT |
| 852 TimelineDurationScope tds2(thread(), | 877 TimelineDurationScope tds2(thread(), |
| 853 compiler_timeline, | 878 compiler_timeline, |
| 854 "DeadStoreElimination"); | 879 "DeadStoreElimination"); |
| 880 #endif // !PRODUCT |
| 855 DeadStoreElimination::Optimize(flow_graph); | 881 DeadStoreElimination::Optimize(flow_graph); |
| 856 } | 882 } |
| 857 | 883 |
| 858 if (FLAG_range_analysis) { | 884 if (FLAG_range_analysis) { |
| 885 #ifndef PRODUCT |
| 859 TimelineDurationScope tds2(thread(), | 886 TimelineDurationScope tds2(thread(), |
| 860 compiler_timeline, | 887 compiler_timeline, |
| 861 "RangeAnalysis"); | 888 "RangeAnalysis"); |
| 889 #endif // !PRODUCT |
| 862 // Propagate types after store-load-forwarding. Some phis may have | 890 // Propagate types after store-load-forwarding. Some phis may have |
| 863 // become smi phis that can be processed by range analysis. | 891 // become smi phis that can be processed by range analysis. |
| 864 FlowGraphTypePropagator::Propagate(flow_graph); | 892 FlowGraphTypePropagator::Propagate(flow_graph); |
| 865 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 893 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 866 | 894 |
| 867 // We have to perform range analysis after LICM because it | 895 // We have to perform range analysis after LICM because it |
| 868 // optimistically moves CheckSmi through phis into loop preheaders | 896 // optimistically moves CheckSmi through phis into loop preheaders |
| 869 // making some phis smi. | 897 // making some phis smi. |
| 870 optimizer.InferIntRanges(); | 898 optimizer.InferIntRanges(); |
| 871 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 899 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 872 } | 900 } |
| 873 | 901 |
| 874 if (FLAG_constant_propagation) { | 902 if (FLAG_constant_propagation) { |
| 903 #ifndef PRODUCT |
| 875 TimelineDurationScope tds2(thread(), | 904 TimelineDurationScope tds2(thread(), |
| 876 compiler_timeline, | 905 compiler_timeline, |
| 877 "ConstantPropagator::OptimizeBranches"); | 906 "ConstantPropagator::OptimizeBranches"); |
| 907 #endif // !PRODUCT |
| 878 // Constant propagation can use information from range analysis to | 908 // Constant propagation can use information from range analysis to |
| 879 // find unreachable branch targets and eliminate branches that have | 909 // find unreachable branch targets and eliminate branches that have |
| 880 // the same true- and false-target. | 910 // the same true- and false-target. |
| 881 ConstantPropagator::OptimizeBranches(flow_graph); | 911 ConstantPropagator::OptimizeBranches(flow_graph); |
| 882 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 912 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 883 } | 913 } |
| 884 | 914 |
| 885 // Recompute types after code movement was done to ensure correct | 915 // Recompute types after code movement was done to ensure correct |
| 886 // reaching types for hoisted values. | 916 // reaching types for hoisted values. |
| 887 FlowGraphTypePropagator::Propagate(flow_graph); | 917 FlowGraphTypePropagator::Propagate(flow_graph); |
| 888 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 918 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 889 | 919 |
| 890 { | 920 { |
| 921 #ifndef PRODUCT |
| 891 TimelineDurationScope tds2(thread(), | 922 TimelineDurationScope tds2(thread(), |
| 892 compiler_timeline, | 923 compiler_timeline, |
| 893 "TryCatchAnalyzer::Optimize"); | 924 "TryCatchAnalyzer::Optimize"); |
| 925 #endif // !PRODUCT |
| 894 // Optimize try-blocks. | 926 // Optimize try-blocks. |
| 895 TryCatchAnalyzer::Optimize(flow_graph); | 927 TryCatchAnalyzer::Optimize(flow_graph); |
| 896 } | 928 } |
| 897 | 929 |
| 898 // Detach environments from the instructions that can't deoptimize. | 930 // Detach environments from the instructions that can't deoptimize. |
| 899 // Do it before we attempt to perform allocation sinking to minimize | 931 // Do it before we attempt to perform allocation sinking to minimize |
| 900 // amount of materializations it has to perform. | 932 // amount of materializations it has to perform. |
| 901 optimizer.EliminateEnvironments(); | 933 optimizer.EliminateEnvironments(); |
| 902 | 934 |
| 903 { | 935 { |
| 936 #ifndef PRODUCT |
| 904 TimelineDurationScope tds2(thread(), | 937 TimelineDurationScope tds2(thread(), |
| 905 compiler_timeline, | 938 compiler_timeline, |
| 906 "EliminateDeadPhis"); | 939 "EliminateDeadPhis"); |
| 940 #endif // !PRODUCT |
| 907 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 941 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| 908 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 942 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 909 } | 943 } |
| 910 | 944 |
| 911 if (optimizer.Canonicalize()) { | 945 if (optimizer.Canonicalize()) { |
| 912 optimizer.Canonicalize(); | 946 optimizer.Canonicalize(); |
| 913 } | 947 } |
| 914 | 948 |
| 915 // Attempt to sink allocations of temporary non-escaping objects to | 949 // Attempt to sink allocations of temporary non-escaping objects to |
| 916 // the deoptimization path. | 950 // the deoptimization path. |
| 917 AllocationSinking* sinking = NULL; | 951 AllocationSinking* sinking = NULL; |
| 918 if (FLAG_allocation_sinking && | 952 if (FLAG_allocation_sinking && |
| 919 (flow_graph->graph_entry()->SuccessorCount() == 1)) { | 953 (flow_graph->graph_entry()->SuccessorCount() == 1)) { |
| 954 #ifndef PRODUCT |
| 920 TimelineDurationScope tds2(thread(), | 955 TimelineDurationScope tds2(thread(), |
| 921 compiler_timeline, | 956 compiler_timeline, |
| 922 "AllocationSinking::Optimize"); | 957 "AllocationSinking::Optimize"); |
| 958 #endif // !PRODUCT |
| 923 // TODO(fschneider): Support allocation sinking with try-catch. | 959 // TODO(fschneider): Support allocation sinking with try-catch. |
| 924 sinking = new AllocationSinking(flow_graph); | 960 sinking = new AllocationSinking(flow_graph); |
| 925 sinking->Optimize(); | 961 sinking->Optimize(); |
| 926 } | 962 } |
| 927 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 963 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 928 | 964 |
| 929 DeadCodeElimination::EliminateDeadPhis(flow_graph); | 965 DeadCodeElimination::EliminateDeadPhis(flow_graph); |
| 930 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 966 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 931 | 967 |
| 932 FlowGraphTypePropagator::Propagate(flow_graph); | 968 FlowGraphTypePropagator::Propagate(flow_graph); |
| 933 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 969 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 934 | 970 |
| 935 { | 971 { |
| 972 #ifndef PRODUCT |
| 936 TimelineDurationScope tds2(thread(), | 973 TimelineDurationScope tds2(thread(), |
| 937 compiler_timeline, | 974 compiler_timeline, |
| 938 "SelectRepresentations"); | 975 "SelectRepresentations"); |
| 976 #endif // !PRODUCT |
| 939 // Ensure that all phis inserted by optimization passes have | 977 // Ensure that all phis inserted by optimization passes have |
| 940 // consistent representations. | 978 // consistent representations. |
| 941 optimizer.SelectRepresentations(); | 979 optimizer.SelectRepresentations(); |
| 942 } | 980 } |
| 943 | 981 |
| 944 if (optimizer.Canonicalize()) { | 982 if (optimizer.Canonicalize()) { |
| 945 // To fully remove redundant boxing (e.g. BoxDouble used only in | 983 // To fully remove redundant boxing (e.g. BoxDouble used only in |
| 946 // environments and UnboxDouble instructions) instruction we | 984 // environments and UnboxDouble instructions) instruction we |
| 947 // first need to replace all their uses and then fold them away. | 985 // first need to replace all their uses and then fold them away. |
| 948 // For now we just repeat Canonicalize twice to do that. | 986 // For now we just repeat Canonicalize twice to do that. |
| 949 // TODO(vegorov): implement a separate representation folding pass. | 987 // TODO(vegorov): implement a separate representation folding pass. |
| 950 optimizer.Canonicalize(); | 988 optimizer.Canonicalize(); |
| 951 } | 989 } |
| 952 DEBUG_ASSERT(flow_graph->VerifyUseLists()); | 990 DEBUG_ASSERT(flow_graph->VerifyUseLists()); |
| 953 | 991 |
| 954 if (sinking != NULL) { | 992 if (sinking != NULL) { |
| 993 #ifndef PRODUCT |
| 955 TimelineDurationScope tds2( | 994 TimelineDurationScope tds2( |
| 956 thread(), | 995 thread(), |
| 957 compiler_timeline, | 996 compiler_timeline, |
| 958 "AllocationSinking::DetachMaterializations"); | 997 "AllocationSinking::DetachMaterializations"); |
| 998 #endif // !PRODUCT |
| 959 // Remove all MaterializeObject instructions inserted by allocation | 999 // Remove all MaterializeObject instructions inserted by allocation |
| 960 // sinking from the flow graph and let them float on the side | 1000 // sinking from the flow graph and let them float on the side |
| 961 // referenced only from environments. Register allocator will consider | 1001 // referenced only from environments. Register allocator will consider |
| 962 // them as part of a deoptimization environment. | 1002 // them as part of a deoptimization environment. |
| 963 sinking->DetachMaterializations(); | 1003 sinking->DetachMaterializations(); |
| 964 } | 1004 } |
| 965 | 1005 |
| 966 // Compute and store graph informations (call & instruction counts) | 1006 // Compute and store graph informations (call & instruction counts) |
| 967 // to be later used by the inliner. | 1007 // to be later used by the inliner. |
| 968 FlowGraphInliner::CollectGraphInfo(flow_graph, true); | 1008 FlowGraphInliner::CollectGraphInfo(flow_graph, true); |
| 969 | 1009 |
| 970 { | 1010 { |
| 1011 #ifndef PRODUCT |
| 971 TimelineDurationScope tds2(thread(), | 1012 TimelineDurationScope tds2(thread(), |
| 972 compiler_timeline, | 1013 compiler_timeline, |
| 973 "AllocateRegisters"); | 1014 "AllocateRegisters"); |
| 1015 #endif // !PRODUCT |
| 974 // Perform register allocation on the SSA graph. | 1016 // Perform register allocation on the SSA graph. |
| 975 FlowGraphAllocator allocator(*flow_graph); | 1017 FlowGraphAllocator allocator(*flow_graph); |
| 976 allocator.AllocateRegisters(); | 1018 allocator.AllocateRegisters(); |
| 977 } | 1019 } |
| 978 | 1020 |
| 979 if (reorder_blocks) { | 1021 if (reorder_blocks) { |
| 1022 #ifndef PRODUCT |
| 980 TimelineDurationScope tds(thread(), | 1023 TimelineDurationScope tds(thread(), |
| 981 compiler_timeline, | 1024 compiler_timeline, |
| 982 "BlockScheduler::ReorderBlocks"); | 1025 "BlockScheduler::ReorderBlocks"); |
| 1026 #endif // !PRODUCT |
| 983 block_scheduler.ReorderBlocks(); | 1027 block_scheduler.ReorderBlocks(); |
| 984 } | 1028 } |
| 985 | 1029 |
| 986 if (print_flow_graph) { | 1030 if (print_flow_graph) { |
| 987 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); | 1031 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); |
| 988 } | 1032 } |
| 989 } | 1033 } |
| 990 | 1034 |
| 991 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); | 1035 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); |
| 992 Assembler assembler(use_far_branches); | 1036 Assembler assembler(use_far_branches); |
| 993 FlowGraphCompiler graph_compiler(&assembler, flow_graph, | 1037 FlowGraphCompiler graph_compiler(&assembler, flow_graph, |
| 994 *parsed_function(), optimized(), | 1038 *parsed_function(), optimized(), |
| 995 inline_id_to_function, | 1039 inline_id_to_function, |
| 996 caller_inline_id); | 1040 caller_inline_id); |
| 997 { | 1041 { |
| 998 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); | 1042 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); |
| 1043 #ifndef PRODUCT |
| 999 TimelineDurationScope tds(thread(), | 1044 TimelineDurationScope tds(thread(), |
| 1000 compiler_timeline, | 1045 compiler_timeline, |
| 1001 "CompileGraph"); | 1046 "CompileGraph"); |
| 1047 #endif // !PRODUCT |
| 1002 graph_compiler.CompileGraph(); | 1048 graph_compiler.CompileGraph(); |
| 1003 pipeline->FinalizeCompilation(); | 1049 pipeline->FinalizeCompilation(); |
| 1004 } | 1050 } |
| 1005 { | 1051 { |
| 1052 #ifndef PRODUCT |
| 1006 TimelineDurationScope tds(thread(), | 1053 TimelineDurationScope tds(thread(), |
| 1007 compiler_timeline, | 1054 compiler_timeline, |
| 1008 "FinalizeCompilation"); | 1055 "FinalizeCompilation"); |
| 1056 #endif // !PRODUCT |
| 1009 if (thread()->IsMutatorThread()) { | 1057 if (thread()->IsMutatorThread()) { |
| 1010 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); | 1058 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); |
| 1011 } else { | 1059 } else { |
| 1012 // This part of compilation must be at a safepoint. | 1060 // This part of compilation must be at a safepoint. |
| 1013 // Stop mutator thread before creating the instruction object and | 1061 // Stop mutator thread before creating the instruction object and |
| 1014 // installing code. | 1062 // installing code. |
| 1015 // Mutator thread may not run code while we are creating the | 1063 // Mutator thread may not run code while we are creating the |
| 1016 // instruction object, since the creation of instruction object | 1064 // instruction object, since the creation of instruction object |
| 1017 // changes code page access permissions (makes them temporary not | 1065 // changes code page access permissions (makes them temporary not |
| 1018 // executable). | 1066 // executable). |
| (...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1413 #ifdef DART_PRECOMPILER | 1461 #ifdef DART_PRECOMPILER |
| 1414 if (FLAG_precompilation) { | 1462 if (FLAG_precompilation) { |
| 1415 return Precompiler::ExecuteOnce(fragment); | 1463 return Precompiler::ExecuteOnce(fragment); |
| 1416 } | 1464 } |
| 1417 #endif | 1465 #endif |
| 1418 LongJumpScope jump; | 1466 LongJumpScope jump; |
| 1419 if (setjmp(*jump.Set()) == 0) { | 1467 if (setjmp(*jump.Set()) == 0) { |
| 1420 Thread* const thread = Thread::Current(); | 1468 Thread* const thread = Thread::Current(); |
| 1421 if (FLAG_trace_compiler) { | 1469 if (FLAG_trace_compiler) { |
| 1422 THR_Print("compiling expression: "); | 1470 THR_Print("compiling expression: "); |
| 1423 AstPrinter::PrintNode(fragment); | 1471 if (FLAG_support_ast_printer) { |
| 1472 AstPrinter::PrintNode(fragment); |
| 1473 } |
| 1424 } | 1474 } |
| 1425 | 1475 |
| 1426 // Create a dummy function object for the code generator. | 1476 // Create a dummy function object for the code generator. |
| 1427 // The function needs to be associated with a named Class: the interface | 1477 // The function needs to be associated with a named Class: the interface |
| 1428 // Function fits the bill. | 1478 // Function fits the bill. |
| 1429 const char* kEvalConst = "eval_const"; | 1479 const char* kEvalConst = "eval_const"; |
| 1430 const Function& func = Function::ZoneHandle(Function::New( | 1480 const Function& func = Function::ZoneHandle(Function::New( |
| 1431 String::Handle(Symbols::New(kEvalConst)), | 1481 String::Handle(Symbols::New(kEvalConst)), |
| 1432 RawFunction::kRegularFunction, | 1482 RawFunction::kRegularFunction, |
| 1433 true, // static function | 1483 true, // static function |
| (...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1835 } | 1885 } |
| 1836 | 1886 |
| 1837 | 1887 |
| 1838 void BackgroundCompiler::EnsureInit(Thread* thread) { | 1888 void BackgroundCompiler::EnsureInit(Thread* thread) { |
| 1839 UNREACHABLE(); | 1889 UNREACHABLE(); |
| 1840 } | 1890 } |
| 1841 | 1891 |
| 1842 #endif // DART_PRECOMPILED_RUNTIME | 1892 #endif // DART_PRECOMPILED_RUNTIME |
| 1843 | 1893 |
| 1844 } // namespace dart | 1894 } // namespace dart |
| OLD | NEW |