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

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

Issue 11567012: Store optimized flow graph statistics on the function itself. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years 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
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/flow_graph_inliner.h" 5 #include "vm/flow_graph_inliner.h"
6 6
7 #include "vm/compiler.h" 7 #include "vm/compiler.h"
8 #include "vm/flags.h" 8 #include "vm/flags.h"
9 #include "vm/flow_graph.h" 9 #include "vm/flow_graph.h"
10 #include "vm/flow_graph_builder.h" 10 #include "vm/flow_graph_builder.h"
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
346 } 346 }
347 347
348 // Abort if this function has deoptimized too much. 348 // Abort if this function has deoptimized too much.
349 if (function.deoptimization_counter() >= 349 if (function.deoptimization_counter() >=
350 FLAG_deoptimization_counter_threshold) { 350 FLAG_deoptimization_counter_threshold) {
351 function.set_is_inlinable(false); 351 function.set_is_inlinable(false);
352 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n")); 352 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n"));
353 return false; 353 return false;
354 } 354 }
355 355
356 if (!ShouldWeInline(call->GetBlock()->loop_depth(),
357 function.optimized_instruction_count(),
358 function.optimized_call_site_count(),
359 CountConstants(*arguments))) {
360 TRACE_INLINING(OS::Print(" Bailout: early heuristics\n"));
srdjan 2012/12/13 19:00:17 Maybe print also the arguments that led to inlinin
Vyacheslav Egorov (Google) 2012/12/13 19:14:11 Done.
361 return false;
362 }
363
356 // Abort if this is a recursive occurrence. 364 // Abort if this is a recursive occurrence.
357 if (IsCallRecursive(function, call)) { 365 if (IsCallRecursive(function, call)) {
358 function.set_is_inlinable(false); 366 function.set_is_inlinable(false);
359 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); 367 TRACE_INLINING(OS::Print(" Bailout: recursive function\n"));
360 return false; 368 return false;
361 } 369 }
362 370
363 // Abort if the callee has an intrinsic translation. 371 // Abort if the callee has an intrinsic translation.
364 if (Intrinsifier::CanIntrinsify(function)) { 372 if (Intrinsifier::CanIntrinsify(function)) {
365 function.set_is_inlinable(false); 373 function.set_is_inlinable(false);
(...skipping 24 matching lines...) Expand all
390 } 398 }
391 399
392 // Load IC data for the callee. 400 // Load IC data for the callee.
393 if (function.HasCode()) { 401 if (function.HasCode()) {
394 const Code& unoptimized_code = 402 const Code& unoptimized_code =
395 Code::Handle(function.unoptimized_code()); 403 Code::Handle(function.unoptimized_code());
396 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); 404 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
397 } 405 }
398 406
399 // Build the callee graph. 407 // Build the callee graph.
400 const intptr_t loop_depth = call->GetBlock()->loop_depth(); 408 const intptr_t loop_depth = call->GetBlock()->loop_depth();
Kevin Millikin (Google) 2012/12/13 16:43:40 Move this above the first call to ShouldWeInline.
Vyacheslav Egorov (Google) 2012/12/13 18:54:46 Done.
401 FlowGraphBuilder builder(*parsed_function); 409 FlowGraphBuilder builder(*parsed_function);
402 builder.SetInitialBlockId(caller_graph_->max_block_id()); 410 builder.SetInitialBlockId(caller_graph_->max_block_id());
403 FlowGraph* callee_graph; 411 FlowGraph* callee_graph;
404 { 412 {
405 TimerScope timer(FLAG_compiler_stats, 413 TimerScope timer(FLAG_compiler_stats,
406 &CompilerStats::graphinliner_build_timer, 414 &CompilerStats::graphinliner_build_timer,
407 isolate); 415 isolate);
408 callee_graph = 416 callee_graph =
409 builder.BuildGraph(FlowGraphBuilder::kValueContext, loop_depth); 417 builder.BuildGraph(FlowGraphBuilder::kValueContext, loop_depth);
410 } 418 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 476
469 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 477 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
470 OS::Print("Callee graph for inlining %s\n", 478 OS::Print("Callee graph for inlining %s\n",
471 function.ToFullyQualifiedCString()); 479 function.ToFullyQualifiedCString());
472 FlowGraphPrinter printer(*callee_graph); 480 FlowGraphPrinter printer(*callee_graph);
473 printer.PrintBlocks(); 481 printer.PrintBlocks();
474 } 482 }
475 483
476 // Collect information about the call site and caller graph. 484 // Collect information about the call site and caller graph.
477 // TODO(zerny): Do this after CP and dead code elimination. 485 // TODO(zerny): Do this after CP and dead code elimination.
478 intptr_t constants_count = 0; 486 intptr_t constants_count = 0;
Kevin Millikin (Google) 2012/12/13 16:43:40 There's no reason to count this again, is there?
Vyacheslav Egorov (Google) 2012/12/13 18:54:46 Actually the count above is just an approximation
479 for (intptr_t i = 0; i < param_stubs.length(); ++i) { 487 for (intptr_t i = 0; i < param_stubs.length(); ++i) {
480 if (param_stubs[i]->IsConstant()) ++constants_count; 488 if (param_stubs[i]->IsConstant()) ++constants_count;
481 } 489 }
482 GraphInfoCollector info; 490 GraphInfoCollector info;
483 info.Collect(*callee_graph); 491 info.Collect(*callee_graph);
484 const intptr_t size = info.instruction_count(); 492 const intptr_t size = info.instruction_count();
485 // Use heuristics do decide if this call should be inlined. 493 // Use heuristics do decide if this call should be inlined.
486 if (!ShouldWeInline(loop_depth, 494 if (!ShouldWeInline(loop_depth,
Kevin Millikin (Google) 2012/12/13 16:43:40 It seems strange to call this twice? Is it needed
Vyacheslav Egorov (Google) 2012/12/13 18:54:46 Yes. Sometimes we attempt to inline big function t
487 size, 495 size,
488 info.call_site_count(), 496 info.call_site_count(),
489 constants_count)) { 497 constants_count)) {
490 // If size is larger than all thresholds, don't consider it again. 498 // If size is larger than all thresholds, don't consider it again.
491 if ((size > FLAG_inlining_size_threshold) && 499 if ((size > FLAG_inlining_size_threshold) &&
492 (size > FLAG_inlining_in_loop_size_threshold) && 500 (size > FLAG_inlining_in_loop_size_threshold) &&
493 (size > FLAG_inlining_callee_call_sites_threshold) && 501 (size > FLAG_inlining_callee_call_sites_threshold) &&
494 (size > FLAG_inlining_constant_arguments_size_threshold)) { 502 (size > FLAG_inlining_constant_arguments_size_threshold)) {
495 function.set_is_inlinable(false); 503 function.set_is_inlinable(false);
496 } 504 }
505 function.set_optimized_instruction_count(size);
Kevin Millikin (Google) 2012/12/13 16:43:40 Also a bit strange to set this only when we decide
Vyacheslav Egorov (Google) 2012/12/13 18:54:46 Yep, this is wrong.
506 function.set_optimized_call_site_count(info.call_site_count());
497 isolate->set_long_jump_base(base); 507 isolate->set_long_jump_base(base);
498 isolate->set_deopt_id(prev_deopt_id); 508 isolate->set_deopt_id(prev_deopt_id);
499 isolate->set_ic_data_array(prev_ic_data.raw()); 509 isolate->set_ic_data_array(prev_ic_data.raw());
500 TRACE_INLINING(OS::Print(" Bailout: heuristics with " 510 TRACE_INLINING(OS::Print(" Bailout: heuristics with "
501 "loop depth: %"Pd", " 511 "loop depth: %"Pd", "
502 "code size: %"Pd", " 512 "code size: %"Pd", "
503 "call sites: %"Pd", " 513 "call sites: %"Pd", "
504 "const args: %"Pd"\n", 514 "const args: %"Pd"\n",
505 loop_depth, 515 loop_depth,
506 size, 516 size,
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 error = isolate->object_store()->sticky_error(); 583 error = isolate->object_store()->sticky_error();
574 isolate->object_store()->clear_sticky_error(); 584 isolate->object_store()->clear_sticky_error();
575 isolate->set_long_jump_base(base); 585 isolate->set_long_jump_base(base);
576 isolate->set_deopt_id(prev_deopt_id); 586 isolate->set_deopt_id(prev_deopt_id);
577 isolate->set_ic_data_array(prev_ic_data.raw()); 587 isolate->set_ic_data_array(prev_ic_data.raw());
578 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 588 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
579 return false; 589 return false;
580 } 590 }
581 } 591 }
582 592
593 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) {
594 intptr_t count = 0;
595 for (intptr_t i = 0; i < arguments.length(); i++) {
596 if (arguments[i]->BindsToConstant()) count++;
597 }
598 return count;
599 }
600
583 // Parse a function reusing the cache if possible. 601 // Parse a function reusing the cache if possible.
584 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) { 602 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) {
585 // TODO(zerny): Use a hash map for the cache. 603 // TODO(zerny): Use a hash map for the cache.
586 for (intptr_t i = 0; i < function_cache_.length(); ++i) { 604 for (intptr_t i = 0; i < function_cache_.length(); ++i) {
587 ParsedFunction* parsed_function = function_cache_[i]; 605 ParsedFunction* parsed_function = function_cache_[i];
588 if (parsed_function->function().raw() == function.raw()) { 606 if (parsed_function->function().raw() == function.raw()) {
589 *in_cache = true; 607 *in_cache = true;
590 SourceLabelResetter reset; 608 SourceLabelResetter reset;
591 parsed_function->node_sequence()->Visit(&reset); 609 parsed_function->node_sequence()->Visit(&reset);
592 return parsed_function; 610 return parsed_function;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 intptr_t inlined_size_; 780 intptr_t inlined_size_;
763 intptr_t inlining_depth_; 781 intptr_t inlining_depth_;
764 CallSites* collected_call_sites_; 782 CallSites* collected_call_sites_;
765 CallSites* inlining_call_sites_; 783 CallSites* inlining_call_sites_;
766 GrowableArray<ParsedFunction*> function_cache_; 784 GrowableArray<ParsedFunction*> function_cache_;
767 785
768 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); 786 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
769 }; 787 };
770 788
771 789
790 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph) {
791 GraphInfoCollector info;
792 info.Collect(*flow_graph);
793 const Function& function = flow_graph->parsed_function().function();
794 function.set_optimized_instruction_count(
795 static_cast<uint16_t>(info.instruction_count()));
796 function.set_optimized_call_site_count(
797 static_cast<uint16_t>(info.call_site_count()));
798 }
799
800
772 void FlowGraphInliner::Inline() { 801 void FlowGraphInliner::Inline() {
773 if ((FLAG_inlining_filter != NULL) && 802 if ((FLAG_inlining_filter != NULL) &&
774 (strstr(flow_graph_-> 803 (strstr(flow_graph_->
775 parsed_function().function().ToFullyQualifiedCString(), 804 parsed_function().function().ToFullyQualifiedCString(),
776 FLAG_inlining_filter) == NULL)) { 805 FLAG_inlining_filter) == NULL)) {
777 return; 806 return;
778 } 807 }
779 808
780 TRACE_INLINING(OS::Print( 809 TRACE_INLINING(OS::Print(
781 "Inlining calls in %s\n", 810 "Inlining calls in %s\n",
(...skipping 17 matching lines...) Expand all
799 OS::Print("After Inlining of %s\n", flow_graph_-> 828 OS::Print("After Inlining of %s\n", flow_graph_->
800 parsed_function().function().ToFullyQualifiedCString()); 829 parsed_function().function().ToFullyQualifiedCString());
801 FlowGraphPrinter printer(*flow_graph_); 830 FlowGraphPrinter printer(*flow_graph_);
802 printer.PrintBlocks(); 831 printer.PrintBlocks();
803 } 832 }
804 } 833 }
805 } 834 }
806 } 835 }
807 836
808 } // namespace dart 837 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698