Chromium Code Reviews| 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 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 158 void Collect(const FlowGraph& graph) { | 158 void Collect(const FlowGraph& graph) { |
| 159 call_site_count_ = 0; | 159 call_site_count_ = 0; |
| 160 instruction_count_ = 0; | 160 instruction_count_ = 0; |
| 161 for (BlockIterator block_it = graph.postorder_iterator(); | 161 for (BlockIterator block_it = graph.postorder_iterator(); |
| 162 !block_it.Done(); | 162 !block_it.Done(); |
| 163 block_it.Advance()) { | 163 block_it.Advance()) { |
| 164 for (ForwardInstructionIterator it(block_it.Current()); | 164 for (ForwardInstructionIterator it(block_it.Current()); |
| 165 !it.Done(); | 165 !it.Done(); |
| 166 it.Advance()) { | 166 it.Advance()) { |
| 167 ++instruction_count_; | 167 ++instruction_count_; |
| 168 if (it.Current()->IsStaticCall() || | 168 Instruction* current = it.Current(); |
| 169 it.Current()->IsClosureCall() || | 169 if (current->IsStaticCall() || |
| 170 it.Current()->IsPolymorphicInstanceCall()) { | 170 current->IsClosureCall() || |
| 171 (current->IsPolymorphicInstanceCall() && | |
| 172 !current->AsPolymorphicInstanceCall()->HasRecognizedTarget())) { | |
| 171 ++call_site_count_; | 173 ++call_site_count_; |
| 172 } | 174 } |
| 173 } | 175 } |
| 174 } | 176 } |
| 175 } | 177 } |
| 176 | 178 |
| 177 intptr_t call_site_count() const { return call_site_count_; } | 179 intptr_t call_site_count() const { return call_site_count_; } |
| 178 intptr_t instruction_count() const { return instruction_count_; } | 180 intptr_t instruction_count() const { return instruction_count_; } |
| 179 | 181 |
| 180 private: | 182 private: |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 279 block_it.Advance()) { | 281 block_it.Advance()) { |
| 280 for (ForwardInstructionIterator it(block_it.Current()); | 282 for (ForwardInstructionIterator it(block_it.Current()); |
| 281 !it.Done(); | 283 !it.Done(); |
| 282 it.Advance()) { | 284 it.Advance()) { |
| 283 it.Current()->Accept(this); | 285 it.Current()->Accept(this); |
| 284 } | 286 } |
| 285 } | 287 } |
| 286 ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix); | 288 ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix); |
| 287 } | 289 } |
| 288 | 290 |
| 291 void FindRecognizedCallSites(FlowGraph* graph) { | |
|
Kevin Millikin (Google)
2013/08/13 11:47:40
Instead of a separate function which is a copy of
Florian Schneider
2013/08/14 12:30:24
Done.
| |
| 292 ASSERT(graph != NULL); | |
| 293 | |
| 294 const intptr_t instance_call_start_ix = instance_calls_.length(); | |
| 295 const intptr_t static_call_start_ix = static_calls_.length(); | |
| 296 for (BlockIterator block_it = graph->postorder_iterator(); | |
| 297 !block_it.Done(); | |
| 298 block_it.Advance()) { | |
| 299 for (ForwardInstructionIterator it(block_it.Current()); | |
| 300 !it.Done(); | |
| 301 it.Advance()) { | |
| 302 PolymorphicInstanceCallInstr* call = | |
| 303 it.Current()->AsPolymorphicInstanceCall(); | |
| 304 if (call != NULL && call->HasRecognizedTarget()) { | |
|
srdjan
2013/08/12 21:49:47
Add ()
Florian Schneider
2013/08/14 12:30:24
Done.
| |
| 305 instance_calls_.Add(InstanceCallInfo(call)); | |
| 306 } | |
| 307 } | |
| 308 } | |
| 309 ComputeCallSiteRatio(static_call_start_ix, instance_call_start_ix); | |
| 310 } | |
| 311 | |
| 289 void VisitClosureCall(ClosureCallInstr* call) { | 312 void VisitClosureCall(ClosureCallInstr* call) { |
| 290 closure_calls_.Add(call); | 313 closure_calls_.Add(call); |
| 291 } | 314 } |
| 292 | 315 |
| 293 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { | 316 void VisitPolymorphicInstanceCall(PolymorphicInstanceCallInstr* call) { |
| 294 instance_calls_.Add(InstanceCallInfo(call)); | 317 instance_calls_.Add(InstanceCallInfo(call)); |
| 295 } | 318 } |
| 296 | 319 |
| 297 void VisitStaticCall(StaticCallInstr* call) { | 320 void VisitStaticCall(StaticCallInstr* call) { |
| 298 if (!call->function().IsInlineable()) return; | 321 if (!call->function().IsInlineable()) return; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 387 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && | 410 if ((const_arg_count >= FLAG_inlining_constant_arguments_count) && |
| 388 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { | 411 (instr_count <= FLAG_inlining_constant_arguments_size_threshold)) { |
| 389 return true; | 412 return true; |
| 390 } | 413 } |
| 391 if (MethodRecognizer::AlwaysInline(callee)) { | 414 if (MethodRecognizer::AlwaysInline(callee)) { |
| 392 return true; | 415 return true; |
| 393 } | 416 } |
| 394 return false; | 417 return false; |
| 395 } | 418 } |
| 396 | 419 |
| 397 // TODO(srdjan): Handle large 'skip_static_call_deopt_ids'. Currently | |
| 398 // max. size observed is 11 (dart2js). | |
|
Florian Schneider
2013/08/12 15:48:14
I think this TODO is obsolete.
| |
| 399 void InlineCalls() { | 420 void InlineCalls() { |
| 400 // If inlining depth is less then one abort. | 421 // If inlining depth is less then one abort. |
| 401 if (FLAG_inlining_depth_threshold < 1) return; | 422 if (FLAG_inlining_depth_threshold < 1) return; |
| 402 if (caller_graph_->parsed_function().function().deoptimization_counter() >= | 423 if (caller_graph_->parsed_function().function().deoptimization_counter() >= |
| 403 FLAG_deoptimization_counter_inlining_threshold) { | 424 FLAG_deoptimization_counter_inlining_threshold) { |
| 404 return; | 425 return; |
| 405 } | 426 } |
| 406 // Create two call site collections to swap between. | 427 // Create two call site collections to swap between. |
| 407 CallSites sites1(caller_graph_); | 428 CallSites sites1(caller_graph_); |
| 408 CallSites sites2(caller_graph_); | 429 CallSites sites2(caller_graph_); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 "const args: %"Pd"\n", | 649 "const args: %"Pd"\n", |
| 629 size, | 650 size, |
| 630 call_site_count, | 651 call_site_count, |
| 631 constants_count)); | 652 constants_count)); |
| 632 return false; | 653 return false; |
| 633 } | 654 } |
| 634 | 655 |
| 635 // If depth is less or equal to threshold recursively add call sites. | 656 // If depth is less or equal to threshold recursively add call sites. |
| 636 if (inlining_depth_ < FLAG_inlining_depth_threshold) { | 657 if (inlining_depth_ < FLAG_inlining_depth_threshold) { |
| 637 collected_call_sites_->FindCallSites(callee_graph); | 658 collected_call_sites_->FindCallSites(callee_graph); |
| 659 } else if (inlining_depth_ == FLAG_inlining_depth_threshold) { | |
|
Kevin Millikin (Google)
2013/08/13 11:47:40
In any case, even if you keep the separate functio
Florian Schneider
2013/08/14 12:30:24
Done. I use only one function. Also change CallSit
| |
| 660 collected_call_sites_->FindRecognizedCallSites(callee_graph); | |
| 638 } | 661 } |
| 639 | 662 |
| 640 // Add the function to the cache. | 663 // Add the function to the cache. |
| 641 if (!in_cache) function_cache_.Add(parsed_function); | 664 if (!in_cache) function_cache_.Add(parsed_function); |
| 642 | 665 |
| 643 // Build succeeded so we restore the bailout jump. | 666 // Build succeeded so we restore the bailout jump. |
| 644 inlined_ = true; | 667 inlined_ = true; |
| 645 inlined_size_ += size; | 668 inlined_size_ += size; |
| 646 isolate->set_long_jump_base(base); | 669 isolate->set_long_jump_base(base); |
| 647 isolate->set_deopt_id(prev_deopt_id); | 670 isolate->set_deopt_id(prev_deopt_id); |
| (...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1057 if (target.raw() == non_inlined_variants_[i].target->raw()) { | 1080 if (target.raw() == non_inlined_variants_[i].target->raw()) { |
| 1058 return true; | 1081 return true; |
| 1059 } | 1082 } |
| 1060 } | 1083 } |
| 1061 | 1084 |
| 1062 return false; | 1085 return false; |
| 1063 } | 1086 } |
| 1064 | 1087 |
| 1065 | 1088 |
| 1066 bool PolymorphicInliner::TryInlining(const Function& target) { | 1089 bool PolymorphicInliner::TryInlining(const Function& target) { |
| 1067 if (!target.is_optimizable()) { | |
|
Kevin Millikin (Google)
2013/08/13 11:47:40
Why remove this check?
Florian Schneider
2013/08/14 12:30:24
It's not strictly necessary, but I'll put it back
| |
| 1068 return false; | |
| 1069 } | |
| 1070 GrowableArray<Value*> arguments(call_->ArgumentCount()); | 1090 GrowableArray<Value*> arguments(call_->ArgumentCount()); |
| 1071 for (int i = 0; i < call_->ArgumentCount(); ++i) { | 1091 for (int i = 0; i < call_->ArgumentCount(); ++i) { |
| 1072 arguments.Add(call_->PushArgumentAt(i)->value()); | 1092 arguments.Add(call_->PushArgumentAt(i)->value()); |
| 1073 } | 1093 } |
| 1074 InlinedCallData call_data(call_, &arguments); | 1094 InlinedCallData call_data(call_, &arguments); |
| 1075 if (!owner_->TryInlining(target, | 1095 if (!owner_->TryInlining(target, |
| 1076 call_->instance_call()->argument_names(), | 1096 call_->instance_call()->argument_names(), |
| 1077 &call_data)) { | 1097 &call_data)) { |
| 1078 return false; | 1098 return false; |
| 1079 } | 1099 } |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1424 OS::Print("After Inlining of %s\n", flow_graph_-> | 1444 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1425 parsed_function().function().ToFullyQualifiedCString()); | 1445 parsed_function().function().ToFullyQualifiedCString()); |
| 1426 FlowGraphPrinter printer(*flow_graph_); | 1446 FlowGraphPrinter printer(*flow_graph_); |
| 1427 printer.PrintBlocks(); | 1447 printer.PrintBlocks(); |
| 1428 } | 1448 } |
| 1429 } | 1449 } |
| 1430 } | 1450 } |
| 1431 } | 1451 } |
| 1432 | 1452 |
| 1433 } // namespace dart | 1453 } // namespace dart |
| OLD | NEW |