| 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/block_scheduler.h" | 7 #include "vm/block_scheduler.h" |
| 8 #include "vm/compiler.h" | 8 #include "vm/compiler.h" |
| 9 #include "vm/flags.h" | 9 #include "vm/flags.h" |
| 10 #include "vm/flow_graph.h" | 10 #include "vm/flow_graph.h" |
| (...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 475 function.set_is_inlinable(false); | 475 function.set_is_inlinable(false); |
| 476 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); | 476 TRACE_INLINING(OS::Print(" Bailout: recursive function\n")); |
| 477 return false; | 477 return false; |
| 478 } | 478 } |
| 479 | 479 |
| 480 Isolate* isolate = Isolate::Current(); | 480 Isolate* isolate = Isolate::Current(); |
| 481 // Save and clear deopt id. | 481 // Save and clear deopt id. |
| 482 const intptr_t prev_deopt_id = isolate->deopt_id(); | 482 const intptr_t prev_deopt_id = isolate->deopt_id(); |
| 483 isolate->set_deopt_id(0); | 483 isolate->set_deopt_id(0); |
| 484 // Install bailout jump. | 484 // Install bailout jump. |
| 485 LongJump* base = isolate->long_jump_base(); | 485 LongJumpScope jump; |
| 486 LongJump jump; | |
| 487 isolate->set_long_jump_base(&jump); | |
| 488 if (setjmp(*jump.Set()) == 0) { | 486 if (setjmp(*jump.Set()) == 0) { |
| 489 // Parse the callee function. | 487 // Parse the callee function. |
| 490 bool in_cache; | 488 bool in_cache; |
| 491 ParsedFunction* parsed_function; | 489 ParsedFunction* parsed_function; |
| 492 { | 490 { |
| 493 TimerScope timer(FLAG_compiler_stats, | 491 TimerScope timer(FLAG_compiler_stats, |
| 494 &CompilerStats::graphinliner_parse_timer, | 492 &CompilerStats::graphinliner_parse_timer, |
| 495 isolate); | 493 isolate); |
| 496 parsed_function = GetParsedFunction(function, &in_cache); | 494 parsed_function = GetParsedFunction(function, &in_cache); |
| 497 } | 495 } |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 // parameters. | 535 // parameters. |
| 538 if (function.HasOptionalParameters()) { | 536 if (function.HasOptionalParameters()) { |
| 539 TRACE_INLINING(OS::Print(" adjusting for optional parameters\n")); | 537 TRACE_INLINING(OS::Print(" adjusting for optional parameters\n")); |
| 540 if (!AdjustForOptionalParameters(*parsed_function, | 538 if (!AdjustForOptionalParameters(*parsed_function, |
| 541 argument_names, | 539 argument_names, |
| 542 arguments, | 540 arguments, |
| 543 param_stubs, | 541 param_stubs, |
| 544 callee_graph)) { | 542 callee_graph)) { |
| 545 function.set_is_inlinable(false); | 543 function.set_is_inlinable(false); |
| 546 TRACE_INLINING(OS::Print(" Bailout: optional arg mismatch\n")); | 544 TRACE_INLINING(OS::Print(" Bailout: optional arg mismatch\n")); |
| 547 isolate->set_long_jump_base(base); | |
| 548 return false; | 545 return false; |
| 549 } | 546 } |
| 550 } | 547 } |
| 551 | 548 |
| 552 // After treating optional parameters the actual/formal count must match. | 549 // After treating optional parameters the actual/formal count must match. |
| 553 ASSERT(arguments->length() == function.NumParameters()); | 550 ASSERT(arguments->length() == function.NumParameters()); |
| 554 ASSERT(param_stubs->length() == callee_graph->parameter_count()); | 551 ASSERT(param_stubs->length() == callee_graph->parameter_count()); |
| 555 | 552 |
| 556 BlockScheduler block_scheduler(callee_graph); | 553 BlockScheduler block_scheduler(callee_graph); |
| 557 block_scheduler.AssignEdgeWeights(); | 554 block_scheduler.AssignEdgeWeights(); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 function.set_optimized_call_site_count(call_site_count); | 601 function.set_optimized_call_site_count(call_site_count); |
| 605 | 602 |
| 606 // Use heuristics do decide if this call should be inlined. | 603 // Use heuristics do decide if this call should be inlined. |
| 607 if (!ShouldWeInline(function, size, call_site_count, constants_count)) { | 604 if (!ShouldWeInline(function, size, call_site_count, constants_count)) { |
| 608 // If size is larger than all thresholds, don't consider it again. | 605 // If size is larger than all thresholds, don't consider it again. |
| 609 if ((size > FLAG_inlining_size_threshold) && | 606 if ((size > FLAG_inlining_size_threshold) && |
| 610 (call_site_count > FLAG_inlining_callee_call_sites_threshold) && | 607 (call_site_count > FLAG_inlining_callee_call_sites_threshold) && |
| 611 (size > FLAG_inlining_constant_arguments_size_threshold)) { | 608 (size > FLAG_inlining_constant_arguments_size_threshold)) { |
| 612 function.set_is_inlinable(false); | 609 function.set_is_inlinable(false); |
| 613 } | 610 } |
| 614 isolate->set_long_jump_base(base); | |
| 615 isolate->set_deopt_id(prev_deopt_id); | 611 isolate->set_deopt_id(prev_deopt_id); |
| 616 TRACE_INLINING(OS::Print(" Bailout: heuristics with " | 612 TRACE_INLINING(OS::Print(" Bailout: heuristics with " |
| 617 "code size: %" Pd ", " | 613 "code size: %" Pd ", " |
| 618 "call sites: %" Pd ", " | 614 "call sites: %" Pd ", " |
| 619 "const args: %" Pd "\n", | 615 "const args: %" Pd "\n", |
| 620 size, | 616 size, |
| 621 call_site_count, | 617 call_site_count, |
| 622 constants_count)); | 618 constants_count)); |
| 623 return false; | 619 return false; |
| 624 } | 620 } |
| 625 | 621 |
| 626 collected_call_sites_->FindCallSites(callee_graph, inlining_depth_); | 622 collected_call_sites_->FindCallSites(callee_graph, inlining_depth_); |
| 627 | 623 |
| 628 // Add the function to the cache. | 624 // Add the function to the cache. |
| 629 if (!in_cache) { | 625 if (!in_cache) { |
| 630 function_cache_.Add(parsed_function); | 626 function_cache_.Add(parsed_function); |
| 631 } | 627 } |
| 632 | 628 |
| 633 // Build succeeded so we restore the bailout jump. | 629 // Build succeeded so we restore the bailout jump. |
| 634 inlined_ = true; | 630 inlined_ = true; |
| 635 inlined_size_ += size; | 631 inlined_size_ += size; |
| 636 isolate->set_long_jump_base(base); | |
| 637 isolate->set_deopt_id(prev_deopt_id); | 632 isolate->set_deopt_id(prev_deopt_id); |
| 638 | 633 |
| 639 call_data->callee_graph = callee_graph; | 634 call_data->callee_graph = callee_graph; |
| 640 call_data->parameter_stubs = param_stubs; | 635 call_data->parameter_stubs = param_stubs; |
| 641 call_data->exit_collector = exit_collector; | 636 call_data->exit_collector = exit_collector; |
| 642 | 637 |
| 643 // When inlined, we add the guarded fields of the callee to the caller's | 638 // When inlined, we add the guarded fields of the callee to the caller's |
| 644 // list of guarded fields. | 639 // list of guarded fields. |
| 645 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { | 640 for (intptr_t i = 0; i < callee_graph->guarded_fields()->length(); ++i) { |
| 646 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), | 641 FlowGraph::AddToGuardedFields(caller_graph_->guarded_fields(), |
| 647 (*callee_graph->guarded_fields())[i]); | 642 (*callee_graph->guarded_fields())[i]); |
| 648 } | 643 } |
| 649 | 644 |
| 650 // We allocate a ZoneHandle for the unoptimized code so that it cannot be | 645 // We allocate a ZoneHandle for the unoptimized code so that it cannot be |
| 651 // disconnected from its function during the rest of compilation. | 646 // disconnected from its function during the rest of compilation. |
| 652 Code::ZoneHandle(unoptimized_code.raw()); | 647 Code::ZoneHandle(unoptimized_code.raw()); |
| 653 TRACE_INLINING(OS::Print(" Success\n")); | 648 TRACE_INLINING(OS::Print(" Success\n")); |
| 654 return true; | 649 return true; |
| 655 } else { | 650 } else { |
| 656 Error& error = Error::Handle(); | 651 Error& error = Error::Handle(); |
| 657 error = isolate->object_store()->sticky_error(); | 652 error = isolate->object_store()->sticky_error(); |
| 658 isolate->object_store()->clear_sticky_error(); | 653 isolate->object_store()->clear_sticky_error(); |
| 659 isolate->set_long_jump_base(base); | |
| 660 isolate->set_deopt_id(prev_deopt_id); | 654 isolate->set_deopt_id(prev_deopt_id); |
| 661 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); | 655 TRACE_INLINING(OS::Print(" Bailout: %s\n", error.ToErrorCString())); |
| 662 return false; | 656 return false; |
| 663 } | 657 } |
| 664 } | 658 } |
| 665 | 659 |
| 666 private: | 660 private: |
| 667 friend class PolymorphicInliner; | 661 friend class PolymorphicInliner; |
| 668 | 662 |
| 669 void InlineCall(InlinedCallData* call_data) { | 663 void InlineCall(InlinedCallData* call_data) { |
| (...skipping 815 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1485 OS::Print("After Inlining of %s\n", flow_graph_-> | 1479 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1486 parsed_function().function().ToFullyQualifiedCString()); | 1480 parsed_function().function().ToFullyQualifiedCString()); |
| 1487 FlowGraphPrinter printer(*flow_graph_); | 1481 FlowGraphPrinter printer(*flow_graph_); |
| 1488 printer.PrintBlocks(); | 1482 printer.PrintBlocks(); |
| 1489 } | 1483 } |
| 1490 } | 1484 } |
| 1491 } | 1485 } |
| 1492 } | 1486 } |
| 1493 | 1487 |
| 1494 } // namespace dart | 1488 } // namespace dart |
| OLD | NEW |