| 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 1194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1205 Definition* receiver = call_->ArgumentAt(0); | 1205 Definition* receiver = call_->ArgumentAt(0); |
| 1206 // There are at least two variants including non-inlined ones, so we have | 1206 // There are at least two variants including non-inlined ones, so we have |
| 1207 // at least one branch on the class id. | 1207 // at least one branch on the class id. |
| 1208 LoadClassIdInstr* load_cid = new LoadClassIdInstr(new Value(receiver)); | 1208 LoadClassIdInstr* load_cid = new LoadClassIdInstr(new Value(receiver)); |
| 1209 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index()); | 1209 load_cid->set_ssa_temp_index(owner_->caller_graph()->alloc_ssa_temp_index()); |
| 1210 cursor = AppendInstruction(cursor, load_cid); | 1210 cursor = AppendInstruction(cursor, load_cid); |
| 1211 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { | 1211 for (intptr_t i = 0; i < inlined_variants_.length(); ++i) { |
| 1212 // 1. Guard the body with a class id check. | 1212 // 1. Guard the body with a class id check. |
| 1213 if ((i == (inlined_variants_.length() - 1)) && | 1213 if ((i == (inlined_variants_.length() - 1)) && |
| 1214 non_inlined_variants_.is_empty()) { | 1214 non_inlined_variants_.is_empty()) { |
| 1215 // If it is the last variant use a check class or check smi | 1215 // If it is the last variant use a check class id instruction which can |
| 1216 // instruction which can deoptimize, followed unconditionally by the | 1216 // deoptimize, followed unconditionally by the body. |
| 1217 // body. Check a redefinition of the receiver, to prevent the check | 1217 const Smi& cid = Smi::ZoneHandle(Smi::New(inlined_variants_[i].cid)); |
| 1218 // from being hoisted. | 1218 ConstantInstr* cid_constant = new ConstantInstr(cid); |
| 1219 RedefinitionInstr* redefinition = | 1219 cid_constant->set_ssa_temp_index( |
| 1220 new RedefinitionInstr(new Value(receiver)); | |
| 1221 redefinition->set_ssa_temp_index( | |
| 1222 owner_->caller_graph()->alloc_ssa_temp_index()); | 1220 owner_->caller_graph()->alloc_ssa_temp_index()); |
| 1223 cursor = AppendInstruction(cursor, redefinition); | 1221 cursor = AppendInstruction(cursor, cid_constant); |
| 1224 if (inlined_variants_[i].cid == kSmiCid) { | 1222 |
| 1225 CheckSmiInstr* check_smi = | 1223 CheckClassIdInstr* check_class_id = |
| 1226 new CheckSmiInstr(new Value(redefinition), call_->deopt_id()); | 1224 new CheckClassIdInstr(new Value(load_cid), |
| 1227 check_smi->InheritDeoptTarget(call_); | 1225 new Value(cid_constant), |
| 1228 cursor = AppendInstruction(cursor, check_smi); | 1226 call_->deopt_id()); |
| 1229 } else { | 1227 check_class_id->InheritDeoptTarget(call_); |
| 1230 const ICData& old_checks = call_->ic_data(); | 1228 cursor = AppendInstruction(cursor, check_class_id); |
| 1231 const ICData& new_checks = ICData::ZoneHandle( | 1229 |
| 1232 ICData::New(Function::Handle(old_checks.function()), | |
| 1233 String::Handle(old_checks.target_name()), | |
| 1234 Array::Handle(old_checks.arguments_descriptor()), | |
| 1235 old_checks.deopt_id(), | |
| 1236 1)); // Number of args tested. | |
| 1237 new_checks.AddReceiverCheck(inlined_variants_[i].cid, | |
| 1238 *inlined_variants_[i].target); | |
| 1239 CheckClassInstr* check_class = | |
| 1240 new CheckClassInstr(new Value(redefinition), | |
| 1241 call_->deopt_id(), | |
| 1242 new_checks); | |
| 1243 check_class->InheritDeoptTarget(call_); | |
| 1244 cursor = AppendInstruction(cursor, check_class); | |
| 1245 } | |
| 1246 // The next instruction is the first instruction of the inlined body. | 1230 // The next instruction is the first instruction of the inlined body. |
| 1247 // Handle the two possible cases (unshared and shared subsequent | 1231 // Handle the two possible cases (unshared and shared subsequent |
| 1248 // predecessors) separately. | 1232 // predecessors) separately. |
| 1249 BlockEntryInstr* callee_entry = inlined_entries_[i]; | 1233 BlockEntryInstr* callee_entry = inlined_entries_[i]; |
| 1250 if (callee_entry->IsGraphEntry()) { | 1234 if (callee_entry->IsGraphEntry()) { |
| 1251 // Unshared. Graft the normal entry on after the check class | 1235 // Unshared. Graft the normal entry on after the check class |
| 1252 // instruction. | 1236 // instruction. |
| 1253 TargetEntryInstr* target = | 1237 TargetEntryInstr* target = |
| 1254 callee_entry->AsGraphEntry()->normal_entry(); | 1238 callee_entry->AsGraphEntry()->normal_entry(); |
| 1255 cursor->LinkTo(target->next()); | 1239 cursor->LinkTo(target->next()); |
| (...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1499 OS::Print("After Inlining of %s\n", flow_graph_-> | 1483 OS::Print("After Inlining of %s\n", flow_graph_-> |
| 1500 parsed_function().function().ToFullyQualifiedCString()); | 1484 parsed_function().function().ToFullyQualifiedCString()); |
| 1501 FlowGraphPrinter printer(*flow_graph_); | 1485 FlowGraphPrinter printer(*flow_graph_); |
| 1502 printer.PrintBlocks(); | 1486 printer.PrintBlocks(); |
| 1503 } | 1487 } |
| 1504 } | 1488 } |
| 1505 } | 1489 } |
| 1506 } | 1490 } |
| 1507 | 1491 |
| 1508 } // namespace dart | 1492 } // namespace dart |
| OLD | NEW |