| OLD | NEW |
| 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 447 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 } | 458 } |
| 459 | 459 |
| 460 // Abort if the callee has an intrinsic translation. | 460 // Abort if the callee has an intrinsic translation. |
| 461 if (Intrinsifier::CanIntrinsify(function)) { | 461 if (Intrinsifier::CanIntrinsify(function)) { |
| 462 function.set_is_inlinable(false); | 462 function.set_is_inlinable(false); |
| 463 TRACE_INLINING(OS::Print(" Bailout: can intrinsify\n")); | 463 TRACE_INLINING(OS::Print(" Bailout: can intrinsify\n")); |
| 464 return false; | 464 return false; |
| 465 } | 465 } |
| 466 | 466 |
| 467 Isolate* isolate = Isolate::Current(); | 467 Isolate* isolate = Isolate::Current(); |
| 468 // Save and clear IC data. | |
| 469 const Array& prev_ic_data = Array::Handle(isolate->ic_data_array()); | |
| 470 isolate->set_ic_data_array(Array::null()); | |
| 471 // Save and clear deopt id. | 468 // Save and clear deopt id. |
| 472 const intptr_t prev_deopt_id = isolate->deopt_id(); | 469 const intptr_t prev_deopt_id = isolate->deopt_id(); |
| 473 isolate->set_deopt_id(0); | 470 isolate->set_deopt_id(0); |
| 474 // Install bailout jump. | 471 // Install bailout jump. |
| 475 LongJump* base = isolate->long_jump_base(); | 472 LongJump* base = isolate->long_jump_base(); |
| 476 LongJump jump; | 473 LongJump jump; |
| 477 isolate->set_long_jump_base(&jump); | 474 isolate->set_long_jump_base(&jump); |
| 478 if (setjmp(*jump.Set()) == 0) { | 475 if (setjmp(*jump.Set()) == 0) { |
| 479 // Parse the callee function. | 476 // Parse the callee function. |
| 480 bool in_cache; | 477 bool in_cache; |
| 481 ParsedFunction* parsed_function; | 478 ParsedFunction* parsed_function; |
| 482 { | 479 { |
| 483 TimerScope timer(FLAG_compiler_stats, | 480 TimerScope timer(FLAG_compiler_stats, |
| 484 &CompilerStats::graphinliner_parse_timer, | 481 &CompilerStats::graphinliner_parse_timer, |
| 485 isolate); | 482 isolate); |
| 486 parsed_function = GetParsedFunction(function, &in_cache); | 483 parsed_function = GetParsedFunction(function, &in_cache); |
| 487 } | 484 } |
| 488 | 485 |
| 489 // Load IC data for the callee. | 486 // Load IC data for the callee. |
| 487 Array& ic_data_array = Array::Handle(); |
| 490 if (function.HasCode()) { | 488 if (function.HasCode()) { |
| 491 const Code& unoptimized_code = | 489 const Code& unoptimized_code = |
| 492 Code::Handle(function.unoptimized_code()); | 490 Code::Handle(function.unoptimized_code()); |
| 493 isolate->set_ic_data_array(unoptimized_code.ExtractTypeFeedbackArray()); | 491 ic_data_array = unoptimized_code.ExtractTypeFeedbackArray(); |
| 494 } | 492 } |
| 495 | 493 |
| 496 // Build the callee graph. | 494 // Build the callee graph. |
| 497 InlineExitCollector* exit_collector = | 495 InlineExitCollector* exit_collector = |
| 498 new InlineExitCollector(caller_graph_, call); | 496 new InlineExitCollector(caller_graph_, call); |
| 499 FlowGraphBuilder builder(*parsed_function, exit_collector); | 497 FlowGraphBuilder builder(*parsed_function, ic_data_array, exit_collector); |
| 500 builder.SetInitialBlockId(caller_graph_->max_block_id()); | 498 builder.SetInitialBlockId(caller_graph_->max_block_id()); |
| 501 FlowGraph* callee_graph; | 499 FlowGraph* callee_graph; |
| 502 { | 500 { |
| 503 TimerScope timer(FLAG_compiler_stats, | 501 TimerScope timer(FLAG_compiler_stats, |
| 504 &CompilerStats::graphinliner_build_timer, | 502 &CompilerStats::graphinliner_build_timer, |
| 505 isolate); | 503 isolate); |
| 506 callee_graph = builder.BuildGraph(); | 504 callee_graph = builder.BuildGraph(); |
| 507 } | 505 } |
| 508 | 506 |
| 509 // The parameter stubs are a copy of the actual arguments providing | 507 // The parameter stubs are a copy of the actual arguments providing |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 info.call_site_count(), | 588 info.call_site_count(), |
| 591 constants_count)) { | 589 constants_count)) { |
| 592 // If size is larger than all thresholds, don't consider it again. | 590 // If size is larger than all thresholds, don't consider it again. |
| 593 if ((size > FLAG_inlining_size_threshold) && | 591 if ((size > FLAG_inlining_size_threshold) && |
| 594 (size > FLAG_inlining_callee_call_sites_threshold) && | 592 (size > FLAG_inlining_callee_call_sites_threshold) && |
| 595 (size > FLAG_inlining_constant_arguments_size_threshold)) { | 593 (size > FLAG_inlining_constant_arguments_size_threshold)) { |
| 596 function.set_is_inlinable(false); | 594 function.set_is_inlinable(false); |
| 597 } | 595 } |
| 598 isolate->set_long_jump_base(base); | 596 isolate->set_long_jump_base(base); |
| 599 isolate->set_deopt_id(prev_deopt_id); | 597 isolate->set_deopt_id(prev_deopt_id); |
| 600 isolate->set_ic_data_array(prev_ic_data.raw()); | |
| 601 TRACE_INLINING(OS::Print(" Bailout: heuristics with " | 598 TRACE_INLINING(OS::Print(" Bailout: heuristics with " |
| 602 "code size: %"Pd", " | 599 "code size: %"Pd", " |
| 603 "call sites: %"Pd", " | 600 "call sites: %"Pd", " |
| 604 "const args: %"Pd"\n", | 601 "const args: %"Pd"\n", |
| 605 size, | 602 size, |
| 606 info.call_site_count(), | 603 info.call_site_count(), |
| 607 constants_count)); | 604 constants_count)); |
| 608 return false; | 605 return false; |
| 609 } | 606 } |
| 610 | 607 |
| 611 // If depth is less or equal to threshold recursively add call sites. | 608 // If depth is less or equal to threshold recursively add call sites. |
| 612 if (inlining_depth_ < FLAG_inlining_depth_threshold) { | 609 if (inlining_depth_ < FLAG_inlining_depth_threshold) { |
| 613 collected_call_sites_->FindCallSites(callee_graph); | 610 collected_call_sites_->FindCallSites(callee_graph); |
| 614 } | 611 } |
| 615 | 612 |
| 616 // Add the function to the cache. | 613 // Add the function to the cache. |
| 617 if (!in_cache) function_cache_.Add(parsed_function); | 614 if (!in_cache) function_cache_.Add(parsed_function); |
| 618 | 615 |
| 619 // Build succeeded so we restore the bailout jump. | 616 // Build succeeded so we restore the bailout jump. |
| 620 inlined_ = true; | 617 inlined_ = true; |
| 621 inlined_size_ += size; | 618 inlined_size_ += size; |
| 622 isolate->set_long_jump_base(base); | 619 isolate->set_long_jump_base(base); |
| 623 isolate->set_deopt_id(prev_deopt_id); | 620 isolate->set_deopt_id(prev_deopt_id); |
| 624 isolate->set_ic_data_array(prev_ic_data.raw()); | |
| 625 | 621 |
| 626 call_data->callee_graph = callee_graph; | 622 call_data->callee_graph = callee_graph; |
| 627 call_data->parameter_stubs = param_stubs; | 623 call_data->parameter_stubs = param_stubs; |
| 628 call_data->exit_collector = exit_collector; | 624 call_data->exit_collector = exit_collector; |
| 629 TRACE_INLINING(OS::Print(" Success\n")); | 625 TRACE_INLINING(OS::Print(" Success\n")); |
| 630 return true; | 626 return true; |
| 631 } else { | 627 } else { |
| 632 Error& error = Error::Handle(); | 628 Error& error = Error::Handle(); |
| 633 error = isolate->object_store()->sticky_error(); | 629 error = isolate->object_store()->sticky_error(); |
| 634 isolate->object_store()->clear_sticky_error(); | 630 isolate->object_store()->clear_sticky_error(); |
| 635 isolate->set_long_jump_base(base); | 631 isolate->set_long_jump_base(base); |
| 636 isolate->set_deopt_id(prev_deopt_id); | 632 isolate->set_deopt_id(prev_deopt_id); |
| 637 isolate->set_ic_data_array(prev_ic_data.raw()); | |
| 638 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); | 633 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); |
| 639 return false; | 634 return false; |
| 640 } | 635 } |
| 641 } | 636 } |
| 642 | 637 |
| 643 private: | 638 private: |
| 644 void InlineCall(InlinedCallData* call_data) { | 639 void InlineCall(InlinedCallData* call_data) { |
| 645 TimerScope timer(FLAG_compiler_stats, | 640 TimerScope timer(FLAG_compiler_stats, |
| 646 &CompilerStats::graphinliner_subst_timer, | 641 &CompilerStats::graphinliner_subst_timer, |
| 647 Isolate::Current()); | 642 Isolate::Current()); |
| (...skipping 692 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1340 OS::Print("After Inlining of %s\n", flow_graph_-> | 1335 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1341 parsed_function().function().ToFullyQualifiedCString()); | 1336 parsed_function().function().ToFullyQualifiedCString()); |
| 1342 FlowGraphPrinter printer(*flow_graph_); | 1337 FlowGraphPrinter printer(*flow_graph_); |
| 1343 printer.PrintBlocks(); | 1338 printer.PrintBlocks(); |
| 1344 } | 1339 } |
| 1345 } | 1340 } |
| 1346 } | 1341 } |
| 1347 } | 1342 } |
| 1348 | 1343 |
| 1349 } // namespace dart | 1344 } // namespace dart |
| OLD | NEW |