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