| OLD | NEW |
| 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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 239 |
| 240 DISALLOW_COPY_AND_ASSIGN(CallSites); | 240 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 241 }; | 241 }; |
| 242 | 242 |
| 243 | 243 |
| 244 class CallSiteInliner : public ValueObject { | 244 class CallSiteInliner : public ValueObject { |
| 245 public: | 245 public: |
| 246 explicit CallSiteInliner(FlowGraph* flow_graph) | 246 explicit CallSiteInliner(FlowGraph* flow_graph) |
| 247 : caller_graph_(flow_graph), | 247 : caller_graph_(flow_graph), |
| 248 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), | 248 next_ssa_temp_index_(flow_graph->max_virtual_register_number()), |
| 249 inlined_(false), |
| 249 initial_size_(flow_graph->InstructionCount()), | 250 initial_size_(flow_graph->InstructionCount()), |
| 250 inlined_size_(0), | 251 inlined_size_(0), |
| 251 inlining_depth_(1), | 252 inlining_depth_(1), |
| 252 collected_call_sites_(NULL), | 253 collected_call_sites_(NULL), |
| 253 inlining_call_sites_(NULL), | 254 inlining_call_sites_(NULL), |
| 254 function_cache_() { } | 255 function_cache_() { } |
| 255 | 256 |
| 256 // Inlining heuristics based on Cooper et al. 2008. | 257 // Inlining heuristics based on Cooper et al. 2008. |
| 257 bool ShouldWeInline(intptr_t loop_depth, | 258 bool ShouldWeInline(intptr_t loop_depth, |
| 258 intptr_t instr_count, | 259 intptr_t instr_count, |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 InlineStaticCalls(); | 298 InlineStaticCalls(); |
| 298 InlineClosureCalls(); | 299 InlineClosureCalls(); |
| 299 InlineInstanceCalls(); | 300 InlineInstanceCalls(); |
| 300 // Increment the inlining depth. Checked before recursive inlining. | 301 // Increment the inlining depth. Checked before recursive inlining. |
| 301 ++inlining_depth_; | 302 ++inlining_depth_; |
| 302 } | 303 } |
| 303 collected_call_sites_ = NULL; | 304 collected_call_sites_ = NULL; |
| 304 inlining_call_sites_ = NULL; | 305 inlining_call_sites_ = NULL; |
| 305 } | 306 } |
| 306 | 307 |
| 307 intptr_t inlined_instructions() const { return inlined_size_; } | 308 bool inlined() const { return inlined_; } |
| 309 |
| 310 double GrowthFactor() const { |
| 311 return static_cast<double>(inlined_size_) / |
| 312 static_cast<double>(initial_size_); |
| 313 } |
| 308 | 314 |
| 309 private: | 315 private: |
| 310 bool TryInlining(const Function& function, | 316 bool TryInlining(const Function& function, |
| 311 const Array& argument_names, | 317 const Array& argument_names, |
| 312 GrowableArray<Value*>* arguments, | 318 GrowableArray<Value*>* arguments, |
| 313 Definition* call) { | 319 Definition* call) { |
| 314 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", | 320 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", |
| 315 function.ToCString(), | 321 function.ToCString(), |
| 316 function.deoptimization_counter())); | 322 function.deoptimization_counter())); |
| 317 | 323 |
| (...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 490 | 496 |
| 491 { | 497 { |
| 492 TimerScope timer(FLAG_compiler_stats, | 498 TimerScope timer(FLAG_compiler_stats, |
| 493 &CompilerStats::graphinliner_subst_timer, | 499 &CompilerStats::graphinliner_subst_timer, |
| 494 isolate); | 500 isolate); |
| 495 | 501 |
| 496 // Plug result in the caller graph. | 502 // Plug result in the caller graph. |
| 497 caller_graph_->InlineCall(call, callee_graph); | 503 caller_graph_->InlineCall(call, callee_graph); |
| 498 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number(); | 504 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number(); |
| 499 | 505 |
| 506 // Remove push arguments of the call. |
| 507 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 508 PushArgumentInstr* push = call->ArgumentAt(i); |
| 509 push->ReplaceUsesWith(push->value()->definition()); |
| 510 push->RemoveFromGraph(); |
| 511 } |
| 512 |
| 500 // Replace each stub with the actual argument or the caller's constant. | 513 // Replace each stub with the actual argument or the caller's constant. |
| 501 // Nulls denote optional parameters for which no actual was given. | 514 // Nulls denote optional parameters for which no actual was given. |
| 502 for (intptr_t i = 0; i < arguments->length(); ++i) { | 515 for (intptr_t i = 0; i < arguments->length(); ++i) { |
| 503 Definition* stub = param_stubs[i]; | 516 Definition* stub = param_stubs[i]; |
| 504 Value* actual = (*arguments)[i]; | 517 Value* actual = (*arguments)[i]; |
| 505 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); | 518 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); |
| 506 } | 519 } |
| 520 |
| 521 // Replace remaining constants with uses by constants in the caller's |
| 522 // initial definitions. |
| 523 GrowableArray<Definition*>* defns = |
| 524 callee_graph->graph_entry()->initial_definitions(); |
| 525 for (intptr_t i = 0; i < defns->length(); ++i) { |
| 526 ConstantInstr* constant = (*defns)[i]->AsConstant(); |
| 527 if (constant == NULL || |
| 528 ((constant->input_use_list() == NULL) && |
| 529 (constant->env_use_list() == NULL))) { |
| 530 continue; |
| 531 } |
| 532 constant->ReplaceUsesWith( |
| 533 caller_graph_->AddConstantToInitialDefinitions(constant->value())); |
| 534 } |
| 507 } | 535 } |
| 508 | 536 |
| 509 TRACE_INLINING(OS::Print( | 537 TRACE_INLINING(OS::Print(" Success\n")); |
| 510 " Success (inlined %"Pd" instructions)\n", size)); | |
| 511 | 538 |
| 512 // Add the function to the cache. | 539 // Add the function to the cache. |
| 513 if (!in_cache) function_cache_.Add(parsed_function); | 540 if (!in_cache) function_cache_.Add(parsed_function); |
| 514 | 541 |
| 515 // Check that inlining maintains use lists. | 542 // Check that inlining maintains use lists. |
| 516 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); | 543 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); |
| 517 | 544 |
| 518 // Build succeeded so we restore the bailout jump. | 545 // Build succeeded so we restore the bailout jump. |
| 546 inlined_ = true; |
| 519 inlined_size_ += size; | 547 inlined_size_ += size; |
| 520 isolate->set_long_jump_base(base); | 548 isolate->set_long_jump_base(base); |
| 521 isolate->set_deopt_id(prev_deopt_id); | 549 isolate->set_deopt_id(prev_deopt_id); |
| 522 isolate->set_ic_data_array(prev_ic_data.raw()); | 550 isolate->set_ic_data_array(prev_ic_data.raw()); |
| 523 return true; | 551 return true; |
| 524 } else { | 552 } else { |
| 525 Error& error = Error::Handle(); | 553 Error& error = Error::Handle(); |
| 526 error = isolate->object_store()->sticky_error(); | 554 error = isolate->object_store()->sticky_error(); |
| 527 isolate->object_store()->clear_sticky_error(); | 555 isolate->object_store()->clear_sticky_error(); |
| 528 isolate->set_long_jump_base(base); | 556 isolate->set_long_jump_base(base); |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 704 } else { | 732 } else { |
| 705 param_stubs->Add( | 733 param_stubs->Add( |
| 706 GetDefaultValue(i - fixed_param_count, parsed_function)); | 734 GetDefaultValue(i - fixed_param_count, parsed_function)); |
| 707 } | 735 } |
| 708 } | 736 } |
| 709 } | 737 } |
| 710 | 738 |
| 711 | 739 |
| 712 FlowGraph* caller_graph_; | 740 FlowGraph* caller_graph_; |
| 713 intptr_t next_ssa_temp_index_; | 741 intptr_t next_ssa_temp_index_; |
| 742 bool inlined_; |
| 714 intptr_t initial_size_; | 743 intptr_t initial_size_; |
| 715 intptr_t inlined_size_; | 744 intptr_t inlined_size_; |
| 716 intptr_t inlining_depth_; | 745 intptr_t inlining_depth_; |
| 717 CallSites* collected_call_sites_; | 746 CallSites* collected_call_sites_; |
| 718 CallSites* inlining_call_sites_; | 747 CallSites* inlining_call_sites_; |
| 719 GrowableArray<ParsedFunction*> function_cache_; | 748 GrowableArray<ParsedFunction*> function_cache_; |
| 720 | 749 |
| 721 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); | 750 DISALLOW_COPY_AND_ASSIGN(CallSiteInliner); |
| 722 }; | 751 }; |
| 723 | 752 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 737 if (FLAG_trace_inlining && FLAG_print_flow_graph) { | 766 if (FLAG_trace_inlining && FLAG_print_flow_graph) { |
| 738 OS::Print("Before Inlining of %s\n", flow_graph_-> | 767 OS::Print("Before Inlining of %s\n", flow_graph_-> |
| 739 parsed_function().function().ToFullyQualifiedCString()); | 768 parsed_function().function().ToFullyQualifiedCString()); |
| 740 FlowGraphPrinter printer(*flow_graph_); | 769 FlowGraphPrinter printer(*flow_graph_); |
| 741 printer.PrintBlocks(); | 770 printer.PrintBlocks(); |
| 742 } | 771 } |
| 743 | 772 |
| 744 CallSiteInliner inliner(flow_graph_); | 773 CallSiteInliner inliner(flow_graph_); |
| 745 inliner.InlineCalls(); | 774 inliner.InlineCalls(); |
| 746 | 775 |
| 747 if (inliner.inlined_instructions() > 0) { | 776 if (inliner.inlined()) { |
| 748 flow_graph_->RepairGraphAfterInlining(); | 777 flow_graph_->RepairGraphAfterInlining(); |
| 749 if (FLAG_trace_inlining) { | 778 if (FLAG_trace_inlining) { |
| 750 OS::Print("Inlined %"Pd" instructions\n", inliner.inlined_instructions()); | 779 OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor()); |
| 751 if (FLAG_print_flow_graph) { | 780 if (FLAG_print_flow_graph) { |
| 752 OS::Print("After Inlining of %s\n", flow_graph_-> | 781 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 753 parsed_function().function().ToFullyQualifiedCString()); | 782 parsed_function().function().ToFullyQualifiedCString()); |
| 754 FlowGraphPrinter printer(*flow_graph_); | 783 FlowGraphPrinter printer(*flow_graph_); |
| 755 printer.PrintBlocks(); | 784 printer.PrintBlocks(); |
| 756 } | 785 } |
| 757 } | 786 } |
| 758 } | 787 } |
| 759 } | 788 } |
| 760 | 789 |
| 761 } // namespace dart | 790 } // namespace dart |
| OLD | NEW |