| 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 |