Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Side by Side Diff: runtime/vm/compiler.cc

Issue 1715123003: - Add DEBUG_ONLY and NOT_IN_PRODUCT macros. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Update status files. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/ast_printer.cc ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 257 matching lines...) Expand 10 before | Expand all | Expand 10 after
268 Thread* thread = Thread::Current(); 268 Thread* thread = Thread::Current();
269 Error& error = Error::Handle(thread->zone()); 269 Error& error = Error::Handle(thread->zone());
270 error = thread->sticky_error(); 270 error = thread->sticky_error();
271 thread->clear_sticky_error(); 271 thread->clear_sticky_error();
272 return error.raw(); 272 return error.raw();
273 } 273 }
274 } 274 }
275 275
276 Thread* const thread = Thread::Current(); 276 Thread* const thread = Thread::Current();
277 StackZone zone(thread); 277 StackZone zone(thread);
278 #ifndef PRODUCT 278 NOT_IN_PRODUCT(
279 VMTagScope tagScope(thread, VMTag::kCompileClassTagId); 279 VMTagScope tagScope(thread, VMTag::kCompileClassTagId);
280 TimelineDurationScope tds(thread, 280 TimelineDurationScope tds(thread,
281 thread->isolate()->GetCompilerStream(), 281 thread->isolate()->GetCompilerStream(),
282 "CompileClass"); 282 "CompileClass");
283 if (tds.enabled()) { 283 if (tds.enabled()) {
284 tds.SetNumArguments(1); 284 tds.SetNumArguments(1);
285 tds.CopyArgument(0, "class", cls.ToCString()); 285 tds.CopyArgument(0, "class", cls.ToCString());
286 } 286 }
287 #endif // !PRODUCT 287 ) // !PRODUCT
288 288
289 // We remember all the classes that are being compiled in these lists. This 289 // We remember all the classes that are being compiled in these lists. This
290 // also allows us to reset the marked_for_parsing state in case we see an 290 // also allows us to reset the marked_for_parsing state in case we see an
291 // error. 291 // error.
292 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4); 292 GrowableHandlePtrArray<const Class> parse_list(thread->zone(), 4);
293 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4); 293 GrowableHandlePtrArray<const Class> patch_list(thread->zone(), 4);
294 294
295 // Parse the class and all the interfaces it implements and super classes. 295 // Parse the class and all the interfaces it implements and super classes.
296 LongJumpScope jump; 296 LongJumpScope jump;
297 if (setjmp(*jump.Set()) == 0) { 297 if (setjmp(*jump.Set()) == 0) {
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 // If optimized_result_code is not NULL then it is caller's responsibility 556 // If optimized_result_code is not NULL then it is caller's responsibility
557 // to install code. 557 // to install code.
558 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) { 558 bool CompileParsedFunctionHelper::Compile(CompilationPipeline* pipeline) {
559 ASSERT(!FLAG_precompilation); 559 ASSERT(!FLAG_precompilation);
560 const Function& function = parsed_function()->function(); 560 const Function& function = parsed_function()->function();
561 if (optimized() && !function.IsOptimizable()) { 561 if (optimized() && !function.IsOptimizable()) {
562 return false; 562 return false;
563 } 563 }
564 bool is_compiled = false; 564 bool is_compiled = false;
565 Zone* const zone = thread()->zone(); 565 Zone* const zone = thread()->zone();
566 #ifndef PRODUCT 566 NOT_IN_PRODUCT(
567 TimelineStream* compiler_timeline = isolate()->GetCompilerStream(); 567 TimelineStream* compiler_timeline = isolate()->GetCompilerStream());
568 #endif
569 CSTAT_TIMER_SCOPE(thread(), codegen_timer); 568 CSTAT_TIMER_SCOPE(thread(), codegen_timer);
570 HANDLESCOPE(thread()); 569 HANDLESCOPE(thread());
571 570
572 // We may reattempt compilation if the function needs to be assembled using 571 // We may reattempt compilation if the function needs to be assembled using
573 // far branches on ARM and MIPS. In the else branch of the setjmp call, 572 // far branches on ARM and MIPS. In the else branch of the setjmp call,
574 // done is set to false, and use_far_branches is set to true if there is a 573 // done is set to false, and use_far_branches is set to true if there is a
575 // longjmp from the ARM or MIPS assemblers. In all other paths through this 574 // longjmp from the ARM or MIPS assemblers. In all other paths through this
576 // while loop, done is set to true. use_far_branches is always false on ia32 575 // while loop, done is set to true. use_far_branches is always false on ia32
577 // and x64. 576 // and x64.
578 volatile bool done = false; 577 volatile bool done = false;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
620 if (FLAG_print_ic_data_map) { 619 if (FLAG_print_ic_data_map) {
621 for (intptr_t i = 0; i < ic_data_array->length(); i++) { 620 for (intptr_t i = 0; i < ic_data_array->length(); i++) {
622 if ((*ic_data_array)[i] != NULL) { 621 if ((*ic_data_array)[i] != NULL) {
623 THR_Print("%" Pd " ", i); 622 THR_Print("%" Pd " ", i);
624 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]); 623 FlowGraphPrinter::PrintICData(*(*ic_data_array)[i]);
625 } 624 }
626 } 625 }
627 } 626 }
628 } 627 }
629 628
630 #ifndef PRODUCT 629 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
631 TimelineDurationScope tds(thread(), 630 compiler_timeline,
632 compiler_timeline, 631 "BuildFlowGraph");)
633 "BuildFlowGraph");
634 #endif // !PRODUCT
635 flow_graph = pipeline->BuildFlowGraph(zone, 632 flow_graph = pipeline->BuildFlowGraph(zone,
636 parsed_function(), 633 parsed_function(),
637 *ic_data_array, 634 *ic_data_array,
638 osr_id()); 635 osr_id());
639 } 636 }
640 637
641 const bool print_flow_graph = 638 const bool print_flow_graph =
642 (FLAG_print_flow_graph || 639 (FLAG_print_flow_graph ||
643 (optimized() && FLAG_print_flow_graph_optimized)) && 640 (optimized() && FLAG_print_flow_graph_optimized)) &&
644 FlowGraphPrinter::ShouldPrint(function); 641 FlowGraphPrinter::ShouldPrint(function);
645 642
646 if (print_flow_graph) { 643 if (print_flow_graph) {
647 if (osr_id() == Compiler::kNoOSRDeoptId) { 644 if (osr_id() == Compiler::kNoOSRDeoptId) {
648 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph); 645 FlowGraphPrinter::PrintGraph("Before Optimizations", flow_graph);
649 } else { 646 } else {
650 FlowGraphPrinter::PrintGraph("For OSR", flow_graph); 647 FlowGraphPrinter::PrintGraph("For OSR", flow_graph);
651 } 648 }
652 } 649 }
653 650
654 BlockScheduler block_scheduler(flow_graph); 651 BlockScheduler block_scheduler(flow_graph);
655 const bool reorder_blocks = 652 const bool reorder_blocks =
656 FlowGraph::ShouldReorderBlocks(function, optimized()); 653 FlowGraph::ShouldReorderBlocks(function, optimized());
657 if (reorder_blocks) { 654 if (reorder_blocks) {
658 #ifndef PRODUCT 655 NOT_IN_PRODUCT(TimelineDurationScope tds(
659 TimelineDurationScope tds(thread(), 656 thread(), compiler_timeline, "BlockScheduler::AssignEdgeWeights"));
660 compiler_timeline,
661 "BlockScheduler::AssignEdgeWeights");
662 #endif // !PRODUCT
663 block_scheduler.AssignEdgeWeights(); 657 block_scheduler.AssignEdgeWeights();
664 } 658 }
665 659
666 if (optimized()) { 660 if (optimized()) {
667 #ifndef PRODUCT 661 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
668 TimelineDurationScope tds(thread(), 662 compiler_timeline,
669 compiler_timeline, 663 "ComputeSSA"));
670 "ComputeSSA");
671 #endif // !PRODUCT
672 CSTAT_TIMER_SCOPE(thread(), ssa_timer); 664 CSTAT_TIMER_SCOPE(thread(), ssa_timer);
673 // Transform to SSA (virtual register 0 and no inlining arguments). 665 // Transform to SSA (virtual register 0 and no inlining arguments).
674 flow_graph->ComputeSSA(0, NULL); 666 flow_graph->ComputeSSA(0, NULL);
675 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 667 DEBUG_ASSERT(flow_graph->VerifyUseLists());
676 if (print_flow_graph) { 668 if (print_flow_graph) {
677 FlowGraphPrinter::PrintGraph("After SSA", flow_graph); 669 FlowGraphPrinter::PrintGraph("After SSA", flow_graph);
678 } 670 }
679 } 671 }
680 672
681 // Maps inline_id_to_function[inline_id] -> function. Top scope 673 // Maps inline_id_to_function[inline_id] -> function. Top scope
682 // function has inline_id 0. The map is populated by the inliner. 674 // function has inline_id 0. The map is populated by the inliner.
683 GrowableArray<const Function*> inline_id_to_function; 675 GrowableArray<const Function*> inline_id_to_function;
684 // For a given inlining-id(index) specifies the caller's inlining-id. 676 // For a given inlining-id(index) specifies the caller's inlining-id.
685 GrowableArray<intptr_t> caller_inline_id; 677 GrowableArray<intptr_t> caller_inline_id;
686 // Collect all instance fields that are loaded in the graph and 678 // Collect all instance fields that are loaded in the graph and
687 // have non-generic type feedback attached to them that can 679 // have non-generic type feedback attached to them that can
688 // potentially affect optimizations. 680 // potentially affect optimizations.
689 if (optimized()) { 681 if (optimized()) {
690 #ifndef PRODUCT 682 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
691 TimelineDurationScope tds(thread(), 683 compiler_timeline,
692 compiler_timeline, 684 "OptimizationPasses"));
693 "OptimizationPasses");
694 #endif // !PRODUCT
695 inline_id_to_function.Add(&function); 685 inline_id_to_function.Add(&function);
696 // Top scope function has no caller (-1). 686 // Top scope function has no caller (-1).
697 caller_inline_id.Add(-1); 687 caller_inline_id.Add(-1);
698 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer); 688 CSTAT_TIMER_SCOPE(thread(), graphoptimizer_timer);
699 689
700 FlowGraphOptimizer optimizer(flow_graph, 690 FlowGraphOptimizer optimizer(flow_graph,
701 use_speculative_inlining, 691 use_speculative_inlining,
702 NULL); 692 NULL);
703 optimizer.ApplyICData(); 693 optimizer.ApplyICData();
704 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 694 DEBUG_ASSERT(flow_graph->VerifyUseLists());
705 695
706 // Optimize (a << b) & c patterns, merge operations. 696 // Optimize (a << b) & c patterns, merge operations.
707 // Run early in order to have more opportunity to optimize left shifts. 697 // Run early in order to have more opportunity to optimize left shifts.
708 optimizer.TryOptimizePatterns(); 698 optimizer.TryOptimizePatterns();
709 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 699 DEBUG_ASSERT(flow_graph->VerifyUseLists());
710 700
711 FlowGraphInliner::SetInliningId(flow_graph, 0); 701 FlowGraphInliner::SetInliningId(flow_graph, 0);
712 702
713 // Inlining (mutates the flow graph) 703 // Inlining (mutates the flow graph)
714 if (FLAG_use_inlining) { 704 if (FLAG_use_inlining) {
715 #ifndef PRODUCT 705 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
716 TimelineDurationScope tds2(thread(), 706 compiler_timeline,
717 compiler_timeline, 707 "Inlining"));
718 "Inlining");
719 #endif // !PRODUCT
720 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer); 708 CSTAT_TIMER_SCOPE(thread(), graphinliner_timer);
721 // Propagate types to create more inlining opportunities. 709 // Propagate types to create more inlining opportunities.
722 FlowGraphTypePropagator::Propagate(flow_graph); 710 FlowGraphTypePropagator::Propagate(flow_graph);
723 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 711 DEBUG_ASSERT(flow_graph->VerifyUseLists());
724 712
725 // Use propagated class-ids to create more inlining opportunities. 713 // Use propagated class-ids to create more inlining opportunities.
726 optimizer.ApplyClassIds(); 714 optimizer.ApplyClassIds();
727 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 715 DEBUG_ASSERT(flow_graph->VerifyUseLists());
728 716
729 FlowGraphInliner inliner(flow_graph, 717 FlowGraphInliner inliner(flow_graph,
730 &inline_id_to_function, 718 &inline_id_to_function,
731 &caller_inline_id, 719 &caller_inline_id,
732 use_speculative_inlining, 720 use_speculative_inlining,
733 NULL); 721 NULL);
734 inliner.Inline(); 722 inliner.Inline();
735 // Use lists are maintained and validated by the inliner. 723 // Use lists are maintained and validated by the inliner.
736 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 724 DEBUG_ASSERT(flow_graph->VerifyUseLists());
737 } 725 }
738 726
739 // Propagate types and eliminate more type tests. 727 // Propagate types and eliminate more type tests.
740 FlowGraphTypePropagator::Propagate(flow_graph); 728 FlowGraphTypePropagator::Propagate(flow_graph);
741 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 729 DEBUG_ASSERT(flow_graph->VerifyUseLists());
742 730
743 { 731 {
744 #ifndef PRODUCT 732 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
745 TimelineDurationScope tds2(thread(), 733 compiler_timeline,
746 compiler_timeline, 734 "ApplyClassIds"));
747 "ApplyClassIds");
748 #endif // !PRODUCT
749 // Use propagated class-ids to optimize further. 735 // Use propagated class-ids to optimize further.
750 optimizer.ApplyClassIds(); 736 optimizer.ApplyClassIds();
751 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 737 DEBUG_ASSERT(flow_graph->VerifyUseLists());
752 } 738 }
753 739
754 // Propagate types for potentially newly added instructions by 740 // Propagate types for potentially newly added instructions by
755 // ApplyClassIds(). Must occur before canonicalization. 741 // ApplyClassIds(). Must occur before canonicalization.
756 FlowGraphTypePropagator::Propagate(flow_graph); 742 FlowGraphTypePropagator::Propagate(flow_graph);
757 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 743 DEBUG_ASSERT(flow_graph->VerifyUseLists());
758 744
759 // Do optimizations that depend on the propagated type information. 745 // Do optimizations that depend on the propagated type information.
760 if (flow_graph->Canonicalize()) { 746 if (flow_graph->Canonicalize()) {
761 // Invoke Canonicalize twice in order to fully canonicalize patterns 747 // Invoke Canonicalize twice in order to fully canonicalize patterns
762 // like "if (a & const == 0) { }". 748 // like "if (a & const == 0) { }".
763 flow_graph->Canonicalize(); 749 flow_graph->Canonicalize();
764 } 750 }
765 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 751 DEBUG_ASSERT(flow_graph->VerifyUseLists());
766 752
767 { 753 {
768 #ifndef PRODUCT 754 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
769 TimelineDurationScope tds2(thread(), 755 compiler_timeline,
770 compiler_timeline, 756 "BranchSimplifier"));
771 "BranchSimplifier");
772 #endif // !PRODUCT
773 BranchSimplifier::Simplify(flow_graph); 757 BranchSimplifier::Simplify(flow_graph);
774 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 758 DEBUG_ASSERT(flow_graph->VerifyUseLists());
775 759
776 IfConverter::Simplify(flow_graph); 760 IfConverter::Simplify(flow_graph);
777 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 761 DEBUG_ASSERT(flow_graph->VerifyUseLists());
778 } 762 }
779 763
780 if (FLAG_constant_propagation) { 764 if (FLAG_constant_propagation) {
781 #ifndef PRODUCT 765 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
782 TimelineDurationScope tds2(thread(), 766 compiler_timeline,
783 compiler_timeline, 767 "ConstantPropagation");
784 "ConstantPropagation"); 768 ConstantPropagator::Optimize(flow_graph));
785 #endif // !PRODUCT
786 ConstantPropagator::Optimize(flow_graph);
787 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 769 DEBUG_ASSERT(flow_graph->VerifyUseLists());
788 // A canonicalization pass to remove e.g. smi checks on smi constants. 770 // A canonicalization pass to remove e.g. smi checks on smi constants.
789 flow_graph->Canonicalize(); 771 flow_graph->Canonicalize();
790 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 772 DEBUG_ASSERT(flow_graph->VerifyUseLists());
791 // Canonicalization introduced more opportunities for constant 773 // Canonicalization introduced more opportunities for constant
792 // propagation. 774 // propagation.
793 ConstantPropagator::Optimize(flow_graph); 775 ConstantPropagator::Optimize(flow_graph);
794 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 776 DEBUG_ASSERT(flow_graph->VerifyUseLists());
795 } 777 }
796 778
797 // Optimistically convert loop phis that have a single non-smi input 779 // Optimistically convert loop phis that have a single non-smi input
798 // coming from the loop pre-header into smi-phis. 780 // coming from the loop pre-header into smi-phis.
799 if (FLAG_loop_invariant_code_motion) { 781 if (FLAG_loop_invariant_code_motion) {
800 LICM licm(flow_graph); 782 LICM licm(flow_graph);
801 licm.OptimisticallySpecializeSmiPhis(); 783 licm.OptimisticallySpecializeSmiPhis();
802 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 784 DEBUG_ASSERT(flow_graph->VerifyUseLists());
803 } 785 }
804 786
805 // Propagate types and eliminate even more type tests. 787 // Propagate types and eliminate even more type tests.
806 // Recompute types after constant propagation to infer more precise 788 // Recompute types after constant propagation to infer more precise
807 // types for uses that were previously reached by now eliminated phis. 789 // types for uses that were previously reached by now eliminated phis.
808 FlowGraphTypePropagator::Propagate(flow_graph); 790 FlowGraphTypePropagator::Propagate(flow_graph);
809 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 791 DEBUG_ASSERT(flow_graph->VerifyUseLists());
810 792
811 { 793 {
812 #ifndef PRODUCT 794 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
813 TimelineDurationScope tds2(thread(), 795 compiler_timeline,
814 compiler_timeline, 796 "SelectRepresentations"));
815 "SelectRepresentations");
816 #endif // !PRODUCT
817 // Where beneficial convert Smi operations into Int32 operations. 797 // Where beneficial convert Smi operations into Int32 operations.
818 // Only meanigful for 32bit platforms right now. 798 // Only meanigful for 32bit platforms right now.
819 flow_graph->WidenSmiToInt32(); 799 flow_graph->WidenSmiToInt32();
820 800
821 // Unbox doubles. Performed after constant propagation to minimize 801 // Unbox doubles. Performed after constant propagation to minimize
822 // interference from phis merging double values and tagged 802 // interference from phis merging double values and tagged
823 // values coming from dead paths. 803 // values coming from dead paths.
824 flow_graph->SelectRepresentations(); 804 flow_graph->SelectRepresentations();
825 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 805 DEBUG_ASSERT(flow_graph->VerifyUseLists());
826 } 806 }
827 807
828 { 808 {
829 #ifndef PRODUCT 809 NOT_IN_PRODUCT(TimelineDurationScope tds2(
830 TimelineDurationScope tds2(thread(), 810 thread(), compiler_timeline, "CommonSubexpressionElinination"));
831 compiler_timeline,
832 "CommonSubexpressionElinination");
833 #endif // !PRODUCT
834 if (FLAG_common_subexpression_elimination || 811 if (FLAG_common_subexpression_elimination ||
835 FLAG_loop_invariant_code_motion) { 812 FLAG_loop_invariant_code_motion) {
836 flow_graph->ComputeBlockEffects(); 813 flow_graph->ComputeBlockEffects();
837 } 814 }
838 815
839 if (FLAG_common_subexpression_elimination) { 816 if (FLAG_common_subexpression_elimination) {
840 if (DominatorBasedCSE::Optimize(flow_graph)) { 817 if (DominatorBasedCSE::Optimize(flow_graph)) {
841 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 818 DEBUG_ASSERT(flow_graph->VerifyUseLists());
842 flow_graph->Canonicalize(); 819 flow_graph->Canonicalize();
843 // Do another round of CSE to take secondary effects into account: 820 // Do another round of CSE to take secondary effects into account:
(...skipping 17 matching lines...) Expand all
861 flow_graph->RemoveRedefinitions(); 838 flow_graph->RemoveRedefinitions();
862 } 839 }
863 840
864 // Optimize (a << b) & c patterns, merge operations. 841 // Optimize (a << b) & c patterns, merge operations.
865 // Run after CSE in order to have more opportunity to merge 842 // Run after CSE in order to have more opportunity to merge
866 // instructions that have same inputs. 843 // instructions that have same inputs.
867 optimizer.TryOptimizePatterns(); 844 optimizer.TryOptimizePatterns();
868 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 845 DEBUG_ASSERT(flow_graph->VerifyUseLists());
869 846
870 { 847 {
871 #ifndef PRODUCT 848 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
872 TimelineDurationScope tds2(thread(), 849 compiler_timeline,
873 compiler_timeline, 850 "DeadStoreElimination"));
874 "DeadStoreElimination");
875 #endif // !PRODUCT
876 DeadStoreElimination::Optimize(flow_graph); 851 DeadStoreElimination::Optimize(flow_graph);
877 } 852 }
878 853
879 if (FLAG_range_analysis) { 854 if (FLAG_range_analysis) {
880 #ifndef PRODUCT 855 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
881 TimelineDurationScope tds2(thread(), 856 compiler_timeline,
882 compiler_timeline, 857 "RangeAnalysis"));
883 "RangeAnalysis");
884 #endif // !PRODUCT
885 // Propagate types after store-load-forwarding. Some phis may have 858 // Propagate types after store-load-forwarding. Some phis may have
886 // become smi phis that can be processed by range analysis. 859 // become smi phis that can be processed by range analysis.
887 FlowGraphTypePropagator::Propagate(flow_graph); 860 FlowGraphTypePropagator::Propagate(flow_graph);
888 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 861 DEBUG_ASSERT(flow_graph->VerifyUseLists());
889 862
890 // We have to perform range analysis after LICM because it 863 // We have to perform range analysis after LICM because it
891 // optimistically moves CheckSmi through phis into loop preheaders 864 // optimistically moves CheckSmi through phis into loop preheaders
892 // making some phis smi. 865 // making some phis smi.
893 RangeAnalysis range_analysis(flow_graph); 866 RangeAnalysis range_analysis(flow_graph);
894 range_analysis.Analyze(); 867 range_analysis.Analyze();
895 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 868 DEBUG_ASSERT(flow_graph->VerifyUseLists());
896 } 869 }
897 870
898 if (FLAG_constant_propagation) { 871 if (FLAG_constant_propagation) {
899 #ifndef PRODUCT 872 NOT_IN_PRODUCT(TimelineDurationScope tds2(
900 TimelineDurationScope tds2(thread(), 873 thread(), compiler_timeline,
901 compiler_timeline, 874 "ConstantPropagator::OptimizeBranches"));
902 "ConstantPropagator::OptimizeBranches");
903 #endif // !PRODUCT
904 // Constant propagation can use information from range analysis to 875 // Constant propagation can use information from range analysis to
905 // find unreachable branch targets and eliminate branches that have 876 // find unreachable branch targets and eliminate branches that have
906 // the same true- and false-target. 877 // the same true- and false-target.
907 ConstantPropagator::OptimizeBranches(flow_graph); 878 ConstantPropagator::OptimizeBranches(flow_graph);
908 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 879 DEBUG_ASSERT(flow_graph->VerifyUseLists());
909 } 880 }
910 881
911 // Recompute types after code movement was done to ensure correct 882 // Recompute types after code movement was done to ensure correct
912 // reaching types for hoisted values. 883 // reaching types for hoisted values.
913 FlowGraphTypePropagator::Propagate(flow_graph); 884 FlowGraphTypePropagator::Propagate(flow_graph);
914 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 885 DEBUG_ASSERT(flow_graph->VerifyUseLists());
915 886
916 { 887 {
917 #ifndef PRODUCT 888 NOT_IN_PRODUCT(TimelineDurationScope tds2(
918 TimelineDurationScope tds2(thread(), 889 thread(), compiler_timeline, "TryCatchAnalyzer::Optimize"));
919 compiler_timeline,
920 "TryCatchAnalyzer::Optimize");
921 #endif // !PRODUCT
922 // Optimize try-blocks. 890 // Optimize try-blocks.
923 TryCatchAnalyzer::Optimize(flow_graph); 891 TryCatchAnalyzer::Optimize(flow_graph);
924 } 892 }
925 893
926 // Detach environments from the instructions that can't deoptimize. 894 // Detach environments from the instructions that can't deoptimize.
927 // Do it before we attempt to perform allocation sinking to minimize 895 // Do it before we attempt to perform allocation sinking to minimize
928 // amount of materializations it has to perform. 896 // amount of materializations it has to perform.
929 flow_graph->EliminateEnvironments(); 897 flow_graph->EliminateEnvironments();
930 898
931 { 899 {
932 #ifndef PRODUCT 900 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
933 TimelineDurationScope tds2(thread(), 901 compiler_timeline,
934 compiler_timeline, 902 "EliminateDeadPhis"));
935 "EliminateDeadPhis");
936 #endif // !PRODUCT
937 DeadCodeElimination::EliminateDeadPhis(flow_graph); 903 DeadCodeElimination::EliminateDeadPhis(flow_graph);
938 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 904 DEBUG_ASSERT(flow_graph->VerifyUseLists());
939 } 905 }
940 906
941 if (flow_graph->Canonicalize()) { 907 if (flow_graph->Canonicalize()) {
942 flow_graph->Canonicalize(); 908 flow_graph->Canonicalize();
943 } 909 }
944 910
945 // Attempt to sink allocations of temporary non-escaping objects to 911 // Attempt to sink allocations of temporary non-escaping objects to
946 // the deoptimization path. 912 // the deoptimization path.
947 AllocationSinking* sinking = NULL; 913 AllocationSinking* sinking = NULL;
948 if (FLAG_allocation_sinking && 914 if (FLAG_allocation_sinking &&
949 (flow_graph->graph_entry()->SuccessorCount() == 1)) { 915 (flow_graph->graph_entry()->SuccessorCount() == 1)) {
950 #ifndef PRODUCT 916 NOT_IN_PRODUCT(TimelineDurationScope tds2(
951 TimelineDurationScope tds2(thread(), 917 thread(), compiler_timeline, "AllocationSinking::Optimize"));
952 compiler_timeline,
953 "AllocationSinking::Optimize");
954 #endif // !PRODUCT
955 // TODO(fschneider): Support allocation sinking with try-catch. 918 // TODO(fschneider): Support allocation sinking with try-catch.
956 sinking = new AllocationSinking(flow_graph); 919 sinking = new AllocationSinking(flow_graph);
957 sinking->Optimize(); 920 sinking->Optimize();
958 } 921 }
959 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 922 DEBUG_ASSERT(flow_graph->VerifyUseLists());
960 923
961 DeadCodeElimination::EliminateDeadPhis(flow_graph); 924 DeadCodeElimination::EliminateDeadPhis(flow_graph);
962 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 925 DEBUG_ASSERT(flow_graph->VerifyUseLists());
963 926
964 FlowGraphTypePropagator::Propagate(flow_graph); 927 FlowGraphTypePropagator::Propagate(flow_graph);
965 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 928 DEBUG_ASSERT(flow_graph->VerifyUseLists());
966 929
967 { 930 {
968 #ifndef PRODUCT 931 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
969 TimelineDurationScope tds2(thread(), 932 compiler_timeline,
970 compiler_timeline, 933 "SelectRepresentations"));
971 "SelectRepresentations");
972 #endif // !PRODUCT
973 // Ensure that all phis inserted by optimization passes have 934 // Ensure that all phis inserted by optimization passes have
974 // consistent representations. 935 // consistent representations.
975 flow_graph->SelectRepresentations(); 936 flow_graph->SelectRepresentations();
976 } 937 }
977 938
978 if (flow_graph->Canonicalize()) { 939 if (flow_graph->Canonicalize()) {
979 // To fully remove redundant boxing (e.g. BoxDouble used only in 940 // To fully remove redundant boxing (e.g. BoxDouble used only in
980 // environments and UnboxDouble instructions) instruction we 941 // environments and UnboxDouble instructions) instruction we
981 // first need to replace all their uses and then fold them away. 942 // first need to replace all their uses and then fold them away.
982 // For now we just repeat Canonicalize twice to do that. 943 // For now we just repeat Canonicalize twice to do that.
983 // TODO(vegorov): implement a separate representation folding pass. 944 // TODO(vegorov): implement a separate representation folding pass.
984 flow_graph->Canonicalize(); 945 flow_graph->Canonicalize();
985 } 946 }
986 DEBUG_ASSERT(flow_graph->VerifyUseLists()); 947 DEBUG_ASSERT(flow_graph->VerifyUseLists());
987 948
988 if (sinking != NULL) { 949 if (sinking != NULL) {
989 #ifndef PRODUCT 950 NOT_IN_PRODUCT(TimelineDurationScope tds2(
990 TimelineDurationScope tds2( 951 thread(), compiler_timeline,
991 thread(), 952 "AllocationSinking::DetachMaterializations"));
992 compiler_timeline,
993 "AllocationSinking::DetachMaterializations");
994 #endif // !PRODUCT
995 // Remove all MaterializeObject instructions inserted by allocation 953 // Remove all MaterializeObject instructions inserted by allocation
996 // sinking from the flow graph and let them float on the side 954 // sinking from the flow graph and let them float on the side
997 // referenced only from environments. Register allocator will consider 955 // referenced only from environments. Register allocator will consider
998 // them as part of a deoptimization environment. 956 // them as part of a deoptimization environment.
999 sinking->DetachMaterializations(); 957 sinking->DetachMaterializations();
1000 } 958 }
1001 959
1002 // Compute and store graph informations (call & instruction counts) 960 // Compute and store graph informations (call & instruction counts)
1003 // to be later used by the inliner. 961 // to be later used by the inliner.
1004 FlowGraphInliner::CollectGraphInfo(flow_graph, true); 962 FlowGraphInliner::CollectGraphInfo(flow_graph, true);
1005 963
1006 { 964 {
1007 #ifndef PRODUCT 965 NOT_IN_PRODUCT(TimelineDurationScope tds2(thread(),
1008 TimelineDurationScope tds2(thread(), 966 compiler_timeline,
1009 compiler_timeline, 967 "AllocateRegisters"));
1010 "AllocateRegisters");
1011 #endif // !PRODUCT
1012 // Perform register allocation on the SSA graph. 968 // Perform register allocation on the SSA graph.
1013 FlowGraphAllocator allocator(*flow_graph); 969 FlowGraphAllocator allocator(*flow_graph);
1014 allocator.AllocateRegisters(); 970 allocator.AllocateRegisters();
1015 } 971 }
1016 972
1017 if (reorder_blocks) { 973 if (reorder_blocks) {
1018 #ifndef PRODUCT 974 NOT_IN_PRODUCT(TimelineDurationScope tds(
1019 TimelineDurationScope tds(thread(), 975 thread(), compiler_timeline, "BlockScheduler::ReorderBlocks"));
1020 compiler_timeline,
1021 "BlockScheduler::ReorderBlocks");
1022 #endif // !PRODUCT
1023 block_scheduler.ReorderBlocks(); 976 block_scheduler.ReorderBlocks();
1024 } 977 }
1025 978
1026 if (print_flow_graph) { 979 if (print_flow_graph) {
1027 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph); 980 FlowGraphPrinter::PrintGraph("After Optimizations", flow_graph);
1028 } 981 }
1029 } 982 }
1030 983
1031 ASSERT(inline_id_to_function.length() == caller_inline_id.length()); 984 ASSERT(inline_id_to_function.length() == caller_inline_id.length());
1032 Assembler assembler(use_far_branches); 985 Assembler assembler(use_far_branches);
1033 FlowGraphCompiler graph_compiler(&assembler, flow_graph, 986 FlowGraphCompiler graph_compiler(&assembler, flow_graph,
1034 *parsed_function(), optimized(), 987 *parsed_function(), optimized(),
1035 inline_id_to_function, 988 inline_id_to_function,
1036 caller_inline_id); 989 caller_inline_id);
1037 { 990 {
1038 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer); 991 CSTAT_TIMER_SCOPE(thread(), graphcompiler_timer);
1039 #ifndef PRODUCT 992 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
1040 TimelineDurationScope tds(thread(), 993 compiler_timeline,
1041 compiler_timeline, 994 "CompileGraph"));
1042 "CompileGraph");
1043 #endif // !PRODUCT
1044 graph_compiler.CompileGraph(); 995 graph_compiler.CompileGraph();
1045 pipeline->FinalizeCompilation(); 996 pipeline->FinalizeCompilation();
1046 } 997 }
1047 { 998 {
1048 #ifndef PRODUCT 999 NOT_IN_PRODUCT(TimelineDurationScope tds(thread(),
1049 TimelineDurationScope tds(thread(), 1000 compiler_timeline,
1050 compiler_timeline, 1001 "FinalizeCompilation"));
1051 "FinalizeCompilation");
1052 #endif // !PRODUCT
1053 if (thread()->IsMutatorThread()) { 1002 if (thread()->IsMutatorThread()) {
1054 FinalizeCompilation(&assembler, &graph_compiler, flow_graph); 1003 FinalizeCompilation(&assembler, &graph_compiler, flow_graph);
1055 } else { 1004 } else {
1056 // This part of compilation must be at a safepoint. 1005 // This part of compilation must be at a safepoint.
1057 // Stop mutator thread before creating the instruction object and 1006 // Stop mutator thread before creating the instruction object and
1058 // installing code. 1007 // installing code.
1059 // Mutator thread may not run code while we are creating the 1008 // Mutator thread may not run code while we are creating the
1060 // instruction object, since the creation of instruction object 1009 // instruction object, since the creation of instruction object
1061 // changes code page access permissions (makes them temporary not 1010 // changes code page access permissions (makes them temporary not
1062 // executable). 1011 // executable).
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1107 } 1056 }
1108 is_compiled = false; 1057 is_compiled = false;
1109 } 1058 }
1110 // Reset global isolate state. 1059 // Reset global isolate state.
1111 thread()->set_deopt_id(prev_deopt_id); 1060 thread()->set_deopt_id(prev_deopt_id);
1112 } 1061 }
1113 return is_compiled; 1062 return is_compiled;
1114 } 1063 }
1115 1064
1116 1065
1117 #if defined(DEBUG) 1066 DEBUG_ONLY(
1118 // Verifies that the inliner is always in the list of inlined functions. 1067 // Verifies that the inliner is always in the list of inlined functions.
1119 // If this fails run with --trace-inlining-intervals to get more information. 1068 // If this fails run with --trace-inlining-intervals to get more information.
1120 static void CheckInliningIntervals(const Function& function) { 1069 static void CheckInliningIntervals(const Function& function) {
1121 const Code& code = Code::Handle(function.CurrentCode()); 1070 const Code& code = Code::Handle(function.CurrentCode());
1122 const Array& intervals = Array::Handle(code.GetInlinedIntervals()); 1071 const Array& intervals = Array::Handle(code.GetInlinedIntervals());
1123 if (intervals.IsNull() || (intervals.Length() == 0)) return; 1072 if (intervals.IsNull() || (intervals.Length() == 0)) return;
1124 Smi& start = Smi::Handle(); 1073 Smi& start = Smi::Handle();
1125 GrowableArray<Function*> inlined_functions; 1074 GrowableArray<Function*> inlined_functions;
1126 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) { 1075 for (intptr_t i = 0; i < intervals.Length(); i += Code::kInlIntNumEntries) {
1127 start ^= intervals.At(i + Code::kInlIntStart); 1076 start ^= intervals.At(i + Code::kInlIntStart);
1128 ASSERT(!start.IsNull()); 1077 ASSERT(!start.IsNull());
1129 if (start.IsNull()) continue; 1078 if (start.IsNull()) continue;
1130 code.GetInlinedFunctionsAt(start.Value(), &inlined_functions); 1079 code.GetInlinedFunctionsAt(start.Value(), &inlined_functions);
1131 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() == 1080 ASSERT(inlined_functions[inlined_functions.length() - 1]->raw() ==
1132 function.raw()); 1081 function.raw());
1133 } 1082 }
1134 } 1083 }
1135 #endif 1084 )
1136
1137 1085
1138 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline, 1086 static RawError* CompileFunctionHelper(CompilationPipeline* pipeline,
1139 const Function& function, 1087 const Function& function,
1140 bool optimized, 1088 bool optimized,
1141 intptr_t osr_id) { 1089 intptr_t osr_id) {
1142 ASSERT(!FLAG_precompilation); 1090 ASSERT(!FLAG_precompilation);
1143 LongJumpScope jump; 1091 LongJumpScope jump;
1144 if (setjmp(*jump.Set()) == 0) { 1092 if (setjmp(*jump.Set()) == 0) {
1145 Thread* const thread = Thread::Current(); 1093 Thread* const thread = Thread::Current();
1146 Isolate* const isolate = thread->isolate(); 1094 Isolate* const isolate = thread->isolate();
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
1222 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) { 1170 if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
1223 Disassembler::DisassembleCode(function, optimized); 1171 Disassembler::DisassembleCode(function, optimized);
1224 } else if (FLAG_disassemble_optimized && 1172 } else if (FLAG_disassemble_optimized &&
1225 optimized && 1173 optimized &&
1226 FlowGraphPrinter::ShouldPrint(function)) { 1174 FlowGraphPrinter::ShouldPrint(function)) {
1227 // TODO(fschneider): Print unoptimized code along with the optimized code. 1175 // TODO(fschneider): Print unoptimized code along with the optimized code.
1228 THR_Print("*** BEGIN CODE\n"); 1176 THR_Print("*** BEGIN CODE\n");
1229 Disassembler::DisassembleCode(function, true); 1177 Disassembler::DisassembleCode(function, true);
1230 THR_Print("*** END CODE\n"); 1178 THR_Print("*** END CODE\n");
1231 } 1179 }
1232 #if defined(DEBUG) 1180 DEBUG_ONLY(CheckInliningIntervals(function));
1233 CheckInliningIntervals(function);
1234 #endif
1235 return Error::null(); 1181 return Error::null();
1236 } else { 1182 } else {
1237 Thread* const thread = Thread::Current(); 1183 Thread* const thread = Thread::Current();
1238 StackZone stack_zone(thread); 1184 StackZone stack_zone(thread);
1239 Error& error = Error::Handle(); 1185 Error& error = Error::Handle();
1240 // We got an error during compilation. 1186 // We got an error during compilation.
1241 error = thread->sticky_error(); 1187 error = thread->sticky_error();
1242 thread->clear_sticky_error(); 1188 thread->clear_sticky_error();
1243 // Unoptimized compilation or precompilation may encounter compile-time 1189 // Unoptimized compilation or precompilation may encounter compile-time
1244 // errors, but regular optimized compilation should not. 1190 // errors, but regular optimized compilation should not.
(...skipping 647 matching lines...) Expand 10 before | Expand all | Expand 10 after
1892 } 1838 }
1893 1839
1894 1840
1895 void BackgroundCompiler::EnsureInit(Thread* thread) { 1841 void BackgroundCompiler::EnsureInit(Thread* thread) {
1896 UNREACHABLE(); 1842 UNREACHABLE();
1897 } 1843 }
1898 1844
1899 #endif // DART_PRECOMPILED_RUNTIME 1845 #endif // DART_PRECOMPILED_RUNTIME
1900 1846
1901 } // namespace dart 1847 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/ast_printer.cc ('k') | runtime/vm/dart.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698