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

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

Issue 11236063: Restructure code generation timers and add sub-timers for inlining phases. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Include and declare Created 8 years, 1 month 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/compiler_stats.cc ('k') | no next file » | 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) 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"
11 #include "vm/flow_graph_optimizer.h" 11 #include "vm/flow_graph_optimizer.h"
12 #include "vm/il_printer.h" 12 #include "vm/il_printer.h"
13 #include "vm/intrinsifier.h" 13 #include "vm/intrinsifier.h"
14 #include "vm/longjump.h" 14 #include "vm/longjump.h"
15 #include "vm/object.h" 15 #include "vm/object.h"
16 #include "vm/object_store.h" 16 #include "vm/object_store.h"
17 #include "vm/timer.h"
17 18
18 namespace dart { 19 namespace dart {
19 20
20 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining"); 21 DEFINE_FLAG(bool, trace_inlining, false, "Trace inlining");
21 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function"); 22 DEFINE_FLAG(charp, inlining_filter, NULL, "Inline only in named function");
22 DEFINE_FLAG(int, inlining_size_threshold, 50, 23 DEFINE_FLAG(int, inlining_size_threshold, 50,
23 "Inline only functions with up to threshold instructions (default 50)"); 24 "Inline only functions with up to threshold instructions (default 50)");
24 // TODO(srdjan): set to 3 once crash in apidoc.dart is resolved. 25 // TODO(srdjan): set to 3 once crash in apidoc.dart is resolved.
25 DEFINE_FLAG(int, inlining_depth_threshold, 3, 26 DEFINE_FLAG(int, inlining_depth_threshold, 3,
26 "Inline recursively up to threshold depth (default 3)"); 27 "Inline recursively up to threshold depth (default 3)");
27 DEFINE_FLAG(bool, inline_control_flow, true, 28 DEFINE_FLAG(bool, inline_control_flow, true,
28 "Inline functions with control flow."); 29 "Inline functions with control flow.");
29 DECLARE_FLAG(bool, print_flow_graph); 30 DECLARE_FLAG(bool, print_flow_graph);
30 DECLARE_FLAG(int, deoptimization_counter_threshold); 31 DECLARE_FLAG(int, deoptimization_counter_threshold);
31 DECLARE_FLAG(bool, verify_compiler); 32 DECLARE_FLAG(bool, verify_compiler);
33 DECLARE_FLAG(bool, compiler_stats);
32 34
33 #define TRACE_INLINING(statement) \ 35 #define TRACE_INLINING(statement) \
34 do { \ 36 do { \
35 if (FLAG_trace_inlining) statement; \ 37 if (FLAG_trace_inlining) statement; \
36 } while (false) 38 } while (false)
37 39
38 40
39 // Test if a call is recursive by looking in the deoptimization environment. 41 // Test if a call is recursive by looking in the deoptimization environment.
40 static bool IsCallRecursive(const Function& function, Definition* call) { 42 static bool IsCallRecursive(const Function& function, Definition* call) {
41 Environment* env = call->env(); 43 Environment* env = call->env();
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
262 // Save and clear deopt id. 264 // Save and clear deopt id.
263 const intptr_t prev_deopt_id = isolate->deopt_id(); 265 const intptr_t prev_deopt_id = isolate->deopt_id();
264 isolate->set_deopt_id(0); 266 isolate->set_deopt_id(0);
265 // Install bailout jump. 267 // Install bailout jump.
266 LongJump* base = isolate->long_jump_base(); 268 LongJump* base = isolate->long_jump_base();
267 LongJump jump; 269 LongJump jump;
268 isolate->set_long_jump_base(&jump); 270 isolate->set_long_jump_base(&jump);
269 if (setjmp(*jump.Set()) == 0) { 271 if (setjmp(*jump.Set()) == 0) {
270 // Parse the callee function. 272 // Parse the callee function.
271 bool in_cache; 273 bool in_cache;
272 ParsedFunction* parsed_function = ParseFunction(function, &in_cache); 274 ParsedFunction* parsed_function;
275 {
276 TimerScope timer(FLAG_compiler_stats,
277 &CompilerStats::graphinliner_parse_timer,
278 isolate);
279 parsed_function = ParseFunction(function, &in_cache);
280 }
273 281
274 // Load IC data for the callee. 282 // Load IC data for the callee.
275 if (function.HasCode()) { 283 if (function.HasCode()) {
276 const Code& unoptimized_code = 284 const Code& unoptimized_code =
277 Code::Handle(function.unoptimized_code()); 285 Code::Handle(function.unoptimized_code());
278 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); 286 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
279 } 287 }
280 288
281 // Build the callee graph. 289 // Build the callee graph.
282 FlowGraphBuilder builder(*parsed_function); 290 FlowGraphBuilder builder(*parsed_function);
283 builder.SetInitialBlockId(caller_graph_->max_block_id()); 291 builder.SetInitialBlockId(caller_graph_->max_block_id());
284 FlowGraph* callee_graph = 292 FlowGraph* callee_graph;
285 builder.BuildGraph(FlowGraphBuilder::kValueContext); 293 {
294 TimerScope timer(FLAG_compiler_stats,
295 &CompilerStats::graphinliner_build_timer,
296 isolate);
297 callee_graph = builder.BuildGraph(FlowGraphBuilder::kValueContext);
298 }
286 299
287 // Abort if the callee graph contains control flow. 300 // Abort if the callee graph contains control flow.
288 if (!FLAG_inline_control_flow && 301 if (!FLAG_inline_control_flow &&
289 (callee_graph->preorder().length() != 2)) { 302 (callee_graph->preorder().length() != 2)) {
290 function.set_is_inlinable(false); 303 function.set_is_inlinable(false);
291 isolate->set_long_jump_base(base); 304 isolate->set_long_jump_base(base);
292 isolate->set_ic_data_array(prev_ic_data.raw()); 305 isolate->set_ic_data_array(prev_ic_data.raw());
293 TRACE_INLINING(OS::Print(" Bailout: control flow\n")); 306 TRACE_INLINING(OS::Print(" Bailout: control flow\n"));
294 return false; 307 return false;
295 } 308 }
296 309
297 // Compute SSA on the callee graph, catching bailouts. 310 {
298 callee_graph->ComputeSSA(next_ssa_temp_index_); 311 TimerScope timer(FLAG_compiler_stats,
299 callee_graph->ComputeUseLists(); 312 &CompilerStats::graphinliner_ssa_timer,
313 isolate);
314 // Compute SSA on the callee graph, catching bailouts.
315 callee_graph->ComputeSSA(next_ssa_temp_index_);
316 callee_graph->ComputeUseLists();
317 }
300 318
301 // TODO(zerny): Do more optimization passes on the callee graph. 319 {
302 FlowGraphOptimizer optimizer(callee_graph); 320 TimerScope timer(FLAG_compiler_stats,
303 optimizer.ApplyICData(); 321 &CompilerStats::graphinliner_opt_timer,
304 callee_graph->ComputeUseLists(); 322 isolate);
323 // TODO(zerny): Do more optimization passes on the callee graph.
324 FlowGraphOptimizer optimizer(callee_graph);
325 optimizer.ApplyICData();
326 callee_graph->ComputeUseLists();
327 }
305 328
306 if (FLAG_trace_inlining && FLAG_print_flow_graph) { 329 if (FLAG_trace_inlining && FLAG_print_flow_graph) {
307 OS::Print("Callee graph for inlining %s\n", 330 OS::Print("Callee graph for inlining %s\n",
308 function.ToFullyQualifiedCString()); 331 function.ToFullyQualifiedCString());
309 FlowGraphPrinter printer(*callee_graph); 332 FlowGraphPrinter printer(*callee_graph);
310 printer.PrintBlocks(); 333 printer.PrintBlocks();
311 } 334 }
312 335
313 // If result is more than size threshold then abort. 336 // If result is more than size threshold then abort.
314 // TODO(zerny): Do this after CP and dead code elimination. 337 // TODO(zerny): Do this after CP and dead code elimination.
315 intptr_t size = callee_graph->InstructionCount(); 338 intptr_t size = callee_graph->InstructionCount();
316 if (size > FLAG_inlining_size_threshold) { 339 if (size > FLAG_inlining_size_threshold) {
317 function.set_is_inlinable(false); 340 function.set_is_inlinable(false);
318 isolate->set_long_jump_base(base); 341 isolate->set_long_jump_base(base);
319 isolate->set_deopt_id(prev_deopt_id); 342 isolate->set_deopt_id(prev_deopt_id);
320 isolate->set_ic_data_array(prev_ic_data.raw()); 343 isolate->set_ic_data_array(prev_ic_data.raw());
321 TRACE_INLINING(OS::Print(" Bailout: graph size %"Pd"\n", size)); 344 TRACE_INLINING(OS::Print(" Bailout: graph size %"Pd"\n", size));
322 return false; 345 return false;
323 } 346 }
324 347
325 // If depth is less or equal to threshold recursively add call sites. 348 // If depth is less or equal to threshold recursively add call sites.
326 if (inlining_depth_ < FLAG_inlining_depth_threshold) { 349 if (inlining_depth_ < FLAG_inlining_depth_threshold) {
327 collected_call_sites_->FindCallSites(callee_graph); 350 collected_call_sites_->FindCallSites(callee_graph);
328 } 351 }
329 352
330 // Plug result in the caller graph. 353 {
331 caller_graph_->InlineCall(call, callee_graph); 354 TimerScope timer(FLAG_compiler_stats,
332 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number(); 355 &CompilerStats::graphinliner_subst_timer,
356 isolate);
333 357
334 // Remove push arguments of the call. 358 // Plug result in the caller graph.
335 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) { 359 caller_graph_->InlineCall(call, callee_graph);
336 PushArgumentInstr* push = call->ArgumentAt(i); 360 next_ssa_temp_index_ = caller_graph_->max_virtual_register_number();
337 push->ReplaceUsesWith(push->value()->definition()); 361
338 push->RemoveFromGraph(); 362 // Remove push arguments of the call.
363 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
364 PushArgumentInstr* push = call->ArgumentAt(i);
365 push->ReplaceUsesWith(push->value()->definition());
366 push->RemoveFromGraph();
367 }
368
369 // Replace formal parameters with actuals.
370 intptr_t arg_index = 0;
371 GrowableArray<Definition*>* defns =
372 callee_graph->graph_entry()->initial_definitions();
373 for (intptr_t i = 0; i < defns->length(); ++i) {
374 ParameterInstr* param = (*defns)[i]->AsParameter();
375 if (param != NULL) {
376 param->ReplaceUsesWith((*arguments)[arg_index++]->definition());
377 }
378 }
379 ASSERT(arg_index == arguments->length());
380
381 // Replace callee's null constant with caller's null constant.
382 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith(
383 caller_graph_->graph_entry()->constant_null());
339 } 384 }
340 385
341 // Replace formal parameters with actuals.
342 intptr_t arg_index = 0;
343 GrowableArray<Definition*>* defns =
344 callee_graph->graph_entry()->initial_definitions();
345 for (intptr_t i = 0; i < defns->length(); ++i) {
346 ParameterInstr* param = (*defns)[i]->AsParameter();
347 if (param != NULL) {
348 param->ReplaceUsesWith((*arguments)[arg_index++]->definition());
349 }
350 }
351 ASSERT(arg_index == arguments->length());
352
353 // Replace callee's null constant with caller's null constant.
354 callee_graph->graph_entry()->constant_null()->ReplaceUsesWith(
355 caller_graph_->graph_entry()->constant_null());
356
357 TRACE_INLINING(OS::Print(" Success\n")); 386 TRACE_INLINING(OS::Print(" Success\n"));
358 387
359 // Add the function to the cache. 388 // Add the function to the cache.
360 if (!in_cache) function_cache.Add(parsed_function); 389 if (!in_cache) function_cache.Add(parsed_function);
361 390
362 // Check that inlining maintains use lists. 391 // Check that inlining maintains use lists.
363 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists()); 392 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->ValidateUseLists());
364 393
365 // Build succeeded so we restore the bailout jump. 394 // Build succeeded so we restore the bailout jump.
366 inlined_ = true; 395 inlined_ = true;
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 OS::Print("After Inlining of %s\n", flow_graph_-> 535 OS::Print("After Inlining of %s\n", flow_graph_->
507 parsed_function().function().ToFullyQualifiedCString()); 536 parsed_function().function().ToFullyQualifiedCString());
508 FlowGraphPrinter printer(*flow_graph_); 537 FlowGraphPrinter printer(*flow_graph_);
509 printer.PrintBlocks(); 538 printer.PrintBlocks();
510 } 539 }
511 } 540 }
512 } 541 }
513 } 542 }
514 543
515 } // namespace dart 544 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/compiler_stats.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698