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

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

Issue 24315002: Reland: Fix bug in field type tracking and polymorphic inlining. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 3 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/flow_graph_optimizer.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) 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 364 matching lines...) Expand 10 before | Expand all | Expand 10 after
375 375
376 GrowableArray<CidTarget> inlined_variants_; 376 GrowableArray<CidTarget> inlined_variants_;
377 GrowableArray<CidTarget> non_inlined_variants_; 377 GrowableArray<CidTarget> non_inlined_variants_;
378 GrowableArray<BlockEntryInstr*> inlined_entries_; 378 GrowableArray<BlockEntryInstr*> inlined_entries_;
379 InlineExitCollector* exit_collector_; 379 InlineExitCollector* exit_collector_;
380 }; 380 };
381 381
382 382
383 class CallSiteInliner : public ValueObject { 383 class CallSiteInliner : public ValueObject {
384 public: 384 public:
385 CallSiteInliner(FlowGraph* flow_graph, 385 explicit CallSiteInliner(FlowGraph* flow_graph)
386 GrowableArray<const Field*>* guarded_fields)
387 : caller_graph_(flow_graph), 386 : caller_graph_(flow_graph),
388 inlined_(false), 387 inlined_(false),
389 initial_size_(flow_graph->InstructionCount()), 388 initial_size_(flow_graph->InstructionCount()),
390 inlined_size_(0), 389 inlined_size_(0),
391 inlining_depth_(1), 390 inlining_depth_(1),
392 collected_call_sites_(NULL), 391 collected_call_sites_(NULL),
393 inlining_call_sites_(NULL), 392 inlining_call_sites_(NULL),
394 function_cache_(), 393 function_cache_() { }
395 guarded_fields_(guarded_fields) { }
396 394
397 FlowGraph* caller_graph() const { return caller_graph_; } 395 FlowGraph* caller_graph() const { return caller_graph_; }
398 396
399 // Inlining heuristics based on Cooper et al. 2008. 397 // Inlining heuristics based on Cooper et al. 2008.
400 bool ShouldWeInline(const Function& callee, 398 bool ShouldWeInline(const Function& callee,
401 intptr_t instr_count, 399 intptr_t instr_count,
402 intptr_t call_site_count, 400 intptr_t call_site_count,
403 intptr_t const_arg_count) { 401 intptr_t const_arg_count) {
404 if (inlined_size_ > FLAG_inlining_caller_size_threshold) { 402 if (inlined_size_ > FLAG_inlining_caller_size_threshold) {
405 // Prevent methods becoming humongous and thus slow to compile. 403 // Prevent methods becoming humongous and thus slow to compile.
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 Array& ic_data_array = Array::Handle(); 535 Array& ic_data_array = Array::Handle();
538 if (function.HasCode()) { 536 if (function.HasCode()) {
539 const Code& unoptimized_code = 537 const Code& unoptimized_code =
540 Code::Handle(function.unoptimized_code()); 538 Code::Handle(function.unoptimized_code());
541 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); 539 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray();
542 } 540 }
543 541
544 // Build the callee graph. 542 // Build the callee graph.
545 InlineExitCollector* exit_collector = 543 InlineExitCollector* exit_collector =
546 new InlineExitCollector(caller_graph_, call); 544 new InlineExitCollector(caller_graph_, call);
547 FlowGraphBuilder builder(parsed_function, 545 GrowableArray<const Field*> inlined_guarded_fields;
548 ic_data_array, 546 FlowGraphBuilder* builder = new FlowGraphBuilder(parsed_function,
549 exit_collector, 547 ic_data_array,
550 Isolate::kNoDeoptId); 548 exit_collector,
551 builder.SetInitialBlockId(caller_graph_->max_block_id()); 549 &inlined_guarded_fields,
550 Isolate::kNoDeoptId);
551 builder->SetInitialBlockId(caller_graph_->max_block_id());
552 FlowGraph* callee_graph; 552 FlowGraph* callee_graph;
553 { 553 {
554 TimerScope timer(FLAG_compiler_stats, 554 TimerScope timer(FLAG_compiler_stats,
555 &CompilerStats::graphinliner_build_timer, 555 &CompilerStats::graphinliner_build_timer,
556 isolate); 556 isolate);
557 callee_graph = builder.BuildGraph(); 557 callee_graph = builder->BuildGraph();
558 } 558 }
559 559
560 // The parameter stubs are a copy of the actual arguments providing 560 // The parameter stubs are a copy of the actual arguments providing
561 // concrete information about the values, for example constant values, 561 // concrete information about the values, for example constant values,
562 // without linking between the caller and callee graphs. 562 // without linking between the caller and callee graphs.
563 // TODO(zerny): Put more information in the stubs, eg, type information. 563 // TODO(zerny): Put more information in the stubs, eg, type information.
564 ZoneGrowableArray<Definition*>* param_stubs = 564 ZoneGrowableArray<Definition*>* param_stubs =
565 new ZoneGrowableArray<Definition*>(function.NumParameters()); 565 new ZoneGrowableArray<Definition*>(function.NumParameters());
566 566
567 // Create a parameter stub for each fixed positional parameter. 567 // Create a parameter stub for each fixed positional parameter.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), 600 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
601 param_stubs); 601 param_stubs);
602 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 602 DEBUG_ASSERT(callee_graph->VerifyUseLists());
603 } 603 }
604 604
605 { 605 {
606 TimerScope timer(FLAG_compiler_stats, 606 TimerScope timer(FLAG_compiler_stats,
607 &CompilerStats::graphinliner_opt_timer, 607 &CompilerStats::graphinliner_opt_timer,
608 isolate); 608 isolate);
609 // TODO(zerny): Do more optimization passes on the callee graph. 609 // TODO(zerny): Do more optimization passes on the callee graph.
610 FlowGraphOptimizer optimizer(callee_graph, guarded_fields_); 610 FlowGraphOptimizer optimizer(callee_graph);
611 optimizer.ApplyICData(); 611 optimizer.ApplyICData();
612 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 612 DEBUG_ASSERT(callee_graph->VerifyUseLists());
613 } 613 }
614 614
615 if (FLAG_trace_inlining && 615 if (FLAG_trace_inlining &&
616 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 616 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
617 OS::Print("Callee graph for inlining %s\n", 617 OS::Print("Callee graph for inlining %s\n",
618 function.ToFullyQualifiedCString()); 618 function.ToFullyQualifiedCString());
619 FlowGraphPrinter printer(*callee_graph); 619 FlowGraphPrinter printer(*callee_graph);
620 printer.PrintBlocks(); 620 printer.PrintBlocks();
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
661 661
662 // Build succeeded so we restore the bailout jump. 662 // Build succeeded so we restore the bailout jump.
663 inlined_ = true; 663 inlined_ = true;
664 inlined_size_ += size; 664 inlined_size_ += size;
665 isolate->set_long_jump_base(base); 665 isolate->set_long_jump_base(base);
666 isolate->set_deopt_id(prev_deopt_id); 666 isolate->set_deopt_id(prev_deopt_id);
667 667
668 call_data->callee_graph = callee_graph; 668 call_data->callee_graph = callee_graph;
669 call_data->parameter_stubs = param_stubs; 669 call_data->parameter_stubs = param_stubs;
670 call_data->exit_collector = exit_collector; 670 call_data->exit_collector = exit_collector;
671
672 // When inlined, we add the guarded fields of the callee to the caller's
673 // list of guarded fields.
674 for (intptr_t i = 0; i < inlined_guarded_fields.length(); ++i) {
675 caller_graph_->builder().AddToGuardedFields(*inlined_guarded_fields[i]);
676 }
677
671 TRACE_INLINING(OS::Print(" Success\n")); 678 TRACE_INLINING(OS::Print(" Success\n"));
672 return true; 679 return true;
673 } else { 680 } else {
674 Error& error = Error::Handle(); 681 Error& error = Error::Handle();
675 error = isolate->object_store()->sticky_error(); 682 error = isolate->object_store()->sticky_error();
676 isolate->object_store()->clear_sticky_error(); 683 isolate->object_store()->clear_sticky_error();
677 isolate->set_long_jump_base(base); 684 isolate->set_long_jump_base(base);
678 isolate->set_deopt_id(prev_deopt_id); 685 isolate->set_deopt_id(prev_deopt_id);
679 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 686 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
680 return false; 687 return false;
(...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after
991 998
992 999
993 FlowGraph* caller_graph_; 1000 FlowGraph* caller_graph_;
994 bool inlined_; 1001 bool inlined_;
995 intptr_t initial_size_; 1002 intptr_t initial_size_;
996 intptr_t inlined_size_; 1003 intptr_t inlined_size_;
997 intptr_t inlining_depth_; 1004 intptr_t inlining_depth_;
998 CallSites* collected_call_sites_; 1005 CallSites* collected_call_sites_;
999 CallSites* inlining_call_sites_; 1006 CallSites* inlining_call_sites_;
1000 GrowableArray<ParsedFunction*> function_cache_; 1007 GrowableArray<ParsedFunction*> function_cache_;
1001 GrowableArray<const Field*>* guarded_fields_;
1002 1008
1003 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); 1009 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner);
1004 }; 1010 };
1005 1011
1006 1012
1007 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, 1013 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner,
1008 PolymorphicInstanceCallInstr* call) 1014 PolymorphicInstanceCallInstr* call)
1009 : owner_(owner), 1015 : owner_(owner),
1010 call_(call), 1016 call_(call),
1011 num_variants_(call->ic_data().NumberOfChecks()), 1017 num_variants_(call->ic_data().NumberOfChecks()),
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) { 1152 for (intptr_t i = second->InputCount() - 1; i >= 0; --i) {
1147 Value* input = second->InputAt(i); 1153 Value* input = second->InputAt(i);
1148 input->definition()->AddInputUse(input); 1154 input->definition()->AddInputUse(input);
1149 } 1155 }
1150 first->LinkTo(second); 1156 first->LinkTo(second);
1151 return second; 1157 return second;
1152 } 1158 }
1153 1159
1154 1160
1155 bool PolymorphicInliner::TryInlineRecognizedMethod(const Function& target) { 1161 bool PolymorphicInliner::TryInlineRecognizedMethod(const Function& target) {
1156 FlowGraphOptimizer optimizer(owner_->caller_graph(), 1162 FlowGraphOptimizer optimizer(owner_->caller_graph());
1157 NULL); // No guarded fields needed.
1158 TargetEntryInstr* entry; 1163 TargetEntryInstr* entry;
1159 Definition* last; 1164 Definition* last;
1160 if (optimizer.TryInlineRecognizedMethod(target, 1165 if (optimizer.TryInlineRecognizedMethod(target,
1161 call_, 1166 call_,
1162 call_->ic_data(), 1167 call_->ic_data(),
1163 &entry, &last)) { 1168 &entry, &last)) {
1164 // Create a graph fragment. 1169 // Create a graph fragment.
1165 InlineExitCollector* exit_collector = 1170 InlineExitCollector* exit_collector =
1166 new InlineExitCollector(owner_->caller_graph(), call_); 1171 new InlineExitCollector(owner_->caller_graph(), call_);
1167 1172
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1468 flow_graph_->parsed_function().function().ToCString())); 1473 flow_graph_->parsed_function().function().ToCString()));
1469 1474
1470 if (FLAG_trace_inlining && 1475 if (FLAG_trace_inlining &&
1471 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 1476 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
1472 OS::Print("Before Inlining of %s\n", flow_graph_-> 1477 OS::Print("Before Inlining of %s\n", flow_graph_->
1473 parsed_function().function().ToFullyQualifiedCString()); 1478 parsed_function().function().ToFullyQualifiedCString());
1474 FlowGraphPrinter printer(*flow_graph_); 1479 FlowGraphPrinter printer(*flow_graph_);
1475 printer.PrintBlocks(); 1480 printer.PrintBlocks();
1476 } 1481 }
1477 1482
1478 CallSiteInliner inliner(flow_graph_, guarded_fields_); 1483 CallSiteInliner inliner(flow_graph_);
1479 inliner.InlineCalls(); 1484 inliner.InlineCalls();
1480 1485
1481 if (inliner.inlined()) { 1486 if (inliner.inlined()) {
1482 flow_graph_->DiscoverBlocks(); 1487 flow_graph_->DiscoverBlocks();
1483 if (FLAG_trace_inlining) { 1488 if (FLAG_trace_inlining) {
1484 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); 1489 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
1485 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { 1490 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) {
1486 OS::Print("After Inlining of %s\n", flow_graph_-> 1491 OS::Print("After Inlining of %s\n", flow_graph_->
1487 parsed_function().function().ToFullyQualifiedCString()); 1492 parsed_function().function().ToFullyQualifiedCString());
1488 FlowGraphPrinter printer(*flow_graph_); 1493 FlowGraphPrinter printer(*flow_graph_);
1489 printer.PrintBlocks(); 1494 printer.PrintBlocks();
1490 } 1495 }
1491 } 1496 }
1492 } 1497 }
1493 } 1498 }
1494 1499
1495 } // namespace dart 1500 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/flow_graph_inliner.h ('k') | runtime/vm/flow_graph_optimizer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698