| 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 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 42 "Inline function calls with sufficient constant arguments " | 42 "Inline function calls with sufficient constant arguments " |
| 43 "and up to the increased threshold on instructions"); | 43 "and up to the increased threshold on instructions"); |
| 44 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60, | 44 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60, |
| 45 "Inline function calls with sufficient constant arguments " | 45 "Inline function calls with sufficient constant arguments " |
| 46 "and up to the increased threshold on instructions"); | 46 "and up to the increased threshold on instructions"); |
| 47 DEFINE_FLAG(int, inlining_hotness, 10, | 47 DEFINE_FLAG(int, inlining_hotness, 10, |
| 48 "Inline only hotter calls, in percents (0 .. 100); " | 48 "Inline only hotter calls, in percents (0 .. 100); " |
| 49 "default 10%: calls above-equal 10% of max-count are inlined."); | 49 "default 10%: calls above-equal 10% of max-count are inlined."); |
| 50 DEFINE_FLAG(bool, inline_recursive, true, | 50 DEFINE_FLAG(bool, inline_recursive, true, |
| 51 "Inline recursive calls."); | 51 "Inline recursive calls."); |
| 52 DEFINE_FLAG(int, max_inlined_per_depth, 500, |
| 53 "Max. number of inlined calls per depth"); |
| 52 DEFINE_FLAG(bool, print_inlining_tree, false, "Print inlining tree"); | 54 DEFINE_FLAG(bool, print_inlining_tree, false, "Print inlining tree"); |
| 53 | 55 |
| 54 DECLARE_FLAG(bool, compiler_stats); | 56 DECLARE_FLAG(bool, compiler_stats); |
| 55 DECLARE_FLAG(bool, enable_type_checks); | 57 DECLARE_FLAG(bool, enable_type_checks); |
| 56 DECLARE_FLAG(int, deoptimization_counter_threshold); | 58 DECLARE_FLAG(int, deoptimization_counter_threshold); |
| 57 DECLARE_FLAG(bool, print_flow_graph); | 59 DECLARE_FLAG(bool, print_flow_graph); |
| 58 DECLARE_FLAG(bool, print_flow_graph_optimized); | 60 DECLARE_FLAG(bool, print_flow_graph_optimized); |
| 59 DECLARE_FLAG(bool, verify_compiler); | 61 DECLARE_FLAG(bool, verify_compiler); |
| 60 | 62 |
| 61 #define TRACE_INLINING(statement) \ | 63 #define TRACE_INLINING(statement) \ |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 233 const GrowableArray<ClosureCallInfo>& closure_calls() const { | 235 const GrowableArray<ClosureCallInfo>& closure_calls() const { |
| 234 return closure_calls_; | 236 return closure_calls_; |
| 235 } | 237 } |
| 236 | 238 |
| 237 bool HasCalls() const { | 239 bool HasCalls() const { |
| 238 return !(static_calls_.is_empty() && | 240 return !(static_calls_.is_empty() && |
| 239 closure_calls_.is_empty() && | 241 closure_calls_.is_empty() && |
| 240 instance_calls_.is_empty()); | 242 instance_calls_.is_empty()); |
| 241 } | 243 } |
| 242 | 244 |
| 245 intptr_t NumCalls() const { |
| 246 return instance_calls_.length() + |
| 247 static_calls_.length() + |
| 248 closure_calls_.length(); |
| 249 } |
| 250 |
| 243 void Clear() { | 251 void Clear() { |
| 244 static_calls_.Clear(); | 252 static_calls_.Clear(); |
| 245 closure_calls_.Clear(); | 253 closure_calls_.Clear(); |
| 246 instance_calls_.Clear(); | 254 instance_calls_.Clear(); |
| 247 } | 255 } |
| 248 | 256 |
| 249 void ComputeCallSiteRatio(intptr_t static_call_start_ix, | 257 void ComputeCallSiteRatio(intptr_t static_call_start_ix, |
| 250 intptr_t instance_call_start_ix) { | 258 intptr_t instance_call_start_ix) { |
| 251 const intptr_t num_static_calls = | 259 const intptr_t num_static_calls = |
| 252 static_calls_.length() - static_call_start_ix; | 260 static_calls_.length() - static_call_start_ix; |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 509 CallSites* call_sites_temp = NULL; | 517 CallSites* call_sites_temp = NULL; |
| 510 collected_call_sites_ = &sites1; | 518 collected_call_sites_ = &sites1; |
| 511 inlining_call_sites_ = &sites2; | 519 inlining_call_sites_ = &sites2; |
| 512 // Collect initial call sites. | 520 // Collect initial call sites. |
| 513 collected_call_sites_->FindCallSites(caller_graph_, | 521 collected_call_sites_->FindCallSites(caller_graph_, |
| 514 inlining_depth_, | 522 inlining_depth_, |
| 515 &inlined_info_); | 523 &inlined_info_); |
| 516 while (collected_call_sites_->HasCalls()) { | 524 while (collected_call_sites_->HasCalls()) { |
| 517 TRACE_INLINING(OS::Print(" Depth %" Pd " ----------\n", | 525 TRACE_INLINING(OS::Print(" Depth %" Pd " ----------\n", |
| 518 inlining_depth_)); | 526 inlining_depth_)); |
| 527 if (collected_call_sites_->NumCalls() > FLAG_max_inlined_per_depth) { |
| 528 break; |
| 529 } |
| 530 if (FLAG_print_inlining_tree) { |
| 531 OS::Print("**Depth % " Pd " calls to inline %" Pd "\n", |
| 532 inlining_depth_, collected_call_sites_->NumCalls()); |
| 533 } |
| 519 // Swap collected and inlining arrays and clear the new collecting array. | 534 // Swap collected and inlining arrays and clear the new collecting array. |
| 520 call_sites_temp = collected_call_sites_; | 535 call_sites_temp = collected_call_sites_; |
| 521 collected_call_sites_ = inlining_call_sites_; | 536 collected_call_sites_ = inlining_call_sites_; |
| 522 inlining_call_sites_ = call_sites_temp; | 537 inlining_call_sites_ = call_sites_temp; |
| 523 collected_call_sites_->Clear(); | 538 collected_call_sites_->Clear(); |
| 524 // Inline call sites at the current depth. | 539 // Inline call sites at the current depth. |
| 525 InlineInstanceCalls(); | 540 InlineInstanceCalls(); |
| 526 InlineStaticCalls(); | 541 InlineStaticCalls(); |
| 527 InlineClosureCalls(); | 542 InlineClosureCalls(); |
| 528 // Increment the inlining depth. Checked before recursive inlining. | 543 // Increment the inlining depth. Checked before recursive inlining. |
| (...skipping 466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 995 ASSERT(call->ArgumentCount() > 0); | 1010 ASSERT(call->ArgumentCount() > 0); |
| 996 Function& target = Function::ZoneHandle(); | 1011 Function& target = Function::ZoneHandle(); |
| 997 AllocateObjectInstr* alloc = | 1012 AllocateObjectInstr* alloc = |
| 998 call->ArgumentAt(0)->OriginalDefinition()->AsAllocateObject(); | 1013 call->ArgumentAt(0)->OriginalDefinition()->AsAllocateObject(); |
| 999 if ((alloc != NULL) && !alloc->closure_function().IsNull()) { | 1014 if ((alloc != NULL) && !alloc->closure_function().IsNull()) { |
| 1000 target ^= alloc->closure_function().raw(); | 1015 target ^= alloc->closure_function().raw(); |
| 1001 ASSERT(target.signature_class() == alloc->cls().raw()); | 1016 ASSERT(target.signature_class() == alloc->cls().raw()); |
| 1002 } | 1017 } |
| 1003 if (target.IsNull()) { | 1018 if (target.IsNull()) { |
| 1004 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n")); | 1019 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n")); |
| 1005 PRINT_INLINING_TREE("Non-closure operator", | |
| 1006 call_info[call_idx].caller, &target, call); | |
| 1007 continue; | 1020 continue; |
| 1008 } | 1021 } |
| 1009 GrowableArray<Value*> arguments(call->ArgumentCount()); | 1022 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 1010 for (int i = 0; i < call->ArgumentCount(); ++i) { | 1023 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 1011 arguments.Add(call->PushArgumentAt(i)->value()); | 1024 arguments.Add(call->PushArgumentAt(i)->value()); |
| 1012 } | 1025 } |
| 1013 InlinedCallData call_data(call, &arguments, *call_info[call_idx].caller); | 1026 InlinedCallData call_data(call, &arguments, *call_info[call_idx].caller); |
| 1014 if (TryInlining(target, | 1027 if (TryInlining(target, |
| 1015 call->argument_names(), | 1028 call->argument_names(), |
| 1016 &call_data)) { | 1029 &call_data)) { |
| (...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1660 // Collect graph info and store it on the function. | 1673 // Collect graph info and store it on the function. |
| 1661 // We might later use it for an early bailout from the inlining. | 1674 // We might later use it for an early bailout from the inlining. |
| 1662 CollectGraphInfo(flow_graph_); | 1675 CollectGraphInfo(flow_graph_); |
| 1663 | 1676 |
| 1664 const Function& top = flow_graph_->parsed_function().function(); | 1677 const Function& top = flow_graph_->parsed_function().function(); |
| 1665 if ((FLAG_inlining_filter != NULL) && | 1678 if ((FLAG_inlining_filter != NULL) && |
| 1666 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { | 1679 (strstr(top.ToFullyQualifiedCString(), FLAG_inlining_filter) == NULL)) { |
| 1667 return; | 1680 return; |
| 1668 } | 1681 } |
| 1669 | 1682 |
| 1670 if (FLAG_enable_type_checks) { | |
| 1671 // TODO(srdjan): Fix out-of-memory crash in checked mode. | |
| 1672 return; | |
| 1673 } | |
| 1674 | |
| 1675 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); | 1683 TRACE_INLINING(OS::Print("Inlining calls in %s\n", top.ToCString())); |
| 1676 | 1684 |
| 1677 if (FLAG_trace_inlining && | 1685 if (FLAG_trace_inlining && |
| 1678 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | 1686 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
| 1679 OS::Print("Before Inlining of %s\n", flow_graph_-> | 1687 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 1680 parsed_function().function().ToFullyQualifiedCString()); | 1688 parsed_function().function().ToFullyQualifiedCString()); |
| 1681 FlowGraphPrinter printer(*flow_graph_); | 1689 FlowGraphPrinter printer(*flow_graph_); |
| 1682 printer.PrintBlocks(); | 1690 printer.PrintBlocks(); |
| 1683 } | 1691 } |
| 1684 | 1692 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1696 OS::Print("After Inlining of %s\n", flow_graph_-> | 1704 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1697 parsed_function().function().ToFullyQualifiedCString()); | 1705 parsed_function().function().ToFullyQualifiedCString()); |
| 1698 FlowGraphPrinter printer(*flow_graph_); | 1706 FlowGraphPrinter printer(*flow_graph_); |
| 1699 printer.PrintBlocks(); | 1707 printer.PrintBlocks(); |
| 1700 } | 1708 } |
| 1701 } | 1709 } |
| 1702 } | 1710 } |
| 1703 } | 1711 } |
| 1704 | 1712 |
| 1705 } // namespace dart | 1713 } // namespace dart |
| OLD | NEW |