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

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

Issue 133073019: Improve inlining decision: --inline_getters_setters_smaller_than (default 10). Don not inline gette… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/intermediate_language.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) 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"
11 #include "vm/flow_graph_builder.h" 11 #include "vm/flow_graph_builder.h"
12 #include "vm/flow_graph_compiler.h" 12 #include "vm/flow_graph_compiler.h"
13 #include "vm/flow_graph_optimizer.h" 13 #include "vm/flow_graph_optimizer.h"
14 #include "vm/il_printer.h" 14 #include "vm/il_printer.h"
15 #include "vm/intrinsifier.h" 15 #include "vm/intrinsifier.h"
16 #include "vm/longjump.h" 16 #include "vm/longjump.h"
17 #include "vm/object.h" 17 #include "vm/object.h"
18 #include "vm/object_store.h" 18 #include "vm/object_store.h"
19 #include "vm/timer.h" 19 #include "vm/timer.h"
20 20
21 namespace dart { 21 namespace dart {
22 22
23 DEFINE_FLAG(int, deoptimization_counter_inlining_threshold, 12, 23 DEFINE_FLAG(int, deoptimization_counter_inlining_threshold, 12,
24 "How many times we allow deoptimization before we stop inlining."); 24 "How many times we allow deoptimization before we stop inlining.");
25 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 25 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
26 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 26 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
27 27
28 // Flags for inlining heuristics. 28 // Flags for inlining heuristics.
29 DEFINE_FLAG(int, inline_getters_setters_smaller_than, 10,
30 "Always inline getters and setters that have fewer instructions");
29 DEFINE_FLAG(int, inlining_depth_threshold, 3, 31 DEFINE_FLAG(int, inlining_depth_threshold, 3,
30 "Inline function calls up to threshold nesting depth"); 32 "Inline function calls up to threshold nesting depth");
31 DEFINE_FLAG(int, inlining_size_threshold, 25, 33 DEFINE_FLAG(int, inlining_size_threshold, 25,
32 "Always inline functions that have threshold or fewer instructions"); 34 "Always inline functions that have threshold or fewer instructions");
33 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1, 35 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1,
34 "Always inline functions containing threshold or fewer calls."); 36 "Always inline functions containing threshold or fewer calls.");
35 DEFINE_FLAG(int, inlining_caller_size_threshold, 50000, 37 DEFINE_FLAG(int, inlining_caller_size_threshold, 50000,
36 "Stop inlining once caller reaches the threshold."); 38 "Stop inlining once caller reaches the threshold.");
37 DEFINE_FLAG(int, inlining_constant_arguments_count, 1, 39 DEFINE_FLAG(int, inlining_constant_arguments_count, 1,
38 "Inline function calls with sufficient constant arguments " 40 "Inline function calls with sufficient constant arguments "
(...skipping 317 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 358
357 // Inlining heuristics based on Cooper et al. 2008. 359 // Inlining heuristics based on Cooper et al. 2008.
358 bool ShouldWeInline(const Function& callee, 360 bool ShouldWeInline(const Function& callee,
359 intptr_t instr_count, 361 intptr_t instr_count,
360 intptr_t call_site_count, 362 intptr_t call_site_count,
361 intptr_t const_arg_count) { 363 intptr_t const_arg_count) {
362 if (inlined_size_ > FLAG_inlining_caller_size_threshold) { 364 if (inlined_size_ > FLAG_inlining_caller_size_threshold) {
363 // Prevent methods becoming humongous and thus slow to compile. 365 // Prevent methods becoming humongous and thus slow to compile.
364 return false; 366 return false;
365 } 367 }
366 if (instr_count <= FLAG_inlining_size_threshold) { 368 // 'instr_count' can be 0 if it was not computed yet.
369 if ((instr_count != 0) && (instr_count <= FLAG_inlining_size_threshold)) {
367 return true; 370 return true;
368 } 371 }
369 if (call_site_count <= FLAG_inlining_callee_call_sites_threshold) { 372 if (call_site_count <= FLAG_inlining_callee_call_sites_threshold) {
370 return true; 373 return true;
371 } 374 }
372 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && 375 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) &&
373 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { 376 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) {
374 return true; 377 return true;
375 } 378 }
376 if (MethodRecognizer::AlwaysInline(callee)) { 379 if (FlowGraphInliner::AlwaysInline(callee)) {
377 return true; 380 return true;
378 } 381 }
379 return false; 382 return false;
380 } 383 }
381 384
382 void InlineCalls() { 385 void InlineCalls() {
383 // If inlining depth is less then one abort. 386 // If inlining depth is less then one abort.
384 if (FLAG_inlining_depth_threshold < 1) return; 387 if (FLAG_inlining_depth_threshold < 1) return;
385 if (caller_graph_->parsed_function().function().deoptimization_counter() >= 388 if (caller_graph_->parsed_function().function().deoptimization_counter() >=
386 FLAG_deoptimization_counter_inlining_threshold) { 389 FLAG_deoptimization_counter_inlining_threshold) {
(...skipping 381 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 ASSERT(call->ArgumentCount() <= 2); 771 ASSERT(call->ArgumentCount() <= 2);
769 // Arg 0: Instantiator type arguments. 772 // Arg 0: Instantiator type arguments.
770 // Arg 1: Length (optional). 773 // Arg 1: Length (optional).
771 if ((call->ArgumentCount() == 2) && 774 if ((call->ArgumentCount() == 2) &&
772 (!call->PushArgumentAt(1)->value()->BindsToConstant())) { 775 (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
773 // Do not inline since a non-constant argument was passed. 776 // Do not inline since a non-constant argument was passed.
774 continue; 777 continue;
775 } 778 }
776 } 779 }
777 const Function& target = call->function(); 780 const Function& target = call->function();
778 if (!MethodRecognizer::AlwaysInline(target) && 781 if (!FlowGraphInliner::AlwaysInline(target) &&
779 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { 782 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
780 TRACE_INLINING(OS::Print( 783 TRACE_INLINING(OS::Print(
781 " => %s (deopt count %d)\n Bailout: cold %f\n", 784 " => %s (deopt count %d)\n Bailout: cold %f\n",
782 target.ToCString(), 785 target.ToCString(),
783 target.deoptimization_counter(), 786 target.deoptimization_counter(),
784 call_info[call_idx].ratio)); 787 call_info[call_idx].ratio));
785 continue; 788 continue;
786 } 789 }
787 GrowableArray<Value*> arguments(call->ArgumentCount()); 790 GrowableArray<Value*> arguments(call->ArgumentCount());
788 for (int i = 0; i < call->ArgumentCount(); ++i) { 791 for (int i = 0; i < call->ArgumentCount(); ++i) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) { 843 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
841 PolymorphicInstanceCallInstr* call = call_info[call_idx].call; 844 PolymorphicInstanceCallInstr* call = call_info[call_idx].call;
842 if (call->with_checks()) { 845 if (call->with_checks()) {
843 PolymorphicInliner inliner(this, call); 846 PolymorphicInliner inliner(this, call);
844 inliner.Inline(); 847 inliner.Inline();
845 continue; 848 continue;
846 } 849 }
847 850
848 const ICData& ic_data = call->ic_data(); 851 const ICData& ic_data = call->ic_data();
849 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 852 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
850 if (!MethodRecognizer::AlwaysInline(target) && 853 if (!FlowGraphInliner::AlwaysInline(target) &&
851 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) { 854 (call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
852 TRACE_INLINING(OS::Print( 855 TRACE_INLINING(OS::Print(
853 " => %s (deopt count %d)\n Bailout: cold %f\n", 856 " => %s (deopt count %d)\n Bailout: cold %f\n",
854 target.ToCString(), 857 target.ToCString(),
855 target.deoptimization_counter(), 858 target.deoptimization_counter(),
856 call_info[call_idx].ratio)); 859 call_info[call_idx].ratio));
857 continue; 860 continue;
858 } 861 }
859 GrowableArray<Value*> arguments(call->ArgumentCount()); 862 GrowableArray<Value*> arguments(call->ArgumentCount());
860 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) { 863 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) {
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph) { 1442 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph) {
1440 GraphInfoCollector info; 1443 GraphInfoCollector info;
1441 info.Collect(*flow_graph); 1444 info.Collect(*flow_graph);
1442 const Function& function = flow_graph->parsed_function().function(); 1445 const Function& function = flow_graph->parsed_function().function();
1443 function.set_optimized_instruction_count( 1446 function.set_optimized_instruction_count(
1444 ClampUint16(info.instruction_count())); 1447 ClampUint16(info.instruction_count()));
1445 function.set_optimized_call_site_count(ClampUint16(info.call_site_count())); 1448 function.set_optimized_call_site_count(ClampUint16(info.call_site_count()));
1446 } 1449 }
1447 1450
1448 1451
1452 bool FlowGraphInliner::AlwaysInline(const Function& function) {
1453 if (function.IsImplicitGetterFunction() || function.IsGetterFunction() ||
1454 function.IsImplicitSetterFunction() || function.IsSetterFunction()) {
1455 const intptr_t count = function.optimized_instruction_count();
1456 if ((count != 0) && (count < FLAG_inline_getters_setters_smaller_than)) {
1457 return true;
1458 }
1459 }
1460 return MethodRecognizer::AlwaysInline(function);
1461 }
1462
1463
1449 void FlowGraphInliner::Inline() { 1464 void FlowGraphInliner::Inline() {
1450 // Collect graph info and store it on the function. 1465 // Collect graph info and store it on the function.
1451 // We might later use it for an early bailout from the inlining. 1466 // We might later use it for an early bailout from the inlining.
1452 CollectGraphInfo(flow_graph_); 1467 CollectGraphInfo(flow_graph_);
1453 1468
1454 if ((FLAG_inlining_filter != NULL) && 1469 if ((FLAG_inlining_filter != NULL) &&
1455 (strstr(flow_graph_-> 1470 (strstr(flow_graph_->
1456 parsed_function().function().ToFullyQualifiedCString(), 1471 parsed_function().function().ToFullyQualifiedCString(),
1457 FLAG_inlining_filter) == NULL)) { 1472 FLAG_inlining_filter) == NULL)) {
1458 return; 1473 return;
(...skipping 22 matching lines...) Expand all
1481 OS::Print("After Inlining of %s\n", flow_graph_-> 1496 OS::Print("After Inlining of %s\n", flow_graph_->
1482 parsed_function().function().ToFullyQualifiedCString()); 1497 parsed_function().function().ToFullyQualifiedCString());
1483 FlowGraphPrinter printer(*flow_graph_); 1498 FlowGraphPrinter printer(*flow_graph_);
1484 printer.PrintBlocks(); 1499 printer.PrintBlocks();
1485 } 1500 }
1486 } 1501 }
1487 } 1502 }
1488 } 1503 }
1489 1504
1490 } // namespace dart 1505 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/intermediate_language.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698