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/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 6597 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6608 } | 6608 } |
| 6609 } | 6609 } |
| 6610 | 6610 |
| 6611 | 6611 |
| 6612 void Function::RestoreICDataMap( | 6612 void Function::RestoreICDataMap( |
| 6613 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { | 6613 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { |
| 6614 Isolate* isolate = Isolate::Current(); | 6614 Isolate* isolate = Isolate::Current(); |
| 6615 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); | 6615 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); |
| 6616 if (saved_icd.Length() == 0) { | 6616 if (saved_icd.Length() == 0) { |
| 6617 deopt_id_to_ic_data->Clear(); | 6617 deopt_id_to_ic_data->Clear(); |
| 6618 return;; | 6618 return; |
| 6619 } | 6619 } |
| 6620 ICData& icd = ICData::Handle(); | 6620 ICData& icd = ICData::Handle(); |
| 6621 icd ^= saved_icd.At(saved_icd.Length() - 1); | 6621 icd ^= saved_icd.At(saved_icd.Length() - 1); |
| 6622 const intptr_t len = icd.deopt_id() + 1; | 6622 const intptr_t len = icd.deopt_id() + 1; |
| 6623 deopt_id_to_ic_data->SetLength(len); | 6623 deopt_id_to_ic_data->SetLength(len); |
| 6624 for (intptr_t i = 0; i < len; i++) { | 6624 for (intptr_t i = 0; i < len; i++) { |
| 6625 (*deopt_id_to_ic_data)[i] = NULL; | 6625 (*deopt_id_to_ic_data)[i] = NULL; |
| 6626 } | 6626 } |
| 6627 for (intptr_t i = 0; i < saved_icd.Length(); i++) { | 6627 for (intptr_t i = 0; i < saved_icd.Length(); i++) { |
| 6628 ICData& icd = ICData::ZoneHandle(isolate); | 6628 ICData& icd = ICData::ZoneHandle(isolate); |
| (...skipping 4643 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11272 return TestEntryLengthFor(NumArgsTested()); | 11272 return TestEntryLengthFor(NumArgsTested()); |
| 11273 } | 11273 } |
| 11274 | 11274 |
| 11275 | 11275 |
| 11276 intptr_t ICData::NumberOfChecks() const { | 11276 intptr_t ICData::NumberOfChecks() const { |
| 11277 // Do not count the sentinel; | 11277 // Do not count the sentinel; |
| 11278 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; | 11278 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; |
| 11279 } | 11279 } |
| 11280 | 11280 |
| 11281 | 11281 |
| 11282 // Discounts any checks with usage of zero. | |
| 11283 intptr_t ICData::NumberOfUsedChecks() const { | |
| 11284 intptr_t n = NumberOfChecks(); | |
| 11285 if (n == 0) { | |
| 11286 return 0; | |
| 11287 } | |
| 11288 intptr_t count = 0; | |
| 11289 for (intptr_t i = 0; i < n; i++) { | |
| 11290 if (GetCountAt(i) > 0) { | |
| 11291 count++; | |
| 11292 } | |
| 11293 } | |
| 11294 return count; | |
| 11295 } | |
| 11296 | |
| 11297 | |
| 11282 void ICData::WriteSentinel(const Array& data) const { | 11298 void ICData::WriteSentinel(const Array& data) const { |
| 11283 ASSERT(!data.IsNull()); | 11299 ASSERT(!data.IsNull()); |
| 11284 for (intptr_t i = 1; i <= TestEntryLength(); i++) { | 11300 for (intptr_t i = 1; i <= TestEntryLength(); i++) { |
| 11285 data.SetAt(data.Length() - i, smi_illegal_cid()); | 11301 data.SetAt(data.Length() - i, smi_illegal_cid()); |
| 11286 } | 11302 } |
| 11287 } | 11303 } |
| 11288 | 11304 |
| 11289 | 11305 |
| 11290 #if defined(DEBUG) | 11306 #if defined(DEBUG) |
| 11291 // Used in asserts to verify that a check is not added twice. | 11307 // Used in asserts to verify that a check is not added twice. |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 11316 ASSERT(!target.IsNull()); | 11332 ASSERT(!target.IsNull()); |
| 11317 if (NumArgsTested() > 0) { | 11333 if (NumArgsTested() > 0) { |
| 11318 // Create a fake cid entry, so that we can store the target. | 11334 // Create a fake cid entry, so that we can store the target. |
| 11319 GrowableArray<intptr_t> class_ids(NumArgsTested()); | 11335 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
| 11320 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 11336 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 11321 class_ids.Add(kObjectCid); | 11337 class_ids.Add(kObjectCid); |
| 11322 } | 11338 } |
| 11323 AddCheck(class_ids, target); | 11339 AddCheck(class_ids, target); |
| 11324 return; | 11340 return; |
| 11325 } | 11341 } |
| 11326 ASSERT(NumArgsTested() >= 0); | 11342 ASSERT(NumArgsTested() == 0); |
| 11327 // Can add only once. | 11343 // Can add only once. |
| 11328 const intptr_t old_num = NumberOfChecks(); | 11344 const intptr_t old_num = NumberOfChecks(); |
| 11329 ASSERT(old_num == 0); | 11345 ASSERT(old_num == 0); |
| 11330 Array& data = Array::Handle(ic_data()); | 11346 Array& data = Array::Handle(ic_data()); |
| 11331 const intptr_t new_len = data.Length() + TestEntryLength(); | 11347 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 11332 data = Array::Grow(data, new_len, Heap::kOld); | 11348 data = Array::Grow(data, new_len, Heap::kOld); |
| 11333 set_ic_data(data); | 11349 set_ic_data(data); |
| 11334 WriteSentinel(data); | 11350 WriteSentinel(data); |
| 11335 intptr_t data_pos = old_num * TestEntryLength(); | 11351 intptr_t data_pos = old_num * TestEntryLength(); |
| 11336 ASSERT(!target.IsNull()); | 11352 ASSERT(!target.IsNull()); |
| 11337 data.SetAt(data_pos++, target); | 11353 data.SetAt(data_pos++, target); |
| 11354 // Set count to 0 as this is called during compilation, before the | |
| 11355 // call has been executed. | |
| 11338 const Smi& value = Smi::Handle(Smi::New(0)); | 11356 const Smi& value = Smi::Handle(Smi::New(0)); |
| 11339 data.SetAt(data_pos, value); | 11357 data.SetAt(data_pos, value); |
| 11340 } | 11358 } |
| 11341 | 11359 |
| 11342 | 11360 |
| 11343 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 11361 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
| 11344 const Function& target) const { | 11362 const Function& target) const { |
| 11345 ASSERT(!target.IsNull()); | 11363 ASSERT(!target.IsNull()); |
| 11364 ASSERT(target.name() == target_name()); | |
| 11346 DEBUG_ASSERT(!HasCheck(class_ids)); | 11365 DEBUG_ASSERT(!HasCheck(class_ids)); |
| 11347 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. | 11366 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. |
| 11348 ASSERT(class_ids.length() == NumArgsTested()); | 11367 ASSERT(class_ids.length() == NumArgsTested()); |
| 11349 const intptr_t old_num = NumberOfChecks(); | 11368 const intptr_t old_num = NumberOfChecks(); |
| 11350 Array& data = Array::Handle(ic_data()); | 11369 Array& data = Array::Handle(ic_data()); |
| 11351 // ICData of static calls with NumArgsTested() > 0 have initially a | 11370 // ICData of static calls with NumArgsTested() > 0 have initially a |
| 11352 // dummy set of cids entered (see ICData::AddTarget). That entry is | 11371 // dummy set of cids entered (see ICData::AddTarget). That entry is |
| 11353 // overwritten by first real type feedback data. | 11372 // overwritten by first real type feedback data. |
| 11354 if (old_num == 1) { | 11373 if (old_num == 1) { |
| 11355 bool has_dummy_entry = true; | 11374 bool has_dummy_entry = true; |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11547 ICData& result = ICData::Handle(ICData::New( | 11566 ICData& result = ICData::Handle(ICData::New( |
| 11548 Function::Handle(owner()), | 11567 Function::Handle(owner()), |
| 11549 String::Handle(target_name()), | 11568 String::Handle(target_name()), |
| 11550 Array::Handle(arguments_descriptor()), | 11569 Array::Handle(arguments_descriptor()), |
| 11551 deopt_id(), | 11570 deopt_id(), |
| 11552 kNumArgsTested)); | 11571 kNumArgsTested)); |
| 11553 const intptr_t len = NumberOfChecks(); | 11572 const intptr_t len = NumberOfChecks(); |
| 11554 for (intptr_t i = 0; i < len; i++) { | 11573 for (intptr_t i = 0; i < len; i++) { |
| 11555 const intptr_t class_id = GetClassIdAt(i, arg_nr); | 11574 const intptr_t class_id = GetClassIdAt(i, arg_nr); |
| 11556 const intptr_t count = GetCountAt(i); | 11575 const intptr_t count = GetCountAt(i); |
| 11576 if (count == 0) { | |
| 11577 continue; | |
| 11578 } | |
| 11557 intptr_t duplicate_class_id = -1; | 11579 intptr_t duplicate_class_id = -1; |
| 11558 const intptr_t result_len = result.NumberOfChecks(); | 11580 const intptr_t result_len = result.NumberOfChecks(); |
| 11559 for (intptr_t k = 0; k < result_len; k++) { | 11581 for (intptr_t k = 0; k < result_len; k++) { |
| 11560 if (class_id == result.GetReceiverClassIdAt(k)) { | 11582 if (class_id == result.GetReceiverClassIdAt(k)) { |
| 11561 duplicate_class_id = k; | 11583 duplicate_class_id = k; |
| 11562 break; | 11584 break; |
| 11563 } | 11585 } |
| 11564 } | 11586 } |
| 11565 if (duplicate_class_id >= 0) { | 11587 if (duplicate_class_id >= 0) { |
| 11566 // This check is valid only when checking the receiver. | 11588 // This check is valid only when checking the receiver. |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 11579 | 11601 |
| 11580 return result.raw(); | 11602 return result.raw(); |
| 11581 } | 11603 } |
| 11582 | 11604 |
| 11583 | 11605 |
| 11584 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { | 11606 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { |
| 11585 if (NumberOfChecks() == 0) return false; | 11607 if (NumberOfChecks() == 0) return false; |
| 11586 Class& cls = Class::Handle(); | 11608 Class& cls = Class::Handle(); |
| 11587 const intptr_t len = NumberOfChecks(); | 11609 const intptr_t len = NumberOfChecks(); |
| 11588 for (intptr_t i = 0; i < len; i++) { | 11610 for (intptr_t i = 0; i < len; i++) { |
| 11589 cls = Function::Handle(GetTargetAt(i)).Owner(); | 11611 if (IsUsedAt(i)) { |
| 11590 if (cls.id() != owner_cid) { | 11612 cls = Function::Handle(GetTargetAt(i)).Owner(); |
| 11591 return false; | 11613 if (cls.id() != owner_cid) { |
| 11614 return false; | |
| 11615 } | |
| 11592 } | 11616 } |
| 11593 } | 11617 } |
| 11594 return true; | 11618 return true; |
| 11595 } | 11619 } |
| 11596 | 11620 |
| 11597 | 11621 |
| 11598 bool ICData::AllReceiversAreNumbers() const { | 11622 bool ICData::AllReceiversAreNumbers() const { |
| 11599 if (NumberOfChecks() == 0) return false; | 11623 if (NumberOfChecks() == 0) return false; |
| 11600 Class& cls = Class::Handle(); | 11624 Class& cls = Class::Handle(); |
| 11601 const intptr_t len = NumberOfChecks(); | 11625 const intptr_t len = NumberOfChecks(); |
| 11602 for (intptr_t i = 0; i < len; i++) { | 11626 for (intptr_t i = 0; i < len; i++) { |
| 11603 cls = Function::Handle(GetTargetAt(i)).Owner(); | 11627 if (IsUsedAt(i)) { |
| 11604 const intptr_t cid = cls.id(); | 11628 cls = Function::Handle(GetTargetAt(i)).Owner(); |
| 11605 if ((cid != kSmiCid) && | 11629 const intptr_t cid = cls.id(); |
| 11606 (cid != kMintCid) && | 11630 if ((cid != kSmiCid) && |
| 11607 (cid != kBigintCid) && | 11631 (cid != kMintCid) && |
| 11608 (cid != kDoubleCid)) { | 11632 (cid != kBigintCid) && |
| 11609 return false; | 11633 (cid != kDoubleCid)) { |
| 11634 return false; | |
| 11635 } | |
| 11610 } | 11636 } |
| 11611 } | 11637 } |
| 11612 return true; | 11638 return true; |
| 11613 } | 11639 } |
| 11614 | 11640 |
| 11615 | 11641 |
| 11616 bool ICData::HasReceiverClassId(intptr_t class_id) const { | 11642 bool ICData::HasReceiverClassId(intptr_t class_id) const { |
| 11617 ASSERT(NumArgsTested() > 0); | 11643 ASSERT(NumArgsTested() > 0); |
| 11618 const intptr_t len = NumberOfChecks(); | 11644 const intptr_t len = NumberOfChecks(); |
| 11619 for (intptr_t i = 0; i < len; i++) { | 11645 for (intptr_t i = 0; i < len; i++) { |
| 11620 const intptr_t test_class_id = GetReceiverClassIdAt(i); | 11646 if (IsUsedAt(i)) { |
| 11621 if (test_class_id == class_id) { | 11647 const intptr_t test_class_id = GetReceiverClassIdAt(i); |
| 11622 return true; | 11648 if (test_class_id == class_id) { |
| 11649 return true; | |
| 11650 } | |
| 11623 } | 11651 } |
| 11624 } | 11652 } |
| 11625 return false; | 11653 return false; |
| 11626 } | 11654 } |
| 11627 | 11655 |
| 11628 | 11656 |
| 11629 // Returns true if all targets are the same. | 11657 // Returns true if all targets are the same. |
| 11630 // TODO(srdjan): if targets are native use their C_function to compare. | 11658 // TODO(srdjan): if targets are native use their C_function to compare. |
| 11631 bool ICData::HasOneTarget() const { | 11659 bool ICData::HasOneTarget() const { |
| 11632 ASSERT(NumberOfChecks() > 0); | 11660 ASSERT(NumberOfChecks() > 0); |
| 11633 const Function& first_target = Function::Handle(GetTargetAt(0)); | 11661 const Function& first_target = Function::Handle(GetTargetAt(0)); |
| 11634 const intptr_t len = NumberOfChecks(); | 11662 const intptr_t len = NumberOfChecks(); |
| 11635 for (intptr_t i = 1; i < len; i++) { | 11663 for (intptr_t i = 1; i < len; i++) { |
| 11636 if (GetTargetAt(i) != first_target.raw()) { | 11664 if (IsUsedAt(i) && (GetTargetAt(i) != first_target.raw())) { |
| 11637 return false; | 11665 return false; |
| 11638 } | 11666 } |
| 11639 } | 11667 } |
| 11640 return true; | 11668 return true; |
| 11641 } | 11669 } |
| 11642 | 11670 |
| 11643 | 11671 |
| 11672 void ICData::GetUsedCidsForTwoArgs(GrowableArray<intptr_t>* first, | |
| 11673 GrowableArray<intptr_t>* second) const { | |
| 11674 ASSERT(NumArgsTested() == 2); | |
| 11675 first->Clear(); | |
| 11676 second->Clear(); | |
| 11677 Function& target = Function::Handle(); | |
| 11678 GrowableArray<intptr_t> class_ids; | |
| 11679 const intptr_t len = NumberOfChecks(); | |
| 11680 for (intptr_t i = 0; i < len; i++) { | |
| 11681 if (GetCountAt(i) > 0) { | |
| 11682 GetCheckAt(i, &class_ids, &target); | |
| 11683 ASSERT(class_ids.length() == 2); | |
| 11684 first->Add(class_ids[0]); | |
| 11685 second->Add(class_ids[1]); | |
| 11686 } | |
| 11687 } | |
| 11688 } | |
| 11689 | |
| 11690 | |
| 11691 bool ICData::IsUsedAt(intptr_t i) const { | |
| 11692 if (GetCountAt(i) <= 0) { | |
| 11693 // Do not mistake unoptimized static call ICData for unused. | |
| 11694 // See ICData::AddTarget. | |
| 11695 // TODO(srdjan): Make this test more robust. | |
| 11696 if (NumArgsTested() > 0) { | |
| 11697 const intptr_t cid = GetReceiverClassIdAt(i); | |
| 11698 if (cid == kObjectCid) { | |
| 11699 return true; | |
| 11700 } | |
| 11701 } | |
| 11702 return false; | |
| 11703 } | |
| 11704 return true; | |
| 11705 } | |
| 11706 | |
| 11707 | |
| 11708 | |
|
zra
2014/08/20 20:17:10
Extra newline.
srdjan
2014/08/21 17:30:22
removed
| |
| 11644 RawICData* ICData::New(const Function& owner, | 11709 RawICData* ICData::New(const Function& owner, |
| 11645 const String& target_name, | 11710 const String& target_name, |
| 11646 const Array& arguments_descriptor, | 11711 const Array& arguments_descriptor, |
| 11647 intptr_t deopt_id, | 11712 intptr_t deopt_id, |
| 11648 intptr_t num_args_tested) { | 11713 intptr_t num_args_tested) { |
| 11649 ASSERT(!owner.IsNull()); | 11714 ASSERT(!owner.IsNull()); |
| 11650 ASSERT(!target_name.IsNull()); | 11715 ASSERT(!target_name.IsNull()); |
| 11651 ASSERT(!arguments_descriptor.IsNull()); | 11716 ASSERT(!arguments_descriptor.IsNull()); |
| 11652 ASSERT(Object::icdata_class() != Class::null()); | 11717 ASSERT(Object::icdata_class() != Class::null()); |
| 11653 ASSERT(num_args_tested >= 0); | 11718 ASSERT(num_args_tested >= 0); |
| (...skipping 7819 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19473 return tag_label.ToCString(); | 19538 return tag_label.ToCString(); |
| 19474 } | 19539 } |
| 19475 | 19540 |
| 19476 | 19541 |
| 19477 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19542 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 19478 Instance::PrintJSONImpl(stream, ref); | 19543 Instance::PrintJSONImpl(stream, ref); |
| 19479 } | 19544 } |
| 19480 | 19545 |
| 19481 | 19546 |
| 19482 } // namespace dart | 19547 } // namespace dart |
| OLD | NEW |