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 |