| OLD | NEW |
| 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 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 680 inlining_recursion_depth_ >= FLAG_inlining_recursion_depth_threshold) { | 680 inlining_recursion_depth_ >= FLAG_inlining_recursion_depth_threshold) { |
| 681 TRACE_INLINING(THR_Print(" Bailout: recursive function\n")); | 681 TRACE_INLINING(THR_Print(" Bailout: recursive function\n")); |
| 682 PRINT_INLINING_TREE("Recursive function", | 682 PRINT_INLINING_TREE("Recursive function", |
| 683 &call_data->caller, &function, call_data->call); | 683 &call_data->caller, &function, call_data->call); |
| 684 return false; | 684 return false; |
| 685 } | 685 } |
| 686 | 686 |
| 687 // Save and clear deopt id. | 687 // Save and clear deopt id. |
| 688 const intptr_t prev_deopt_id = thread()->deopt_id(); | 688 const intptr_t prev_deopt_id = thread()->deopt_id(); |
| 689 thread()->set_deopt_id(0); | 689 thread()->set_deopt_id(0); |
| 690 // Install bailout jump. | 690 Error& error = Error::Handle(); |
| 691 LongJumpScope jump; | 691 { |
| 692 if (setjmp(*jump.Set()) == 0) { | 692 // Install bailout jump. |
| 693 // Parse the callee function. | 693 LongJumpScope jump; |
| 694 bool in_cache; | 694 if (setjmp(*jump.Set()) == 0) { |
| 695 ParsedFunction* parsed_function; | 695 // Parse the callee function. |
| 696 { | 696 bool in_cache; |
| 697 CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer); | 697 ParsedFunction* parsed_function; |
| 698 parsed_function = GetParsedFunction(function, &in_cache); | 698 { |
| 699 } | 699 CSTAT_TIMER_SCOPE(thread(), graphinliner_parse_timer); |
| 700 | 700 parsed_function = GetParsedFunction(function, &in_cache); |
| 701 // Load IC data for the callee. | 701 } |
| 702 ZoneGrowableArray<const ICData*>* ic_data_array = | 702 |
| 703 new(Z) ZoneGrowableArray<const ICData*>(); | 703 // Load IC data for the callee. |
| 704 const bool clone_descriptors = Compiler::IsBackgroundCompilation(); | 704 ZoneGrowableArray<const ICData*>* ic_data_array = |
| 705 function.RestoreICDataMap(ic_data_array, clone_descriptors); | 705 new(Z) ZoneGrowableArray<const ICData*>(); |
| 706 | 706 const bool clone_descriptors = Compiler::IsBackgroundCompilation(); |
| 707 // Build the callee graph. | 707 function.RestoreICDataMap(ic_data_array, clone_descriptors); |
| 708 InlineExitCollector* exit_collector = | 708 |
| 709 new(Z) InlineExitCollector(caller_graph_, call); | 709 // Build the callee graph. |
| 710 FlowGraphBuilder builder(*parsed_function, | 710 InlineExitCollector* exit_collector = |
| 711 *ic_data_array, | 711 new(Z) InlineExitCollector(caller_graph_, call); |
| 712 exit_collector, | 712 FlowGraphBuilder builder(*parsed_function, |
| 713 Compiler::kNoOSRDeoptId); | 713 *ic_data_array, |
| 714 builder.SetInitialBlockId(caller_graph_->max_block_id()); | 714 exit_collector, |
| 715 FlowGraph* callee_graph; | 715 Compiler::kNoOSRDeoptId); |
| 716 { | 716 builder.SetInitialBlockId(caller_graph_->max_block_id()); |
| 717 CSTAT_TIMER_SCOPE(thread(), graphinliner_build_timer); | 717 FlowGraph* callee_graph; |
| 718 callee_graph = builder.BuildGraph(); | 718 { |
| 719 } | 719 CSTAT_TIMER_SCOPE(thread(), graphinliner_build_timer); |
| 720 | 720 callee_graph = builder.BuildGraph(); |
| 721 // The parameter stubs are a copy of the actual arguments providing | 721 } |
| 722 // concrete information about the values, for example constant values, | 722 |
| 723 // without linking between the caller and callee graphs. | 723 // The parameter stubs are a copy of the actual arguments providing |
| 724 // TODO(zerny): Put more information in the stubs, eg, type information. | 724 // concrete information about the values, for example constant values, |
| 725 ZoneGrowableArray<Definition*>* param_stubs = | 725 // without linking between the caller and callee graphs. |
| 726 new(Z) ZoneGrowableArray<Definition*>( | 726 // TODO(zerny): Put more information in the stubs, eg, type information. |
| 727 function.NumParameters()); | 727 ZoneGrowableArray<Definition*>* param_stubs = |
| 728 | 728 new(Z) ZoneGrowableArray<Definition*>( |
| 729 // Create a parameter stub for each fixed positional parameter. | 729 function.NumParameters()); |
| 730 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { | 730 |
| 731 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); | 731 // Create a parameter stub for each fixed positional parameter. |
| 732 } | 732 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { |
| 733 | 733 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], |
| 734 // If the callee has optional parameters, rebuild the argument and stub | 734 callee_graph)); |
| 735 // arrays so that actual arguments are in one-to-one with the formal | 735 } |
| 736 // parameters. | 736 |
| 737 if (function.HasOptionalParameters()) { | 737 // If the callee has optional parameters, rebuild the argument and stub |
| 738 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); | 738 // arrays so that actual arguments are in one-to-one with the formal |
| 739 if (!AdjustForOptionalParameters(*parsed_function, | 739 // parameters. |
| 740 argument_names, | 740 if (function.HasOptionalParameters()) { |
| 741 arguments, | 741 TRACE_INLINING(THR_Print(" adjusting for optional parameters\n")); |
| 742 param_stubs, | 742 if (!AdjustForOptionalParameters(*parsed_function, |
| 743 callee_graph)) { | 743 argument_names, |
| 744 function.set_is_inlinable(false); | 744 arguments, |
| 745 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); | 745 param_stubs, |
| 746 PRINT_INLINING_TREE("Optional arg mismatch", | 746 callee_graph)) { |
| 747 function.set_is_inlinable(false); |
| 748 TRACE_INLINING(THR_Print(" Bailout: optional arg mismatch\n")); |
| 749 PRINT_INLINING_TREE("Optional arg mismatch", |
| 750 &call_data->caller, &function, call_data->call); |
| 751 return false; |
| 752 } |
| 753 } |
| 754 |
| 755 // After treating optional parameters the actual/formal count must |
| 756 // match. |
| 757 ASSERT(arguments->length() == function.NumParameters()); |
| 758 ASSERT(param_stubs->length() == callee_graph->parameter_count()); |
| 759 |
| 760 // Update try-index of the callee graph. |
| 761 BlockEntryInstr* call_block = call_data->call->GetBlock(); |
| 762 if (call_block->InsideTryBlock()) { |
| 763 intptr_t try_index = call_block->try_index(); |
| 764 for (BlockIterator it = callee_graph->reverse_postorder_iterator(); |
| 765 !it.Done(); it.Advance()) { |
| 766 BlockEntryInstr* block = it.Current(); |
| 767 block->set_try_index(try_index); |
| 768 } |
| 769 } |
| 770 |
| 771 BlockScheduler block_scheduler(callee_graph); |
| 772 block_scheduler.AssignEdgeWeights(); |
| 773 |
| 774 { |
| 775 CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer); |
| 776 // Compute SSA on the callee graph, catching bailouts. |
| 777 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), |
| 778 param_stubs); |
| 779 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 780 } |
| 781 |
| 782 { |
| 783 CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer); |
| 784 // TODO(fschneider): Improve suppression of speculative inlining. |
| 785 // Deopt-ids overlap between caller and callee. |
| 786 FlowGraphOptimizer optimizer(callee_graph, |
| 787 inliner_->use_speculative_inlining_, |
| 788 inliner_->inlining_black_list_); |
| 789 if (Compiler::always_optimize()) { |
| 790 optimizer.PopulateWithICData(); |
| 791 |
| 792 optimizer.ApplyClassIds(); |
| 793 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 794 |
| 795 FlowGraphTypePropagator::Propagate(callee_graph); |
| 796 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 797 } |
| 798 optimizer.ApplyICData(); |
| 799 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 800 |
| 801 // Optimize (a << b) & c patterns, merge instructions. Must occur |
| 802 // before 'SelectRepresentations' which inserts conversion nodes. |
| 803 optimizer.TryOptimizePatterns(); |
| 804 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
| 805 } |
| 806 |
| 807 if (FLAG_trace_inlining && |
| 808 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
| 809 THR_Print("Callee graph for inlining %s\n", |
| 810 function.ToFullyQualifiedCString()); |
| 811 FlowGraphPrinter printer(*callee_graph); |
| 812 printer.PrintBlocks(); |
| 813 } |
| 814 |
| 815 // Collect information about the call site and caller graph. |
| 816 // TODO(zerny): Do this after CP and dead code elimination. |
| 817 intptr_t constants_count = 0; |
| 818 for (intptr_t i = 0; i < param_stubs->length(); ++i) { |
| 819 if ((*param_stubs)[i]->IsConstant()) ++constants_count; |
| 820 } |
| 821 |
| 822 FlowGraphInliner::CollectGraphInfo(callee_graph); |
| 823 const intptr_t size = function.optimized_instruction_count(); |
| 824 const intptr_t call_site_count = function.optimized_call_site_count(); |
| 825 |
| 826 function.set_optimized_instruction_count(size); |
| 827 function.set_optimized_call_site_count(call_site_count); |
| 828 |
| 829 // Use heuristics do decide if this call should be inlined. |
| 830 if (!ShouldWeInline(function, size, call_site_count, constants_count)) { |
| 831 // If size is larger than all thresholds, don't consider it again. |
| 832 if ((size > FLAG_inlining_size_threshold) && |
| 833 (call_site_count > FLAG_inlining_callee_call_sites_threshold) && |
| 834 (size > FLAG_inlining_constant_arguments_min_size_threshold) && |
| 835 (size > FLAG_inlining_constant_arguments_max_size_threshold)) { |
| 836 function.set_is_inlinable(false); |
| 837 } |
| 838 thread()->set_deopt_id(prev_deopt_id); |
| 839 TRACE_INLINING(THR_Print(" Bailout: heuristics with " |
| 840 "code size: %" Pd ", " |
| 841 "call sites: %" Pd ", " |
| 842 "const args: %" Pd "\n", |
| 843 size, |
| 844 call_site_count, |
| 845 constants_count)); |
| 846 PRINT_INLINING_TREE("Heuristic fail", |
| 747 &call_data->caller, &function, call_data->call); | 847 &call_data->caller, &function, call_data->call); |
| 748 return false; | 848 return false; |
| 749 } | 849 } |
| 850 |
| 851 // Inline dispatcher methods regardless of the current depth. |
| 852 const intptr_t depth = |
| 853 (function.IsInvokeFieldDispatcher() || |
| 854 function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_; |
| 855 collected_call_sites_->FindCallSites(callee_graph, depth, |
| 856 &inlined_info_); |
| 857 |
| 858 // Add the function to the cache. |
| 859 if (!in_cache) { |
| 860 function_cache_.Add(parsed_function); |
| 861 } |
| 862 |
| 863 // Build succeeded so we restore the bailout jump. |
| 864 inlined_ = true; |
| 865 inlined_size_ += size; |
| 866 if (is_recursive_call) { |
| 867 inlined_recursive_call_ = true; |
| 868 } |
| 869 thread()->set_deopt_id(prev_deopt_id); |
| 870 |
| 871 call_data->callee_graph = callee_graph; |
| 872 call_data->parameter_stubs = param_stubs; |
| 873 call_data->exit_collector = exit_collector; |
| 874 |
| 875 // When inlined, we add the guarded fields of the callee to the caller's |
| 876 // list of guarded fields. |
| 877 for (intptr_t i = 0; |
| 878 i < callee_graph->guarded_fields()->length(); |
| 879 ++i) { |
| 880 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), |
| 881 (*callee_graph->guarded_fields())[i]); |
| 882 } |
| 883 // When inlined, we add the deferred prefixes of the callee to the |
| 884 // caller's list of deferred prefixes. |
| 885 caller_graph()->AddToDeferredPrefixes( |
| 886 callee_graph->deferred_prefixes()); |
| 887 |
| 888 FlowGraphInliner::SetInliningId(callee_graph, |
| 889 inliner_->NextInlineId(callee_graph->function(), |
| 890 call_data->caller_inlining_id_)); |
| 891 TRACE_INLINING(THR_Print(" Success\n")); |
| 892 PRINT_INLINING_TREE(NULL, |
| 893 &call_data->caller, &function, call); |
| 894 return true; |
| 895 } else { |
| 896 error = isolate()->object_store()->sticky_error(); |
| 897 isolate()->object_store()->clear_sticky_error(); |
| 898 ASSERT(error.IsLanguageError()); |
| 899 |
| 900 if (LanguageError::Cast(error).kind() == Report::kBailout) { |
| 901 thread()->set_deopt_id(prev_deopt_id); |
| 902 TRACE_INLINING(THR_Print(" Bailout: %s\n", |
| 903 error.ToErrorCString())); |
| 904 PRINT_INLINING_TREE("Bailout", |
| 905 &call_data->caller, &function, call); |
| 906 return false; |
| 907 } else { |
| 908 // Fall through to exit long jump scope. |
| 909 } |
| 750 } | 910 } |
| 751 | |
| 752 // After treating optional parameters the actual/formal count must match. | |
| 753 ASSERT(arguments->length() == function.NumParameters()); | |
| 754 ASSERT(param_stubs->length() == callee_graph->parameter_count()); | |
| 755 | |
| 756 // Update try-index of the callee graph. | |
| 757 BlockEntryInstr* call_block = call_data->call->GetBlock(); | |
| 758 if (call_block->InsideTryBlock()) { | |
| 759 intptr_t try_index = call_block->try_index(); | |
| 760 for (BlockIterator it = callee_graph->reverse_postorder_iterator(); | |
| 761 !it.Done(); it.Advance()) { | |
| 762 BlockEntryInstr* block = it.Current(); | |
| 763 block->set_try_index(try_index); | |
| 764 } | |
| 765 } | |
| 766 | |
| 767 BlockScheduler block_scheduler(callee_graph); | |
| 768 block_scheduler.AssignEdgeWeights(); | |
| 769 | |
| 770 { | |
| 771 CSTAT_TIMER_SCOPE(thread(), graphinliner_ssa_timer); | |
| 772 // Compute SSA on the callee graph, catching bailouts. | |
| 773 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), | |
| 774 param_stubs); | |
| 775 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | |
| 776 } | |
| 777 | |
| 778 { | |
| 779 CSTAT_TIMER_SCOPE(thread(), graphinliner_opt_timer); | |
| 780 // TODO(fschneider): Improve suppression of speculative inlining. | |
| 781 // Deopt-ids overlap between caller and callee. | |
| 782 FlowGraphOptimizer optimizer(callee_graph, | |
| 783 inliner_->use_speculative_inlining_, | |
| 784 inliner_->inlining_black_list_); | |
| 785 if (Compiler::always_optimize()) { | |
| 786 optimizer.PopulateWithICData(); | |
| 787 | |
| 788 optimizer.ApplyClassIds(); | |
| 789 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | |
| 790 | |
| 791 FlowGraphTypePropagator::Propagate(callee_graph); | |
| 792 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | |
| 793 } | |
| 794 optimizer.ApplyICData(); | |
| 795 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | |
| 796 | |
| 797 // Optimize (a << b) & c patterns, merge instructions. Must occur before | |
| 798 // 'SelectRepresentations' which inserts conversion nodes. | |
| 799 optimizer.TryOptimizePatterns(); | |
| 800 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | |
| 801 } | |
| 802 | |
| 803 if (FLAG_trace_inlining && | |
| 804 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | |
| 805 THR_Print("Callee graph for inlining %s\n", | |
| 806 function.ToFullyQualifiedCString()); | |
| 807 FlowGraphPrinter printer(*callee_graph); | |
| 808 printer.PrintBlocks(); | |
| 809 } | |
| 810 | |
| 811 // Collect information about the call site and caller graph. | |
| 812 // TODO(zerny): Do this after CP and dead code elimination. | |
| 813 intptr_t constants_count = 0; | |
| 814 for (intptr_t i = 0; i < param_stubs->length(); ++i) { | |
| 815 if ((*param_stubs)[i]->IsConstant()) ++constants_count; | |
| 816 } | |
| 817 | |
| 818 FlowGraphInliner::CollectGraphInfo(callee_graph); | |
| 819 const intptr_t size = function.optimized_instruction_count(); | |
| 820 const intptr_t call_site_count = function.optimized_call_site_count(); | |
| 821 | |
| 822 function.set_optimized_instruction_count(size); | |
| 823 function.set_optimized_call_site_count(call_site_count); | |
| 824 | |
| 825 // Use heuristics do decide if this call should be inlined. | |
| 826 if (!ShouldWeInline(function, size, call_site_count, constants_count)) { | |
| 827 // If size is larger than all thresholds, don't consider it again. | |
| 828 if ((size > FLAG_inlining_size_threshold) && | |
| 829 (call_site_count > FLAG_inlining_callee_call_sites_threshold) && | |
| 830 (size > FLAG_inlining_constant_arguments_min_size_threshold) && | |
| 831 (size > FLAG_inlining_constant_arguments_max_size_threshold)) { | |
| 832 function.set_is_inlinable(false); | |
| 833 } | |
| 834 thread()->set_deopt_id(prev_deopt_id); | |
| 835 TRACE_INLINING(THR_Print(" Bailout: heuristics with " | |
| 836 "code size: %" Pd ", " | |
| 837 "call sites: %" Pd ", " | |
| 838 "const args: %" Pd "\n", | |
| 839 size, | |
| 840 call_site_count, | |
| 841 constants_count)); | |
| 842 PRINT_INLINING_TREE("Heuristic fail", | |
| 843 &call_data->caller, &function, call_data->call); | |
| 844 return false; | |
| 845 } | |
| 846 | |
| 847 // Inline dispatcher methods regardless of the current depth. | |
| 848 const intptr_t depth = | |
| 849 (function.IsInvokeFieldDispatcher() || | |
| 850 function.IsNoSuchMethodDispatcher()) ? 0 : inlining_depth_; | |
| 851 collected_call_sites_->FindCallSites(callee_graph, depth, &inlined_info_); | |
| 852 | |
| 853 // Add the function to the cache. | |
| 854 if (!in_cache) { | |
| 855 function_cache_.Add(parsed_function); | |
| 856 } | |
| 857 | |
| 858 // Build succeeded so we restore the bailout jump. | |
| 859 inlined_ = true; | |
| 860 inlined_size_ += size; | |
| 861 if (is_recursive_call) { | |
| 862 inlined_recursive_call_ = true; | |
| 863 } | |
| 864 thread()->set_deopt_id(prev_deopt_id); | |
| 865 | |
| 866 call_data->callee_graph = callee_graph; | |
| 867 call_data->parameter_stubs = param_stubs; | |
| 868 call_data->exit_collector = exit_collector; | |
| 869 | |
| 870 // When inlined, we add the guarded fields of the callee to the caller's | |
| 871 // list of guarded fields. | |
| 872 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { | |
| 873 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), | |
| 874 (*callee_graph->guarded_fields())[i]); | |
| 875 } | |
| 876 // When inlined, we add the deferred prefixes of the callee to the | |
| 877 // caller's list of deferred prefixes. | |
| 878 caller_graph()->AddToDeferredPrefixes(callee_graph->deferred_prefixes()); | |
| 879 | |
| 880 FlowGraphInliner::SetInliningId(callee_graph, | |
| 881 inliner_->NextInlineId(callee_graph->function(), | |
| 882 call_data->caller_inlining_id_)); | |
| 883 TRACE_INLINING(THR_Print(" Success\n")); | |
| 884 PRINT_INLINING_TREE(NULL, | |
| 885 &call_data->caller, &function, call); | |
| 886 return true; | |
| 887 } else { | |
| 888 Error& error = Error::Handle(); | |
| 889 error = isolate()->object_store()->sticky_error(); | |
| 890 isolate()->object_store()->clear_sticky_error(); | |
| 891 thread()->set_deopt_id(prev_deopt_id); | |
| 892 TRACE_INLINING(THR_Print(" Bailout: %s\n", error.ToErrorCString())); | |
| 893 PRINT_INLINING_TREE("Bailout", | |
| 894 &call_data->caller, &function, call); | |
| 895 return false; | |
| 896 } | 911 } |
| 912 |
| 913 // Propagate a compile-time error. Only in precompilation do we attempt to |
| 914 // inline functions that have never been compiled before; when JITing we |
| 915 // should only see compile-time errors in unoptimized compilation. |
| 916 ASSERT(Compiler::always_optimize()); |
| 917 Thread::Current()->long_jump_base()->Jump(1, error); |
| 918 UNREACHABLE(); |
| 919 return false; |
| 897 } | 920 } |
| 898 | 921 |
| 899 void PrintInlinedInfo(const Function& top) { | 922 void PrintInlinedInfo(const Function& top) { |
| 900 if (inlined_info_.length() > 0) { | 923 if (inlined_info_.length() > 0) { |
| 901 THR_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n", | 924 THR_Print("Inlining into: '%s' growth: %f (%" Pd " -> %" Pd ")\n", |
| 902 top.ToFullyQualifiedCString(), | 925 top.ToFullyQualifiedCString(), |
| 903 GrowthFactor(), | 926 GrowthFactor(), |
| 904 initial_size_, | 927 initial_size_, |
| 905 inlined_size_); | 928 inlined_size_); |
| 906 PrintInlinedInfoFor(top, 1); | 929 PrintInlinedInfoFor(top, 1); |
| (...skipping 1005 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1912 intptr_t FlowGraphInliner::NextInlineId(const Function& function, | 1935 intptr_t FlowGraphInliner::NextInlineId(const Function& function, |
| 1913 intptr_t parent_id) { | 1936 intptr_t parent_id) { |
| 1914 const intptr_t id = inline_id_to_function_->length(); | 1937 const intptr_t id = inline_id_to_function_->length(); |
| 1915 inline_id_to_function_->Add(&function); | 1938 inline_id_to_function_->Add(&function); |
| 1916 caller_inline_id_->Add(parent_id); | 1939 caller_inline_id_->Add(parent_id); |
| 1917 return id; | 1940 return id; |
| 1918 } | 1941 } |
| 1919 | 1942 |
| 1920 | 1943 |
| 1921 } // namespace dart | 1944 } // namespace dart |
| OLD | NEW |