| 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 429 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 } | 440 } |
| 441 | 441 |
| 442 // Load IC data for the callee. | 442 // Load IC data for the callee. |
| 443 if (function.HasCode()) { | 443 if (function.HasCode()) { |
| 444 const Code& unoptimized_code = | 444 const Code& unoptimized_code = |
| 445 Code::Handle(function.unoptimized_code()); | 445 Code::Handle(function.unoptimized_code()); |
| 446 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); | 446 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); |
| 447 } | 447 } |
| 448 | 448 |
| 449 // Build the callee graph. | 449 // Build the callee graph. |
| 450 FlowGraphBuilder builder(*parsed_function); | 450 ValueInliningContext* inlining_context = new ValueInliningContext(); |
| 451 FlowGraphBuilder builder(*parsed_function, inlining_context); |
| 451 builder.SetInitialBlockId(caller_graph_->max_block_id()); | 452 builder.SetInitialBlockId(caller_graph_->max_block_id()); |
| 452 FlowGraph* callee_graph; | 453 FlowGraph* callee_graph; |
| 453 { | 454 { |
| 454 TimerScope timer(FLAG_compiler_stats, | 455 TimerScope timer(FLAG_compiler_stats, |
| 455 &CompilerStats::graphinliner_build_timer, | 456 &CompilerStats::graphinliner_build_timer, |
| 456 isolate); | 457 isolate); |
| 457 callee_graph = | 458 callee_graph = builder.BuildGraph(loop_depth); |
| 458 builder.BuildGraph(FlowGraphBuilder::kValueContext, loop_depth); | |
| 459 } | 459 } |
| 460 | 460 |
| 461 // The parameter stubs are a copy of the actual arguments providing | 461 // The parameter stubs are a copy of the actual arguments providing |
| 462 // concrete information about the values, for example constant values, | 462 // concrete information about the values, for example constant values, |
| 463 // without linking between the caller and callee graphs. | 463 // without linking between the caller and callee graphs. |
| 464 // TODO(zerny): Put more information in the stubs, eg, type information. | 464 // TODO(zerny): Put more information in the stubs, eg, type information. |
| 465 GrowableArray<Definition*> param_stubs(function.NumParameters()); | 465 GrowableArray<Definition*> param_stubs(function.NumParameters()); |
| 466 | 466 |
| 467 // Create a parameter stub for each fixed positional parameter. | 467 // Create a parameter stub for each fixed positional parameter. |
| 468 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { | 468 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 567 if (inlining_depth_ < FLAG_inlining_depth_threshold) { | 567 if (inlining_depth_ < FLAG_inlining_depth_threshold) { |
| 568 collected_call_sites_->FindCallSites(callee_graph); | 568 collected_call_sites_->FindCallSites(callee_graph); |
| 569 } | 569 } |
| 570 | 570 |
| 571 { | 571 { |
| 572 TimerScope timer(FLAG_compiler_stats, | 572 TimerScope timer(FLAG_compiler_stats, |
| 573 &CompilerStats::graphinliner_subst_timer, | 573 &CompilerStats::graphinliner_subst_timer, |
| 574 isolate); | 574 isolate); |
| 575 | 575 |
| 576 // Plug result in the caller graph. | 576 // Plug result in the caller graph. |
| 577 caller_graph_->InlineCall(call, callee_graph); | 577 caller_graph_->InlineCall(call, callee_graph, inlining_context); |
| 578 | 578 |
| 579 // Remove push arguments of the call. | 579 // Remove push arguments of the call. |
| 580 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { | 580 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { |
| 581 PushArgumentInstr* push = call->ArgumentAt(i); | 581 PushArgumentInstr* push = call->ArgumentAt(i); |
| 582 push->ReplaceUsesWith(push->value()->definition()); | 582 push->ReplaceUsesWith(push->value()->definition()); |
| 583 push->RemoveFromGraph(); | 583 push->RemoveFromGraph(); |
| 584 } | 584 } |
| 585 | 585 |
| 586 // Replace each stub with the actual argument or the caller's constant. | 586 // Replace each stub with the actual argument or the caller's constant. |
| 587 // Nulls denote optional parameters for which no actual was given. | 587 // Nulls denote optional parameters for which no actual was given. |
| 588 for (intptr_t i = 0; i < arguments->length(); ++i) { | 588 for (intptr_t i = 0; i < arguments->length(); ++i) { |
| 589 Definition* stub = param_stubs[i]; | 589 Definition* stub = param_stubs[i]; |
| 590 Value* actual = (*arguments)[i]; | 590 Value* actual = (*arguments)[i]; |
| 591 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); | 591 if (actual != NULL) stub->ReplaceUsesWith(actual->definition()); |
| 592 } | 592 } |
| 593 | 593 |
| 594 // Replace remaining constants with uses by constants in the caller's | 594 // Replace remaining constants with uses by constants in the caller's |
| 595 // initial definitions. | 595 // initial definitions. |
| 596 GrowableArray<Definition*>* defns = | 596 GrowableArray<Definition*>* defns = |
| 597 callee_graph->graph_entry()->initial_definitions(); | 597 callee_graph->graph_entry()->initial_definitions(); |
| 598 for (intptr_t i = 0; i < defns->length(); ++i) { | 598 for (intptr_t i = 0; i < defns->length(); ++i) { |
| 599 ConstantInstr* constant = (*defns)[i]->AsConstant(); | 599 ConstantInstr* constant = (*defns)[i]->AsConstant(); |
| 600 if (constant == NULL || | 600 if ((constant != NULL) && constant->HasUses()) { |
| 601 ((constant->input_use_list() == NULL) && | 601 constant->ReplaceUsesWith( |
| 602 (constant->env_use_list() == NULL))) { | 602 caller_graph_->AddConstantToInitialDefinitions( |
| 603 continue; | 603 constant->value())); |
| 604 } | 604 } |
| 605 constant->ReplaceUsesWith( | |
| 606 caller_graph_->AddConstantToInitialDefinitions(constant->value())); | |
| 607 } | 605 } |
| 608 } | 606 } |
| 609 | 607 |
| 610 TRACE_INLINING(OS::Print(" Success\n")); | 608 TRACE_INLINING(OS::Print(" Success\n")); |
| 611 | 609 |
| 612 // Add the function to the cache. | 610 // Add the function to the cache. |
| 613 if (!in_cache) function_cache_.Add(parsed_function); | 611 if (!in_cache) function_cache_.Add(parsed_function); |
| 614 | 612 |
| 615 // Check that inlining maintains use lists. | 613 // Check that inlining maintains use lists. |
| 616 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); | 614 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); |
| (...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 885 OS::Print("After Inlining of %s\n", flow_graph_-> | 883 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 886 parsed_function().function().ToFullyQualifiedCString()); | 884 parsed_function().function().ToFullyQualifiedCString()); |
| 887 FlowGraphPrinter printer(*flow_graph_); | 885 FlowGraphPrinter printer(*flow_graph_); |
| 888 printer.PrintBlocks(); | 886 printer.PrintBlocks(); |
| 889 } | 887 } |
| 890 } | 888 } |
| 891 } | 889 } |
| 892 } | 890 } |
| 893 | 891 |
| 894 } // namespace dart | 892 } // namespace dart |
| OLD | NEW |