Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 DEFINE_FLAG(int, inlining_in_loop_size_threshold, 80, | 29 DEFINE_FLAG(int, inlining_in_loop_size_threshold, 80, |
| 30 "Inline functions in loops that have threshold or fewer instructions"); | 30 "Inline functions in loops that have threshold or fewer instructions"); |
| 31 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1, | 31 DEFINE_FLAG(int, inlining_callee_call_sites_threshold, 1, |
| 32 "Always inline functions containing threshold or fewer calls."); | 32 "Always inline functions containing threshold or fewer calls."); |
| 33 DEFINE_FLAG(int, inlining_constant_arguments_count, 1, | 33 DEFINE_FLAG(int, inlining_constant_arguments_count, 1, |
| 34 "Inline function calls with sufficient constant arguments " | 34 "Inline function calls with sufficient constant arguments " |
| 35 "and up to the increased threshold on instructions"); | 35 "and up to the increased threshold on instructions"); |
| 36 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60, | 36 DEFINE_FLAG(int, inlining_constant_arguments_size_threshold, 60, |
| 37 "Inline function calls with sufficient constant arguments " | 37 "Inline function calls with sufficient constant arguments " |
| 38 "and up to the increased threshold on instructions"); | 38 "and up to the increased threshold on instructions"); |
| 39 DEFINE_FLAG(int, inlining_hotness, 15, | |
| 40 "Inline only hotter calls, in percents (0 .. 100); " | |
| 41 "default 20%: calls above-equal 20% of max-count are inlined."); | |
|
Vyacheslav Egorov (Google)
2012/12/17 13:16:05
comment does not match the default value.
srdjan
2012/12/17 22:46:13
Done.
| |
| 39 | 42 |
| 40 DECLARE_FLAG(bool, print_flow_graph); | 43 DECLARE_FLAG(bool, print_flow_graph); |
| 41 DECLARE_FLAG(int, deoptimization_counter_threshold); | 44 DECLARE_FLAG(int, deoptimization_counter_threshold); |
| 42 DECLARE_FLAG(bool, verify_compiler); | 45 DECLARE_FLAG(bool, verify_compiler); |
| 43 DECLARE_FLAG(bool, compiler_stats); | 46 DECLARE_FLAG(bool, compiler_stats); |
| 44 | 47 |
| 45 #define TRACE_INLINING(statement) \ | 48 #define TRACE_INLINING(statement) \ |
| 46 do { \ | 49 do { \ |
| 47 if (FLAG_trace_inlining) statement; \ | 50 if (FLAG_trace_inlining) statement; \ |
| 48 } while (false) | 51 } while (false) |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 176 | 179 |
| 177 | 180 |
| 178 // A collection of call sites to consider for inlining. | 181 // A collection of call sites to consider for inlining. |
| 179 class CallSites : public FlowGraphVisitor { | 182 class CallSites : public FlowGraphVisitor { |
| 180 public: | 183 public: |
| 181 explicit CallSites(FlowGraph* flow_graph) | 184 explicit CallSites(FlowGraph* flow_graph) |
| 182 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. | 185 : FlowGraphVisitor(flow_graph->postorder()), // We don't use this order. |
| 183 static_calls_(), | 186 static_calls_(), |
| 184 closure_calls_(), | 187 closure_calls_(), |
| 185 instance_calls_(), | 188 instance_calls_(), |
| 186 skip_static_call_deopt_ids_() { } | 189 instance_calls_caller_count_(), |
| 190 skip_static_call_deopt_ids_(), | |
| 191 caller_count_(1) { } | |
| 187 | 192 |
| 188 GrowableArray<StaticCallInstr*>* static_calls() { | 193 const GrowableArray<StaticCallInstr*>& static_calls() const { |
| 189 return &static_calls_; | 194 return static_calls_; |
| 190 } | 195 } |
| 191 | 196 |
| 192 GrowableArray<ClosureCallInstr*>* closure_calls() { | 197 const GrowableArray<ClosureCallInstr*>& closure_calls() const { |
| 193 return &closure_calls_; | 198 return closure_calls_; |
| 194 } | 199 } |
| 195 | 200 |
| 196 GrowableArray<PolymorphicInstanceCallInstr*>* instance_calls() { | 201 const GrowableArray<PolymorphicInstanceCallInstr*>& instance_calls() const { |
|
Vyacheslav Egorov (Google)
2012/12/17 13:16:05
I'd prefer that this array contained a two field s
srdjan
2012/12/17 22:46:13
Done.
| |
| 197 return &instance_calls_; | 202 return instance_calls_; |
| 203 } | |
| 204 | |
| 205 const GrowableArray<intptr_t>& instance_calls_caller_count() const { | |
| 206 return instance_calls_caller_count_; | |
| 198 } | 207 } |
| 199 | 208 |
| 200 bool HasCalls() const { | 209 bool HasCalls() const { |
| 210 ASSERT(instance_calls_.length() == instance_calls_caller_count_.length()); | |
| 201 return !(static_calls_.is_empty() && | 211 return !(static_calls_.is_empty() && |
| 202 closure_calls_.is_empty() && | 212 closure_calls_.is_empty() && |
| 203 instance_calls_.is_empty()); | 213 instance_calls_.is_empty()); |
| 204 } | 214 } |
| 205 | 215 |
| 206 void Clear() { | 216 void Clear() { |
| 207 static_calls_.Clear(); | 217 static_calls_.Clear(); |
| 208 closure_calls_.Clear(); | 218 closure_calls_.Clear(); |
| 209 instance_calls_.Clear(); | 219 instance_calls_.Clear(); |
| 220 instance_calls_caller_count_.Clear(); | |
| 210 skip_static_call_deopt_ids_.Clear(); | 221 skip_static_call_deopt_ids_.Clear(); |
| 211 } | 222 } |
| 212 | 223 |
| 213 void FindCallSites(FlowGraph* graph) { | 224 void FindCallSites(FlowGraph* graph, intptr_t caller_count) { |
| 225 const intptr_t prev_caller_count = caller_count_; | |
| 226 caller_count_ = caller_count; | |
| 214 ASSERT(graph != NULL); | 227 ASSERT(graph != NULL); |
| 215 const Function& function = graph->parsed_function().function(); | 228 const Function& function = graph->parsed_function().function(); |
| 216 ASSERT(function.HasCode()); | 229 ASSERT(function.HasCode()); |
| 217 const Code& code = Code::Handle(function.unoptimized_code()); | 230 const Code& code = Code::Handle(function.unoptimized_code()); |
| 218 skip_static_call_deopt_ids_.Clear(); | 231 skip_static_call_deopt_ids_.Clear(); |
| 219 code.ExtractUncalledStaticCallDeoptIds(&skip_static_call_deopt_ids_); | 232 code.ExtractUncalledStaticCallDeoptIds(&skip_static_call_deopt_ids_); |
| 220 for (BlockIterator block_it = graph->postorder_iterator(); | 233 for (BlockIterator block_it = graph->postorder_iterator(); |
| 221 !block_it.Done(); | 234 !block_it.Done(); |
| 222 block_it.Advance()) { | 235 block_it.Advance()) { |
| 223 for (ForwardInstructionIterator it(block_it.Current()); | 236 for (ForwardInstructionIterator it(block_it.Current()); |
| 224 !it.Done(); | 237 !it.Done(); |
| 225 it.Advance()) { | 238 it.Advance()) { |
| 226 it.Current()->Accept(this); | 239 it.Current()->Accept(this); |
| 227 } | 240 } |
| 228 } | 241 } |
| 242 caller_count_ = prev_caller_count; | |
| 229 } | 243 } |
| 230 | 244 |
| 231 void VisitClosureCall(ClosureCallInstr* call) { | 245 void VisitClosureCall(ClosureCallInstr* call) { |
| 232 closure_calls_.Add(call); | 246 closure_calls_.Add(call); |
| 233 } | 247 } |
| 234 | 248 |
| 235 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { | 249 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { |
| 236 instance_calls_.Add(call); | 250 instance_calls_.Add(call); |
| 251 instance_calls_caller_count_.Add(caller_count_); | |
| 237 } | 252 } |
| 238 | 253 |
| 239 void VisitStaticCall(StaticCallInstr* call) { | 254 void VisitStaticCall(StaticCallInstr* call) { |
| 240 if (!call->function().IsInlineable()) return; | 255 if (!call->function().IsInlineable()) return; |
| 241 const intptr_t call_deopt_id = call->deopt_id(); | 256 const intptr_t call_deopt_id = call->deopt_id(); |
| 242 for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) { | 257 for (intptr_t i = 0; i < skip_static_call_deopt_ids_.length(); i++) { |
| 243 if (call_deopt_id == skip_static_call_deopt_ids_[i]) { | 258 if (call_deopt_id == skip_static_call_deopt_ids_[i]) { |
| 244 // Do not inline this call. | 259 // Do not inline this call. |
| 245 return; | 260 return; |
| 246 } | 261 } |
| 247 } | 262 } |
| 248 static_calls_.Add(call); | 263 static_calls_.Add(call); |
| 249 } | 264 } |
| 250 | 265 |
| 251 private: | 266 private: |
| 252 GrowableArray<StaticCallInstr*> static_calls_; | 267 GrowableArray<StaticCallInstr*> static_calls_; |
| 253 GrowableArray<ClosureCallInstr*> closure_calls_; | 268 GrowableArray<ClosureCallInstr*> closure_calls_; |
| 254 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; | 269 GrowableArray<PolymorphicInstanceCallInstr*> instance_calls_; |
| 270 GrowableArray<intptr_t> instance_calls_caller_count_; | |
| 255 GrowableArray<intptr_t> skip_static_call_deopt_ids_; | 271 GrowableArray<intptr_t> skip_static_call_deopt_ids_; |
| 272 intptr_t caller_count_; | |
| 256 | 273 |
| 257 DISALLOW_COPY_AND_ASSIGN(CallSites); | 274 DISALLOW_COPY_AND_ASSIGN(CallSites); |
| 258 }; | 275 }; |
| 259 | 276 |
| 260 | 277 |
| 261 class CallSiteInliner : public ValueObject { | 278 class CallSiteInliner : public ValueObject { |
| 262 public: | 279 public: |
| 263 explicit CallSiteInliner(FlowGraph* flow_graph) | 280 explicit CallSiteInliner(FlowGraph* flow_graph) |
| 264 : caller_graph_(flow_graph), | 281 : caller_graph_(flow_graph), |
| 265 inlined_(false), | 282 inlined_(false), |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 void InlineCalls() { | 314 void InlineCalls() { |
| 298 // If inlining depth is less then one abort. | 315 // If inlining depth is less then one abort. |
| 299 if (FLAG_inlining_depth_threshold < 1) return; | 316 if (FLAG_inlining_depth_threshold < 1) return; |
| 300 // Create two call site collections to swap between. | 317 // Create two call site collections to swap between. |
| 301 CallSites sites1(caller_graph_); | 318 CallSites sites1(caller_graph_); |
| 302 CallSites sites2(caller_graph_); | 319 CallSites sites2(caller_graph_); |
| 303 CallSites* call_sites_temp = NULL; | 320 CallSites* call_sites_temp = NULL; |
| 304 collected_call_sites_ = &sites1; | 321 collected_call_sites_ = &sites1; |
| 305 inlining_call_sites_ = &sites2; | 322 inlining_call_sites_ = &sites2; |
| 306 // Collect initial call sites. | 323 // Collect initial call sites. |
| 307 collected_call_sites_->FindCallSites(caller_graph_); | 324 collected_call_sites_->FindCallSites(caller_graph_, 1); |
| 308 while (collected_call_sites_->HasCalls()) { | 325 while (collected_call_sites_->HasCalls()) { |
| 309 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); | 326 TRACE_INLINING(OS::Print(" Depth %"Pd" ----------\n", inlining_depth_)); |
| 310 // Swap collected and inlining arrays and clear the new collecting array. | 327 // Swap collected and inlining arrays and clear the new collecting array. |
| 311 call_sites_temp = collected_call_sites_; | 328 call_sites_temp = collected_call_sites_; |
| 312 collected_call_sites_ = inlining_call_sites_; | 329 collected_call_sites_ = inlining_call_sites_; |
| 313 inlining_call_sites_ = call_sites_temp; | 330 inlining_call_sites_ = call_sites_temp; |
| 314 collected_call_sites_->Clear(); | 331 collected_call_sites_->Clear(); |
| 315 // Inline call sites at the current depth. | 332 // Inline call sites at the current depth. |
| 316 InlineStaticCalls(); | 333 InlineStaticCalls(); |
| 317 InlineClosureCalls(); | 334 InlineClosureCalls(); |
| 318 InlineInstanceCalls(); | 335 InlineInstanceCalls(); |
| 319 // Increment the inlining depth. Checked before recursive inlining. | 336 // Increment the inlining depth. Checked before recursive inlining. |
| 320 ++inlining_depth_; | 337 ++inlining_depth_; |
| 321 } | 338 } |
| 322 collected_call_sites_ = NULL; | 339 collected_call_sites_ = NULL; |
| 323 inlining_call_sites_ = NULL; | 340 inlining_call_sites_ = NULL; |
| 324 } | 341 } |
| 325 | 342 |
| 326 bool inlined() const { return inlined_; } | 343 bool inlined() const { return inlined_; } |
| 327 | 344 |
| 328 double GrowthFactor() const { | 345 double GrowthFactor() const { |
| 329 return static_cast<double>(inlined_size_) / | 346 return static_cast<double>(inlined_size_) / |
| 330 static_cast<double>(initial_size_); | 347 static_cast<double>(initial_size_); |
| 331 } | 348 } |
| 332 | 349 |
| 333 private: | 350 private: |
| 334 bool TryInlining(const Function& function, | 351 bool TryInlining(const Function& function, |
| 335 const Array& argument_names, | 352 const Array& argument_names, |
| 336 GrowableArray<Value*>* arguments, | 353 GrowableArray<Value*>* arguments, |
| 337 Definition* call) { | 354 Definition* call, |
| 355 intptr_t caller_count) { | |
| 338 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", | 356 TRACE_INLINING(OS::Print(" => %s (deopt count %d)\n", |
| 339 function.ToCString(), | 357 function.ToCString(), |
| 340 function.deoptimization_counter())); | 358 function.deoptimization_counter())); |
| 341 | 359 |
| 342 // Abort if the inlinable bit on the function is low. | 360 // Abort if the inlinable bit on the function is low. |
| 343 if (!function.IsInlineable()) { | 361 if (!function.IsInlineable()) { |
| 344 TRACE_INLINING(OS::Print(" Bailout: not inlinable\n")); | 362 TRACE_INLINING(OS::Print(" Bailout: not inlinable\n")); |
| 345 return false; | 363 return false; |
| 346 } | 364 } |
| 347 | 365 |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 504 "const args: %"Pd"\n", | 522 "const args: %"Pd"\n", |
| 505 loop_depth, | 523 loop_depth, |
| 506 size, | 524 size, |
| 507 info.call_site_count(), | 525 info.call_site_count(), |
| 508 constants_count)); | 526 constants_count)); |
| 509 return false; | 527 return false; |
| 510 } | 528 } |
| 511 | 529 |
| 512 // If depth is less or equal to threshold recursively add call sites. | 530 // If depth is less or equal to threshold recursively add call sites. |
| 513 if (inlining_depth_ < FLAG_inlining_depth_threshold) { | 531 if (inlining_depth_ < FLAG_inlining_depth_threshold) { |
| 514 collected_call_sites_->FindCallSites(callee_graph); | 532 collected_call_sites_->FindCallSites(callee_graph, caller_count); |
| 515 } | 533 } |
| 516 | 534 |
| 517 { | 535 { |
| 518 TimerScope timer(FLAG_compiler_stats, | 536 TimerScope timer(FLAG_compiler_stats, |
| 519 &CompilerStats::graphinliner_subst_timer, | 537 &CompilerStats::graphinliner_subst_timer, |
| 520 isolate); | 538 isolate); |
| 521 | 539 |
| 522 // Plug result in the caller graph. | 540 // Plug result in the caller graph. |
| 523 caller_graph_->InlineCall(call, callee_graph); | 541 caller_graph_->InlineCall(call, callee_graph); |
| 524 | 542 |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 594 } | 612 } |
| 595 *in_cache = false; | 613 *in_cache = false; |
| 596 ParsedFunction* parsed_function = new ParsedFunction(function); | 614 ParsedFunction* parsed_function = new ParsedFunction(function); |
| 597 Parser::ParseFunction(parsed_function); | 615 Parser::ParseFunction(parsed_function); |
| 598 parsed_function->AllocateVariables(); | 616 parsed_function->AllocateVariables(); |
| 599 return parsed_function; | 617 return parsed_function; |
| 600 } | 618 } |
| 601 | 619 |
| 602 void InlineStaticCalls() { | 620 void InlineStaticCalls() { |
| 603 const GrowableArray<StaticCallInstr*>& calls = | 621 const GrowableArray<StaticCallInstr*>& calls = |
| 604 *inlining_call_sites_->static_calls(); | 622 inlining_call_sites_->static_calls(); |
| 605 TRACE_INLINING(OS::Print(" Static Calls (%d)\n", calls.length())); | 623 TRACE_INLINING(OS::Print(" Static Calls (%d)\n", calls.length())); |
| 606 for (intptr_t i = 0; i < calls.length(); ++i) { | 624 for (intptr_t i = 0; i < calls.length(); ++i) { |
| 607 StaticCallInstr* call = calls[i]; | 625 StaticCallInstr* call = calls[i]; |
| 608 GrowableArray<Value*> arguments(call->ArgumentCount()); | 626 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 609 for (int i = 0; i < call->ArgumentCount(); ++i) { | 627 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 610 arguments.Add(call->ArgumentAt(i)->value()); | 628 arguments.Add(call->ArgumentAt(i)->value()); |
| 611 } | 629 } |
| 612 TryInlining(call->function(), call->argument_names(), &arguments, call); | 630 TryInlining(call->function(), |
| 631 call->argument_names(), | |
| 632 &arguments, | |
| 633 call, | |
| 634 1); | |
| 613 } | 635 } |
| 614 } | 636 } |
| 615 | 637 |
| 616 void InlineClosureCalls() { | 638 void InlineClosureCalls() { |
| 617 const GrowableArray<ClosureCallInstr*>& calls = | 639 const GrowableArray<ClosureCallInstr*>& calls = |
| 618 *inlining_call_sites_->closure_calls(); | 640 inlining_call_sites_->closure_calls(); |
| 619 TRACE_INLINING(OS::Print(" Closure Calls (%d)\n", calls.length())); | 641 TRACE_INLINING(OS::Print(" Closure Calls (%d)\n", calls.length())); |
| 620 for (intptr_t i = 0; i < calls.length(); ++i) { | 642 for (intptr_t i = 0; i < calls.length(); ++i) { |
| 621 ClosureCallInstr* call = calls[i]; | 643 ClosureCallInstr* call = calls[i]; |
| 622 // Find the closure of the callee. | 644 // Find the closure of the callee. |
| 623 ASSERT(call->ArgumentCount() > 0); | 645 ASSERT(call->ArgumentCount() > 0); |
| 624 const CreateClosureInstr* closure = | 646 const CreateClosureInstr* closure = |
| 625 call->ArgumentAt(0)->value()->definition()->AsCreateClosure(); | 647 call->ArgumentAt(0)->value()->definition()->AsCreateClosure(); |
| 626 if (closure == NULL) { | 648 if (closure == NULL) { |
| 627 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n")); | 649 TRACE_INLINING(OS::Print(" Bailout: non-closure operator\n")); |
| 628 continue; | 650 continue; |
| 629 } | 651 } |
| 630 GrowableArray<Value*> arguments(call->ArgumentCount()); | 652 GrowableArray<Value*> arguments(call->ArgumentCount()); |
| 631 for (int i = 0; i < call->ArgumentCount(); ++i) { | 653 for (int i = 0; i < call->ArgumentCount(); ++i) { |
| 632 arguments.Add(call->ArgumentAt(i)->value()); | 654 arguments.Add(call->ArgumentAt(i)->value()); |
| 633 } | 655 } |
| 634 TryInlining(closure->function(), | 656 TryInlining(closure->function(), |
| 635 call->argument_names(), | 657 call->argument_names(), |
| 636 &arguments, | 658 &arguments, |
| 637 call); | 659 call, |
| 660 1); | |
| 638 } | 661 } |
| 639 } | 662 } |
| 640 | 663 |
| 641 void InlineInstanceCalls() { | 664 void InlineInstanceCalls() { |
| 642 const GrowableArray<PolymorphicInstanceCallInstr*>& calls = | 665 const GrowableArray<PolymorphicInstanceCallInstr*>& calls = |
| 643 *inlining_call_sites_->instance_calls(); | 666 inlining_call_sites_->instance_calls(); |
| 667 const GrowableArray<intptr_t>& calls_caller_count = | |
| 668 inlining_call_sites_->instance_calls_caller_count(); | |
| 644 TRACE_INLINING(OS::Print(" Polymorphic Instance Calls (%d)\n", | 669 TRACE_INLINING(OS::Print(" Polymorphic Instance Calls (%d)\n", |
| 645 calls.length())); | 670 calls.length())); |
| 671 GrowableArray<intptr_t> call_counts(calls.length()); | |
| 672 intptr_t max_count = 0; | |
| 673 for (intptr_t i = 0; i < calls.length(); ++i) { | |
| 674 const intptr_t count = | |
| 675 calls[i]->ic_data().AggregateCount() * calls_caller_count[i]; | |
|
Vyacheslav Egorov (Google)
2012/12/17 13:16:05
I can't fully grasp the physical meaning behind th
srdjan
2012/12/17 22:46:13
You are right. Changed to use a ratio per one scop
| |
| 676 call_counts.Add(count); | |
| 677 if (count > max_count) { | |
| 678 max_count = count; | |
| 679 } | |
| 680 } | |
| 646 for (intptr_t i = 0; i < calls.length(); ++i) { | 681 for (intptr_t i = 0; i < calls.length(); ++i) { |
| 647 PolymorphicInstanceCallInstr* instr = calls[i]; | 682 PolymorphicInstanceCallInstr* instr = calls[i]; |
| 648 const ICData& ic_data = instr->ic_data(); | 683 const ICData& ic_data = instr->ic_data(); |
| 649 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); | 684 const Function& target = Function::ZoneHandle(ic_data.GetTargetAt(0)); |
| 650 if (instr->with_checks()) { | 685 if (instr->with_checks()) { |
| 651 TRACE_INLINING(OS::Print( | 686 TRACE_INLINING(OS::Print( |
| 652 " => %s (deopt count %d)\n Bailout: %"Pd" checks\n", | 687 " => %s (deopt count %d)\n Bailout: %"Pd" checks\n", |
| 653 target.ToCString(), | 688 target.ToCString(), |
| 654 target.deoptimization_counter(), | 689 target.deoptimization_counter(), |
| 655 ic_data.NumberOfChecks())); | 690 ic_data.NumberOfChecks())); |
| 691 continue; | |
| 692 } | |
| 693 const intptr_t count_threshold = FLAG_inlining_hotness < 0 ? | |
| 694 0 : (max_count * FLAG_inlining_hotness) / 100; | |
| 695 if (call_counts[i] < count_threshold) { | |
| 696 TRACE_INLINING(OS::Print( | |
| 697 " => %s (deopt count %d)\n Bailout: cold %"Pd" limit %"Pd"\n", | |
| 698 target.ToCString(), | |
| 699 target.deoptimization_counter(), | |
| 700 call_counts[i], | |
| 701 count_threshold)); | |
| 656 continue; | 702 continue; |
| 657 } | 703 } |
| 658 GrowableArray<Value*> arguments(instr->ArgumentCount()); | 704 GrowableArray<Value*> arguments(instr->ArgumentCount()); |
| 659 for (int i = 0; i < instr->ArgumentCount(); ++i) { | 705 for (int arg_i = 0; arg_i < instr->ArgumentCount(); ++arg_i) { |
| 660 arguments.Add(instr->ArgumentAt(i)->value()); | 706 arguments.Add(instr->ArgumentAt(arg_i)->value()); |
| 661 } | 707 } |
| 662 TryInlining(target, | 708 TryInlining(target, |
| 663 instr->instance_call()->argument_names(), | 709 instr->instance_call()->argument_names(), |
| 664 &arguments, | 710 &arguments, |
| 665 instr); | 711 instr, |
| 712 call_counts[i]); | |
| 666 } | 713 } |
| 667 } | 714 } |
| 668 | 715 |
| 669 void AdjustForOptionalParameters(const ParsedFunction& parsed_function, | 716 void AdjustForOptionalParameters(const ParsedFunction& parsed_function, |
| 670 const Array& argument_names, | 717 const Array& argument_names, |
| 671 GrowableArray<Value*>* arguments, | 718 GrowableArray<Value*>* arguments, |
| 672 GrowableArray<Definition*>* param_stubs, | 719 GrowableArray<Definition*>* param_stubs, |
| 673 FlowGraph* callee_graph) { | 720 FlowGraph* callee_graph) { |
| 674 const Function& function = parsed_function.function(); | 721 const Function& function = parsed_function.function(); |
| 675 // The language and this code does not support both optional positional | 722 // The language and this code does not support both optional positional |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 OS::Print("After Inlining of %s\n", flow_graph_-> | 846 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 800 parsed_function().function().ToFullyQualifiedCString()); | 847 parsed_function().function().ToFullyQualifiedCString()); |
| 801 FlowGraphPrinter printer(*flow_graph_); | 848 FlowGraphPrinter printer(*flow_graph_); |
| 802 printer.PrintBlocks(); | 849 printer.PrintBlocks(); |
| 803 } | 850 } |
| 804 } | 851 } |
| 805 } | 852 } |
| 806 } | 853 } |
| 807 | 854 |
| 808 } // namespace dart | 855 } // namespace dart |
| OLD | NEW |