| 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/object.h" | 5 #include "vm/object.h" |
| 6 | 6 |
| 7 #include "include/dart_api.h" | 7 #include "include/dart_api.h" |
| 8 #include "platform/assert.h" | 8 #include "platform/assert.h" |
| 9 #include "vm/assembler.h" | 9 #include "vm/assembler.h" |
| 10 #include "vm/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 6628 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6639 } | 6639 } |
| 6640 } | 6640 } |
| 6641 | 6641 |
| 6642 | 6642 |
| 6643 void Function::RestoreICDataMap( | 6643 void Function::RestoreICDataMap( |
| 6644 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { | 6644 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { |
| 6645 Isolate* isolate = Isolate::Current(); | 6645 Isolate* isolate = Isolate::Current(); |
| 6646 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); | 6646 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); |
| 6647 if (saved_icd.Length() == 0) { | 6647 if (saved_icd.Length() == 0) { |
| 6648 deopt_id_to_ic_data->Clear(); | 6648 deopt_id_to_ic_data->Clear(); |
| 6649 return;; | 6649 return; |
| 6650 } | 6650 } |
| 6651 ICData& icd = ICData::Handle(); | 6651 ICData& icd = ICData::Handle(); |
| 6652 icd ^= saved_icd.At(saved_icd.Length() - 1); | 6652 icd ^= saved_icd.At(saved_icd.Length() - 1); |
| 6653 const intptr_t len = icd.deopt_id() + 1; | 6653 const intptr_t len = icd.deopt_id() + 1; |
| 6654 deopt_id_to_ic_data->SetLength(len); | 6654 deopt_id_to_ic_data->SetLength(len); |
| 6655 for (intptr_t i = 0; i < len; i++) { | 6655 for (intptr_t i = 0; i < len; i++) { |
| 6656 (*deopt_id_to_ic_data)[i] = NULL; | 6656 (*deopt_id_to_ic_data)[i] = NULL; |
| 6657 } | 6657 } |
| 6658 for (intptr_t i = 0; i < saved_icd.Length(); i++) { | 6658 for (intptr_t i = 0; i < saved_icd.Length(); i++) { |
| 6659 ICData& icd = ICData::ZoneHandle(isolate); | 6659 ICData& icd = ICData::ZoneHandle(isolate); |
| (...skipping 4647 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11307 return TestEntryLengthFor(NumArgsTested()); | 11307 return TestEntryLengthFor(NumArgsTested()); |
| 11308 } | 11308 } |
| 11309 | 11309 |
| 11310 | 11310 |
| 11311 intptr_t ICData::NumberOfChecks() const { | 11311 intptr_t ICData::NumberOfChecks() const { |
| 11312 // Do not count the sentinel; | 11312 // Do not count the sentinel; |
| 11313 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; | 11313 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; |
| 11314 } | 11314 } |
| 11315 | 11315 |
| 11316 | 11316 |
| 11317 // Discounts any checks with usage of zero. |
| 11318 intptr_t ICData::NumberOfUsedChecks() const { |
| 11319 intptr_t n = NumberOfChecks(); |
| 11320 if (n == 0) { |
| 11321 return 0; |
| 11322 } |
| 11323 intptr_t count = 0; |
| 11324 for (intptr_t i = 0; i < n; i++) { |
| 11325 if (GetCountAt(i) > 0) { |
| 11326 count++; |
| 11327 } |
| 11328 } |
| 11329 return count; |
| 11330 } |
| 11331 |
| 11332 |
| 11317 void ICData::WriteSentinel(const Array& data) const { | 11333 void ICData::WriteSentinel(const Array& data) const { |
| 11318 ASSERT(!data.IsNull()); | 11334 ASSERT(!data.IsNull()); |
| 11319 for (intptr_t i = 1; i <= TestEntryLength(); i++) { | 11335 for (intptr_t i = 1; i <= TestEntryLength(); i++) { |
| 11320 data.SetAt(data.Length() - i, smi_illegal_cid()); | 11336 data.SetAt(data.Length() - i, smi_illegal_cid()); |
| 11321 } | 11337 } |
| 11322 } | 11338 } |
| 11323 | 11339 |
| 11324 | 11340 |
| 11325 #if defined(DEBUG) | 11341 #if defined(DEBUG) |
| 11326 // Used in asserts to verify that a check is not added twice. | 11342 // Used in asserts to verify that a check is not added twice. |
| (...skipping 28 matching lines...) Expand all Loading... |
| 11355 AddReceiverCheck(kObjectCid, target, 1); | 11371 AddReceiverCheck(kObjectCid, target, 1); |
| 11356 } else { | 11372 } else { |
| 11357 GrowableArray<intptr_t> class_ids(NumArgsTested()); | 11373 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
| 11358 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 11374 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 11359 class_ids.Add(kObjectCid); | 11375 class_ids.Add(kObjectCid); |
| 11360 } | 11376 } |
| 11361 AddCheck(class_ids, target); | 11377 AddCheck(class_ids, target); |
| 11362 } | 11378 } |
| 11363 return; | 11379 return; |
| 11364 } | 11380 } |
| 11365 ASSERT(NumArgsTested() >= 0); | 11381 ASSERT(NumArgsTested() == 0); |
| 11366 // Can add only once. | 11382 // Can add only once. |
| 11367 const intptr_t old_num = NumberOfChecks(); | 11383 const intptr_t old_num = NumberOfChecks(); |
| 11368 ASSERT(old_num == 0); | 11384 ASSERT(old_num == 0); |
| 11369 Array& data = Array::Handle(ic_data()); | 11385 Array& data = Array::Handle(ic_data()); |
| 11370 const intptr_t new_len = data.Length() + TestEntryLength(); | 11386 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 11371 data = Array::Grow(data, new_len, Heap::kOld); | 11387 data = Array::Grow(data, new_len, Heap::kOld); |
| 11372 set_ic_data(data); | 11388 set_ic_data(data); |
| 11373 WriteSentinel(data); | 11389 WriteSentinel(data); |
| 11374 intptr_t data_pos = old_num * TestEntryLength(); | 11390 intptr_t data_pos = old_num * TestEntryLength(); |
| 11375 ASSERT(!target.IsNull()); | 11391 ASSERT(!target.IsNull()); |
| 11376 data.SetAt(data_pos++, target); | 11392 data.SetAt(data_pos++, target); |
| 11393 // Set count to 0 as this is called during compilation, before the |
| 11394 // call has been executed. |
| 11377 const Smi& value = Smi::Handle(Smi::New(0)); | 11395 const Smi& value = Smi::Handle(Smi::New(0)); |
| 11378 data.SetAt(data_pos, value); | 11396 data.SetAt(data_pos, value); |
| 11379 } | 11397 } |
| 11380 | 11398 |
| 11381 | 11399 |
| 11382 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 11400 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
| 11383 const Function& target) const { | 11401 const Function& target) const { |
| 11384 ASSERT(!target.IsNull()); | 11402 ASSERT(!target.IsNull()); |
| 11403 ASSERT(target.name() == target_name()); |
| 11385 DEBUG_ASSERT(!HasCheck(class_ids)); | 11404 DEBUG_ASSERT(!HasCheck(class_ids)); |
| 11386 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. | 11405 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. |
| 11387 ASSERT(class_ids.length() == NumArgsTested()); | 11406 ASSERT(class_ids.length() == NumArgsTested()); |
| 11388 const intptr_t old_num = NumberOfChecks(); | 11407 const intptr_t old_num = NumberOfChecks(); |
| 11389 Array& data = Array::Handle(ic_data()); | 11408 Array& data = Array::Handle(ic_data()); |
| 11390 // ICData of static calls with NumArgsTested() > 0 have initially a | 11409 // ICData of static calls with NumArgsTested() > 0 have initially a |
| 11391 // dummy set of cids entered (see ICData::AddTarget). That entry is | 11410 // dummy set of cids entered (see ICData::AddTarget). That entry is |
| 11392 // overwritten by first real type feedback data. | 11411 // overwritten by first real type feedback data. |
| 11393 if (old_num == 1) { | 11412 if (old_num == 1) { |
| 11394 bool has_dummy_entry = true; | 11413 bool has_dummy_entry = true; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 11586 ICData& result = ICData::Handle(ICData::New( | 11605 ICData& result = ICData::Handle(ICData::New( |
| 11587 Function::Handle(owner()), | 11606 Function::Handle(owner()), |
| 11588 String::Handle(target_name()), | 11607 String::Handle(target_name()), |
| 11589 Array::Handle(arguments_descriptor()), | 11608 Array::Handle(arguments_descriptor()), |
| 11590 deopt_id(), | 11609 deopt_id(), |
| 11591 kNumArgsTested)); | 11610 kNumArgsTested)); |
| 11592 const intptr_t len = NumberOfChecks(); | 11611 const intptr_t len = NumberOfChecks(); |
| 11593 for (intptr_t i = 0; i < len; i++) { | 11612 for (intptr_t i = 0; i < len; i++) { |
| 11594 const intptr_t class_id = GetClassIdAt(i, arg_nr); | 11613 const intptr_t class_id = GetClassIdAt(i, arg_nr); |
| 11595 const intptr_t count = GetCountAt(i); | 11614 const intptr_t count = GetCountAt(i); |
| 11615 if (count == 0) { |
| 11616 continue; |
| 11617 } |
| 11596 intptr_t duplicate_class_id = -1; | 11618 intptr_t duplicate_class_id = -1; |
| 11597 const intptr_t result_len = result.NumberOfChecks(); | 11619 const intptr_t result_len = result.NumberOfChecks(); |
| 11598 for (intptr_t k = 0; k < result_len; k++) { | 11620 for (intptr_t k = 0; k < result_len; k++) { |
| 11599 if (class_id == result.GetReceiverClassIdAt(k)) { | 11621 if (class_id == result.GetReceiverClassIdAt(k)) { |
| 11600 duplicate_class_id = k; | 11622 duplicate_class_id = k; |
| 11601 break; | 11623 break; |
| 11602 } | 11624 } |
| 11603 } | 11625 } |
| 11604 if (duplicate_class_id >= 0) { | 11626 if (duplicate_class_id >= 0) { |
| 11605 // This check is valid only when checking the receiver. | 11627 // This check is valid only when checking the receiver. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 11618 | 11640 |
| 11619 return result.raw(); | 11641 return result.raw(); |
| 11620 } | 11642 } |
| 11621 | 11643 |
| 11622 | 11644 |
| 11623 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { | 11645 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { |
| 11624 if (NumberOfChecks() == 0) return false; | 11646 if (NumberOfChecks() == 0) return false; |
| 11625 Class& cls = Class::Handle(); | 11647 Class& cls = Class::Handle(); |
| 11626 const intptr_t len = NumberOfChecks(); | 11648 const intptr_t len = NumberOfChecks(); |
| 11627 for (intptr_t i = 0; i < len; i++) { | 11649 for (intptr_t i = 0; i < len; i++) { |
| 11628 cls = Function::Handle(GetTargetAt(i)).Owner(); | 11650 if (IsUsedAt(i)) { |
| 11629 if (cls.id() != owner_cid) { | 11651 cls = Function::Handle(GetTargetAt(i)).Owner(); |
| 11630 return false; | 11652 if (cls.id() != owner_cid) { |
| 11653 return false; |
| 11654 } |
| 11631 } | 11655 } |
| 11632 } | 11656 } |
| 11633 return true; | 11657 return true; |
| 11634 } | 11658 } |
| 11635 | 11659 |
| 11636 | 11660 |
| 11637 bool ICData::AllReceiversAreNumbers() const { | 11661 bool ICData::AllReceiversAreNumbers() const { |
| 11638 if (NumberOfChecks() == 0) return false; | 11662 if (NumberOfChecks() == 0) return false; |
| 11639 Class& cls = Class::Handle(); | 11663 Class& cls = Class::Handle(); |
| 11640 const intptr_t len = NumberOfChecks(); | 11664 const intptr_t len = NumberOfChecks(); |
| 11641 for (intptr_t i = 0; i < len; i++) { | 11665 for (intptr_t i = 0; i < len; i++) { |
| 11642 cls = Function::Handle(GetTargetAt(i)).Owner(); | 11666 if (IsUsedAt(i)) { |
| 11643 const intptr_t cid = cls.id(); | 11667 cls = Function::Handle(GetTargetAt(i)).Owner(); |
| 11644 if ((cid != kSmiCid) && | 11668 const intptr_t cid = cls.id(); |
| 11645 (cid != kMintCid) && | 11669 if ((cid != kSmiCid) && |
| 11646 (cid != kBigintCid) && | 11670 (cid != kMintCid) && |
| 11647 (cid != kDoubleCid)) { | 11671 (cid != kBigintCid) && |
| 11648 return false; | 11672 (cid != kDoubleCid)) { |
| 11673 return false; |
| 11674 } |
| 11649 } | 11675 } |
| 11650 } | 11676 } |
| 11651 return true; | 11677 return true; |
| 11652 } | 11678 } |
| 11653 | 11679 |
| 11654 | 11680 |
| 11655 bool ICData::HasReceiverClassId(intptr_t class_id) const { | 11681 bool ICData::HasReceiverClassId(intptr_t class_id) const { |
| 11656 ASSERT(NumArgsTested() > 0); | 11682 ASSERT(NumArgsTested() > 0); |
| 11657 const intptr_t len = NumberOfChecks(); | 11683 const intptr_t len = NumberOfChecks(); |
| 11658 for (intptr_t i = 0; i < len; i++) { | 11684 for (intptr_t i = 0; i < len; i++) { |
| 11659 const intptr_t test_class_id = GetReceiverClassIdAt(i); | 11685 if (IsUsedAt(i)) { |
| 11660 if (test_class_id == class_id) { | 11686 const intptr_t test_class_id = GetReceiverClassIdAt(i); |
| 11661 return true; | 11687 if (test_class_id == class_id) { |
| 11688 return true; |
| 11689 } |
| 11662 } | 11690 } |
| 11663 } | 11691 } |
| 11664 return false; | 11692 return false; |
| 11665 } | 11693 } |
| 11666 | 11694 |
| 11667 | 11695 |
| 11668 // Returns true if all targets are the same. | 11696 // Returns true if all targets are the same. |
| 11669 // TODO(srdjan): if targets are native use their C_function to compare. | 11697 // TODO(srdjan): if targets are native use their C_function to compare. |
| 11670 bool ICData::HasOneTarget() const { | 11698 bool ICData::HasOneTarget() const { |
| 11671 ASSERT(NumberOfChecks() > 0); | 11699 ASSERT(NumberOfChecks() > 0); |
| 11672 const Function& first_target = Function::Handle(GetTargetAt(0)); | 11700 const Function& first_target = Function::Handle(GetTargetAt(0)); |
| 11673 const intptr_t len = NumberOfChecks(); | 11701 const intptr_t len = NumberOfChecks(); |
| 11674 for (intptr_t i = 1; i < len; i++) { | 11702 for (intptr_t i = 1; i < len; i++) { |
| 11675 if (GetTargetAt(i) != first_target.raw()) { | 11703 if (IsUsedAt(i) && (GetTargetAt(i) != first_target.raw())) { |
| 11676 return false; | 11704 return false; |
| 11677 } | 11705 } |
| 11678 } | 11706 } |
| 11679 return true; | 11707 return true; |
| 11680 } | 11708 } |
| 11681 | 11709 |
| 11682 | 11710 |
| 11711 void ICData::GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, |
| 11712 GrowableArray<intptr_t>* second) const { |
| 11713 ASSERT(NumArgsTested() == 2); |
| 11714 first->Clear(); |
| 11715 second->Clear(); |
| 11716 Function& target = Function::Handle(); |
| 11717 GrowableArray<intptr_t> class_ids; |
| 11718 const intptr_t len = NumberOfChecks(); |
| 11719 for (intptr_t i = 0; i < len; i++) { |
| 11720 if (GetCountAt(i) > 0) { |
| 11721 GetCheckAt(i, &class_ids, &target); |
| 11722 ASSERT(class_ids.length() == 2); |
| 11723 first->Add(class_ids[0]); |
| 11724 second->Add(class_ids[1]); |
| 11725 } |
| 11726 } |
| 11727 } |
| 11728 |
| 11729 |
| 11730 bool ICData::IsUsedAt(intptr_t i) const { |
| 11731 if (GetCountAt(i) <= 0) { |
| 11732 // Do not mistake unoptimized static call ICData for unused. |
| 11733 // See ICData::AddTarget. |
| 11734 // TODO(srdjan): Make this test more robust. |
| 11735 if (NumArgsTested() > 0) { |
| 11736 const intptr_t cid = GetReceiverClassIdAt(i); |
| 11737 if (cid == kObjectCid) { |
| 11738 return true; |
| 11739 } |
| 11740 } |
| 11741 return false; |
| 11742 } |
| 11743 return true; |
| 11744 } |
| 11745 |
| 11746 |
| 11683 RawICData* ICData::New(const Function& owner, | 11747 RawICData* ICData::New(const Function& owner, |
| 11684 const String& target_name, | 11748 const String& target_name, |
| 11685 const Array& arguments_descriptor, | 11749 const Array& arguments_descriptor, |
| 11686 intptr_t deopt_id, | 11750 intptr_t deopt_id, |
| 11687 intptr_t num_args_tested) { | 11751 intptr_t num_args_tested) { |
| 11688 ASSERT(!owner.IsNull()); | 11752 ASSERT(!owner.IsNull()); |
| 11689 ASSERT(!target_name.IsNull()); | 11753 ASSERT(!target_name.IsNull()); |
| 11690 ASSERT(!arguments_descriptor.IsNull()); | 11754 ASSERT(!arguments_descriptor.IsNull()); |
| 11691 ASSERT(Object::icdata_class() != Class::null()); | 11755 ASSERT(Object::icdata_class() != Class::null()); |
| 11692 ASSERT(num_args_tested >= 0); | 11756 ASSERT(num_args_tested >= 0); |
| (...skipping 7826 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 19519 return tag_label.ToCString(); | 19583 return tag_label.ToCString(); |
| 19520 } | 19584 } |
| 19521 | 19585 |
| 19522 | 19586 |
| 19523 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19587 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 19524 Instance::PrintJSONImpl(stream, ref); | 19588 Instance::PrintJSONImpl(stream, ref); |
| 19525 } | 19589 } |
| 19526 | 19590 |
| 19527 | 19591 |
| 19528 } // namespace dart | 19592 } // namespace dart |
| OLD | NEW |