| Index: runtime/vm/flow_graph_inliner.cc
|
| diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
|
| index 819b28e3708c2683ee7aa25bc8f78053050f40cb..c01304d3f1ea29d271d5742b2b3ab9353a153a1f 100644
|
| --- a/runtime/vm/flow_graph_inliner.cc
|
| +++ b/runtime/vm/flow_graph_inliner.cc
|
| @@ -19,10 +19,6 @@ namespace dart {
|
|
|
| DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
|
| DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
|
| -DEFINE_FLAG(int, inlining_size_threshold, 250,
|
| - "Inline only functions with up to threshold instructions");
|
| -DEFINE_FLAG(int, inlining_growth_factor, 3,
|
| - "Stop inlining when a function grows by the factor");
|
| DECLARE_FLAG(bool, print_flow_graph);
|
| DECLARE_FLAG(int, deoptimization_counter_threshold);
|
|
|
| @@ -49,43 +45,8 @@ class CallSiteInliner : public FlowGraphVisitor {
|
| : FlowGraphVisitor(flow_graph->postorder()),
|
| caller_graph_(flow_graph),
|
| next_ssa_temp_index_(flow_graph->max_virtual_register_number()),
|
| - inlined_(false),
|
| - initial_size_(flow_graph->InstructionCount()),
|
| - inlined_size_(0),
|
| - static_calls_(),
|
| - closure_calls_(),
|
| - instance_calls_() { }
|
| + inlined_(false) { }
|
|
|
| - void VisitClosureCall(ClosureCallInstr* call) {
|
| - closure_calls_.Add(call);
|
| - }
|
| -
|
| - void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) {
|
| - instance_calls_.Add(call);
|
| - }
|
| -
|
| - void VisitStaticCall(StaticCallInstr* call) {
|
| - if (call->function().is_inlinable()) static_calls_.Add(call);
|
| - }
|
| -
|
| - void FindCallSites() {
|
| - VisitBlocks();
|
| - }
|
| -
|
| - void InlineCalls() {
|
| - InlineStaticCalls();
|
| - InlineClosureCalls();
|
| - InlineInstanceCalls();
|
| - }
|
| -
|
| - bool inlined() const { return inlined_; }
|
| -
|
| - double GrowthFactor() const {
|
| - return static_cast<double>(inlined_size_) /
|
| - static_cast<double>(initial_size_);
|
| - }
|
| -
|
| - private:
|
| bool TryInlining(const Function& function,
|
| GrowableArray<Value*>* arguments,
|
| Definition* call) {
|
| @@ -148,10 +109,18 @@ class CallSiteInliner : public FlowGraphVisitor {
|
|
|
| // Build the callee graph.
|
| FlowGraphBuilder builder(parsed_function);
|
| - builder.SetInitialBlockId(caller_graph_->max_block_id());
|
| FlowGraph* callee_graph =
|
| builder.BuildGraph(FlowGraphBuilder::kValueContext);
|
|
|
| + // Abort if the callee graph contains control flow.
|
| + if (callee_graph->preorder().length() != 2) {
|
| + function.set_is_inlinable(false);
|
| + isolate->set_long_jump_base(base);
|
| + isolate->set_ic_data_array(prev_ic_data.raw());
|
| + TRACE_INLINING(OS::Print(" Bailout: control flow\n"));
|
| + return false;
|
| + }
|
| +
|
| // Compute SSA on the callee graph, catching bailouts.
|
| callee_graph->ComputeSSA(next_ssa_temp_index_);
|
| callee_graph->ComputeUseLists();
|
| @@ -168,31 +137,7 @@ class CallSiteInliner : public FlowGraphVisitor {
|
| printer.PrintBlocks();
|
| }
|
|
|
| - // If result is more than size threshold then abort.
|
| - // TODO(zerny): Do this after CP and dead code elimination.
|
| - intptr_t size = callee_graph->InstructionCount();
|
| - if (size > FLAG_inlining_size_threshold) {
|
| - function.set_is_inlinable(false);
|
| - isolate->set_long_jump_base(base);
|
| - isolate->set_deopt_id(prev_deopt_id);
|
| - isolate->set_ic_data_array(prev_ic_data.raw());
|
| - TRACE_INLINING(OS::Print(" Bailout: graph size %"Pd"\n", size));
|
| - return false;
|
| - }
|
| -
|
| - // If the growth factor is more than threshold abort.
|
| - double growth =
|
| - static_cast<double>(inlined_size_ + size) /
|
| - static_cast<double>(initial_size_);
|
| - if (growth > static_cast<double>(FLAG_inlining_growth_factor)) {
|
| - function.set_is_inlinable(false);
|
| - isolate->set_long_jump_base(base);
|
| - isolate->set_deopt_id(prev_deopt_id);
|
| - isolate->set_ic_data_array(prev_ic_data.raw());
|
| - TRACE_INLINING(OS::Print(" Bailout: growth factor %f\n",
|
| - growth));
|
| - return false;
|
| - }
|
| + // TODO(zerny): If result is more than size threshold then abort.
|
|
|
| // TODO(zerny): If effort is less than threshold then inline recursively.
|
|
|
| @@ -200,6 +145,9 @@ class CallSiteInliner : public FlowGraphVisitor {
|
| caller_graph_->InlineCall(call, callee_graph);
|
| next_ssa_temp_index_ = caller_graph_->max_virtual_register_number();
|
|
|
| + // Check that inlining maintains use lists.
|
| + DEBUG_ASSERT(caller_graph_->ValidateUseLists());
|
| +
|
| // Remove push arguments of the call.
|
| for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
|
| PushArgumentInstr* push = call->ArgumentAt(i);
|
| @@ -225,12 +173,8 @@ class CallSiteInliner : public FlowGraphVisitor {
|
|
|
| TRACE_INLINING(OS::Print(" Success\n"));
|
|
|
| - // Check that inlining maintains use lists.
|
| - DEBUG_ASSERT(caller_graph_->ValidateUseLists());
|
| -
|
| // Build succeeded so we restore the bailout jump.
|
| inlined_ = true;
|
| - inlined_size_ += size;
|
| isolate->set_long_jump_base(base);
|
| isolate->set_deopt_id(prev_deopt_id);
|
| isolate->set_ic_data_array(prev_ic_data.raw());
|
| @@ -247,70 +191,57 @@ class CallSiteInliner : public FlowGraphVisitor {
|
| }
|
| }
|
|
|
| - void InlineStaticCalls() {
|
| - TRACE_INLINING(OS::Print(" Static Calls (%d)\n",
|
| - static_calls_.length()));
|
| - for (intptr_t i = 0; i < static_calls_.length(); ++i) {
|
| - StaticCallInstr* call = static_calls_[i];
|
| - GrowableArray<Value*> arguments(call->ArgumentCount());
|
| - for (int i = 0; i < call->ArgumentCount(); ++i) {
|
| - arguments.Add(call->ArgumentAt(i)->value());
|
| - }
|
| - TryInlining(call->function(), &arguments, call);
|
| + void VisitClosureCall(ClosureCallInstr* call) {
|
| + TRACE_INLINING(OS::Print(" ClosureCall\n"));
|
| + // Find the closure of the callee.
|
| + ASSERT(call->ArgumentCount() > 0);
|
| + const CreateClosureInstr* closure =
|
| + call->ArgumentAt(0)->value()->definition()->AsCreateClosure();
|
| + if (closure == NULL) {
|
| + TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n"));
|
| + return;
|
| + }
|
| + GrowableArray<Value*> arguments(call->ArgumentCount() - 1);
|
| + for (int i = 1; i < call->ArgumentCount(); ++i) {
|
| + arguments.Add(call->ArgumentAt(i)->value());
|
| }
|
| + TryInlining(closure->function(), &arguments, call);
|
| }
|
|
|
| - void InlineClosureCalls() {
|
| - TRACE_INLINING(OS::Print(" Closure Calls (%d)\n",
|
| - closure_calls_.length()));
|
| - for (intptr_t i = 0; i < closure_calls_.length(); ++i) {
|
| - ClosureCallInstr* call = closure_calls_[i];
|
| - // Find the closure of the callee.
|
| - ASSERT(call->ArgumentCount() > 0);
|
| - const CreateClosureInstr* closure =
|
| - call->ArgumentAt(0)->value()->definition()->AsCreateClosure();
|
| - if (closure == NULL) {
|
| - TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n"));
|
| - continue;
|
| - }
|
| - GrowableArray<Value*> arguments(call->ArgumentCount() - 1);
|
| - for (int i = 1; i < call->ArgumentCount(); ++i) {
|
| - arguments.Add(call->ArgumentAt(i)->value());
|
| - }
|
| - TryInlining(closure->function(), &arguments, call);
|
| + void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* instr) {
|
| + TRACE_INLINING(OS::Print(" PolymorphicInstanceCall\n"));
|
| + const ICData& ic_data = instr->ic_data();
|
| + const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
| + if (instr->with_checks()) {
|
| + TRACE_INLINING(OS::Print(" Bailout: %"Pd" checks target '%s'\n",
|
| + ic_data.NumberOfChecks(),
|
| + target.ToCString()));
|
| + return;
|
| + }
|
| +
|
| + GrowableArray<Value*> arguments(instr->ArgumentCount());
|
| + for (int i = 0; i < instr->ArgumentCount(); ++i) {
|
| + arguments.Add(instr->ArgumentAt(i)->value());
|
| }
|
| +
|
| + TryInlining(target, &arguments, instr);
|
| }
|
|
|
| - void InlineInstanceCalls() {
|
| - TRACE_INLINING(OS::Print(" Polymorphic Instance Calls (%d)\n",
|
| - instance_calls_.length()));
|
| - for (intptr_t i = 0; i < instance_calls_.length(); ++i) {
|
| - PolymorphicInstanceCallInstr* instr = instance_calls_[i];
|
| - const ICData& ic_data = instr->ic_data();
|
| - const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
|
| - if (instr->with_checks()) {
|
| - TRACE_INLINING(OS::Print(" Bailout: %"Pd" checks target '%s'\n",
|
| - ic_data.NumberOfChecks(),
|
| - target.ToCString()));
|
| - continue;
|
| - }
|
| - GrowableArray<Value*> arguments(instr->ArgumentCount());
|
| - for (int i = 0; i < instr->ArgumentCount(); ++i) {
|
| - arguments.Add(instr->ArgumentAt(i)->value());
|
| - }
|
| - TryInlining(target, &arguments, instr);
|
| + void VisitStaticCall(StaticCallInstr* call) {
|
| + TRACE_INLINING(OS::Print(" StaticCall\n"));
|
| + GrowableArray<Value*> arguments(call->ArgumentCount());
|
| + for (int i = 0; i < call->ArgumentCount(); ++i) {
|
| + arguments.Add(call->ArgumentAt(i)->value());
|
| }
|
| + TryInlining(call->function(), &arguments, call);
|
| }
|
|
|
| + bool inlined() const { return inlined_; }
|
| +
|
| + private:
|
| FlowGraph* caller_graph_;
|
| intptr_t next_ssa_temp_index_;
|
| bool inlined_;
|
| - intptr_t initial_size_;
|
| - intptr_t inlined_size_;
|
| -
|
| - GrowableArray<StaticCallInstr*> static_calls_;
|
| - GrowableArray<ClosureCallInstr*> closure_calls_;
|
| - GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_;
|
| };
|
|
|
|
|
| @@ -334,18 +265,14 @@ void FlowGraphInliner::Inline() {
|
| }
|
|
|
| CallSiteInliner inliner(flow_graph_);
|
| - inliner.FindCallSites();
|
| - inliner.InlineCalls();
|
| + inliner.VisitBlocks();
|
|
|
| if (inliner.inlined()) {
|
| - if (FLAG_trace_inlining) {
|
| - OS::Print("Inlining growth factor: %f\n", inliner.GrowthFactor());
|
| - if (FLAG_print_flow_graph) {
|
| - OS::Print("After Inlining of %s\n", flow_graph_->
|
| - parsed_function().function().ToFullyQualifiedCString());
|
| - FlowGraphPrinter printer(*flow_graph_);
|
| - printer.PrintBlocks();
|
| - }
|
| + if (FLAG_trace_inlining && FLAG_print_flow_graph) {
|
| + OS::Print("After Inlining of %s\n", flow_graph_->
|
| + parsed_function().function().ToFullyQualifiedCString());
|
| + FlowGraphPrinter printer(*flow_graph_);
|
| + printer.PrintBlocks();
|
| }
|
| }
|
| }
|
|
|