Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1366)

Unified Diff: runtime/vm/flow_graph_inliner.cc

Issue 10916228: Inline monomorphic calls. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Incorporated review comments. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/flow_graph_inliner.cc
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 76893c0b6092bf4f30189e03c9951c00cb131230..6b55e141331e8d3d172782129cd0b0f7268eb5ad 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -26,18 +26,20 @@ class CallSiteInliner : public FlowGraphVisitor {
next_ssa_temp_index_(flow_graph->max_virtual_register_number()),
inlined_(false) { }
- void TryInlining(const Function& function,
+ bool TryInlining(const Function& function,
GrowableArray<Value*>* arguments,
- StaticCallInstr* call) {
- // TODO(zerny): Generalize to all calls.
+ Definition* call) {
+ if (FLAG_trace_inlining) {
+ OS::Print("--- %s\n", function.ToFullyQualifiedCString());
+ }
- // Abort if the callee has optional parameters.
+ // Abort if the callee has named parameters.
if (function.HasOptionalParameters()) {
if (FLAG_trace_inlining) {
OS::Print("Inline aborted %s\nReason: optional parameters\n",
function.ToFullyQualifiedCString());
}
- return;
+ return false;
}
// Assuming no optional parameters the actual/formal count should match.
@@ -55,11 +57,12 @@ class CallSiteInliner : public FlowGraphVisitor {
// Parse the callee function.
ParsedFunction parsed_function(function);
Parser::ParseFunction(&parsed_function);
+ parsed_function.AllocateVariables();
FlowGraphBuilder builder(parsed_function);
// Build the callee graph.
FlowGraph* callee_graph =
- builder.BuildGraphForInlining(FlowGraphBuilder::kValueContext);
+ builder.BuildGraph(FlowGraphBuilder::kValueContext);
// Abort if the callee graph contains control flow.
if (callee_graph->preorder().length() != 2) {
@@ -69,7 +72,7 @@ class CallSiteInliner : public FlowGraphVisitor {
OS::Print("Inline aborted %s\nReason: control flow\n",
parsed_function.function().ToFullyQualifiedCString());
}
- return;
+ return false;
}
if (FLAG_trace_inlining && FLAG_print_flow_graph) {
@@ -101,6 +104,13 @@ class CallSiteInliner : public FlowGraphVisitor {
caller_graph_->InlineCall(call, callee_graph);
next_ssa_temp_index_ = caller_graph_->max_virtual_register_number();
+ // Remove (all) push arguments of the call.
+ for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+ PushArgumentInstr* push = call->ArgumentAt(i);
+ push->ReplaceUsesWith(push->value()->definition());
+ push->RemoveFromGraph();
+ }
+
// Replace all the formal parameters with the actuals.
for (intptr_t i = 0; i < arguments->length(); ++i) {
Value* val = callee_graph->graph_entry()->start_env()->ValueAt(i);
@@ -109,6 +119,10 @@ class CallSiteInliner : public FlowGraphVisitor {
param->ReplaceUsesWith((*arguments)[i]->definition());
}
+ // Replace callee's null constant with caller's null constant.
+ callee_graph->graph_entry()->constant_null()->ReplaceUsesWith(
+ caller_graph_->graph_entry()->constant_null());
+
if (FLAG_trace_inlining) {
OS::Print("Inlined %s\n", function.ToFullyQualifiedCString());
}
@@ -117,6 +131,7 @@ class CallSiteInliner : public FlowGraphVisitor {
inlined_ = true;
isolate->set_long_jump_base(base);
isolate->set_ic_data_array(old_ic_data.raw());
+ return true;
} else {
Error& error = Error::Handle();
error = isolate->object_store()->sticky_error();
@@ -128,19 +143,84 @@ class CallSiteInliner : public FlowGraphVisitor {
function.ToFullyQualifiedCString(),
error.ToErrorCString());
}
+ return false;
+ }
+ }
+
+ void VisitClosureCall(ClosureCallInstr* call) {
+ if (FLAG_trace_inlining) OS::Print("Closure call\n");
+ // Find the closure of the callee.
+ ASSERT(call->ArgumentCount() > 0);
+ const CreateClosureInstr* closure =
+ call->ArgumentAt(0)->value()->definition()->AsCreateClosure();
+ if (closure == NULL) {
+ if (FLAG_trace_inlining) {
+ OS::Print("Inline aborted: 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 VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* instr) {
+ if (FLAG_trace_inlining) OS::Print("Polymorphic instance call\n");
+ InstanceCallInstr* call = instr->instance_call();
+ if (!call->HasICData()) {
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: has no IC data\n");
+ return;
}
+ const ICData& ic_data = *call->ic_data();
Florian Schneider 2012/09/11 16:54:15 This can be made even simpler for monomorphic call
+
+ ASSERT(ic_data.num_args_tested() > 0);
+
+ if (ic_data.NumberOfChecks() == 0) {
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: no IC checks\n");
+ return;
+ }
+ if (ic_data.NumberOfChecks() != 1) {
Florian Schneider 2012/09/11 16:54:15 I think this check is not necesary since we only g
+ // TODO(zerny): proceed if each check has the same target?
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: non monomorphic\n");
+ return;
+ }
+ GrowableArray<intptr_t> class_ids;
+ Function& target = Function::Handle();
+ ic_data.GetCheckAt(0, &class_ids, &target);
Florian Schneider 2012/09/11 16:54:15 const Function& target = Function::ZoneHandle(ic_d
+ intptr_t class_id = class_ids[0];
+ if (class_id == kIllegalCid) {
Florian Schneider 2012/09/11 16:54:15 Not sure if those can actually occur in type feedb
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: invalid receiver\n");
+ return;
+ }
+ if (class_id == kDynamicCid) {
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: dynamic receiver\n");
+ return;
+ }
+ if (class_id == kSmiCid) {
+ if (FLAG_trace_inlining) OS::Print("Inline aborted: smi receiver\n");
+ return;
+ }
+
+ GrowableArray<Value*> arguments(call->ArgumentCount());
+ for (int i = 0; i < call->ArgumentCount(); ++i) {
+ arguments.Add(call->ArgumentAt(i)->value());
+ }
+
+ TryInlining(target, &arguments, instr);
}
- void VisitStaticCall(StaticCallInstr* instr) {
+ void VisitStaticCall(StaticCallInstr* call) {
if (FLAG_trace_inlining) OS::Print("Static call\n");
- GrowableArray<Value*> arguments(instr->ArgumentCount());
- for (int i = 0; i < instr->ArgumentCount(); ++i) {
- arguments.Add(instr->ArgumentAt(i)->value());
+ GrowableArray<Value*> arguments(call->ArgumentCount());
+ for (int i = 0; i < call->ArgumentCount(); ++i) {
+ arguments.Add(call->ArgumentAt(i)->value());
}
- TryInlining(instr->function(), &arguments, instr);
+ TryInlining(call->function(), &arguments, call);
}
- bool preformed_inlining() const { return inlined_; }
+ bool inlined() const { return inlined_; }
private:
FlowGraph* caller_graph_;
@@ -167,7 +247,7 @@ void FlowGraphInliner::Inline() {
CallSiteInliner inliner(flow_graph_);
inliner.VisitBlocks();
- if (inliner.preformed_inlining()) {
+ if (inliner.inlined()) {
if (FLAG_trace_inlining && FLAG_print_flow_graph) {
OS::Print("After Inlining of %s\n", flow_graph_->
parsed_function().function().ToFullyQualifiedCString());
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698