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 363 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
374 | 374 |
375 GrowableArray<CidTarget> inlined_variants_; | 375 GrowableArray<CidTarget> inlined_variants_; |
376 GrowableArray<CidTarget> non_inlined_variants_; | 376 GrowableArray<CidTarget> non_inlined_variants_; |
377 GrowableArray<BlockEntryInstr*> inlined_entries_; | 377 GrowableArray<BlockEntryInstr*> inlined_entries_; |
378 InlineExitCollector* exit_collector_; | 378 InlineExitCollector* exit_collector_; |
379 }; | 379 }; |
380 | 380 |
381 | 381 |
382 class CallSiteInliner : public ValueObject { | 382 class CallSiteInliner : public ValueObject { |
383 public: | 383 public: |
384 CallSiteInliner(FlowGraph* flow_graph, | 384 explicit CallSiteInliner(FlowGraph* flow_graph) |
385 GrowableArray<const Field*>* guarded_fields) | |
386 : caller_graph_(flow_graph), | 385 : caller_graph_(flow_graph), |
387 inlined_(false), | 386 inlined_(false), |
388 initial_size_(flow_graph->InstructionCount()), | 387 initial_size_(flow_graph->InstructionCount()), |
389 inlined_size_(0), | 388 inlined_size_(0), |
390 inlining_depth_(1), | 389 inlining_depth_(1), |
391 collected_call_sites_(NULL), | 390 collected_call_sites_(NULL), |
392 inlining_call_sites_(NULL), | 391 inlining_call_sites_(NULL), |
393 function_cache_(), | 392 function_cache_() { } |
394 guarded_fields_(guarded_fields) { } | |
395 | 393 |
396 FlowGraph* caller_graph() const { return caller_graph_; } | 394 FlowGraph* caller_graph() const { return caller_graph_; } |
397 | 395 |
398 // Inlining heuristics based on Cooper et al. 2008. | 396 // Inlining heuristics based on Cooper et al. 2008. |
399 bool ShouldWeInline(const Function& callee, | 397 bool ShouldWeInline(const Function& callee, |
400 intptr_t instr_count, | 398 intptr_t instr_count, |
401 intptr_t call_site_count, | 399 intptr_t call_site_count, |
402 intptr_t const_arg_count) { | 400 intptr_t const_arg_count) { |
403 if (inlined_size_ > FLAG_inlining_caller_size_threshold) { | 401 if (inlined_size_ > FLAG_inlining_caller_size_threshold) { |
404 // Prevent methods becoming humongous and thus slow to compile. | 402 // Prevent methods becoming humongous and thus slow to compile. |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
536 Array& ic_data_array = Array::Handle(); | 534 Array& ic_data_array = Array::Handle(); |
537 if (function.HasCode()) { | 535 if (function.HasCode()) { |
538 const Code& unoptimized_code = | 536 const Code& unoptimized_code = |
539 Code::Handle(function.unoptimized_code()); | 537 Code::Handle(function.unoptimized_code()); |
540 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); | 538 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); |
541 } | 539 } |
542 | 540 |
543 // Build the callee graph. | 541 // Build the callee graph. |
544 InlineExitCollector* exit_collector = | 542 InlineExitCollector* exit_collector = |
545 new InlineExitCollector(caller_graph_, call); | 543 new InlineExitCollector(caller_graph_, call); |
| 544 GrowableArray<const Field*> inlined_guarded_fields; |
546 FlowGraphBuilder builder(parsed_function, | 545 FlowGraphBuilder builder(parsed_function, |
547 ic_data_array, | 546 ic_data_array, |
548 exit_collector, | 547 exit_collector, |
| 548 &inlined_guarded_fields, |
549 Isolate::kNoDeoptId); | 549 Isolate::kNoDeoptId); |
550 builder.SetInitialBlockId(caller_graph_->max_block_id()); | 550 builder.SetInitialBlockId(caller_graph_->max_block_id()); |
551 FlowGraph* callee_graph; | 551 FlowGraph* callee_graph; |
552 { | 552 { |
553 TimerScope timer(FLAG_compiler_stats, | 553 TimerScope timer(FLAG_compiler_stats, |
554 &CompilerStats::graphinliner_build_timer, | 554 &CompilerStats::graphinliner_build_timer, |
555 isolate); | 555 isolate); |
556 callee_graph = builder.BuildGraph(); | 556 callee_graph = builder.BuildGraph(); |
557 } | 557 } |
558 | 558 |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), | 599 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), |
600 param_stubs); | 600 param_stubs); |
601 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | 601 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
602 } | 602 } |
603 | 603 |
604 { | 604 { |
605 TimerScope timer(FLAG_compiler_stats, | 605 TimerScope timer(FLAG_compiler_stats, |
606 &CompilerStats::graphinliner_opt_timer, | 606 &CompilerStats::graphinliner_opt_timer, |
607 isolate); | 607 isolate); |
608 // TODO(zerny): Do more optimization passes on the callee graph. | 608 // TODO(zerny): Do more optimization passes on the callee graph. |
609 FlowGraphOptimizer optimizer(callee_graph, guarded_fields_); | 609 FlowGraphOptimizer optimizer(callee_graph); |
610 optimizer.ApplyICData(); | 610 optimizer.ApplyICData(); |
611 DEBUG_ASSERT(callee_graph->VerifyUseLists()); | 611 DEBUG_ASSERT(callee_graph->VerifyUseLists()); |
612 } | 612 } |
613 | 613 |
614 if (FLAG_trace_inlining && | 614 if (FLAG_trace_inlining && |
615 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | 615 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
616 OS::Print("Callee graph for inlining %s\n", | 616 OS::Print("Callee graph for inlining %s\n", |
617 function.ToFullyQualifiedCString()); | 617 function.ToFullyQualifiedCString()); |
618 FlowGraphPrinter printer(*callee_graph); | 618 FlowGraphPrinter printer(*callee_graph); |
619 printer.PrintBlocks(); | 619 printer.PrintBlocks(); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
660 | 660 |
661 // Build succeeded so we restore the bailout jump. | 661 // Build succeeded so we restore the bailout jump. |
662 inlined_ = true; | 662 inlined_ = true; |
663 inlined_size_ += size; | 663 inlined_size_ += size; |
664 isolate->set_long_jump_base(base); | 664 isolate->set_long_jump_base(base); |
665 isolate->set_deopt_id(prev_deopt_id); | 665 isolate->set_deopt_id(prev_deopt_id); |
666 | 666 |
667 call_data->callee_graph = callee_graph; | 667 call_data->callee_graph = callee_graph; |
668 call_data->parameter_stubs = param_stubs; | 668 call_data->parameter_stubs = param_stubs; |
669 call_data->exit_collector = exit_collector; | 669 call_data->exit_collector = exit_collector; |
| 670 |
| 671 // When inlined, we add the guarded fields of the callee to the caller's |
| 672 // list of guarded fields. |
| 673 for (intptr_t i = 0; i < inlined_guarded_fields.length(); ++i) { |
| 674 caller_graph_->builder().AddToGuardedFields(*inlined_guarded_fields[i]); |
| 675 } |
| 676 |
670 TRACE_INLINING(OS::Print(" Success\n")); | 677 TRACE_INLINING(OS::Print(" Success\n")); |
671 return true; | 678 return true; |
672 } else { | 679 } else { |
673 Error& error = Error::Handle(); | 680 Error& error = Error::Handle(); |
674 error = isolate->object_store()->sticky_error(); | 681 error = isolate->object_store()->sticky_error(); |
675 isolate->object_store()->clear_sticky_error(); | 682 isolate->object_store()->clear_sticky_error(); |
676 isolate->set_long_jump_base(base); | 683 isolate->set_long_jump_base(base); |
677 isolate->set_deopt_id(prev_deopt_id); | 684 isolate->set_deopt_id(prev_deopt_id); |
678 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); | 685 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); |
679 return false; | 686 return false; |
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
988 | 995 |
989 | 996 |
990 FlowGraph* caller_graph_; | 997 FlowGraph* caller_graph_; |
991 bool inlined_; | 998 bool inlined_; |
992 intptr_t initial_size_; | 999 intptr_t initial_size_; |
993 intptr_t inlined_size_; | 1000 intptr_t inlined_size_; |
994 intptr_t inlining_depth_; | 1001 intptr_t inlining_depth_; |
995 CallSites* collected_call_sites_; | 1002 CallSites* collected_call_sites_; |
996 CallSites* inlining_call_sites_; | 1003 CallSites* inlining_call_sites_; |
997 GrowableArray<ParsedFunction*> function_cache_; | 1004 GrowableArray<ParsedFunction*> function_cache_; |
998 GrowableArray<const Field*>* guarded_fields_; | |
999 | 1005 |
1000 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); | 1006 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); |
1001 }; | 1007 }; |
1002 | 1008 |
1003 | 1009 |
1004 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, | 1010 PolymorphicInliner::PolymorphicInliner(CallSiteInliner* owner, |
1005 PolymorphicInstanceCallInstr* call) | 1011 PolymorphicInstanceCallInstr* call) |
1006 : owner_(owner), | 1012 : owner_(owner), |
1007 call_(call), | 1013 call_(call), |
1008 num_variants_(call->ic_data().NumberOfChecks()), | 1014 num_variants_(call->ic_data().NumberOfChecks()), |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1424 flow_graph_->parsed_function().function().ToCString())); | 1430 flow_graph_->parsed_function().function().ToCString())); |
1425 | 1431 |
1426 if (FLAG_trace_inlining && | 1432 if (FLAG_trace_inlining && |
1427 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { | 1433 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { |
1428 OS::Print("Before Inlining of %s\n", flow_graph_-> | 1434 OS::Print("Before Inlining of %s\n", flow_graph_-> |
1429 parsed_function().function().ToFullyQualifiedCString()); | 1435 parsed_function().function().ToFullyQualifiedCString()); |
1430 FlowGraphPrinter printer(*flow_graph_); | 1436 FlowGraphPrinter printer(*flow_graph_); |
1431 printer.PrintBlocks(); | 1437 printer.PrintBlocks(); |
1432 } | 1438 } |
1433 | 1439 |
1434 CallSiteInliner inliner(flow_graph_, guarded_fields_); | 1440 CallSiteInliner inliner(flow_graph_); |
1435 inliner.InlineCalls(); | 1441 inliner.InlineCalls(); |
1436 | 1442 |
1437 if (inliner.inlined()) { | 1443 if (inliner.inlined()) { |
1438 flow_graph_->DiscoverBlocks(); | 1444 flow_graph_->DiscoverBlocks(); |
1439 if (FLAG_trace_inlining) { | 1445 if (FLAG_trace_inlining) { |
1440 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); | 1446 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
1441 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { | 1447 if (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized) { |
1442 OS::Print("After Inlining of %s\n", flow_graph_-> | 1448 OS::Print("After Inlining of %s\n", flow_graph_-> |
1443 parsed_function().function().ToFullyQualifiedCString()); | 1449 parsed_function().function().ToFullyQualifiedCString()); |
1444 FlowGraphPrinter printer(*flow_graph_); | 1450 FlowGraphPrinter printer(*flow_graph_); |
1445 printer.PrintBlocks(); | 1451 printer.PrintBlocks(); |
1446 } | 1452 } |
1447 } | 1453 } |
1448 } | 1454 } |
1449 } | 1455 } |
1450 | 1456 |
1451 } // namespace dart | 1457 } // namespace dart |
OLD | NEW |