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

Side by Side Diff: runtime/vm/flow_graph_inliner.cc

Issue 10893027: Inlining of static calls with trivial function bodies. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #include "vm/flow_graph_inliner.h"
6
7 #include "vm/object.h"
Kevin Millikin (Google) 2012/08/29 14:01:04 These are normally sorted alphabetically (M-x sort
zerny-google 2012/08/30 07:31:40 Done.
8 #include "vm/object_store.h"
9 #include "vm/flags.h"
10 #include "vm/flow_graph.h"
11 #include "vm/flow_graph_builder.h"
12 #include "vm/il_printer.h"
13 #include "vm/longjump.h"
14
15 namespace dart {
16
17 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
18 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
19 DECLARE_FLAG(bool, print_flow_graph);
20
21 class CallSiteInliner : public FlowGraphVisitor {
22 public:
23 explicit CallSiteInliner(FlowGraph* flow_graph)
24 : FlowGraphVisitor(flow_graph->postorder()),
25 caller_graph_(flow_graph),
26 next_ssa_temp_index_(flow_graph->max_virtual_register_number()),
27 inlined_(false) { }
28
Kevin Millikin (Google) 2012/08/29 14:01:04 Too many blank lines.
zerny-google 2012/08/30 07:31:40 Done.
29
30 void TryInlining(const Function& function,
31 GrowableArray<Value*>* arguments,
32 StaticCallComp* comp, // TODO(zerny): Generalize to calls.
33 BindInstr* instr) {
34 // Parse the callee function.
35 ParsedFunction parsed_function(function);
36 Parser::ParseFunction(&parsed_function);
37 FlowGraphBuilder builder(parsed_function);
38
39 // Install bailout jump.
40 Isolate* isolate = Isolate::Current();
41 LongJump* base = isolate->long_jump_base();
42 LongJump jump;
43 isolate->set_long_jump_base(&jump);
44 if (setjmp(*jump.Set()) == 0) {
45 // Build the callee graph.
46 FlowGraph* callee_graph =
47 builder.BuildGraphForInlining(FlowGraphBuilder::kValueContext);
48
49 // Bailout if the callee graph contains control flow.
50 if (callee_graph->preorder().length() != 2) {
51 isolate->set_long_jump_base(base);
52 if (FLAG_trace_inlining) {
53 OS::Print("Inline aborted %s\nReason: control flow\n",
54 parsed_function.function().ToFullyQualifiedCString());
55 }
56 return;
57 }
58
59 // Bailout if the formal/actual parameter count does not match.
60 if (arguments->length() != callee_graph->parameter_count()) {
61 if (FLAG_trace_inlining) {
62 OS::Print("Inline aborted %s\nReason: formal/actual mismatch\n",
63 parsed_function.function().ToFullyQualifiedCString());
64 }
65 return;
66 }
srdjan 2012/08/29 21:31:33 You may also want to bailout if the callee has nam
zerny-google 2012/08/30 07:31:40 Done.
67
68 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
69 OS::Print("Callee graph for inlining %s\n",
Kevin Millikin (Google) 2012/08/29 14:01:04 Might be useful to write 'before SSA' here and 'af
zerny-google 2012/08/30 07:31:40 Done.
70 parsed_function.function().ToFullyQualifiedCString());
71 FlowGraphPrinter printer(*callee_graph);
72 printer.PrintBlocks();
73 }
74
75 // Compute SSA on the callee graph. (catching bailouts)
76 callee_graph->ComputeSSAForInlining(next_ssa_temp_index_);
77
78 // Build succeeded so we restore the bailout jump.
79 isolate->set_long_jump_base(base);
80
81 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
82 OS::Print("Callee graph for inlining %s\n",
83 parsed_function.function().ToFullyQualifiedCString());
84 FlowGraphPrinter printer(*callee_graph);
85 printer.PrintBlocks();
86 }
87
88 callee_graph->ComputeUseLists();
89
90 // TODO(zerny): Do optimization passes on the callee graph.
91
92 // TODO(zerny): If result is more than size threshold then abort.
93
94 // TODO(zerny): If effort is less than threshold then inline recursively.
95
96 // Plug result in the caller graph.
97 caller_graph_->InlineCall(instr, comp, callee_graph);
98 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number();
99
100 // Replace all the formal parameters with the actuals.
101 for (intptr_t i = 0; i < arguments->length(); ++i) {
102 Value* val = callee_graph->graph_entry()->start_env()->values()[i];
103 ASSERT(val != NULL && val->IsUse());
104 ParameterInstr* param = val->AsUse()->definition()->AsParameter();
105 ASSERT(param != NULL);
106 param->ReplaceUsesWith((*arguments)[i]);
107 }
108
109 inlined_ = true;
110 if (FLAG_trace_inlining) {
111 OS::Print("Inlined %s\n",
112 parsed_function.function().ToFullyQualifiedCString());
113 }
114 } else {
115 Error& error = Error::Handle();
116 error = isolate->object_store()->sticky_error();
117 isolate->object_store()->clear_sticky_error();
118 isolate->set_long_jump_base(base);
119 if (FLAG_trace_inlining) {
120 OS::Print("Inline aborted for %s\nReason: %s\n",
121 parsed_function.function().ToFullyQualifiedCString(),
122 error.ToErrorCString());
123 }
124 }
125 }
126
127
128 void VisitBind(BindInstr* instr) {
129 instr->computation()->Accept(this, instr);
130 }
131
132 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallComp* comp,
133 BindInstr* instr) {
134 // if (FLAG_trace_inlining) OS::Print("Polymorphic call\n");
Kevin Millikin (Google) 2012/08/29 14:01:04 Remove the commented-out code.
zerny-google 2012/08/30 07:31:40 Done.
135 }
136
137 void VisitInstanceCall(InstanceCallComp* comp, BindInstr* instr) {
138 // if (FLAG_trace_inlining) OS::Print("Instance call\n");
srdjan 2012/08/29 21:31:33 remove dead code.
zerny-google 2012/08/30 07:31:40 Done.
139 }
140
141 void VisitStaticCall(StaticCallComp* comp, BindInstr* instr) {
142 if (FLAG_trace_inlining) OS::Print("Static call\n");
143 GrowableArray<Value*> arguments(comp->ArgumentCount());
144 for (int i = 0; i < comp->ArgumentCount(); ++i) {
145 arguments.Add(comp->ArgumentAt(i)->value());
146 }
147 TryInlining(comp->function(), &arguments, comp, instr);
148 }
149
150 void VisitClosureCall(ClosureCallComp* comp, BindInstr* instr) {
Kevin Millikin (Google) 2012/08/29 14:01:04 Remove all this code for now, too.
zerny-google 2012/08/30 07:31:40 Done.
151 if (FLAG_trace_inlining) OS::Print("Closure call\n");
152 // Find the closure of the callee.
153 ASSERT(comp->ArgumentCount() > 0);
154 UseVal* rator = comp->ArgumentAt(0)->value()->AsUse();
155 if (rator == NULL) {
156 if (FLAG_trace_inlining) OS::Print("Inline aborted: non-use operator.\n");
157 return;
158 }
159 BindInstr* defn = rator->definition()->AsBind();
160 if (defn == NULL) {
161 if (FLAG_trace_inlining) {
162 OS::Print("Inline aborted: non-bind operator.\n");
163 }
164 return;
165 }
166 const CreateClosureComp* closure = defn->computation()->AsCreateClosure();
167 if (closure == NULL) {
168 if (FLAG_trace_inlining) {
169 OS::Print("Inline aborted: non-closure operator.\n");
170 }
171 return;
172 }
173
174 GrowableArray<Value*> arguments(comp->ArgumentCount() - 1);
175 for (int i = 1; i < comp->ArgumentCount(); ++i) {
176 arguments.Add(comp->ArgumentAt(i)->value());
177 }
178
179 // TODO(zerny): Generalize TryInlining.
180 // TryInlining(closure->function(), &arguments, comp, instr);
181 }
srdjan 2012/08/29 21:31:33 Closure calls are rare in the benchmarks targeted.
zerny-google 2012/08/30 07:31:40 Ok.
182
183 bool inlined() const { return inlined_; }
184
185 private:
186 FlowGraph* caller_graph_;
187 intptr_t next_ssa_temp_index_;
188 bool inlined_;
189 };
190
191
192 void FlowGraphInliner::Inline() {
193 if ((FLAG_inlining_filter != NULL) &&
194 (strstr(flow_graph_->
195 parsed_function().function().ToFullyQualifiedCString(),
196 FLAG_inlining_filter) == NULL))
197 return;
srdjan 2012/08/29 21:31:33 Use curly braces if if-statement needs more than o
zerny-google 2012/08/30 07:31:40 Done.
198
199 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
200 OS::Print("Before Inlining of %s\n", flow_graph_->
201 parsed_function().function().ToFullyQualifiedCString());
202 FlowGraphPrinter printer(*flow_graph_);
203 printer.PrintBlocks();
204 }
205
206 CallSiteInliner inliner(flow_graph_);
207 inliner.VisitBlocks();
208
209 if (inliner.inlined()) {
210 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
211 OS::Print("After Inlining of %s\n", flow_graph_->
212 parsed_function().function().ToFullyQualifiedCString());
213 FlowGraphPrinter printer(*flow_graph_);
214 printer.PrintBlocks();
215 }
216 }
217 }
218
219 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698