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

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

Issue 1314673008: Migrate logging infrastructure Isolate->Thread (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Fix test. Created 5 years, 3 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
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/block_scheduler.h" 7 #include "vm/block_scheduler.h"
8 #include "vm/compiler.h" 8 #include "vm/compiler.h"
9 #include "vm/flags.h" 9 #include "vm/flags.h"
10 #include "vm/flow_graph.h" 10 #include "vm/flow_graph.h"
(...skipping 545 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 CallSites sites1(caller_graph_); 556 CallSites sites1(caller_graph_);
557 CallSites sites2(caller_graph_); 557 CallSites sites2(caller_graph_);
558 CallSites* call_sites_temp = NULL; 558 CallSites* call_sites_temp = NULL;
559 collected_call_sites_ = &sites1; 559 collected_call_sites_ = &sites1;
560 inlining_call_sites_ = &sites2; 560 inlining_call_sites_ = &sites2;
561 // Collect initial call sites. 561 // Collect initial call sites.
562 collected_call_sites_->FindCallSites(caller_graph_, 562 collected_call_sites_->FindCallSites(caller_graph_,
563 inlining_depth_, 563 inlining_depth_,
564 &inlined_info_); 564 &inlined_info_);
565 while (collected_call_sites_->HasCalls()) { 565 while (collected_call_sites_->HasCalls()) {
566 TRACE_INLINING(ISL_Print(" Depth %" Pd " ----------\n", 566 TRACE_INLINING(THR_Print(" Depth %" Pd " ----------\n",
567 inlining_depth_)); 567 inlining_depth_));
568 if (collected_call_sites_->NumCalls() > FLAG_max_inlined_per_depth) { 568 if (collected_call_sites_->NumCalls() > FLAG_max_inlined_per_depth) {
569 break; 569 break;
570 } 570 }
571 if (FLAG_print_inlining_tree) { 571 if (FLAG_print_inlining_tree) {
572 ISL_Print("**Depth % " Pd " calls to inline %" Pd "\n", 572 THR_Print("**Depth % " Pd " calls to inline %" Pd "\n",
573 inlining_depth_, collected_call_sites_->NumCalls()); 573 inlining_depth_, collected_call_sites_->NumCalls());
574 } 574 }
575 // Swap collected and inlining arrays and clear the new collecting array. 575 // Swap collected and inlining arrays and clear the new collecting array.
576 call_sites_temp = collected_call_sites_; 576 call_sites_temp = collected_call_sites_;
577 collected_call_sites_ = inlining_call_sites_; 577 collected_call_sites_ = inlining_call_sites_;
578 inlining_call_sites_ = call_sites_temp; 578 inlining_call_sites_ = call_sites_temp;
579 collected_call_sites_->Clear(); 579 collected_call_sites_->Clear();
580 // Inline call sites at the current depth. 580 // Inline call sites at the current depth.
581 InlineInstanceCalls(); 581 InlineInstanceCalls();
582 InlineStaticCalls(); 582 InlineStaticCalls();
(...skipping 24 matching lines...) Expand all
607 if (constant != NULL) { 607 if (constant != NULL) {
608 return new(Z) ConstantInstr(constant->value()); 608 return new(Z) ConstantInstr(constant->value());
609 } else { 609 } else {
610 return new(Z) ParameterInstr(i, graph->graph_entry()); 610 return new(Z) ParameterInstr(i, graph->graph_entry());
611 } 611 }
612 } 612 }
613 613
614 bool TryInlining(const Function& function, 614 bool TryInlining(const Function& function,
615 const Array& argument_names, 615 const Array& argument_names,
616 InlinedCallData* call_data) { 616 InlinedCallData* call_data) {
617 TRACE_INLINING(ISL_Print(" => %s (deopt count %d)\n", 617 TRACE_INLINING(THR_Print(" => %s (deopt count %d)\n",
618 function.ToCString(), 618 function.ToCString(),
619 function.deoptimization_counter())); 619 function.deoptimization_counter()));
620 620
621 // Make a handle for the unoptimized code so that it is not disconnected 621 // Make a handle for the unoptimized code so that it is not disconnected
622 // from the function while we are trying to inline it. 622 // from the function while we are trying to inline it.
623 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); 623 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
624 // Abort if the inlinable bit on the function is low. 624 // Abort if the inlinable bit on the function is low.
625 if (!function.CanBeInlined()) { 625 if (!function.CanBeInlined()) {
626 TRACE_INLINING(ISL_Print(" Bailout: not inlinable\n")); 626 TRACE_INLINING(THR_Print(" Bailout: not inlinable\n"));
627 PRINT_INLINING_TREE("Not inlinable", 627 PRINT_INLINING_TREE("Not inlinable",
628 &call_data->caller, &function, call_data->call); 628 &call_data->caller, &function, call_data->call);
629 return false; 629 return false;
630 } 630 }
631 631
632 // Abort if this function has deoptimized too much. 632 // Abort if this function has deoptimized too much.
633 if (function.deoptimization_counter() >= 633 if (function.deoptimization_counter() >=
634 FLAG_deoptimization_counter_threshold) { 634 FLAG_deoptimization_counter_threshold) {
635 function.set_is_inlinable(false); 635 function.set_is_inlinable(false);
636 TRACE_INLINING(ISL_Print(" Bailout: deoptimization threshold\n")); 636 TRACE_INLINING(THR_Print(" Bailout: deoptimization threshold\n"));
637 PRINT_INLINING_TREE("Deoptimization threshold exceeded", 637 PRINT_INLINING_TREE("Deoptimization threshold exceeded",
638 &call_data->caller, &function, call_data->call); 638 &call_data->caller, &function, call_data->call);
639 return false; 639 return false;
640 } 640 }
641 641
642 const char* kNeverInlineAnnotation = "NeverInline"; 642 const char* kNeverInlineAnnotation = "NeverInline";
643 if (FLAG_enable_inlining_annotations && 643 if (FLAG_enable_inlining_annotations &&
644 HasAnnotation(function, kNeverInlineAnnotation)) { 644 HasAnnotation(function, kNeverInlineAnnotation)) {
645 TRACE_INLINING(ISL_Print(" Bailout: NeverInline annotation\n")); 645 TRACE_INLINING(THR_Print(" Bailout: NeverInline annotation\n"));
646 return false; 646 return false;
647 } 647 }
648 648
649 GrowableArray<Value*>* arguments = call_data->arguments; 649 GrowableArray<Value*>* arguments = call_data->arguments;
650 const intptr_t constant_arguments = CountConstants(*arguments); 650 const intptr_t constant_arguments = CountConstants(*arguments);
651 if (!ShouldWeInline(function, 651 if (!ShouldWeInline(function,
652 function.optimized_instruction_count(), 652 function.optimized_instruction_count(),
653 function.optimized_call_site_count(), 653 function.optimized_call_site_count(),
654 constant_arguments)) { 654 constant_arguments)) {
655 TRACE_INLINING(ISL_Print(" Bailout: early heuristics with " 655 TRACE_INLINING(THR_Print(" Bailout: early heuristics with "
656 "code size: %" Pd ", " 656 "code size: %" Pd ", "
657 "call sites: %" Pd ", " 657 "call sites: %" Pd ", "
658 "const args: %" Pd "\n", 658 "const args: %" Pd "\n",
659 function.optimized_instruction_count(), 659 function.optimized_instruction_count(),
660 function.optimized_call_site_count(), 660 function.optimized_call_site_count(),
661 constant_arguments)); 661 constant_arguments));
662 PRINT_INLINING_TREE("Early heuristic", 662 PRINT_INLINING_TREE("Early heuristic",
663 &call_data->caller, &function, call_data->call); 663 &call_data->caller, &function, call_data->call);
664 return false; 664 return false;
665 } 665 }
666 666
667 // Abort if this is a recursive occurrence. 667 // Abort if this is a recursive occurrence.
668 Definition* call = call_data->call; 668 Definition* call = call_data->call;
669 // Added 'volatile' works around a possible GCC 4.9 compiler bug. 669 // Added 'volatile' works around a possible GCC 4.9 compiler bug.
670 volatile bool is_recursive_call = IsCallRecursive(function, call); 670 volatile bool is_recursive_call = IsCallRecursive(function, call);
671 if (is_recursive_call && 671 if (is_recursive_call &&
672 inlining_recursion_depth_ >= FLAG_inlining_recursion_depth_threshold) { 672 inlining_recursion_depth_ >= FLAG_inlining_recursion_depth_threshold) {
673 TRACE_INLINING(ISL_Print(" Bailout: recursive function\n")); 673 TRACE_INLINING(THR_Print(" Bailout: recursive function\n"));
674 PRINT_INLINING_TREE("Recursive function", 674 PRINT_INLINING_TREE("Recursive function",
675 &call_data->caller, &function, call_data->call); 675 &call_data->caller, &function, call_data->call);
676 return false; 676 return false;
677 } 677 }
678 678
679 // Save and clear deopt id. 679 // Save and clear deopt id.
680 const intptr_t prev_deopt_id = isolate()->deopt_id(); 680 const intptr_t prev_deopt_id = isolate()->deopt_id();
681 isolate()->set_deopt_id(0); 681 isolate()->set_deopt_id(0);
682 // Install bailout jump. 682 // Install bailout jump.
683 LongJumpScope jump; 683 LongJumpScope jump;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
726 726
727 // Create a parameter stub for each fixed positional parameter. 727 // Create a parameter stub for each fixed positional parameter.
728 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { 728 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
729 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); 729 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph));
730 } 730 }
731 731
732 // If the callee has optional parameters, rebuild the argument and stub 732 // If the callee has optional parameters, rebuild the argument and stub
733 // arrays so that actual arguments are in one-to-one with the formal 733 // arrays so that actual arguments are in one-to-one with the formal
734 // parameters. 734 // parameters.
735 if (function.HasOptionalParameters()) { 735 if (function.HasOptionalParameters()) {
736 TRACE_INLINING(ISL_Print(" adjusting for optional parameters\n")); 736 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n"));
737 if (!AdjustForOptionalParameters(*parsed_function, 737 if (!AdjustForOptionalParameters(*parsed_function,
738 argument_names, 738 argument_names,
739 arguments, 739 arguments,
740 param_stubs, 740 param_stubs,
741 callee_graph)) { 741 callee_graph)) {
742 function.set_is_inlinable(false); 742 function.set_is_inlinable(false);
743 TRACE_INLINING(ISL_Print(" Bailout: optional arg mismatch\n")); 743 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n"));
744 PRINT_INLINING_TREE("Optional arg mismatch", 744 PRINT_INLINING_TREE("Optional arg mismatch",
745 &call_data->caller, &function, call_data->call); 745 &call_data->caller, &function, call_data->call);
746 return false; 746 return false;
747 } 747 }
748 } 748 }
749 749
750 // After treating optional parameters the actual/formal count must match. 750 // After treating optional parameters the actual/formal count must match.
751 ASSERT(arguments->length() == function.NumParameters()); 751 ASSERT(arguments->length() == function.NumParameters());
752 ASSERT(param_stubs->length() == callee_graph->parameter_count()); 752 ASSERT(param_stubs->length() == callee_graph->parameter_count());
753 753
(...skipping 30 matching lines...) Expand all
784 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 784 DEBUG_ASSERT(callee_graph->VerifyUseLists());
785 785
786 // Optimize (a << b) & c patterns, merge instructions. Must occur before 786 // Optimize (a << b) & c patterns, merge instructions. Must occur before
787 // 'SelectRepresentations' which inserts conversion nodes. 787 // 'SelectRepresentations' which inserts conversion nodes.
788 optimizer.TryOptimizePatterns(); 788 optimizer.TryOptimizePatterns();
789 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 789 DEBUG_ASSERT(callee_graph->VerifyUseLists());
790 } 790 }
791 791
792 if (FLAG_trace_inlining && 792 if (FLAG_trace_inlining &&
793 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 793 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
794 ISL_Print("Callee graph for inlining %s\n", 794 THR_Print("Callee graph for inlining %s\n",
795 function.ToFullyQualifiedCString()); 795 function.ToFullyQualifiedCString());
796 FlowGraphPrinter printer(*callee_graph); 796 FlowGraphPrinter printer(*callee_graph);
797 printer.PrintBlocks(); 797 printer.PrintBlocks();
798 } 798 }
799 799
800 // Collect information about the call site and caller graph. 800 // Collect information about the call site and caller graph.
801 // TODO(zerny): Do this after CP and dead code elimination. 801 // TODO(zerny): Do this after CP and dead code elimination.
802 intptr_t constants_count = 0; 802 intptr_t constants_count = 0;
803 for (intptr_t i = 0; i < param_stubs->length(); ++i) { 803 for (intptr_t i = 0; i < param_stubs->length(); ++i) {
804 if ((*param_stubs)[i]->IsConstant()) ++constants_count; 804 if ((*param_stubs)[i]->IsConstant()) ++constants_count;
805 } 805 }
806 806
807 FlowGraphInliner::CollectGraphInfo(callee_graph); 807 FlowGraphInliner::CollectGraphInfo(callee_graph);
808 const intptr_t size = function.optimized_instruction_count(); 808 const intptr_t size = function.optimized_instruction_count();
809 const intptr_t call_site_count = function.optimized_call_site_count(); 809 const intptr_t call_site_count = function.optimized_call_site_count();
810 810
811 function.set_optimized_instruction_count(size); 811 function.set_optimized_instruction_count(size);
812 function.set_optimized_call_site_count(call_site_count); 812 function.set_optimized_call_site_count(call_site_count);
813 813
814 // Use heuristics do decide if this call should be inlined. 814 // Use heuristics do decide if this call should be inlined.
815 if (!ShouldWeInline(function, size, call_site_count, constants_count)) { 815 if (!ShouldWeInline(function, size, call_site_count, constants_count)) {
816 // If size is larger than all thresholds, don't consider it again. 816 // If size is larger than all thresholds, don't consider it again.
817 if ((size > FLAG_inlining_size_threshold) && 817 if ((size > FLAG_inlining_size_threshold) &&
818 (call_site_count > FLAG_inlining_callee_call_sites_threshold) && 818 (call_site_count > FLAG_inlining_callee_call_sites_threshold) &&
819 (size > FLAG_inlining_constant_arguments_min_size_threshold) && 819 (size > FLAG_inlining_constant_arguments_min_size_threshold) &&
820 (size > FLAG_inlining_constant_arguments_max_size_threshold)) { 820 (size > FLAG_inlining_constant_arguments_max_size_threshold)) {
821 function.set_is_inlinable(false); 821 function.set_is_inlinable(false);
822 } 822 }
823 isolate()->set_deopt_id(prev_deopt_id); 823 isolate()->set_deopt_id(prev_deopt_id);
824 TRACE_INLINING(ISL_Print(" Bailout: heuristics with " 824 TRACE_INLINING(THR_Print(" Bailout: heuristics with "
825 "code size: %" Pd ", " 825 "code size: %" Pd ", "
826 "call sites: %" Pd ", " 826 "call sites: %" Pd ", "
827 "const args: %" Pd "\n", 827 "const args: %" Pd "\n",
828 size, 828 size,
829 call_site_count, 829 call_site_count,
830 constants_count)); 830 constants_count));
831 PRINT_INLINING_TREE("Heuristic fail", 831 PRINT_INLINING_TREE("Heuristic fail",
832 &call_data->caller, &function, call_data->call); 832 &call_data->caller, &function, call_data->call);
833 return false; 833 return false;
834 } 834 }
(...skipping 30 matching lines...) Expand all
865 // When inlined, we add the deferred prefixes of the callee to the 865 // When inlined, we add the deferred prefixes of the callee to the
866 // caller's list of deferred prefixes. 866 // caller's list of deferred prefixes.
867 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); 867 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes());
868 868
869 FlowGraphInliner::SetInliningId(callee_graph, 869 FlowGraphInliner::SetInliningId(callee_graph,
870 inliner_->NextInlineId(callee_graph->function(), 870 inliner_->NextInlineId(callee_graph->function(),
871 call_data->caller_inlining_id_)); 871 call_data->caller_inlining_id_));
872 // We allocate a ZoneHandle for the unoptimized code so that it cannot be 872 // We allocate a ZoneHandle for the unoptimized code so that it cannot be
873 // disconnected from its function during the rest of compilation. 873 // disconnected from its function during the rest of compilation.
874 Code::ZoneHandle(unoptimized_code.raw()); 874 Code::ZoneHandle(unoptimized_code.raw());
875 TRACE_INLINING(ISL_Print(" Success\n")); 875 TRACE_INLINING(THR_Print(" Success\n"));
876 PRINT_INLINING_TREE(NULL, 876 PRINT_INLINING_TREE(NULL,
877 &call_data->caller, &function, call); 877 &call_data->caller, &function, call);
878 return true; 878 return true;
879 } else { 879 } else {
880 Error& error = Error::Handle(); 880 Error& error = Error::Handle();
881 error = isolate()->object_store()->sticky_error(); 881 error = isolate()->object_store()->sticky_error();
882 isolate()->object_store()->clear_sticky_error(); 882 isolate()->object_store()->clear_sticky_error();
883 isolate()->set_deopt_id(prev_deopt_id); 883 isolate()->set_deopt_id(prev_deopt_id);
884 TRACE_INLINING(ISL_Print(" Bailout: %s\n", error.ToErrorCString())); 884 TRACE_INLINING(THR_Print(" Bailout: %s\n", error.ToErrorCString()));
885 PRINT_INLINING_TREE("Bailout", 885 PRINT_INLINING_TREE("Bailout",
886 &call_data->caller, &function, call); 886 &call_data->caller, &function, call);
887 return false; 887 return false;
888 } 888 }
889 } 889 }
890 890
891 void PrintInlinedInfo(const Function& top) { 891 void PrintInlinedInfo(const Function& top) {
892 if (inlined_info_.length() > 0) { 892 if (inlined_info_.length() > 0) {
893 ISL_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n", 893 THR_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n",
894 top.ToFullyQualifiedCString(), 894 top.ToFullyQualifiedCString(),
895 GrowthFactor(), 895 GrowthFactor(),
896 initial_size_, 896 initial_size_,
897 inlined_size_); 897 inlined_size_);
898 PrintInlinedInfoFor(top, 1); 898 PrintInlinedInfoFor(top, 1);
899 } 899 }
900 } 900 }
901 901
902 private: 902 private:
903 friend class PolymorphicInliner; 903 friend class PolymorphicInliner;
(...skipping 12 matching lines...) Expand all
916 // Print those that were inlined. 916 // Print those that were inlined.
917 for (intptr_t i = 0; i < inlined_info_.length(); i++) { 917 for (intptr_t i = 0; i < inlined_info_.length(); i++) {
918 const InlinedInfo& info = inlined_info_[i]; 918 const InlinedInfo& info = inlined_info_[i];
919 if (info.bailout_reason != NULL) { 919 if (info.bailout_reason != NULL) {
920 continue; 920 continue;
921 } 921 }
922 if ((info.inlined_depth == depth) && 922 if ((info.inlined_depth == depth) &&
923 (info.caller->raw() == caller.raw()) && 923 (info.caller->raw() == caller.raw()) &&
924 !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) { 924 !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
925 for (int t = 0; t < depth; t++) { 925 for (int t = 0; t < depth; t++) {
926 ISL_Print(" "); 926 THR_Print(" ");
927 } 927 }
928 ISL_Print("%" Pd " %s\n", 928 THR_Print("%" Pd " %s\n",
929 info.call_instr->GetDeoptId(), 929 info.call_instr->GetDeoptId(),
930 info.inlined->ToQualifiedCString()); 930 info.inlined->ToQualifiedCString());
931 PrintInlinedInfoFor(*info.inlined, depth + 1); 931 PrintInlinedInfoFor(*info.inlined, depth + 1);
932 call_instructions_printed.Add(info.call_instr->GetDeoptId()); 932 call_instructions_printed.Add(info.call_instr->GetDeoptId());
933 } 933 }
934 } 934 }
935 call_instructions_printed.Clear(); 935 call_instructions_printed.Clear();
936 // Print those that were not inlined. 936 // Print those that were not inlined.
937 for (intptr_t i = 0; i < inlined_info_.length(); i++) { 937 for (intptr_t i = 0; i < inlined_info_.length(); i++) {
938 const InlinedInfo& info = inlined_info_[i]; 938 const InlinedInfo& info = inlined_info_[i];
939 if (info.bailout_reason == NULL) { 939 if (info.bailout_reason == NULL) {
940 continue; 940 continue;
941 } 941 }
942 if ((info.inlined_depth == depth) && 942 if ((info.inlined_depth == depth) &&
943 (info.caller->raw() == caller.raw()) && 943 (info.caller->raw() == caller.raw()) &&
944 !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) { 944 !Contains(call_instructions_printed, info.call_instr->GetDeoptId())) {
945 for (int t = 0; t < depth; t++) { 945 for (int t = 0; t < depth; t++) {
946 ISL_Print(" "); 946 THR_Print(" ");
947 } 947 }
948 ISL_Print("NO %" Pd " %s - %s\n", 948 THR_Print("NO %" Pd " %s - %s\n",
949 info.call_instr->GetDeoptId(), 949 info.call_instr->GetDeoptId(),
950 info.inlined->ToQualifiedCString(), 950 info.inlined->ToQualifiedCString(),
951 info.bailout_reason); 951 info.bailout_reason);
952 call_instructions_printed.Add(info.call_instr->GetDeoptId()); 952 call_instructions_printed.Add(info.call_instr->GetDeoptId());
953 } 953 }
954 } 954 }
955 } 955 }
956 956
957 void InlineCall(InlinedCallData* call_data) { 957 void InlineCall(InlinedCallData* call_data) {
958 CSTAT_TIMER_SCOPE(Thread::Current(), graphinliner_subst_timer); 958 CSTAT_TIMER_SCOPE(Thread::Current(), graphinliner_subst_timer);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1036 parsed_function->AllocateVariables(); 1036 parsed_function->AllocateVariables();
1037 return parsed_function; 1037 return parsed_function;
1038 } 1038 }
1039 1039
1040 // Include special handling for List. factory: inlining it is not helpful 1040 // Include special handling for List. factory: inlining it is not helpful
1041 // if the incoming argument is a non-constant value. 1041 // if the incoming argument is a non-constant value.
1042 // TODO(srdjan): Fix inlining of List. factory. 1042 // TODO(srdjan): Fix inlining of List. factory.
1043 void InlineStaticCalls() { 1043 void InlineStaticCalls() {
1044 const GrowableArray<CallSites::StaticCallInfo>& call_info = 1044 const GrowableArray<CallSites::StaticCallInfo>& call_info =
1045 inlining_call_sites_->static_calls(); 1045 inlining_call_sites_->static_calls();
1046 TRACE_INLINING(ISL_Print(" Static Calls (%" Pd ")\n", call_info.length())); 1046 TRACE_INLINING(THR_Print(" Static Calls (%" Pd ")\n", call_info.length()));
1047 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { 1047 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
1048 StaticCallInstr* call = call_info[call_idx].call; 1048 StaticCallInstr* call = call_info[call_idx].call;
1049 if (call->function().name() == Symbols::ListFactory().raw()) { 1049 if (call->function().name() == Symbols::ListFactory().raw()) {
1050 // Inline only if no arguments or a constant was passed. 1050 // Inline only if no arguments or a constant was passed.
1051 ASSERT(call->function().NumImplicitParameters() == 1); 1051 ASSERT(call->function().NumImplicitParameters() == 1);
1052 ASSERT(call->ArgumentCount() <= 2); 1052 ASSERT(call->ArgumentCount() <= 2);
1053 // Arg 0: Instantiator type arguments. 1053 // Arg 0: Instantiator type arguments.
1054 // Arg 1: Length (optional). 1054 // Arg 1: Length (optional).
1055 if ((call->ArgumentCount() == 2) && 1055 if ((call->ArgumentCount() == 2) &&
1056 (!call->PushArgumentAt(1)->value()->BindsToConstant())) { 1056 (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
1057 // Do not inline since a non-constant argument was passed. 1057 // Do not inline since a non-constant argument was passed.
1058 continue; 1058 continue;
1059 } 1059 }
1060 } 1060 }
1061 const Function& target = call->function(); 1061 const Function& target = call->function();
1062 if (!inliner_->AlwaysInline(target) && 1062 if (!inliner_->AlwaysInline(target) &&
1063 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { 1063 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
1064 TRACE_INLINING(ISL_Print( 1064 TRACE_INLINING(THR_Print(
1065 " => %s (deopt count %d)\n Bailout: cold %f\n", 1065 " => %s (deopt count %d)\n Bailout: cold %f\n",
1066 target.ToCString(), 1066 target.ToCString(),
1067 target.deoptimization_counter(), 1067 target.deoptimization_counter(),
1068 call_info[call_idx].ratio)); 1068 call_info[call_idx].ratio));
1069 PRINT_INLINING_TREE("Too cold", 1069 PRINT_INLINING_TREE("Too cold",
1070 &call_info[call_idx].caller(), &call->function(), call); 1070 &call_info[call_idx].caller(), &call->function(), call);
1071 continue; 1071 continue;
1072 } 1072 }
1073 GrowableArray<Value*> arguments(call->ArgumentCount()); 1073 GrowableArray<Value*> arguments(call->ArgumentCount());
1074 for (int i = 0; i < call->ArgumentCount(); ++i) { 1074 for (int i = 0; i < call->ArgumentCount(); ++i) {
1075 arguments.Add(call->PushArgumentAt(i)->value()); 1075 arguments.Add(call->PushArgumentAt(i)->value());
1076 } 1076 }
1077 InlinedCallData call_data( 1077 InlinedCallData call_data(
1078 call, &arguments, call_info[call_idx].caller(), 1078 call, &arguments, call_info[call_idx].caller(),
1079 call_info[call_idx].caller_graph->inlining_id()); 1079 call_info[call_idx].caller_graph->inlining_id());
1080 if (TryInlining(call->function(), call->argument_names(), &call_data)) { 1080 if (TryInlining(call->function(), call->argument_names(), &call_data)) {
1081 InlineCall(&call_data); 1081 InlineCall(&call_data);
1082 } 1082 }
1083 } 1083 }
1084 } 1084 }
1085 1085
1086 void InlineClosureCalls() { 1086 void InlineClosureCalls() {
1087 const GrowableArray<CallSites::ClosureCallInfo>& call_info = 1087 const GrowableArray<CallSites::ClosureCallInfo>& call_info =
1088 inlining_call_sites_->closure_calls(); 1088 inlining_call_sites_->closure_calls();
1089 TRACE_INLINING(ISL_Print(" Closure Calls (%" Pd ")\n", 1089 TRACE_INLINING(THR_Print(" Closure Calls (%" Pd ")\n",
1090 call_info.length())); 1090 call_info.length()));
1091 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { 1091 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
1092 ClosureCallInstr* call = call_info[call_idx].call; 1092 ClosureCallInstr* call = call_info[call_idx].call;
1093 // Find the closure of the callee. 1093 // Find the closure of the callee.
1094 ASSERT(call->ArgumentCount() > 0); 1094 ASSERT(call->ArgumentCount() > 0);
1095 Function& target = Function::ZoneHandle(); 1095 Function& target = Function::ZoneHandle();
1096 AllocateObjectInstr* alloc = 1096 AllocateObjectInstr* alloc =
1097 call->ArgumentAt(0)->OriginalDefinition()->AsAllocateObject(); 1097 call->ArgumentAt(0)->OriginalDefinition()->AsAllocateObject();
1098 if ((alloc != NULL) && !alloc->closure_function().IsNull()) { 1098 if ((alloc != NULL) && !alloc->closure_function().IsNull()) {
1099 target ^= alloc->closure_function().raw(); 1099 target ^= alloc->closure_function().raw();
1100 ASSERT(target.signature_class() == alloc->cls().raw()); 1100 ASSERT(target.signature_class() == alloc->cls().raw());
1101 } 1101 }
1102 ConstantInstr* constant = 1102 ConstantInstr* constant =
1103 call->ArgumentAt(0)->OriginalDefinition()->AsConstant(); 1103 call->ArgumentAt(0)->OriginalDefinition()->AsConstant();
1104 if ((constant != NULL) && 1104 if ((constant != NULL) &&
1105 constant->value().IsInstance() && 1105 constant->value().IsInstance() &&
1106 Instance::Cast(constant->value()).IsClosure()) { 1106 Instance::Cast(constant->value()).IsClosure()) {
1107 target ^= Closure::function(Instance::Cast(constant->value())); 1107 target ^= Closure::function(Instance::Cast(constant->value()));
1108 } 1108 }
1109 1109
1110 if (target.IsNull()) { 1110 if (target.IsNull()) {
1111 TRACE_INLINING(ISL_Print(" Bailout: non-closure operator\n")); 1111 TRACE_INLINING(THR_Print(" Bailout: non-closure operator\n"));
1112 continue; 1112 continue;
1113 } 1113 }
1114 GrowableArray<Value*> arguments(call->ArgumentCount()); 1114 GrowableArray<Value*> arguments(call->ArgumentCount());
1115 for (int i = 0; i < call->ArgumentCount(); ++i) { 1115 for (int i = 0; i < call->ArgumentCount(); ++i) {
1116 arguments.Add(call->PushArgumentAt(i)->value()); 1116 arguments.Add(call->PushArgumentAt(i)->value());
1117 } 1117 }
1118 InlinedCallData call_data( 1118 InlinedCallData call_data(
1119 call, &arguments, call_info[call_idx].caller(), 1119 call, &arguments, call_info[call_idx].caller(),
1120 call_info[call_idx].caller_graph->inlining_id()); 1120 call_info[call_idx].caller_graph->inlining_id());
1121 if (TryInlining(target, 1121 if (TryInlining(target,
1122 call->argument_names(), 1122 call->argument_names(),
1123 &call_data)) { 1123 &call_data)) {
1124 InlineCall(&call_data); 1124 InlineCall(&call_data);
1125 } 1125 }
1126 } 1126 }
1127 } 1127 }
1128 1128
1129 void InlineInstanceCalls() { 1129 void InlineInstanceCalls() {
1130 const GrowableArray<CallSites::InstanceCallInfo>& call_info = 1130 const GrowableArray<CallSites::InstanceCallInfo>& call_info =
1131 inlining_call_sites_->instance_calls(); 1131 inlining_call_sites_->instance_calls();
1132 TRACE_INLINING(ISL_Print(" Polymorphic Instance Calls (%" Pd ")\n", 1132 TRACE_INLINING(THR_Print(" Polymorphic Instance Calls (%" Pd ")\n",
1133 call_info.length())); 1133 call_info.length()));
1134 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { 1134 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
1135 PolymorphicInstanceCallInstr* call = call_info[call_idx].call; 1135 PolymorphicInstanceCallInstr* call = call_info[call_idx].call;
1136 if (call->with_checks()) { 1136 if (call->with_checks()) {
1137 // PolymorphicInliner introduces deoptimization paths. 1137 // PolymorphicInliner introduces deoptimization paths.
1138 if (!FLAG_polymorphic_with_deopt) return; 1138 if (!FLAG_polymorphic_with_deopt) return;
1139 const Function& cl = call_info[call_idx].caller(); 1139 const Function& cl = call_info[call_idx].caller();
1140 intptr_t caller_inlining_id = 1140 intptr_t caller_inlining_id =
1141 call_info[call_idx].caller_graph->inlining_id(); 1141 call_info[call_idx].caller_graph->inlining_id();
1142 PolymorphicInliner inliner(this, call, cl, caller_inlining_id); 1142 PolymorphicInliner inliner(this, call, cl, caller_inlining_id);
1143 inliner.Inline(); 1143 inliner.Inline();
1144 continue; 1144 continue;
1145 } 1145 }
1146 1146
1147 const ICData& ic_data = call->ic_data(); 1147 const ICData& ic_data = call->ic_data();
1148 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 1148 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
1149 if (!inliner_->AlwaysInline(target) && 1149 if (!inliner_->AlwaysInline(target) &&
1150 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { 1150 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
1151 TRACE_INLINING(ISL_Print( 1151 TRACE_INLINING(THR_Print(
1152 " => %s (deopt count %d)\n Bailout: cold %f\n", 1152 " => %s (deopt count %d)\n Bailout: cold %f\n",
1153 target.ToCString(), 1153 target.ToCString(),
1154 target.deoptimization_counter(), 1154 target.deoptimization_counter(),
1155 call_info[call_idx].ratio)); 1155 call_info[call_idx].ratio));
1156 PRINT_INLINING_TREE("Too cold", 1156 PRINT_INLINING_TREE("Too cold",
1157 &call_info[call_idx].caller(), &target, call); 1157 &call_info[call_idx].caller(), &target, call);
1158 continue; 1158 continue;
1159 } 1159 }
1160 GrowableArray<Value*> arguments(call->ArgumentCount()); 1160 GrowableArray<Value*> arguments(call->ArgumentCount());
1161 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) { 1161 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) {
(...skipping 660 matching lines...) Expand 10 before | Expand all | Expand 10 after
1822 (function.name() == Symbols::AssignIndexToken().raw()) || 1822 (function.name() == Symbols::AssignIndexToken().raw()) ||
1823 (function.name() == Symbols::Plus().raw()) || 1823 (function.name() == Symbols::Plus().raw()) ||
1824 (function.name() == Symbols::Minus().raw()); 1824 (function.name() == Symbols::Minus().raw());
1825 } 1825 }
1826 1826
1827 1827
1828 bool FlowGraphInliner::AlwaysInline(const Function& function) { 1828 bool FlowGraphInliner::AlwaysInline(const Function& function) {
1829 const char* kAlwaysInlineAnnotation = "AlwaysInline"; 1829 const char* kAlwaysInlineAnnotation = "AlwaysInline";
1830 if (FLAG_enable_inlining_annotations && 1830 if (FLAG_enable_inlining_annotations &&
1831 HasAnnotation(function, kAlwaysInlineAnnotation)) { 1831 HasAnnotation(function, kAlwaysInlineAnnotation)) {
1832 TRACE_INLINING(ISL_Print("AlwaysInline annotation for %s\n", 1832 TRACE_INLINING(THR_Print("AlwaysInline annotation for %s\n",
1833 function.ToCString())); 1833 function.ToCString()));
1834 return true; 1834 return true;
1835 } 1835 }
1836 1836
1837 if (function.IsImplicitGetterFunction() || function.IsGetterFunction() || 1837 if (function.IsImplicitGetterFunction() || function.IsGetterFunction() ||
1838 function.IsImplicitSetterFunction() || function.IsSetterFunction() || 1838 function.IsImplicitSetterFunction() || function.IsSetterFunction() ||
1839 IsInlineableOperator(function)) { 1839 IsInlineableOperator(function)) {
1840 const intptr_t count = function.optimized_instruction_count(); 1840 const intptr_t count = function.optimized_instruction_count();
1841 if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) { 1841 if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) {
1842 return true; 1842 return true;
1843 } 1843 }
1844 } 1844 }
1845 return MethodRecognizer::AlwaysInline(function); 1845 return MethodRecognizer::AlwaysInline(function);
1846 } 1846 }
1847 1847
1848 1848
1849 void FlowGraphInliner::Inline() { 1849 void FlowGraphInliner::Inline() {
1850 // Collect graph info and store it on the function. 1850 // Collect graph info and store it on the function.
1851 // We might later use it for an early bailout from the inlining. 1851 // We might later use it for an early bailout from the inlining.
1852 CollectGraphInfo(flow_graph_); 1852 CollectGraphInfo(flow_graph_);
1853 1853
1854 const Function& top = flow_graph_->function(); 1854 const Function& top = flow_graph_->function();
1855 if ((FLAG_inlining_filter != NULL) && 1855 if ((FLAG_inlining_filter != NULL) &&
1856 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { 1856 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) {
1857 return; 1857 return;
1858 } 1858 }
1859 1859
1860 TRACE_INLINING(ISL_Print("Inlining calls in %s\n", top.ToCString())); 1860 TRACE_INLINING(THR_Print("Inlining calls in %s\n", top.ToCString()));
1861 1861
1862 if (trace_inlining() && 1862 if (trace_inlining() &&
1863 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 1863 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
1864 ISL_Print("Before Inlining of %s\n", flow_graph_-> 1864 THR_Print("Before Inlining of %s\n", flow_graph_->
1865 function().ToFullyQualifiedCString()); 1865 function().ToFullyQualifiedCString());
1866 FlowGraphPrinter printer(*flow_graph_); 1866 FlowGraphPrinter printer(*flow_graph_);
1867 printer.PrintBlocks(); 1867 printer.PrintBlocks();
1868 } 1868 }
1869 1869
1870 CallSiteInliner inliner(this); 1870 CallSiteInliner inliner(this);
1871 inliner.InlineCalls(); 1871 inliner.InlineCalls();
1872 if (FLAG_print_inlining_tree) { 1872 if (FLAG_print_inlining_tree) {
1873 inliner.PrintInlinedInfo(top); 1873 inliner.PrintInlinedInfo(top);
1874 } 1874 }
1875 1875
1876 if (inliner.inlined()) { 1876 if (inliner.inlined()) {
1877 flow_graph_->DiscoverBlocks(); 1877 flow_graph_->DiscoverBlocks();
1878 if (trace_inlining()) { 1878 if (trace_inlining()) {
1879 ISL_Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); 1879 THR_Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
1880 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { 1880 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
1881 ISL_Print("After Inlining of %s\n", flow_graph_-> 1881 THR_Print("After Inlining of %s\n", flow_graph_->
1882 function().ToFullyQualifiedCString()); 1882 function().ToFullyQualifiedCString());
1883 FlowGraphPrinter printer(*flow_graph_); 1883 FlowGraphPrinter printer(*flow_graph_);
1884 printer.PrintBlocks(); 1884 printer.PrintBlocks();
1885 } 1885 }
1886 } 1886 }
1887 } 1887 }
1888 } 1888 }
1889 1889
1890 1890
1891 intptr_t FlowGraphInliner::NextInlineId(const Function& function, 1891 intptr_t FlowGraphInliner::NextInlineId(const Function& function,
1892 intptr_t parent_id) { 1892 intptr_t parent_id) {
1893 const intptr_t id = inline_id_to_function_->length(); 1893 const intptr_t id = inline_id_to_function_->length();
1894 inline_id_to_function_->Add(&function); 1894 inline_id_to_function_->Add(&function);
1895 caller_inline_id_->Add(parent_id); 1895 caller_inline_id_->Add(parent_id);
1896 return id; 1896 return id;
1897 } 1897 }
1898 1898
1899 1899
1900 } // namespace dart 1900 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698