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 6616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6627 } | 6627 } |
| 6628 } | 6628 } |
| 6629 | 6629 |
| 6630 | 6630 |
| 6631 void Function::RestoreICDataMap( | 6631 void Function::RestoreICDataMap( |
| 6632 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { | 6632 ZoneGrowableArray<const ICData*>* deopt_id_to_ic_data) const { |
| 6633 Isolate* isolate = Isolate::Current(); | 6633 Isolate* isolate = Isolate::Current(); |
| 6634 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); | 6634 const Array& saved_icd = Array::Handle(isolate, ic_data_array()); |
| 6635 if (saved_icd.Length() == 0) { | 6635 if (saved_icd.Length() == 0) { |
| 6636 deopt_id_to_ic_data->Clear(); | 6636 deopt_id_to_ic_data->Clear(); |
| 6637 return;; | 6637 return; |
| 6638 } | 6638 } |
| 6639 ICData& icd = ICData::Handle(); | 6639 ICData& icd = ICData::Handle(); |
| 6640 icd ^= saved_icd.At(saved_icd.Length() - 1); | 6640 icd ^= saved_icd.At(saved_icd.Length() - 1); |
| 6641 const intptr_t len = icd.deopt_id() + 1; | 6641 const intptr_t len = icd.deopt_id() + 1; |
| 6642 deopt_id_to_ic_data->SetLength(len); | 6642 deopt_id_to_ic_data->SetLength(len); |
| 6643 for (intptr_t i = 0; i < len; i++) { | 6643 for (intptr_t i = 0; i < len; i++) { |
| 6644 (*deopt_id_to_ic_data)[i] = NULL; | 6644 (*deopt_id_to_ic_data)[i] = NULL; |
| 6645 } | 6645 } |
| 6646 for (intptr_t i = 0; i < saved_icd.Length(); i++) { | 6646 for (intptr_t i = 0; i < saved_icd.Length(); i++) { |
| 6647 ICData& icd = ICData::ZoneHandle(isolate); | 6647 ICData& icd = ICData::ZoneHandle(isolate); |
| 6648 icd ^= saved_icd.At(i); | 6648 icd ^= saved_icd.At(i); |
| 6649 // Remove unused entries that have been added at creation time (e.g., | |
| 6650 // optimistic Smi/Smi assumption). | |
| 6651 if (icd.HasUnusedEntries()) { | |
| 6652 icd = icd.FilterUnusedEntries(); | |
| 6653 } | |
| 6649 (*deopt_id_to_ic_data)[icd.deopt_id()] = &icd; | 6654 (*deopt_id_to_ic_data)[icd.deopt_id()] = &icd; |
| 6650 } | 6655 } |
| 6651 } | 6656 } |
| 6652 | 6657 |
| 6653 | 6658 |
| 6654 void Function::set_ic_data_array(const Array& value) const { | 6659 void Function::set_ic_data_array(const Array& value) const { |
| 6655 StorePointer(&raw_ptr()->ic_data_array_, value.raw()); | 6660 StorePointer(&raw_ptr()->ic_data_array_, value.raw()); |
| 6656 } | 6661 } |
| 6657 | 6662 |
| 6658 | 6663 |
| (...skipping 4682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11341 ASSERT(!target.IsNull()); | 11346 ASSERT(!target.IsNull()); |
| 11342 if (NumArgsTested() > 0) { | 11347 if (NumArgsTested() > 0) { |
| 11343 // Create a fake cid entry, so that we can store the target. | 11348 // Create a fake cid entry, so that we can store the target. |
| 11344 GrowableArray<intptr_t> class_ids(NumArgsTested()); | 11349 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
| 11345 for (intptr_t i = 0; i < NumArgsTested(); i++) { | 11350 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
| 11346 class_ids.Add(kObjectCid); | 11351 class_ids.Add(kObjectCid); |
| 11347 } | 11352 } |
| 11348 AddCheck(class_ids, target); | 11353 AddCheck(class_ids, target); |
| 11349 return; | 11354 return; |
| 11350 } | 11355 } |
| 11351 ASSERT(NumArgsTested() >= 0); | 11356 ASSERT(NumArgsTested() == 0); |
| 11352 // Can add only once. | 11357 // Can add only once. |
| 11353 const intptr_t old_num = NumberOfChecks(); | 11358 const intptr_t old_num = NumberOfChecks(); |
| 11354 ASSERT(old_num == 0); | 11359 ASSERT(old_num == 0); |
| 11355 Array& data = Array::Handle(ic_data()); | 11360 Array& data = Array::Handle(ic_data()); |
| 11356 const intptr_t new_len = data.Length() + TestEntryLength(); | 11361 const intptr_t new_len = data.Length() + TestEntryLength(); |
| 11357 data = Array::Grow(data, new_len, Heap::kOld); | 11362 data = Array::Grow(data, new_len, Heap::kOld); |
| 11358 set_ic_data(data); | 11363 set_ic_data(data); |
| 11359 WriteSentinel(data); | 11364 WriteSentinel(data); |
| 11360 intptr_t data_pos = old_num * TestEntryLength(); | 11365 intptr_t data_pos = old_num * TestEntryLength(); |
| 11361 ASSERT(!target.IsNull()); | 11366 ASSERT(!target.IsNull()); |
| 11362 data.SetAt(data_pos++, target); | 11367 data.SetAt(data_pos++, target); |
| 11368 // Set count to 0 as this is called during compilation, before the | |
| 11369 // call has been executed. | |
| 11363 const Smi& value = Smi::Handle(Smi::New(0)); | 11370 const Smi& value = Smi::Handle(Smi::New(0)); |
| 11364 data.SetAt(data_pos, value); | 11371 data.SetAt(data_pos, value); |
| 11365 } | 11372 } |
| 11366 | 11373 |
| 11367 | 11374 |
| 11368 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 11375 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
| 11369 const Function& target) const { | 11376 const Function& target) const { |
| 11370 ASSERT(!target.IsNull()); | 11377 ASSERT(!target.IsNull()); |
| 11378 if (target.name() != target_name()) { | |
| 11379 OS::Print("%s vs %s\n", | |
| 11380 String::Handle(target.name()).ToCString(), | |
|
Cutch
2014/08/15 21:23:28
Should this be an ASSERT?
srdjan
2014/08/15 21:49:00
This is gone, forgot to upload after removing it.
| |
| 11381 String::Handle(target_name()).ToCString()); | |
| 11382 } | |
| 11383 ASSERT(target.name() == target_name()); | |
| 11371 DEBUG_ASSERT(!HasCheck(class_ids)); | 11384 DEBUG_ASSERT(!HasCheck(class_ids)); |
| 11372 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. | 11385 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. |
| 11373 ASSERT(class_ids.length() == NumArgsTested()); | 11386 ASSERT(class_ids.length() == NumArgsTested()); |
| 11374 const intptr_t old_num = NumberOfChecks(); | 11387 const intptr_t old_num = NumberOfChecks(); |
| 11375 Array& data = Array::Handle(ic_data()); | 11388 Array& data = Array::Handle(ic_data()); |
| 11376 // ICData of static calls with NumArgsTested() > 0 have initially a | 11389 // ICData of static calls with NumArgsTested() > 0 have initially a |
| 11377 // dummy set of cids entered (see ICData::AddTarget). That entry is | 11390 // dummy set of cids entered (see ICData::AddTarget). That entry is |
| 11378 // overwritten by first real type feedback data. | 11391 // overwritten by first real type feedback data. |
| 11379 if (old_num == 1) { | 11392 if (old_num == 1) { |
| 11380 bool has_dummy_entry = true; | 11393 bool has_dummy_entry = true; |
| (...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 11659 const intptr_t len = NumberOfChecks(); | 11672 const intptr_t len = NumberOfChecks(); |
| 11660 for (intptr_t i = 1; i < len; i++) { | 11673 for (intptr_t i = 1; i < len; i++) { |
| 11661 if (GetTargetAt(i) != first_target.raw()) { | 11674 if (GetTargetAt(i) != first_target.raw()) { |
| 11662 return false; | 11675 return false; |
| 11663 } | 11676 } |
| 11664 } | 11677 } |
| 11665 return true; | 11678 return true; |
| 11666 } | 11679 } |
| 11667 | 11680 |
| 11668 | 11681 |
| 11682 bool ICData::HasUnusedEntries() const { | |
| 11683 const intptr_t len = NumberOfChecks(); | |
| 11684 for (intptr_t i = 0; i < len; i++) { | |
| 11685 if (GetCountAt(i) == 0) { | |
| 11686 // Do not mistake unoptimized static call ICData for unused. | |
| 11687 // See ICData::AddTarget. | |
| 11688 // TODO(srdjan): Make this test more robust. | |
|
Cutch
2014/08/15 21:23:28
What about factoring this check into:
bool IsUnus
srdjan
2014/08/15 21:49:00
FilterUnusedEntries currently always creates a new
srdjan
2014/08/18 20:28:40
Discussed offline, misunderstood the comment.
Done
| |
| 11689 if (NumArgsTested() > 0) { | |
| 11690 const intptr_t cid = GetReceiverClassIdAt(i); | |
| 11691 if (cid != kObjectCid) { | |
| 11692 return true; | |
| 11693 } | |
| 11694 } | |
| 11695 } | |
| 11696 } | |
| 11697 return false; | |
| 11698 } | |
| 11699 | |
| 11700 | |
| 11701 RawICData* ICData::FilterUnusedEntries() const { | |
| 11702 ICData& result = ICData::Handle(ICData::New( | |
| 11703 Function::Handle(owner()), | |
| 11704 String::Handle(target_name()), | |
| 11705 Array::Handle(arguments_descriptor()), | |
| 11706 deopt_id(), | |
| 11707 NumArgsTested())); | |
| 11708 const intptr_t len = NumberOfChecks(); | |
| 11709 GrowableArray<intptr_t> class_ids; | |
| 11710 Function& target = Function::Handle(); | |
| 11711 for (intptr_t i = 0; i < len; i++) { | |
| 11712 const intptr_t count = GetCountAt(i); | |
| 11713 if (count <= 0) continue; | |
|
zra
2014/08/15 21:45:08
Above, GetCountAt(i) is checked for equality with
srdjan
2014/08/18 20:28:40
Done using Cutch's suggestion.
| |
| 11714 GetCheckAt(i, &class_ids, &target); | |
| 11715 result.AddCheck(class_ids, target); | |
| 11716 result.SetCountAt(result.NumberOfChecks() - 1, count); | |
| 11717 } | |
| 11718 return result.raw(); | |
| 11719 } | |
| 11720 | |
| 11721 | |
| 11669 RawICData* ICData::New(const Function& owner, | 11722 RawICData* ICData::New(const Function& owner, |
| 11670 const String& target_name, | 11723 const String& target_name, |
| 11671 const Array& arguments_descriptor, | 11724 const Array& arguments_descriptor, |
| 11672 intptr_t deopt_id, | 11725 intptr_t deopt_id, |
| 11673 intptr_t num_args_tested) { | 11726 intptr_t num_args_tested) { |
| 11674 ASSERT(!owner.IsNull()); | 11727 ASSERT(!owner.IsNull()); |
| 11675 ASSERT(!target_name.IsNull()); | 11728 ASSERT(!target_name.IsNull()); |
| 11676 ASSERT(!arguments_descriptor.IsNull()); | 11729 ASSERT(!arguments_descriptor.IsNull()); |
| 11677 ASSERT(Object::icdata_class() != Class::null()); | 11730 ASSERT(Object::icdata_class() != Class::null()); |
| 11678 ASSERT(num_args_tested >= 0); | 11731 ASSERT(num_args_tested >= 0); |
| (...skipping 7804 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19483 return tag_label.ToCString(); | 19536 return tag_label.ToCString(); |
| 19484 } | 19537 } |
| 19485 | 19538 |
| 19486 | 19539 |
| 19487 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { | 19540 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { |
| 19488 Instance::PrintJSONImpl(stream, ref); | 19541 Instance::PrintJSONImpl(stream, ref); |
| 19489 } | 19542 } |
| 19490 | 19543 |
| 19491 | 19544 |
| 19492 } // namespace dart | 19545 } // namespace dart |
| OLD | NEW |