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

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

Issue 17646002: Use call counts to determine which static calls to inline. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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
« no previous file with comments | « runtime/vm/flow_graph_builder.cc ('k') | runtime/vm/intermediate_language.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 181
182 // A collection of call sites to consider for inlining. 182 // A collection of call sites to consider for inlining.
183 class CallSites : public FlowGraphVisitor { 183 class CallSites : public FlowGraphVisitor {
184 public: 184 public:
185 explicit CallSites(FlowGraph* flow_graph) 185 explicit CallSites(FlowGraph* flow_graph)
186 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. 186 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order.
187 static_calls_(), 187 static_calls_(),
188 closure_calls_(), 188 closure_calls_(),
189 instance_calls_() { } 189 instance_calls_() { }
190 190
191 const GrowableArray<StaticCallInstr*>& static_calls() const {
192 return static_calls_;
193 }
194
195 const GrowableArray<ClosureCallInstr*>& closure_calls() const { 191 const GrowableArray<ClosureCallInstr*>& closure_calls() const {
196 return closure_calls_; 192 return closure_calls_;
197 } 193 }
198 194
199 struct InstanceCallInfo { 195 struct InstanceCallInfo {
200 PolymorphicInstanceCallInstr* call; 196 PolymorphicInstanceCallInstr* call;
201 double ratio; 197 double ratio;
202 explicit InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg) 198 explicit InstanceCallInfo(PolymorphicInstanceCallInstr* call_arg)
203 : call(call_arg), ratio(0.0) {} 199 : call(call_arg), ratio(0.0) {}
204 }; 200 };
205 201
202 struct StaticCallInfo {
203 StaticCallInstr* call;
204 double ratio;
205 explicit StaticCallInfo(StaticCallInstr* value)
206 : call(value), ratio(0.0) {}
207 };
208
206 const GrowableArray<InstanceCallInfo>& instance_calls() const { 209 const GrowableArray<InstanceCallInfo>& instance_calls() const {
207 return instance_calls_; 210 return instance_calls_;
208 } 211 }
209 212
213 const GrowableArray<StaticCallInfo>& static_calls() const {
214 return static_calls_;
215 }
216
210 bool HasCalls() const { 217 bool HasCalls() const {
211 return !(static_calls_.is_empty() && 218 return !(static_calls_.is_empty() &&
212 closure_calls_.is_empty() && 219 closure_calls_.is_empty() &&
213 instance_calls_.is_empty()); 220 instance_calls_.is_empty());
214 } 221 }
215 222
216 void Clear() { 223 void Clear() {
217 static_calls_.Clear(); 224 static_calls_.Clear();
218 closure_calls_.Clear(); 225 closure_calls_.Clear();
219 instance_calls_.Clear(); 226 instance_calls_.Clear();
220 } 227 }
221 228
229 void ComputeCallSiteRatio(intptr_t static_call_start_ix,
230 intptr_t instance_call_start_ix) {
231 const intptr_t num_static_calls =
232 static_calls_.length() - static_call_start_ix;
233 const intptr_t num_instance_calls =
234 instance_calls_.length() - instance_call_start_ix;
235
236 intptr_t max_count = 0;
237 GrowableArray<intptr_t> instance_call_counts(num_instance_calls);
238 for (intptr_t i = 0; i < num_instance_calls; ++i) {
239 const intptr_t aggregate_count =
240 instance_calls_[i + instance_call_start_ix].
241 call->ic_data().AggregateCount();
242 instance_call_counts.Add(aggregate_count);
243 if (aggregate_count > max_count) max_count = aggregate_count;
244 }
245
246 GrowableArray<intptr_t> static_call_counts(num_static_calls);
247 for (intptr_t i = 0; i < num_static_calls; ++i) {
248 const intptr_t aggregate_count =
249 static_calls_[i + static_call_start_ix].
250 call->ic_data()->AggregateCount();
251 static_call_counts.Add(aggregate_count);
252 if (aggregate_count > max_count) max_count = aggregate_count;
253 }
254
255
256 for (intptr_t i = 0; i < num_instance_calls; ++i) {
257 ASSERT(max_count > 0);
258 const double ratio =
259 static_cast<double>(instance_call_counts[i]) / max_count;
260 instance_calls_[i + instance_call_start_ix].ratio = ratio;
261 }
262 for (intptr_t i = 0; i < num_static_calls; ++i) {
263 ASSERT(max_count > 0);
264 const double ratio =
265 static_cast<double>(static_call_counts[i]) / max_count;
266 static_calls_[i + static_call_start_ix].ratio = ratio;
267 }
268 }
269
222 void FindCallSites(FlowGraph* graph) { 270 void FindCallSites(FlowGraph* graph) {
223 ASSERT(graph != NULL); 271 ASSERT(graph != NULL);
224 272
225 const intptr_t instance_call_start_ix = instance_calls_.length(); 273 const intptr_t instance_call_start_ix = instance_calls_.length();
274 const intptr_t static_call_start_ix = static_calls_.length();
226 for (BlockIterator block_it = graph->postorder_iterator(); 275 for (BlockIterator block_it = graph->postorder_iterator();
227 !block_it.Done(); 276 !block_it.Done();
228 block_it.Advance()) { 277 block_it.Advance()) {
229 for (ForwardInstructionIterator it(block_it.Current()); 278 for (ForwardInstructionIterator it(block_it.Current());
230 !it.Done(); 279 !it.Done();
231 it.Advance()) { 280 it.Advance()) {
232 it.Current()->Accept(this); 281 it.Current()->Accept(this);
233 } 282 }
234 } 283 }
235 // Compute instance call site ratio. 284 ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix);
236 const intptr_t num_instance_calls =
237 instance_calls_.length() - instance_call_start_ix;
238 intptr_t max_count = 0;
239 GrowableArray<intptr_t> call_counts(num_instance_calls);
240 for (intptr_t i = 0; i < num_instance_calls; ++i) {
241 const intptr_t aggregate_count =
242 instance_calls_[i + instance_call_start_ix].
243 call->ic_data().AggregateCount();
244 call_counts.Add(aggregate_count);
245 if (aggregate_count > max_count) max_count = aggregate_count;
246 }
247
248 for (intptr_t i = 0; i < num_instance_calls; ++i) {
249 const double ratio = static_cast<double>(call_counts[i]) / max_count;
250 instance_calls_[i + instance_call_start_ix].ratio = ratio;
251 }
252 } 285 }
253 286
254 void VisitClosureCall(ClosureCallInstr* call) { 287 void VisitClosureCall(ClosureCallInstr* call) {
255 closure_calls_.Add(call); 288 closure_calls_.Add(call);
256 } 289 }
257 290
258 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { 291 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) {
259 instance_calls_.Add(InstanceCallInfo(call)); 292 instance_calls_.Add(InstanceCallInfo(call));
260 } 293 }
261 294
262 void VisitStaticCall(StaticCallInstr* call) { 295 void VisitStaticCall(StaticCallInstr* call) {
263 if (!call->function().IsInlineable()) return; 296 if (!call->function().IsInlineable()) return;
264 static_calls_.Add(call); 297 static_calls_.Add(StaticCallInfo(call));
265 } 298 }
266 299
267 private: 300 private:
268 GrowableArray<StaticCallInstr*> static_calls_; 301 GrowableArray<StaticCallInfo> static_calls_;
269 GrowableArray<ClosureCallInstr*> closure_calls_; 302 GrowableArray<ClosureCallInstr*> closure_calls_;
270 GrowableArray<InstanceCallInfo> instance_calls_; 303 GrowableArray<InstanceCallInfo> instance_calls_;
271 304
272 DISALLOW_COPY_AND_ASSIGN(CallSites); 305 DISALLOW_COPY_AND_ASSIGN(CallSites);
273 }; 306 };
274 307
275 308
276 struct InlinedCallData { 309 struct InlinedCallData {
277 InlinedCallData(Definition* call, GrowableArray<Value*>* arguments) 310 InlinedCallData(Definition* call, GrowableArray<Value*>* arguments)
278 : call(call), 311 : call(call),
(...skipping 410 matching lines...) Expand 10 before | Expand all | Expand 10 after
689 ParsedFunction* parsed_function = new ParsedFunction(function); 722 ParsedFunction* parsed_function = new ParsedFunction(function);
690 Parser::ParseFunction(parsed_function); 723 Parser::ParseFunction(parsed_function);
691 parsed_function->AllocateVariables(); 724 parsed_function->AllocateVariables();
692 return parsed_function; 725 return parsed_function;
693 } 726 }
694 727
695 // Include special handling for List. factory: inlining it is not helpful 728 // Include special handling for List. factory: inlining it is not helpful
696 // if the incoming argument is a non-constant value. 729 // if the incoming argument is a non-constant value.
697 // TODO(srdjan): Fix inlining of List. factory. 730 // TODO(srdjan): Fix inlining of List. factory.
698 void InlineStaticCalls() { 731 void InlineStaticCalls() {
699 const GrowableArray<StaticCallInstr*>& calls = 732 const GrowableArray<CallSites::StaticCallInfo>& call_info =
700 inlining_call_sites_->static_calls(); 733 inlining_call_sites_->static_calls();
701 TRACE_INLINING(OS::Print(" Static Calls (%d)\n", calls.length())); 734 TRACE_INLINING(OS::Print(" Static Calls (%d)\n", call_info.length()));
702 for (intptr_t i = 0; i < calls.length(); ++i) { 735 for (intptr_t call_idx = 0; call_idx < call_info.length(); ++call_idx) {
703 StaticCallInstr* call = calls[i]; 736 StaticCallInstr* call = call_info[call_idx].call;
704 if (call->function().name() == Symbols::ListFactory().raw()) { 737 if (call->function().name() == Symbols::ListFactory().raw()) {
705 // Inline only if no arguments or a constant was passed. 738 // Inline only if no arguments or a constant was passed.
706 ASSERT(call->function().NumImplicitParameters() == 1); 739 ASSERT(call->function().NumImplicitParameters() == 1);
707 ASSERT(call->ArgumentCount() <= 2); 740 ASSERT(call->ArgumentCount() <= 2);
708 // Arg 0: Instantiator type arguments. 741 // Arg 0: Instantiator type arguments.
709 // Arg 1: Length (optional). 742 // Arg 1: Length (optional).
710 if ((call->ArgumentCount() == 2) && 743 if ((call->ArgumentCount() == 2) &&
711 (!call->PushArgumentAt(1)->value()->BindsToConstant())) { 744 (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
712 // Do not inline since a non-constant argument was passed. 745 // Do not inline since a non-constant argument was passed.
713 continue; 746 continue;
714 } 747 }
715 } 748 }
749 if ((call_info[call_idx].ratio * 100) < FLAG_inlining_hotness) {
750 const Function& target = call->function();
751 TRACE_INLINING(OS::Print(
752 " => %s (deopt count %d)\n Bailout: cold %f\n",
753 target.ToCString(),
754 target.deoptimization_counter(),
755 call_info[call_idx].ratio));
756 continue;
757 }
716 GrowableArray<Value*> arguments(call->ArgumentCount()); 758 GrowableArray<Value*> arguments(call->ArgumentCount());
717 for (int i = 0; i < call->ArgumentCount(); ++i) { 759 for (int i = 0; i < call->ArgumentCount(); ++i) {
718 arguments.Add(call->PushArgumentAt(i)->value()); 760 arguments.Add(call->PushArgumentAt(i)->value());
719 } 761 }
720 InlinedCallData call_data(call, &arguments); 762 InlinedCallData call_data(call, &arguments);
721 if (TryInlining(call->function(), call->argument_names(), &call_data)) { 763 if (TryInlining(call->function(), call->argument_names(), &call_data)) {
722 InlineCall(&call_data); 764 InlineCall(&call_data);
723 } 765 }
724 } 766 }
725 } 767 }
(...skipping 600 matching lines...) Expand 10 before | Expand all | Expand 10 after
1326 OS::Print("After Inlining of %s\n", flow_graph_-> 1368 OS::Print("After Inlining of %s\n", flow_graph_->
1327 parsed_function().function().ToFullyQualifiedCString()); 1369 parsed_function().function().ToFullyQualifiedCString());
1328 FlowGraphPrinter printer(*flow_graph_); 1370 FlowGraphPrinter printer(*flow_graph_);
1329 printer.PrintBlocks(); 1371 printer.PrintBlocks();
1330 } 1372 }
1331 } 1373 }
1332 } 1374 }
1333 } 1375 }
1334 1376
1335 } // namespace dart 1377 } // namespace dart
OLDNEW
« 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