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

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: address Srdjan's comments 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
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/object.h » ('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) 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 const intptr_t loop_depth = call->GetBlock()->loop_depth();
357 const intptr_t constant_arguments = CountConstants(*arguments);
358 if (!ShouldWeInline(loop_depth,
359 function.optimized_instruction_count(),
360 function.optimized_call_site_count(),
361 constant_arguments)) {
362 TRACE_INLINING(OS::Print(" Bailout: early heuristics with "
363 "loop depth: %"Pd", "
364 "code size: %"Pd", "
365 "call sites: %"Pd", "
366 "const args: %"Pd"\n",
367 loop_depth,
368 function.optimized_instruction_count(),
369 function.optimized_call_site_count(),
370 constant_arguments));
371 return false;
372 }
373
356 // Abort if this is a recursive occurrence. 374 // Abort if this is a recursive occurrence.
357 if (IsCallRecursive(function, call)) { 375 if (IsCallRecursive(function, call)) {
358 function.set_is_inlinable(false); 376 function.set_is_inlinable(false);
359 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); 377 TRACE_INLINING(OS::Print(" Bailout: recursive function\n"));
360 return false; 378 return false;
361 } 379 }
362 380
363 // Abort if the callee has an intrinsic translation. 381 // Abort if the callee has an intrinsic translation.
364 if (Intrinsifier::CanIntrinsify(function)) { 382 if (Intrinsifier::CanIntrinsify(function)) {
365 function.set_is_inlinable(false); 383 function.set_is_inlinable(false);
(...skipping 24 matching lines...) Expand all
390 } 408 }
391 409
392 // Load IC data for the callee. 410 // Load IC data for the callee.
393 if (function.HasCode()) { 411 if (function.HasCode()) {
394 const Code& unoptimized_code = 412 const Code& unoptimized_code =
395 Code::Handle(function.unoptimized_code()); 413 Code::Handle(function.unoptimized_code());
396 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); 414 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
397 } 415 }
398 416
399 // Build the callee graph. 417 // Build the callee graph.
400 const intptr_t loop_depth = call->GetBlock()->loop_depth();
401 FlowGraphBuilder builder(*parsed_function); 418 FlowGraphBuilder builder(*parsed_function);
402 builder.SetInitialBlockId(caller_graph_->max_block_id()); 419 builder.SetInitialBlockId(caller_graph_->max_block_id());
403 FlowGraph* callee_graph; 420 FlowGraph* callee_graph;
404 { 421 {
405 TimerScope timer(FLAG_compiler_stats, 422 TimerScope timer(FLAG_compiler_stats,
406 &CompilerStats::graphinliner_build_timer, 423 &CompilerStats::graphinliner_build_timer,
407 isolate); 424 isolate);
408 callee_graph = 425 callee_graph =
409 builder.BuildGraph(FlowGraphBuilder::kValueContext, loop_depth); 426 builder.BuildGraph(FlowGraphBuilder::kValueContext, loop_depth);
410 } 427 }
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
475 492
476 // Collect information about the call site and caller graph. 493 // Collect information about the call site and caller graph.
477 // TODO(zerny): Do this after CP and dead code elimination. 494 // TODO(zerny): Do this after CP and dead code elimination.
478 intptr_t constants_count = 0; 495 intptr_t constants_count = 0;
479 for (intptr_t i = 0; i < param_stubs.length(); ++i) { 496 for (intptr_t i = 0; i < param_stubs.length(); ++i) {
480 if (param_stubs[i]->IsConstant()) ++constants_count; 497 if (param_stubs[i]->IsConstant()) ++constants_count;
481 } 498 }
482 GraphInfoCollector info; 499 GraphInfoCollector info;
483 info.Collect(*callee_graph); 500 info.Collect(*callee_graph);
484 const intptr_t size = info.instruction_count(); 501 const intptr_t size = info.instruction_count();
502
503 function.set_optimized_instruction_count(size);
504 function.set_optimized_call_site_count(info.call_site_count());
505
485 // Use heuristics do decide if this call should be inlined. 506 // Use heuristics do decide if this call should be inlined.
486 if (!ShouldWeInline(loop_depth, 507 if (!ShouldWeInline(loop_depth,
487 size, 508 size,
488 info.call_site_count(), 509 info.call_site_count(),
489 constants_count)) { 510 constants_count)) {
490 // If size is larger than all thresholds, don't consider it again. 511 // If size is larger than all thresholds, don't consider it again.
491 if ((size > FLAG_inlining_size_threshold) && 512 if ((size > FLAG_inlining_size_threshold) &&
492 (size > FLAG_inlining_in_loop_size_threshold) && 513 (size > FLAG_inlining_in_loop_size_threshold) &&
493 (size > FLAG_inlining_callee_call_sites_threshold) && 514 (size > FLAG_inlining_callee_call_sites_threshold) &&
494 (size > FLAG_inlining_constant_arguments_size_threshold)) { 515 (size > FLAG_inlining_constant_arguments_size_threshold)) {
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 error = isolate->object_store()->sticky_error(); 594 error = isolate->object_store()->sticky_error();
574 isolate->object_store()->clear_sticky_error(); 595 isolate->object_store()->clear_sticky_error();
575 isolate->set_long_jump_base(base); 596 isolate->set_long_jump_base(base);
576 isolate->set_deopt_id(prev_deopt_id); 597 isolate->set_deopt_id(prev_deopt_id);
577 isolate->set_ic_data_array(prev_ic_data.raw()); 598 isolate->set_ic_data_array(prev_ic_data.raw());
578 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 599 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
579 return false; 600 return false;
580 } 601 }
581 } 602 }
582 603
604 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) {
605 intptr_t count = 0;
606 for (intptr_t i = 0; i < arguments.length(); i++) {
607 if (arguments[i]->BindsToConstant()) count++;
608 }
609 return count;
610 }
611
583 // Parse a function reusing the cache if possible. 612 // Parse a function reusing the cache if possible.
584 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) { 613 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) {
585 // TODO(zerny): Use a hash map for the cache. 614 // TODO(zerny): Use a hash map for the cache.
586 for (intptr_t i = 0; i < function_cache_.length(); ++i) { 615 for (intptr_t i = 0; i < function_cache_.length(); ++i) {
587 ParsedFunction* parsed_function = function_cache_[i]; 616 ParsedFunction* parsed_function = function_cache_[i];
588 if (parsed_function->function().raw() == function.raw()) { 617 if (parsed_function->function().raw() == function.raw()) {
589 *in_cache = true; 618 *in_cache = true;
590 SourceLabelResetter reset; 619 SourceLabelResetter reset;
591 parsed_function->node_sequence()->Visit(&reset); 620 parsed_function->node_sequence()->Visit(&reset);
592 return parsed_function; 621 return parsed_function;
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
762 intptr_t inlined_size_; 791 intptr_t inlined_size_;
763 intptr_t inlining_depth_; 792 intptr_t inlining_depth_;
764 CallSites* collected_call_sites_; 793 CallSites* collected_call_sites_;
765 CallSites* inlining_call_sites_; 794 CallSites* inlining_call_sites_;
766 GrowableArray<ParsedFunction*> function_cache_; 795 GrowableArray<ParsedFunction*> function_cache_;
767 796
768 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); 797 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
769 }; 798 };
770 799
771 800
801 void FlowGraphInliner::CollectGraphInfo(FlowGraph* flow_graph) {
802 GraphInfoCollector info;
803 info.Collect(*flow_graph);
804 const Function& function = flow_graph->parsed_function().function();
805 function.set_optimized_instruction_count(
806 static_cast<uint16_t>(info.instruction_count()));
807 function.set_optimized_call_site_count(
808 static_cast<uint16_t>(info.call_site_count()));
809 }
810
811
772 void FlowGraphInliner::Inline() { 812 void FlowGraphInliner::Inline() {
813 // Collect graph info and store it on the function.
814 // We might later use it for an early bailout from the inlining.
815 CollectGraphInfo(flow_graph_);
816
773 if ((FLAG_inlining_filter != NULL) && 817 if ((FLAG_inlining_filter != NULL) &&
774 (strstr(flow_graph_-> 818 (strstr(flow_graph_->
775 parsed_function().function().ToFullyQualifiedCString(), 819 parsed_function().function().ToFullyQualifiedCString(),
776 FLAG_inlining_filter) == NULL)) { 820 FLAG_inlining_filter) == NULL)) {
777 return; 821 return;
778 } 822 }
779 823
780 TRACE_INLINING(OS::Print( 824 TRACE_INLINING(OS::Print(
781 "Inlining calls in %s\n", 825 "Inlining calls in %s\n",
782 flow_graph_->parsed_function().function().ToCString())); 826 flow_graph_->parsed_function().function().ToCString()));
(...skipping 16 matching lines...) Expand all
799 OS::Print("After Inlining of %s\n", flow_graph_-> 843 OS::Print("After Inlining of %s\n", flow_graph_->
800 parsed_function().function().ToFullyQualifiedCString()); 844 parsed_function().function().ToFullyQualifiedCString());
801 FlowGraphPrinter printer(*flow_graph_); 845 FlowGraphPrinter printer(*flow_graph_);
802 printer.PrintBlocks(); 846 printer.PrintBlocks();
803 } 847 }
804 } 848 }
805 } 849 }
806 } 850 }
807 851
808 } // namespace dart 852 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698