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_optimizer.h" | 5 #include "vm/flow_graph_optimizer.h" |
6 | 6 |
7 #include "vm/flow_graph_builder.h" | 7 #include "vm/flow_graph_builder.h" |
8 #include "vm/il_printer.h" | 8 #include "vm/il_printer.h" |
9 #include "vm/object_store.h" | 9 #include "vm/object_store.h" |
10 | 10 |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
231 field = cls.LookupInstanceField(field_name); | 231 field = cls.LookupInstanceField(field_name); |
232 if (!field.IsNull()) { | 232 if (!field.IsNull()) { |
233 return field.raw(); | 233 return field.raw(); |
234 } | 234 } |
235 cls = cls.SuperClass(); | 235 cls = cls.SuperClass(); |
236 } | 236 } |
237 return Field::null(); | 237 return Field::null(); |
238 } | 238 } |
239 | 239 |
240 | 240 |
241 // Returns ICData with num_args_checked == 1. If necessary creates a new ICData | |
242 // object that contains unique receiver class-ids | |
243 static RawICData* ToUnaryClassChecks(const ICData& ic_data) { | |
244 ASSERT(!ic_data.IsNull()); | |
245 ASSERT(ic_data.num_args_tested() != 0); | |
246 if (ic_data.num_args_tested() == 1) return ic_data.raw(); | |
247 const intptr_t kNumArgsTested = 1; | |
248 ICData& result = ICData::Handle(ICData::New( | |
249 Function::Handle(ic_data.function()), | |
250 String::Handle(ic_data.target_name()), | |
251 ic_data.id(), | |
252 kNumArgsTested)); | |
253 for (intptr_t i = 0; i < ic_data.NumberOfChecks(); i++) { | |
254 const intptr_t class_id = ic_data.GetReceiverClassIdAt(i); | |
255 intptr_t duplicate_class_id = -1; | |
256 for (intptr_t k = 0; k < result.NumberOfChecks(); k++) { | |
257 if (class_id == result.GetReceiverClassIdAt(k)) { | |
258 duplicate_class_id = k; | |
259 break; | |
260 } | |
261 } | |
262 if (duplicate_class_id >= 0) { | |
263 ASSERT(result.GetTargetAt(duplicate_class_id) == ic_data.GetTargetAt(i)); | |
264 } else { | |
265 // This will make sure that Smi is first if it exists. | |
266 result.AddReceiverCheck(class_id, | |
267 Function::Handle(ic_data.GetTargetAt(i))); | |
268 } | |
269 } | |
270 return result.raw(); | |
271 } | |
272 | |
273 | |
274 // Only unique implicit instance getters can be currently handled. | 241 // Only unique implicit instance getters can be currently handled. |
275 bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr, | 242 bool FlowGraphOptimizer::TryInlineInstanceGetter(BindInstr* instr, |
276 InstanceCallComp* comp) { | 243 InstanceCallComp* comp) { |
277 ASSERT(comp->HasICData()); | 244 ASSERT(comp->HasICData()); |
278 const ICData& ic_data = *comp->ic_data(); | 245 const ICData& ic_data = *comp->ic_data(); |
279 if (ic_data.NumberOfChecks() == 0) { | 246 if (ic_data.NumberOfChecks() == 0) { |
280 // No type feedback collected. | 247 // No type feedback collected. |
281 return false; | 248 return false; |
282 } | 249 } |
283 Function& target = Function::Handle(); | 250 Function& target = Function::Handle(); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
402 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) { | 369 if ((op_kind == Token::kGET) && TryInlineInstanceGetter(instr, comp)) { |
403 return; | 370 return; |
404 } | 371 } |
405 if (TryInlineInstanceMethod(instr, comp)) { | 372 if (TryInlineInstanceMethod(instr, comp)) { |
406 return; | 373 return; |
407 } | 374 } |
408 const intptr_t kMaxChecks = 4; | 375 const intptr_t kMaxChecks = 4; |
409 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { | 376 if (comp->ic_data()->NumberOfChecks() <= kMaxChecks) { |
410 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); | 377 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
411 ICData& unary_checks = | 378 ICData& unary_checks = |
412 ICData::ZoneHandle(ToUnaryClassChecks(*comp->ic_data())); | 379 ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks()); |
413 call->set_ic_data(&unary_checks); | 380 call->set_ic_data(&unary_checks); |
414 instr->set_computation(call); | 381 instr->set_computation(call); |
415 } | 382 } |
416 } else { | 383 } else { |
417 // Mark it for deopt. | 384 // Mark it for deopt. |
418 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); | 385 PolymorphicInstanceCallComp* call = new PolymorphicInstanceCallComp(comp); |
419 call->set_ic_data(&ICData::ZoneHandle()); | 386 call->set_ic_data(&ICData::ZoneHandle()); |
420 instr->set_computation(call); | 387 instr->set_computation(call); |
421 } | 388 } |
422 } | 389 } |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 | 560 |
594 | 561 |
595 void FlowGraphOptimizer::VisitStrictCompare(StrictCompareComp* comp, | 562 void FlowGraphOptimizer::VisitStrictCompare(StrictCompareComp* comp, |
596 BindInstr* instr) { | 563 BindInstr* instr) { |
597 TryFuseComparisonWithBranch(instr, comp); | 564 TryFuseComparisonWithBranch(instr, comp); |
598 } | 565 } |
599 | 566 |
600 | 567 |
601 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp, | 568 void FlowGraphOptimizer::VisitEqualityCompare(EqualityCompareComp* comp, |
602 BindInstr* instr) { | 569 BindInstr* instr) { |
603 if (comp->HasICData()) { | 570 if (comp->HasICData() && (comp->ic_data()->NumberOfChecks() == 1)) { |
604 // Replace binary checks with unary ones since EmitNative expects it. | 571 ASSERT(comp->ic_data()->num_args_tested() == 2); |
605 ICData& unary_checks = | 572 GrowableArray<intptr_t> class_ids; |
606 ICData::Handle(ToUnaryClassChecks(*comp->ic_data())); | 573 Function& target = Function::Handle(); |
607 comp->set_ic_data(&unary_checks); | 574 comp->ic_data()->GetCheckAt(0, &class_ids, &target); |
| 575 // TODO(srdjan): allow for mixed mode comparison. |
| 576 if ((class_ids[0] == kSmi) && (class_ids[1] == kSmi)) { |
| 577 comp->set_receiver_class_id(kSmi); |
| 578 } else if ((class_ids[0] == kDouble) && (class_ids[1] == kDouble)) { |
| 579 comp->set_receiver_class_id(kDouble); |
| 580 } |
608 } | 581 } |
609 | |
610 TryFuseComparisonWithBranch(instr, comp); | 582 TryFuseComparisonWithBranch(instr, comp); |
611 } | 583 } |
612 | 584 |
613 | 585 |
614 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { | 586 void FlowGraphOptimizer::VisitBind(BindInstr* instr) { |
615 instr->computation()->Accept(this, instr); | 587 instr->computation()->Accept(this, instr); |
616 } | 588 } |
617 | 589 |
618 | 590 |
619 | 591 |
620 void FlowGraphAnalyzer::Analyze() { | 592 void FlowGraphAnalyzer::Analyze() { |
621 is_leaf_ = true; | 593 is_leaf_ = true; |
622 for (intptr_t i = 0; i < blocks_.length(); ++i) { | 594 for (intptr_t i = 0; i < blocks_.length(); ++i) { |
623 BlockEntryInstr* entry = blocks_[i]; | 595 BlockEntryInstr* entry = blocks_[i]; |
624 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { | 596 for (ForwardInstructionIterator it(entry); !it.Done(); it.Advance()) { |
625 LocationSummary* locs = it.Current()->locs(); | 597 LocationSummary* locs = it.Current()->locs(); |
626 if ((locs != NULL) && locs->is_call()) { | 598 if ((locs != NULL) && locs->is_call()) { |
627 is_leaf_ = false; | 599 is_leaf_ = false; |
628 return; | 600 return; |
629 } | 601 } |
630 } | 602 } |
631 } | 603 } |
632 } | 604 } |
633 | 605 |
634 } // namespace dart | 606 } // namespace dart |
OLD | NEW |