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

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

Issue 13932005: Refactor the code for making inlining decisions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 8 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 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 352 }
353 353
354 bool inlined() const { return inlined_; } 354 bool inlined() const { return inlined_; }
355 355
356 double GrowthFactor() const { 356 double GrowthFactor() const {
357 return static_cast<double>(inlined_size_) / 357 return static_cast<double>(inlined_size_) /
358 static_cast<double>(initial_size_); 358 static_cast<double>(initial_size_);
359 } 359 }
360 360
361 private: 361 private:
362 struct InlinedCallData {
363 public:
364 InlinedCallData(Definition* call, GrowableArray<Value*>* arguments)
365 : call(call),
366 arguments(arguments),
367 callee_graph(NULL),
368 parameter_stubs(NULL),
369 exit_collector(NULL) { }
370
371 Definition* call;
372 GrowableArray<Value*>* arguments;
373 FlowGraph* callee_graph;
374 ZoneGrowableArray<Definition*>* parameter_stubs;
375 InlineExitCollector* exit_collector;
376 };
377
362 bool TryInlining(const Function& function, 378 bool TryInlining(const Function& function,
363 const Array& argument_names, 379 const Array& argument_names,
364 GrowableArray<Value*>* arguments, 380 InlinedCallData* call_data) {
365 Definition* call) {
366 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", 381 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n",
367 function.ToCString(), 382 function.ToCString(),
368 function.deoptimization_counter())); 383 function.deoptimization_counter()));
369 384
370 // Abort if the inlinable bit on the function is low. 385 // Abort if the inlinable bit on the function is low.
371 if (!function.IsInlineable()) { 386 if (!function.IsInlineable()) {
372 TRACE_INLINING(OS::Print(" Bailout: not inlinable\n")); 387 TRACE_INLINING(OS::Print(" Bailout: not inlinable\n"));
373 return false; 388 return false;
374 } 389 }
375 390
376 // Abort if this function has deoptimized too much. 391 // Abort if this function has deoptimized too much.
377 if (function.deoptimization_counter() >= 392 if (function.deoptimization_counter() >=
378 FLAG_deoptimization_counter_threshold) { 393 FLAG_deoptimization_counter_threshold) {
379 function.set_is_inlinable(false); 394 function.set_is_inlinable(false);
380 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n")); 395 TRACE_INLINING(OS::Print(" Bailout: deoptimization threshold\n"));
381 return false; 396 return false;
382 } 397 }
383 398
399 GrowableArray<Value*>* arguments = call_data->arguments;
384 const intptr_t constant_arguments = CountConstants(*arguments); 400 const intptr_t constant_arguments = CountConstants(*arguments);
385 if (!ShouldWeInline(function.optimized_instruction_count(), 401 if (!ShouldWeInline(function.optimized_instruction_count(),
386 function.optimized_call_site_count(), 402 function.optimized_call_site_count(),
387 constant_arguments)) { 403 constant_arguments)) {
388 TRACE_INLINING(OS::Print(" Bailout: early heuristics with " 404 TRACE_INLINING(OS::Print(" Bailout: early heuristics with "
389 "code size: %"Pd", " 405 "code size: %"Pd", "
390 "call sites: %"Pd", " 406 "call sites: %"Pd", "
391 "const args: %"Pd"\n", 407 "const args: %"Pd"\n",
392 function.optimized_instruction_count(), 408 function.optimized_instruction_count(),
393 function.optimized_call_site_count(), 409 function.optimized_call_site_count(),
394 constant_arguments)); 410 constant_arguments));
395 return false; 411 return false;
396 } 412 }
397 413
398 // Abort if this is a recursive occurrence. 414 // Abort if this is a recursive occurrence.
415 Definition* call = call_data->call;
399 if (!FLAG_inline_recursive && IsCallRecursive(function, call)) { 416 if (!FLAG_inline_recursive && IsCallRecursive(function, call)) {
400 function.set_is_inlinable(false); 417 function.set_is_inlinable(false);
401 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); 418 TRACE_INLINING(OS::Print(" Bailout: recursive function\n"));
402 return false; 419 return false;
403 } 420 }
404 421
405 // Abort if the callee has an intrinsic translation. 422 // Abort if the callee has an intrinsic translation.
406 if (Intrinsifier::CanIntrinsify(function)) { 423 if (Intrinsifier::CanIntrinsify(function)) {
407 function.set_is_inlinable(false); 424 function.set_is_inlinable(false);
408 TRACE_INLINING(OS::Print(" Bailout: can intrinsify\n")); 425 TRACE_INLINING(OS::Print(" Bailout: can intrinsify\n"));
(...skipping 23 matching lines...) Expand all
432 } 449 }
433 450
434 // Load IC data for the callee. 451 // Load IC data for the callee.
435 if (function.HasCode()) { 452 if (function.HasCode()) {
436 const Code& unoptimized_code = 453 const Code& unoptimized_code =
437 Code::Handle(function.unoptimized_code()); 454 Code::Handle(function.unoptimized_code());
438 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); 455 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray());
439 } 456 }
440 457
441 // Build the callee graph. 458 // Build the callee graph.
442 InliningContext inlining_context(caller_graph_, call); 459 InlineExitCollector* exit_collector =
443 FlowGraphBuilder builder(*parsed_function, &inlining_context); 460 new InlineExitCollector(caller_graph_, call);
461 FlowGraphBuilder builder(*parsed_function, exit_collector);
444 builder.SetInitialBlockId(caller_graph_->max_block_id()); 462 builder.SetInitialBlockId(caller_graph_->max_block_id());
445 FlowGraph* callee_graph; 463 FlowGraph* callee_graph;
446 { 464 {
447 TimerScope timer(FLAG_compiler_stats, 465 TimerScope timer(FLAG_compiler_stats,
448 &CompilerStats::graphinliner_build_timer, 466 &CompilerStats::graphinliner_build_timer,
449 isolate); 467 isolate);
450 callee_graph = builder.BuildGraph(); 468 callee_graph = builder.BuildGraph();
451 } 469 }
452 470
453 // The parameter stubs are a copy of the actual arguments providing 471 // The parameter stubs are a copy of the actual arguments providing
454 // concrete information about the values, for example constant values, 472 // concrete information about the values, for example constant values,
455 // without linking between the caller and callee graphs. 473 // without linking between the caller and callee graphs.
456 // TODO(zerny): Put more information in the stubs, eg, type information. 474 // TODO(zerny): Put more information in the stubs, eg, type information.
457 GrowableArray<Definition*> param_stubs(function.NumParameters()); 475 ZoneGrowableArray<Definition*>* param_stubs =
476 new ZoneGrowableArray<Definition*>(function.NumParameters());
458 477
459 // Create a parameter stub for each fixed positional parameter. 478 // Create a parameter stub for each fixed positional parameter.
460 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) { 479 for (intptr_t i = 0; i < function.num_fixed_parameters(); ++i) {
461 param_stubs.Add(CreateParameterStub(i, (*arguments)[i], callee_graph)); 480 param_stubs->Add(CreateParameterStub(i, (*arguments)[i], callee_graph));
462 } 481 }
463 482
464 // If the callee has optional parameters, rebuild the argument and stub 483 // If the callee has optional parameters, rebuild the argument and stub
465 // arrays so that actual arguments are in one-to-one with the formal 484 // arrays so that actual arguments are in one-to-one with the formal
466 // parameters. 485 // parameters.
467 if (function.HasOptionalParameters()) { 486 if (function.HasOptionalParameters()) {
468 TRACE_INLINING(OS::Print(" adjusting for optional parameters\n")); 487 TRACE_INLINING(OS::Print(" adjusting for optional parameters\n"));
469 AdjustForOptionalParameters(*parsed_function, 488 AdjustForOptionalParameters(*parsed_function,
470 argument_names, 489 argument_names,
471 arguments, 490 arguments,
472 &param_stubs, 491 param_stubs,
473 callee_graph); 492 callee_graph);
474 // Add a bogus parameter at the end for the (unused) arguments 493 // Add a bogus parameter at the end for the (unused) arguments
475 // descriptor slot. The parser allocates an extra slot between 494 // descriptor slot. The parser allocates an extra slot between
476 // locals and parameters to hold the arguments descriptor in case it 495 // locals and parameters to hold the arguments descriptor in case it
477 // escapes. We currently bailout if there are argument test 496 // escapes. We currently bailout if there are argument test
478 // expressions or escaping variables so this parameter and the stack 497 // expressions or escaping variables so this parameter and the stack
479 // slot are not used. 498 // slot are not used.
480 if (parsed_function->GetSavedArgumentsDescriptorVar() != NULL) { 499 if (parsed_function->GetSavedArgumentsDescriptorVar() != NULL) {
481 param_stubs.Add(new ParameterInstr( 500 param_stubs->Add(new ParameterInstr(
482 function.NumParameters(), callee_graph->graph_entry())); 501 function.NumParameters(), callee_graph->graph_entry()));
483 } 502 }
484 } 503 }
485 504
486 // After treating optional parameters the actual/formal count must match. 505 // After treating optional parameters the actual/formal count must match.
487 ASSERT(arguments->length() == function.NumParameters()); 506 ASSERT(arguments->length() == function.NumParameters());
488 ASSERT(param_stubs.length() == callee_graph->parameter_count()); 507 ASSERT(param_stubs->length() == callee_graph->parameter_count());
489 508
490 { 509 {
491 TimerScope timer(FLAG_compiler_stats, 510 TimerScope timer(FLAG_compiler_stats,
492 &CompilerStats::graphinliner_ssa_timer, 511 &CompilerStats::graphinliner_ssa_timer,
493 isolate); 512 isolate);
494 // Compute SSA on the callee graph, catching bailouts. 513 // Compute SSA on the callee graph, catching bailouts.
495 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(), 514 callee_graph->ComputeSSA(caller_graph_->max_virtual_register_number(),
496 &param_stubs); 515 param_stubs);
497 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 516 DEBUG_ASSERT(callee_graph->VerifyUseLists());
498 } 517 }
499 518
500 { 519 {
501 TimerScope timer(FLAG_compiler_stats, 520 TimerScope timer(FLAG_compiler_stats,
502 &CompilerStats::graphinliner_opt_timer, 521 &CompilerStats::graphinliner_opt_timer,
503 isolate); 522 isolate);
504 // TODO(zerny): Do more optimization passes on the callee graph. 523 // TODO(zerny): Do more optimization passes on the callee graph.
505 FlowGraphOptimizer optimizer(callee_graph, guarded_fields_); 524 FlowGraphOptimizer optimizer(callee_graph, guarded_fields_);
506 optimizer.ApplyICData(); 525 optimizer.ApplyICData();
507 DEBUG_ASSERT(callee_graph->VerifyUseLists()); 526 DEBUG_ASSERT(callee_graph->VerifyUseLists());
508 } 527 }
509 528
510 if (FLAG_trace_inlining && 529 if (FLAG_trace_inlining &&
511 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) { 530 (FLAG_print_flow_graph || FLAG_print_flow_graph_optimized)) {
512 OS::Print("Callee graph for inlining %s\n", 531 OS::Print("Callee graph for inlining %s\n",
513 function.ToFullyQualifiedCString()); 532 function.ToFullyQualifiedCString());
514 FlowGraphPrinter printer(*callee_graph); 533 FlowGraphPrinter printer(*callee_graph);
515 printer.PrintBlocks(); 534 printer.PrintBlocks();
516 } 535 }
517 536
518 // Collect information about the call site and caller graph. 537 // Collect information about the call site and caller graph.
519 // TODO(zerny): Do this after CP and dead code elimination. 538 // TODO(zerny): Do this after CP and dead code elimination.
520 intptr_t constants_count = 0; 539 intptr_t constants_count = 0;
521 for (intptr_t i = 0; i < param_stubs.length(); ++i) { 540 for (intptr_t i = 0; i < param_stubs->length(); ++i) {
522 if (param_stubs[i]->IsConstant()) ++constants_count; 541 if ((*param_stubs)[i]->IsConstant()) ++constants_count;
523 } 542 }
524 GraphInfoCollector info; 543 GraphInfoCollector info;
525 info.Collect(*callee_graph); 544 info.Collect(*callee_graph);
526 const intptr_t size = info.instruction_count(); 545 const intptr_t size = info.instruction_count();
527 546
528 function.set_optimized_instruction_count(size); 547 function.set_optimized_instruction_count(size);
529 function.set_optimized_call_site_count(info.call_site_count()); 548 function.set_optimized_call_site_count(info.call_site_count());
530 549
531 // Use heuristics do decide if this call should be inlined. 550 // Use heuristics do decide if this call should be inlined.
532 if (!ShouldWeInline(size, 551 if (!ShouldWeInline(size,
(...skipping 16 matching lines...) Expand all
549 info.call_site_count(), 568 info.call_site_count(),
550 constants_count)); 569 constants_count));
551 return false; 570 return false;
552 } 571 }
553 572
554 // If depth is less or equal to threshold recursively add call sites. 573 // If depth is less or equal to threshold recursively add call sites.
555 if (inlining_depth_ < FLAG_inlining_depth_threshold) { 574 if (inlining_depth_ < FLAG_inlining_depth_threshold) {
556 collected_call_sites_->FindCallSites(callee_graph); 575 collected_call_sites_->FindCallSites(callee_graph);
557 } 576 }
558 577
559 {
560 TimerScope timer(FLAG_compiler_stats,
561 &CompilerStats::graphinliner_subst_timer,
562 isolate);
563
564 // Plug result in the caller graph.
565 inlining_context.ReplaceCall(callee_graph);
566
567 // Replace each stub with the actual argument or the caller's constant.
568 // Nulls denote optional parameters for which no actual was given.
569 for (intptr_t i = 0; i < arguments->length(); ++i) {
570 Definition* stub = param_stubs[i];
571 Value* actual = (*arguments)[i];
572 if (actual != NULL) stub->ReplaceUsesWith(actual->definition());
573 }
574
575 // Remove push arguments of the call.
576 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
577 PushArgumentInstr* push = call->PushArgumentAt(i);
578 push->ReplaceUsesWith(push->value()->definition());
579 push->RemoveFromGraph();
580 }
581
582 // Replace remaining constants with uses by constants in the caller's
583 // initial definitions.
584 GrowableArray<Definition*>* defns =
585 callee_graph->graph_entry()->initial_definitions();
586 for (intptr_t i = 0; i < defns->length(); ++i) {
587 ConstantInstr* constant = (*defns)[i]->AsConstant();
588 if ((constant != NULL) && constant->HasUses()) {
589 constant->ReplaceUsesWith(
590 caller_graph_->AddConstantToInitialDefinitions(
591 constant->value()));
592 }
593 }
594 }
595
596 TRACE_INLINING(OS::Print(" Success\n"));
597
598 // Add the function to the cache. 578 // Add the function to the cache.
599 if (!in_cache) function_cache_.Add(parsed_function); 579 if (!in_cache) function_cache_.Add(parsed_function);
600 580
601 // Check that inlining maintains use lists.
602 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists());
603
604 // Build succeeded so we restore the bailout jump. 581 // Build succeeded so we restore the bailout jump.
605 inlined_ = true; 582 inlined_ = true;
606 inlined_size_ += size; 583 inlined_size_ += size;
607 isolate->set_long_jump_base(base); 584 isolate->set_long_jump_base(base);
608 isolate->set_deopt_id(prev_deopt_id); 585 isolate->set_deopt_id(prev_deopt_id);
609 isolate->set_ic_data_array(prev_ic_data.raw()); 586 isolate->set_ic_data_array(prev_ic_data.raw());
587
588 call_data->callee_graph = callee_graph;
589 call_data->parameter_stubs = param_stubs;
590 call_data->exit_collector = exit_collector;
591 TRACE_INLINING(OS::Print(" Success\n"));
610 return true; 592 return true;
611 } else { 593 } else {
612 Error& error = Error::Handle(); 594 Error& error = Error::Handle();
613 error = isolate->object_store()->sticky_error(); 595 error = isolate->object_store()->sticky_error();
614 isolate->object_store()->clear_sticky_error(); 596 isolate->object_store()->clear_sticky_error();
615 isolate->set_long_jump_base(base); 597 isolate->set_long_jump_base(base);
616 isolate->set_deopt_id(prev_deopt_id); 598 isolate->set_deopt_id(prev_deopt_id);
617 isolate->set_ic_data_array(prev_ic_data.raw()); 599 isolate->set_ic_data_array(prev_ic_data.raw());
618 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); 600 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString()));
619 return false; 601 return false;
620 } 602 }
621 } 603 }
622 604
605 void InlineCall(InlinedCallData* call_data) {
srdjan 2013/04/16 16:51:17 call_data is read only in this function, you could
tfarina 2013/04/23 02:05:27 I have addressed this here: https://codereview.chr
606 TimerScope timer(FLAG_compiler_stats,
607 &CompilerStats::graphinliner_subst_timer,
608 Isolate::Current());
609
610 // Plug result in the caller graph.
611 FlowGraph* callee_graph = call_data->callee_graph;
612 InlineExitCollector* exit_collector = call_data->exit_collector;
613 exit_collector->PrepareGraphs(callee_graph);
614 exit_collector->ReplaceCall(callee_graph->graph_entry()->normal_entry());
615
616 // Replace each stub with the actual argument or the caller's constant.
617 // Nulls denote optional parameters for which no actual was given.
618 GrowableArray<Value*>* arguments = call_data->arguments;
619 for (intptr_t i = 0; i < arguments->length(); ++i) {
620 Definition* stub = (*call_data->parameter_stubs)[i];
621 Value* actual = (*arguments)[i];
622 if (actual != NULL) stub->ReplaceUsesWith(actual->definition());
623 }
624
625 // Remove push arguments of the call.
626 Definition* call = call_data->call;
627 for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
628 PushArgumentInstr* push = call->PushArgumentAt(i);
629 push->ReplaceUsesWith(push->value()->definition());
630 push->RemoveFromGraph();
631 }
632
633 // Replace remaining constants with uses by constants in the caller's
634 // initial definitions.
635 GrowableArray<Definition*>* defns =
636 callee_graph->graph_entry()->initial_definitions();
637 for (intptr_t i = 0; i < defns->length(); ++i) {
638 ConstantInstr* constant = (*defns)[i]->AsConstant();
639 if ((constant != NULL) && constant->HasUses()) {
640 constant->ReplaceUsesWith(
641 caller_graph_->AddConstantToInitialDefinitions(
642 constant->value()));
643 }
644 }
645
646 // Check that inlining maintains use lists.
647 DEBUG_ASSERT(!FLAG_verify_compiler || caller_graph_->VerifyUseLists());
648 }
649
623 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) { 650 static intptr_t CountConstants(const GrowableArray<Value*>& arguments) {
624 intptr_t count = 0; 651 intptr_t count = 0;
625 for (intptr_t i = 0; i < arguments.length(); i++) { 652 for (intptr_t i = 0; i < arguments.length(); i++) {
626 if (arguments[i]->BindsToConstant()) count++; 653 if (arguments[i]->BindsToConstant()) count++;
627 } 654 }
628 return count; 655 return count;
629 } 656 }
630 657
631 // Parse a function reusing the cache if possible. 658 // Parse a function reusing the cache if possible.
632 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) { 659 ParsedFunction* GetParsedFunction(const Function& function, bool* in_cache) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 if ((call->ArgumentCount() == 2) && 692 if ((call->ArgumentCount() == 2) &&
666 (!call->PushArgumentAt(1)->value()->BindsToConstant())) { 693 (!call->PushArgumentAt(1)->value()->BindsToConstant())) {
667 // Do not inline since a non-constant argument was passed. 694 // Do not inline since a non-constant argument was passed.
668 continue; 695 continue;
669 } 696 }
670 } 697 }
671 GrowableArray<Value*> arguments(call->ArgumentCount()); 698 GrowableArray<Value*> arguments(call->ArgumentCount());
672 for (int i = 0; i < call->ArgumentCount(); ++i) { 699 for (int i = 0; i < call->ArgumentCount(); ++i) {
673 arguments.Add(call->PushArgumentAt(i)->value()); 700 arguments.Add(call->PushArgumentAt(i)->value());
674 } 701 }
675 TryInlining(call->function(), call->argument_names(), &arguments, call); 702 InlinedCallData call_data(call, &arguments);
703 if (TryInlining(call->function(), call->argument_names(), &call_data)) {
704 InlineCall(&call_data);
705 }
676 } 706 }
677 } 707 }
678 708
679 void InlineClosureCalls() { 709 void InlineClosureCalls() {
680 const GrowableArray<ClosureCallInstr*>& calls = 710 const GrowableArray<ClosureCallInstr*>& calls =
681 inlining_call_sites_->closure_calls(); 711 inlining_call_sites_->closure_calls();
682 TRACE_INLINING(OS::Print(" Closure Calls (%d)\n", calls.length())); 712 TRACE_INLINING(OS::Print(" Closure Calls (%d)\n", calls.length()));
683 for (intptr_t i = 0; i < calls.length(); ++i) { 713 for (intptr_t i = 0; i < calls.length(); ++i) {
684 ClosureCallInstr* call = calls[i]; 714 ClosureCallInstr* call = calls[i];
685 // Find the closure of the callee. 715 // Find the closure of the callee.
686 ASSERT(call->ArgumentCount() > 0); 716 ASSERT(call->ArgumentCount() > 0);
687 const CreateClosureInstr* closure = 717 const CreateClosureInstr* closure =
688 call->ArgumentAt(0)->AsCreateClosure(); 718 call->ArgumentAt(0)->AsCreateClosure();
689 if (closure == NULL) { 719 if (closure == NULL) {
690 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n")); 720 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n"));
691 continue; 721 continue;
692 } 722 }
693 GrowableArray<Value*> arguments(call->ArgumentCount()); 723 GrowableArray<Value*> arguments(call->ArgumentCount());
694 for (int i = 0; i < call->ArgumentCount(); ++i) { 724 for (int i = 0; i < call->ArgumentCount(); ++i) {
695 arguments.Add(call->PushArgumentAt(i)->value()); 725 arguments.Add(call->PushArgumentAt(i)->value());
696 } 726 }
697 TryInlining(closure->function(), 727 InlinedCallData call_data(call, &arguments);
698 call->argument_names(), 728 if (TryInlining(closure->function(),
699 &arguments, 729 call->argument_names(),
700 call); 730 &call_data)) {
731 InlineCall(&call_data);
732 }
701 } 733 }
702 } 734 }
703 735
704 void InlineInstanceCalls() { 736 void InlineInstanceCalls() {
705 const GrowableArray<CallSites::InstanceCallInfo>& call_info = 737 const GrowableArray<CallSites::InstanceCallInfo>& call_info =
706 inlining_call_sites_->instance_calls(); 738 inlining_call_sites_->instance_calls();
707 TRACE_INLINING(OS::Print(" Polymorphic Instance Calls (%d)\n", 739 TRACE_INLINING(OS::Print(" Polymorphic Instance Calls (%d)\n",
708 call_info.length())); 740 call_info.length()));
709 for (intptr_t i = 0; i < call_info.length(); ++i) { 741 for (intptr_t i = 0; i < call_info.length(); ++i) {
710 PolymorphicInstanceCallInstr* instr = call_info[i].call; 742 PolymorphicInstanceCallInstr* call = call_info[i].call;
711 const ICData& ic_data = instr->ic_data(); 743 const ICData& ic_data = call->ic_data();
712 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); 744 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0));
713 if (instr->with_checks()) { 745 if (call->with_checks()) {
714 TRACE_INLINING(OS::Print( 746 TRACE_INLINING(OS::Print(
715 " => %s (deopt count %d)\n Bailout: %"Pd" checks\n", 747 " => %s (deopt count %d)\n Bailout: %"Pd" checks\n",
716 target.ToCString(), 748 target.ToCString(),
717 target.deoptimization_counter(), 749 target.deoptimization_counter(),
718 ic_data.NumberOfChecks())); 750 ic_data.NumberOfChecks()));
719 continue; 751 continue;
720 } 752 }
721 if ((call_info[i].ratio * 100) < FLAG_inlining_hotness) { 753 if ((call_info[i].ratio * 100) < FLAG_inlining_hotness) {
722 TRACE_INLINING(OS::Print( 754 TRACE_INLINING(OS::Print(
723 " => %s (deopt count %d)\n Bailout: cold %f\n", 755 " => %s (deopt count %d)\n Bailout: cold %f\n",
724 target.ToCString(), 756 target.ToCString(),
725 target.deoptimization_counter(), 757 target.deoptimization_counter(),
726 call_info[i].ratio)); 758 call_info[i].ratio));
727 continue; 759 continue;
728 } 760 }
729 GrowableArray<Value*> arguments(instr->ArgumentCount()); 761 GrowableArray<Value*> arguments(call->ArgumentCount());
730 for (int arg_i = 0; arg_i < instr->ArgumentCount(); ++arg_i) { 762 for (int arg_i = 0; arg_i < call->ArgumentCount(); ++arg_i) {
731 arguments.Add(instr->PushArgumentAt(arg_i)->value()); 763 arguments.Add(call->PushArgumentAt(arg_i)->value());
732 } 764 }
733 TryInlining(target, 765 InlinedCallData call_data(call, &arguments);
734 instr->instance_call()->argument_names(), 766 if (TryInlining(target,
735 &arguments, 767 call->instance_call()->argument_names(),
736 instr); 768 &call_data)) {
769 InlineCall(&call_data);
770 }
737 } 771 }
738 } 772 }
739 773
740 void AdjustForOptionalParameters(const ParsedFunction& parsed_function, 774 void AdjustForOptionalParameters(const ParsedFunction& parsed_function,
741 const Array& argument_names, 775 const Array& argument_names,
742 GrowableArray<Value*>* arguments, 776 GrowableArray<Value*>* arguments,
743 GrowableArray<Definition*>* param_stubs, 777 ZoneGrowableArray<Definition*>* param_stubs,
744 FlowGraph* callee_graph) { 778 FlowGraph* callee_graph) {
745 const Function& function = parsed_function.function(); 779 const Function& function = parsed_function.function();
746 // The language and this code does not support both optional positional 780 // The language and this code does not support both optional positional
747 // and optional named parameters for the same function. 781 // and optional named parameters for the same function.
748 ASSERT(!function.HasOptionalPositionalParameters() || 782 ASSERT(!function.HasOptionalPositionalParameters() ||
749 !function.HasOptionalNamedParameters()); 783 !function.HasOptionalNamedParameters());
750 784
751 intptr_t arg_count = arguments->length(); 785 intptr_t arg_count = arguments->length();
752 intptr_t param_count = function.NumParameters(); 786 intptr_t param_count = function.NumParameters();
753 intptr_t fixed_param_count = function.num_fixed_parameters(); 787 intptr_t fixed_param_count = function.num_fixed_parameters();
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 OS::Print("After Inlining of %s\n", flow_graph_-> 921 OS::Print("After Inlining of %s\n", flow_graph_->
888 parsed_function().function().ToFullyQualifiedCString()); 922 parsed_function().function().ToFullyQualifiedCString());
889 FlowGraphPrinter printer(*flow_graph_); 923 FlowGraphPrinter printer(*flow_graph_);
890 printer.PrintBlocks(); 924 printer.PrintBlocks();
891 } 925 }
892 } 926 }
893 } 927 }
894 } 928 }
895 929
896 } // namespace dart 930 } // 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