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 10690 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10701 } | 10701 } |
10702 #endif // DEBUG | 10702 #endif // DEBUG |
10703 } | 10703 } |
10704 | 10704 |
10705 | 10705 |
10706 bool Code::HasBreakpoint() const { | 10706 bool Code::HasBreakpoint() const { |
10707 return Isolate::Current()->debugger()->HasBreakpoint(*this); | 10707 return Isolate::Current()->debugger()->HasBreakpoint(*this); |
10708 } | 10708 } |
10709 | 10709 |
10710 | 10710 |
10711 RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc, intptr_t* deopt_reason) const { | 10711 RawDeoptInfo* Code::GetDeoptInfoAtPc(uword pc, |
10712 DeoptReasonId* deopt_reason) const { | |
10712 ASSERT(is_optimized()); | 10713 ASSERT(is_optimized()); |
10713 const Instructions& instrs = Instructions::Handle(instructions()); | 10714 const Instructions& instrs = Instructions::Handle(instructions()); |
10714 uword code_entry = instrs.EntryPoint(); | 10715 uword code_entry = instrs.EntryPoint(); |
10715 const Array& table = Array::Handle(deopt_info_array()); | 10716 const Array& table = Array::Handle(deopt_info_array()); |
10716 ASSERT(!table.IsNull()); | 10717 ASSERT(!table.IsNull()); |
10717 // Linear search for the PC offset matching the target PC. | 10718 // Linear search for the PC offset matching the target PC. |
10718 intptr_t length = DeoptTable::GetLength(table); | 10719 intptr_t length = DeoptTable::GetLength(table); |
10719 Smi& offset = Smi::Handle(); | 10720 Smi& offset = Smi::Handle(); |
10720 Smi& reason = Smi::Handle(); | 10721 Smi& reason = Smi::Handle(); |
10721 DeoptInfo& info = DeoptInfo::Handle(); | 10722 DeoptInfo& info = DeoptInfo::Handle(); |
10722 for (intptr_t i = 0; i < length; ++i) { | 10723 for (intptr_t i = 0; i < length; ++i) { |
10723 DeoptTable::GetEntry(table, i, &offset, &info, &reason); | 10724 DeoptTable::GetEntry(table, i, &offset, &info, &reason); |
10724 if (pc == (code_entry + offset.Value())) { | 10725 if (pc == (code_entry + offset.Value())) { |
10725 ASSERT(!info.IsNull()); | 10726 ASSERT(!info.IsNull()); |
10726 *deopt_reason = reason.Value(); | 10727 ASSERT(static_cast<uword>(reason.Value()) < kDeoptNumReasons); |
srdjan
2014/04/25 20:54:16
Why the cast?
regis
2014/04/25 23:38:28
Done.
Casting to unsigned was to catch negative va
| |
10728 *deopt_reason = static_cast<DeoptReasonId>(reason.Value()); | |
10727 return info.raw(); | 10729 return info.raw(); |
10728 } | 10730 } |
10729 } | 10731 } |
10730 *deopt_reason = kDeoptUnknown; | 10732 *deopt_reason = kDeoptUnknown; |
10731 return DeoptInfo::null(); | 10733 return DeoptInfo::null(); |
10732 } | 10734 } |
10733 | 10735 |
10734 | 10736 |
10735 intptr_t Code::BinarySearchInSCallTable(uword pc) const { | 10737 intptr_t Code::BinarySearchInSCallTable(uword pc) const { |
10736 NoGCScope no_gc; | 10738 NoGCScope no_gc; |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
11410 | 11412 |
11411 void ContextScope::PrintToJSONStream(JSONStream* stream, bool ref) const { | 11413 void ContextScope::PrintToJSONStream(JSONStream* stream, bool ref) const { |
11412 Object::PrintToJSONStream(stream, ref); | 11414 Object::PrintToJSONStream(stream, ref); |
11413 } | 11415 } |
11414 | 11416 |
11415 | 11417 |
11416 const char* ICData::ToCString() const { | 11418 const char* ICData::ToCString() const { |
11417 const char* kFormat = "ICData target:'%s' num-args: %" Pd | 11419 const char* kFormat = "ICData target:'%s' num-args: %" Pd |
11418 " num-checks: %" Pd ""; | 11420 " num-checks: %" Pd ""; |
11419 const String& name = String::Handle(target_name()); | 11421 const String& name = String::Handle(target_name()); |
11420 const intptr_t num_args = num_args_tested(); | 11422 const intptr_t num_args = NumArgsTested(); |
11421 const intptr_t num_checks = NumberOfChecks(); | 11423 const intptr_t num_checks = NumberOfChecks(); |
11422 intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString(), | 11424 intptr_t len = OS::SNPrint(NULL, 0, kFormat, name.ToCString(), |
11423 num_args, num_checks) + 1; | 11425 num_args, num_checks) + 1; |
11424 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 11426 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
11425 OS::SNPrint(chars, len, kFormat, name.ToCString(), num_args, num_checks); | 11427 OS::SNPrint(chars, len, kFormat, name.ToCString(), num_args, num_checks); |
11426 return chars; | 11428 return chars; |
11427 } | 11429 } |
11428 | 11430 |
11429 | 11431 |
11430 void ICData::set_function(const Function& value) const { | 11432 void ICData::set_owner(const Function& value) const { |
11431 ASSERT(!value.IsNull()); | 11433 ASSERT(!value.IsNull()); |
11432 StorePointer(&raw_ptr()->function_, value.raw()); | 11434 StorePointer(&raw_ptr()->owner_, value.raw()); |
11433 } | 11435 } |
11434 | 11436 |
11435 | 11437 |
11436 void ICData::set_target_name(const String& value) const { | 11438 void ICData::set_target_name(const String& value) const { |
11437 ASSERT(!value.IsNull()); | 11439 ASSERT(!value.IsNull()); |
11438 StorePointer(&raw_ptr()->target_name_, value.raw()); | 11440 StorePointer(&raw_ptr()->target_name_, value.raw()); |
11439 } | 11441 } |
11440 | 11442 |
11441 | 11443 |
11442 void ICData::set_arguments_descriptor(const Array& value) const { | 11444 void ICData::set_arguments_descriptor(const Array& value) const { |
11443 ASSERT(!value.IsNull()); | 11445 ASSERT(!value.IsNull()); |
11444 StorePointer(&raw_ptr()->args_descriptor_, value.raw()); | 11446 StorePointer(&raw_ptr()->args_descriptor_, value.raw()); |
11445 } | 11447 } |
11446 | 11448 |
11447 void ICData::set_deopt_id(intptr_t value) const { | 11449 void ICData::set_deopt_id(intptr_t value) const { |
11450 ASSERT(value <= kMaxInt32); | |
11448 raw_ptr()->deopt_id_ = value; | 11451 raw_ptr()->deopt_id_ = value; |
11449 } | 11452 } |
11450 | 11453 |
11451 | 11454 |
11452 void ICData::set_num_args_tested(intptr_t value) const { | |
11453 raw_ptr()->num_args_tested_ = value; | |
11454 } | |
11455 | |
11456 | |
11457 void ICData::set_ic_data(const Array& value) const { | 11455 void ICData::set_ic_data(const Array& value) const { |
11458 ASSERT(!value.IsNull()); | 11456 ASSERT(!value.IsNull()); |
11459 StorePointer(&raw_ptr()->ic_data_, value.raw()); | 11457 StorePointer(&raw_ptr()->ic_data_, value.raw()); |
11460 } | 11458 } |
11461 | 11459 |
11462 | 11460 |
11463 void ICData::set_deopt_reason(intptr_t deopt_reason) const { | 11461 intptr_t ICData::NumArgsTested() const { |
11464 raw_ptr()->deopt_reason_ = deopt_reason; | 11462 return NumArgsTestedBits::decode(raw_ptr()->state_bits_); |
11465 } | 11463 } |
11466 | 11464 |
11467 void ICData::set_is_closure_call(bool value) const { | 11465 |
11468 raw_ptr()->is_closure_call_ = value ? 1 : 0; | 11466 void ICData::SetNumArgsTested(intptr_t value) const { |
11467 ASSERT(Utils::IsUint(2, value)); | |
11468 raw_ptr()->state_bits_ = | |
11469 NumArgsTestedBits::update(value, raw_ptr()->state_bits_); | |
11470 } | |
11471 | |
11472 | |
11473 uint32_t ICData::DeoptReasons() const { | |
11474 return DeoptReasonBits::decode(raw_ptr()->state_bits_); | |
11475 } | |
11476 | |
11477 | |
11478 void ICData::SetDeoptReasons(uint32_t reasons) const { | |
11479 raw_ptr()->state_bits_ = | |
11480 DeoptReasonBits::update(reasons, raw_ptr()->state_bits_); | |
11481 } | |
11482 | |
11483 | |
11484 bool ICData::HasDeoptReason(DeoptReasonId reason) const { | |
11485 return (DeoptReasons() & (1 << reason)) != 0; | |
11486 } | |
11487 | |
11488 | |
11489 void ICData::AddDeoptReason(DeoptReasonId reason) const { | |
11490 SetDeoptReasons(DeoptReasons() | (1 << reason)); | |
11491 } | |
11492 | |
11493 | |
11494 bool ICData::IssuedJSWarning() const { | |
11495 return IssuedJSWarningBit::decode(raw_ptr()->state_bits_); | |
11496 } | |
11497 | |
11498 | |
11499 void ICData::SetIssuedJSWarning() const { | |
11500 raw_ptr()->state_bits_ = | |
11501 IssuedJSWarningBit::update(true, raw_ptr()->state_bits_); | |
11502 } | |
11503 | |
11504 | |
11505 bool ICData::IsClosureCall() const { | |
11506 return IsClosureCallBit::decode(raw_ptr()->state_bits_); | |
11507 } | |
11508 | |
11509 | |
11510 void ICData::SetIsClosureCall() const { | |
11511 raw_ptr()->state_bits_ = | |
11512 IsClosureCallBit::update(true, raw_ptr()->state_bits_); | |
11513 } | |
11514 | |
11515 | |
11516 void ICData::set_state_bits(uint32_t bits) const { | |
11517 raw_ptr()->state_bits_ = bits; | |
11469 } | 11518 } |
11470 | 11519 |
11471 | 11520 |
11472 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { | 11521 intptr_t ICData::TestEntryLengthFor(intptr_t num_args) { |
11473 return num_args + 1 /* target function*/ + 1 /* frequency */; | 11522 return num_args + 1 /* target function*/ + 1 /* frequency */; |
11474 } | 11523 } |
11475 | 11524 |
11476 | 11525 |
11477 intptr_t ICData::TestEntryLength() const { | 11526 intptr_t ICData::TestEntryLength() const { |
11478 return TestEntryLengthFor(num_args_tested()); | 11527 return TestEntryLengthFor(NumArgsTested()); |
11479 } | 11528 } |
11480 | 11529 |
11481 | 11530 |
11482 intptr_t ICData::NumberOfChecks() const { | 11531 intptr_t ICData::NumberOfChecks() const { |
11483 // Do not count the sentinel; | 11532 // Do not count the sentinel; |
11484 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; | 11533 return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength()) - 1; |
11485 } | 11534 } |
11486 | 11535 |
11487 | 11536 |
11488 void ICData::WriteSentinel(const Array& data) const { | 11537 void ICData::WriteSentinel(const Array& data) const { |
(...skipping 24 matching lines...) Expand all Loading... | |
11513 } | 11562 } |
11514 } | 11563 } |
11515 return false; | 11564 return false; |
11516 } | 11565 } |
11517 #endif // DEBUG | 11566 #endif // DEBUG |
11518 | 11567 |
11519 | 11568 |
11520 // Used for unoptimized static calls when no class-ids are checked. | 11569 // Used for unoptimized static calls when no class-ids are checked. |
11521 void ICData::AddTarget(const Function& target) const { | 11570 void ICData::AddTarget(const Function& target) const { |
11522 ASSERT(!target.IsNull()); | 11571 ASSERT(!target.IsNull()); |
11523 if (num_args_tested() > 0) { | 11572 if (NumArgsTested() > 0) { |
11524 // Create a fake cid entry, so that we can store the target. | 11573 // Create a fake cid entry, so that we can store the target. |
11525 GrowableArray<intptr_t> class_ids(num_args_tested()); | 11574 GrowableArray<intptr_t> class_ids(NumArgsTested()); |
11526 for (intptr_t i = 0; i < num_args_tested(); i++) { | 11575 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
11527 class_ids.Add(kObjectCid); | 11576 class_ids.Add(kObjectCid); |
11528 } | 11577 } |
11529 AddCheck(class_ids, target); | 11578 AddCheck(class_ids, target); |
11530 return; | 11579 return; |
11531 } | 11580 } |
11532 ASSERT(num_args_tested() >= 0); | 11581 ASSERT(NumArgsTested() >= 0); |
11533 // Can add only once. | 11582 // Can add only once. |
11534 const intptr_t old_num = NumberOfChecks(); | 11583 const intptr_t old_num = NumberOfChecks(); |
11535 ASSERT(old_num == 0); | 11584 ASSERT(old_num == 0); |
11536 Array& data = Array::Handle(ic_data()); | 11585 Array& data = Array::Handle(ic_data()); |
11537 const intptr_t new_len = data.Length() + TestEntryLength(); | 11586 const intptr_t new_len = data.Length() + TestEntryLength(); |
11538 data = Array::Grow(data, new_len, Heap::kOld); | 11587 data = Array::Grow(data, new_len, Heap::kOld); |
11539 set_ic_data(data); | 11588 set_ic_data(data); |
11540 WriteSentinel(data); | 11589 WriteSentinel(data); |
11541 intptr_t data_pos = old_num * TestEntryLength(); | 11590 intptr_t data_pos = old_num * TestEntryLength(); |
11542 ASSERT(!target.IsNull()); | 11591 ASSERT(!target.IsNull()); |
11543 data.SetAt(data_pos++, target); | 11592 data.SetAt(data_pos++, target); |
11544 const Smi& value = Smi::Handle(Smi::New(0)); | 11593 const Smi& value = Smi::Handle(Smi::New(0)); |
11545 data.SetAt(data_pos, value); | 11594 data.SetAt(data_pos, value); |
11546 } | 11595 } |
11547 | 11596 |
11548 | 11597 |
11549 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, | 11598 void ICData::AddCheck(const GrowableArray<intptr_t>& class_ids, |
11550 const Function& target) const { | 11599 const Function& target) const { |
11551 ASSERT(!target.IsNull()); | 11600 ASSERT(!target.IsNull()); |
11552 DEBUG_ASSERT(!HasCheck(class_ids)); | 11601 DEBUG_ASSERT(!HasCheck(class_ids)); |
11553 ASSERT(num_args_tested() > 1); // Otherwise use 'AddReceiverCheck'. | 11602 ASSERT(NumArgsTested() > 1); // Otherwise use 'AddReceiverCheck'. |
11554 ASSERT(class_ids.length() == num_args_tested()); | 11603 ASSERT(class_ids.length() == NumArgsTested()); |
11555 const intptr_t old_num = NumberOfChecks(); | 11604 const intptr_t old_num = NumberOfChecks(); |
11556 Array& data = Array::Handle(ic_data()); | 11605 Array& data = Array::Handle(ic_data()); |
11557 // ICData of static calls with num_args_tested() > 0 have initially a | 11606 // ICData of static calls with NumArgsTested() > 0 have initially a |
11558 // dummy set of cids entered (see ICData::AddTarget). That entry is | 11607 // dummy set of cids entered (see ICData::AddTarget). That entry is |
11559 // overwritten by first real type feedback data. | 11608 // overwritten by first real type feedback data. |
11560 if (old_num == 1) { | 11609 if (old_num == 1) { |
11561 bool has_dummy_entry = true; | 11610 bool has_dummy_entry = true; |
11562 for (intptr_t i = 0; i < num_args_tested(); i++) { | 11611 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
11563 if (Smi::Value(Smi::RawCast(data.At(i))) != kObjectCid) { | 11612 if (Smi::Value(Smi::RawCast(data.At(i))) != kObjectCid) { |
11564 has_dummy_entry = false; | 11613 has_dummy_entry = false; |
11565 break; | 11614 break; |
11566 } | 11615 } |
11567 } | 11616 } |
11568 if (has_dummy_entry) { | 11617 if (has_dummy_entry) { |
11569 ASSERT(target.raw() == data.At(num_args_tested())); | 11618 ASSERT(target.raw() == data.At(NumArgsTested())); |
11570 // Replace dummy entry. | 11619 // Replace dummy entry. |
11571 Smi& value = Smi::Handle(); | 11620 Smi& value = Smi::Handle(); |
11572 for (intptr_t i = 0; i < num_args_tested(); i++) { | 11621 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
11573 ASSERT(class_ids[i] != kIllegalCid); | 11622 ASSERT(class_ids[i] != kIllegalCid); |
11574 value = Smi::New(class_ids[i]); | 11623 value = Smi::New(class_ids[i]); |
11575 data.SetAt(i, value); | 11624 data.SetAt(i, value); |
11576 } | 11625 } |
11577 return; | 11626 return; |
11578 } | 11627 } |
11579 } | 11628 } |
11580 const intptr_t new_len = data.Length() + TestEntryLength(); | 11629 const intptr_t new_len = data.Length() + TestEntryLength(); |
11581 data = Array::Grow(data, new_len, Heap::kOld); | 11630 data = Array::Grow(data, new_len, Heap::kOld); |
11582 set_ic_data(data); | 11631 set_ic_data(data); |
(...skipping 15 matching lines...) Expand all Loading... | |
11598 | 11647 |
11599 void ICData::AddReceiverCheck(intptr_t receiver_class_id, | 11648 void ICData::AddReceiverCheck(intptr_t receiver_class_id, |
11600 const Function& target, | 11649 const Function& target, |
11601 intptr_t count) const { | 11650 intptr_t count) const { |
11602 #if defined(DEBUG) | 11651 #if defined(DEBUG) |
11603 GrowableArray<intptr_t> class_ids(1); | 11652 GrowableArray<intptr_t> class_ids(1); |
11604 class_ids.Add(receiver_class_id); | 11653 class_ids.Add(receiver_class_id); |
11605 ASSERT(!HasCheck(class_ids)); | 11654 ASSERT(!HasCheck(class_ids)); |
11606 #endif // DEBUG | 11655 #endif // DEBUG |
11607 ASSERT(!target.IsNull()); | 11656 ASSERT(!target.IsNull()); |
11608 ASSERT(num_args_tested() == 1); // Otherwise use 'AddCheck'. | 11657 ASSERT(NumArgsTested() == 1); // Otherwise use 'AddCheck'. |
11609 ASSERT(receiver_class_id != kIllegalCid); | 11658 ASSERT(receiver_class_id != kIllegalCid); |
11610 | 11659 |
11611 const intptr_t old_num = NumberOfChecks(); | 11660 const intptr_t old_num = NumberOfChecks(); |
11612 Array& data = Array::Handle(ic_data()); | 11661 Array& data = Array::Handle(ic_data()); |
11613 const intptr_t new_len = data.Length() + TestEntryLength(); | 11662 const intptr_t new_len = data.Length() + TestEntryLength(); |
11614 data = Array::Grow(data, new_len, Heap::kOld); | 11663 data = Array::Grow(data, new_len, Heap::kOld); |
11615 set_ic_data(data); | 11664 set_ic_data(data); |
11616 WriteSentinel(data); | 11665 WriteSentinel(data); |
11617 intptr_t data_pos = old_num * TestEntryLength(); | 11666 intptr_t data_pos = old_num * TestEntryLength(); |
11618 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { | 11667 if ((receiver_class_id == kSmiCid) && (data_pos > 0)) { |
(...skipping 13 matching lines...) Expand all Loading... | |
11632 | 11681 |
11633 void ICData::GetCheckAt(intptr_t index, | 11682 void ICData::GetCheckAt(intptr_t index, |
11634 GrowableArray<intptr_t>* class_ids, | 11683 GrowableArray<intptr_t>* class_ids, |
11635 Function* target) const { | 11684 Function* target) const { |
11636 ASSERT(index < NumberOfChecks()); | 11685 ASSERT(index < NumberOfChecks()); |
11637 ASSERT(class_ids != NULL); | 11686 ASSERT(class_ids != NULL); |
11638 ASSERT(target != NULL); | 11687 ASSERT(target != NULL); |
11639 class_ids->Clear(); | 11688 class_ids->Clear(); |
11640 const Array& data = Array::Handle(ic_data()); | 11689 const Array& data = Array::Handle(ic_data()); |
11641 intptr_t data_pos = index * TestEntryLength(); | 11690 intptr_t data_pos = index * TestEntryLength(); |
11642 for (intptr_t i = 0; i < num_args_tested(); i++) { | 11691 for (intptr_t i = 0; i < NumArgsTested(); i++) { |
11643 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); | 11692 class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++)))); |
11644 } | 11693 } |
11645 (*target) ^= data.At(data_pos++); | 11694 (*target) ^= data.At(data_pos++); |
11646 } | 11695 } |
11647 | 11696 |
11648 | 11697 |
11649 void ICData::GetOneClassCheckAt(intptr_t index, | 11698 void ICData::GetOneClassCheckAt(intptr_t index, |
11650 intptr_t* class_id, | 11699 intptr_t* class_id, |
11651 Function* target) const { | 11700 Function* target) const { |
11652 ASSERT(class_id != NULL); | 11701 ASSERT(class_id != NULL); |
11653 ASSERT(target != NULL); | 11702 ASSERT(target != NULL); |
11654 ASSERT(num_args_tested() == 1); | 11703 ASSERT(NumArgsTested() == 1); |
11655 const Array& data = Array::Handle(ic_data()); | 11704 const Array& data = Array::Handle(ic_data()); |
11656 const intptr_t data_pos = index * TestEntryLength(); | 11705 const intptr_t data_pos = index * TestEntryLength(); |
11657 *class_id = Smi::Value(Smi::RawCast(data.At(data_pos))); | 11706 *class_id = Smi::Value(Smi::RawCast(data.At(data_pos))); |
11658 *target ^= data.At(data_pos + 1); | 11707 *target ^= data.At(data_pos + 1); |
11659 } | 11708 } |
11660 | 11709 |
11661 | 11710 |
11662 intptr_t ICData::GetCidAt(intptr_t index) const { | 11711 intptr_t ICData::GetCidAt(intptr_t index) const { |
11663 ASSERT(num_args_tested() == 1); | 11712 ASSERT(NumArgsTested() == 1); |
11664 const Array& data = Array::Handle(ic_data()); | 11713 const Array& data = Array::Handle(ic_data()); |
11665 const intptr_t data_pos = index * TestEntryLength(); | 11714 const intptr_t data_pos = index * TestEntryLength(); |
11666 return Smi::Value(Smi::RawCast(data.At(data_pos))); | 11715 return Smi::Value(Smi::RawCast(data.At(data_pos))); |
11667 } | 11716 } |
11668 | 11717 |
11669 | 11718 |
11670 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { | 11719 intptr_t ICData::GetClassIdAt(intptr_t index, intptr_t arg_nr) const { |
11671 GrowableArray<intptr_t> class_ids; | 11720 GrowableArray<intptr_t> class_ids; |
11672 Function& target = Function::Handle(); | 11721 Function& target = Function::Handle(); |
11673 GetCheckAt(index, &class_ids, &target); | 11722 GetCheckAt(index, &class_ids, &target); |
11674 return class_ids[arg_nr]; | 11723 return class_ids[arg_nr]; |
11675 } | 11724 } |
11676 | 11725 |
11677 | 11726 |
11678 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { | 11727 intptr_t ICData::GetReceiverClassIdAt(intptr_t index) const { |
11679 ASSERT(index < NumberOfChecks()); | 11728 ASSERT(index < NumberOfChecks()); |
11680 const Array& data = Array::Handle(ic_data()); | 11729 const Array& data = Array::Handle(ic_data()); |
11681 const intptr_t data_pos = index * TestEntryLength(); | 11730 const intptr_t data_pos = index * TestEntryLength(); |
11682 return Smi::Value(Smi::RawCast(data.At(data_pos))); | 11731 return Smi::Value(Smi::RawCast(data.At(data_pos))); |
11683 } | 11732 } |
11684 | 11733 |
11685 | 11734 |
11686 RawFunction* ICData::GetTargetAt(intptr_t index) const { | 11735 RawFunction* ICData::GetTargetAt(intptr_t index) const { |
11687 const intptr_t data_pos = index * TestEntryLength() + num_args_tested(); | 11736 const intptr_t data_pos = index * TestEntryLength() + NumArgsTested(); |
11688 ASSERT(Object::Handle(Array::Handle(ic_data()).At(data_pos)).IsFunction()); | 11737 ASSERT(Object::Handle(Array::Handle(ic_data()).At(data_pos)).IsFunction()); |
11689 | 11738 |
11690 NoGCScope no_gc; | 11739 NoGCScope no_gc; |
11691 RawArray* raw_data = ic_data(); | 11740 RawArray* raw_data = ic_data(); |
11692 return reinterpret_cast<RawFunction*>(raw_data->ptr()->data()[data_pos]); | 11741 return reinterpret_cast<RawFunction*>(raw_data->ptr()->data()[data_pos]); |
11693 } | 11742 } |
11694 | 11743 |
11695 | 11744 |
11696 void ICData::IncrementCountAt(intptr_t index, intptr_t value) const { | 11745 void ICData::IncrementCountAt(intptr_t index, intptr_t value) const { |
11697 ASSERT(0 <= value); | 11746 ASSERT(0 <= value); |
11698 ASSERT(value <= Smi::kMaxValue); | 11747 ASSERT(value <= Smi::kMaxValue); |
11699 SetCountAt(index, Utils::Minimum(GetCountAt(index) + value, Smi::kMaxValue)); | 11748 SetCountAt(index, Utils::Minimum(GetCountAt(index) + value, Smi::kMaxValue)); |
11700 } | 11749 } |
11701 | 11750 |
11702 | 11751 |
11703 void ICData::SetCountAt(intptr_t index, intptr_t value) const { | 11752 void ICData::SetCountAt(intptr_t index, intptr_t value) const { |
11704 ASSERT(0 <= value); | 11753 ASSERT(0 <= value); |
11705 ASSERT(value <= Smi::kMaxValue); | 11754 ASSERT(value <= Smi::kMaxValue); |
11706 | 11755 |
11707 const Array& data = Array::Handle(ic_data()); | 11756 const Array& data = Array::Handle(ic_data()); |
11708 const intptr_t data_pos = index * TestEntryLength() + | 11757 const intptr_t data_pos = index * TestEntryLength() + |
11709 CountIndexFor(num_args_tested()); | 11758 CountIndexFor(NumArgsTested()); |
11710 data.SetAt(data_pos, Smi::Handle(Smi::New(value))); | 11759 data.SetAt(data_pos, Smi::Handle(Smi::New(value))); |
11711 } | 11760 } |
11712 | 11761 |
11713 | 11762 |
11714 intptr_t ICData::GetCountAt(intptr_t index) const { | 11763 intptr_t ICData::GetCountAt(intptr_t index) const { |
11715 const Array& data = Array::Handle(ic_data()); | 11764 const Array& data = Array::Handle(ic_data()); |
11716 const intptr_t data_pos = index * TestEntryLength() + | 11765 const intptr_t data_pos = index * TestEntryLength() + |
11717 CountIndexFor(num_args_tested()); | 11766 CountIndexFor(NumArgsTested()); |
11718 return Smi::Value(Smi::RawCast(data.At(data_pos))); | 11767 return Smi::Value(Smi::RawCast(data.At(data_pos))); |
11719 } | 11768 } |
11720 | 11769 |
11721 | 11770 |
11722 intptr_t ICData::AggregateCount() const { | 11771 intptr_t ICData::AggregateCount() const { |
11723 if (IsNull()) return 0; | 11772 if (IsNull()) return 0; |
11724 const intptr_t len = NumberOfChecks(); | 11773 const intptr_t len = NumberOfChecks(); |
11725 intptr_t count = 0; | 11774 intptr_t count = 0; |
11726 for (intptr_t i = 0; i < len; i++) { | 11775 for (intptr_t i = 0; i < len; i++) { |
11727 count += GetCountAt(i); | 11776 count += GetCountAt(i); |
11728 } | 11777 } |
11729 return count; | 11778 return count; |
11730 } | 11779 } |
11731 | 11780 |
11732 | 11781 |
11733 RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const { | 11782 RawFunction* ICData::GetTargetForReceiverClassId(intptr_t class_id) const { |
11734 const intptr_t len = NumberOfChecks(); | 11783 const intptr_t len = NumberOfChecks(); |
11735 for (intptr_t i = 0; i < len; i++) { | 11784 for (intptr_t i = 0; i < len; i++) { |
11736 if (GetReceiverClassIdAt(i) == class_id) { | 11785 if (GetReceiverClassIdAt(i) == class_id) { |
11737 return GetTargetAt(i); | 11786 return GetTargetAt(i); |
11738 } | 11787 } |
11739 } | 11788 } |
11740 return Function::null(); | 11789 return Function::null(); |
11741 } | 11790 } |
11742 | 11791 |
11743 | 11792 |
11744 RawICData* ICData::AsUnaryClassChecksForArgNr(intptr_t arg_nr) const { | 11793 RawICData* ICData::AsUnaryClassChecksForArgNr(intptr_t arg_nr) const { |
11745 ASSERT(!IsNull()); | 11794 ASSERT(!IsNull()); |
11746 ASSERT(num_args_tested() > arg_nr); | 11795 ASSERT(NumArgsTested() > arg_nr); |
11747 if ((arg_nr == 0) && (num_args_tested() == 1)) { | 11796 if ((arg_nr == 0) && (NumArgsTested() == 1)) { |
11748 // Frequent case. | 11797 // Frequent case. |
11749 return raw(); | 11798 return raw(); |
11750 } | 11799 } |
11751 const intptr_t kNumArgsTested = 1; | 11800 const intptr_t kNumArgsTested = 1; |
11752 ICData& result = ICData::Handle(ICData::New( | 11801 ICData& result = ICData::Handle(ICData::New( |
11753 Function::Handle(function()), | 11802 Function::Handle(owner()), |
11754 String::Handle(target_name()), | 11803 String::Handle(target_name()), |
11755 Array::Handle(arguments_descriptor()), | 11804 Array::Handle(arguments_descriptor()), |
11756 deopt_id(), | 11805 deopt_id(), |
11757 kNumArgsTested)); | 11806 kNumArgsTested)); |
11758 const intptr_t len = NumberOfChecks(); | 11807 const intptr_t len = NumberOfChecks(); |
11759 for (intptr_t i = 0; i < len; i++) { | 11808 for (intptr_t i = 0; i < len; i++) { |
11760 const intptr_t class_id = GetClassIdAt(i, arg_nr); | 11809 const intptr_t class_id = GetClassIdAt(i, arg_nr); |
11761 const intptr_t count = GetCountAt(i); | 11810 const intptr_t count = GetCountAt(i); |
11762 intptr_t duplicate_class_id = -1; | 11811 intptr_t duplicate_class_id = -1; |
11763 const intptr_t result_len = result.NumberOfChecks(); | 11812 const intptr_t result_len = result.NumberOfChecks(); |
11764 for (intptr_t k = 0; k < result_len; k++) { | 11813 for (intptr_t k = 0; k < result_len; k++) { |
11765 if (class_id == result.GetReceiverClassIdAt(k)) { | 11814 if (class_id == result.GetReceiverClassIdAt(k)) { |
11766 duplicate_class_id = k; | 11815 duplicate_class_id = k; |
11767 break; | 11816 break; |
11768 } | 11817 } |
11769 } | 11818 } |
11770 if (duplicate_class_id >= 0) { | 11819 if (duplicate_class_id >= 0) { |
11771 // This check is valid only when checking the receiver. | 11820 // This check is valid only when checking the receiver. |
11772 ASSERT((arg_nr != 0) || | 11821 ASSERT((arg_nr != 0) || |
11773 (result.GetTargetAt(duplicate_class_id) == GetTargetAt(i))); | 11822 (result.GetTargetAt(duplicate_class_id) == GetTargetAt(i))); |
11774 result.IncrementCountAt(duplicate_class_id, count); | 11823 result.IncrementCountAt(duplicate_class_id, count); |
11775 } else { | 11824 } else { |
11776 // This will make sure that Smi is first if it exists. | 11825 // This will make sure that Smi is first if it exists. |
11777 result.AddReceiverCheck(class_id, | 11826 result.AddReceiverCheck(class_id, |
11778 Function::Handle(GetTargetAt(i)), | 11827 Function::Handle(GetTargetAt(i)), |
11779 count); | 11828 count); |
11780 } | 11829 } |
11781 } | 11830 } |
11782 // Copy deoptimization reason. | 11831 // Copy deoptimization reasons. |
11783 result.set_deopt_reason(deopt_reason()); | 11832 result.SetDeoptReasons(DeoptReasons()); |
11784 | 11833 |
11785 return result.raw(); | 11834 return result.raw(); |
11786 } | 11835 } |
11787 | 11836 |
11788 | 11837 |
11789 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { | 11838 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { |
11790 if (NumberOfChecks() == 0) return false; | 11839 if (NumberOfChecks() == 0) return false; |
11791 Class& cls = Class::Handle(); | 11840 Class& cls = Class::Handle(); |
11792 const intptr_t len = NumberOfChecks(); | 11841 const intptr_t len = NumberOfChecks(); |
11793 for (intptr_t i = 0; i < len; i++) { | 11842 for (intptr_t i = 0; i < len; i++) { |
(...skipping 18 matching lines...) Expand all Loading... | |
11812 (cid != kBigintCid) && | 11861 (cid != kBigintCid) && |
11813 (cid != kDoubleCid)) { | 11862 (cid != kDoubleCid)) { |
11814 return false; | 11863 return false; |
11815 } | 11864 } |
11816 } | 11865 } |
11817 return true; | 11866 return true; |
11818 } | 11867 } |
11819 | 11868 |
11820 | 11869 |
11821 bool ICData::HasReceiverClassId(intptr_t class_id) const { | 11870 bool ICData::HasReceiverClassId(intptr_t class_id) const { |
11822 ASSERT(num_args_tested() > 0); | 11871 ASSERT(NumArgsTested() > 0); |
11823 const intptr_t len = NumberOfChecks(); | 11872 const intptr_t len = NumberOfChecks(); |
11824 for (intptr_t i = 0; i < len; i++) { | 11873 for (intptr_t i = 0; i < len; i++) { |
11825 const intptr_t test_class_id = GetReceiverClassIdAt(i); | 11874 const intptr_t test_class_id = GetReceiverClassIdAt(i); |
11826 if (test_class_id == class_id) { | 11875 if (test_class_id == class_id) { |
11827 return true; | 11876 return true; |
11828 } | 11877 } |
11829 } | 11878 } |
11830 return false; | 11879 return false; |
11831 } | 11880 } |
11832 | 11881 |
11833 | 11882 |
11834 // Returns true if all targets are the same. | 11883 // Returns true if all targets are the same. |
11835 // TODO(srdjan): if targets are native use their C_function to compare. | 11884 // TODO(srdjan): if targets are native use their C_function to compare. |
11836 bool ICData::HasOneTarget() const { | 11885 bool ICData::HasOneTarget() const { |
11837 ASSERT(NumberOfChecks() > 0); | 11886 ASSERT(NumberOfChecks() > 0); |
11838 const Function& first_target = Function::Handle(GetTargetAt(0)); | 11887 const Function& first_target = Function::Handle(GetTargetAt(0)); |
11839 const intptr_t len = NumberOfChecks(); | 11888 const intptr_t len = NumberOfChecks(); |
11840 for (intptr_t i = 1; i < len; i++) { | 11889 for (intptr_t i = 1; i < len; i++) { |
11841 if (GetTargetAt(i) != first_target.raw()) { | 11890 if (GetTargetAt(i) != first_target.raw()) { |
11842 return false; | 11891 return false; |
11843 } | 11892 } |
11844 } | 11893 } |
11845 return true; | 11894 return true; |
11846 } | 11895 } |
11847 | 11896 |
11848 | 11897 |
11849 RawICData* ICData::New(const Function& caller_function, | 11898 RawICData* ICData::New(const Function& owner, |
11850 const String& target_name, | 11899 const String& target_name, |
11851 const Array& arguments_descriptor, | 11900 const Array& arguments_descriptor, |
11852 intptr_t deopt_id, | 11901 intptr_t deopt_id, |
11853 intptr_t num_args_tested) { | 11902 intptr_t num_args_tested) { |
11854 ASSERT(!caller_function.IsNull()); | 11903 ASSERT(!owner.IsNull()); |
11855 ASSERT(!target_name.IsNull()); | 11904 ASSERT(!target_name.IsNull()); |
11856 ASSERT(!arguments_descriptor.IsNull()); | 11905 ASSERT(!arguments_descriptor.IsNull()); |
11857 ASSERT(Object::icdata_class() != Class::null()); | 11906 ASSERT(Object::icdata_class() != Class::null()); |
11858 ASSERT(num_args_tested >= 0); | 11907 ASSERT(num_args_tested >= 0); |
11859 ICData& result = ICData::Handle(); | 11908 ICData& result = ICData::Handle(); |
11860 { | 11909 { |
11861 // IC data objects are long living objects, allocate them in old generation. | 11910 // IC data objects are long living objects, allocate them in old generation. |
11862 RawObject* raw = Object::Allocate(ICData::kClassId, | 11911 RawObject* raw = Object::Allocate(ICData::kClassId, |
11863 ICData::InstanceSize(), | 11912 ICData::InstanceSize(), |
11864 Heap::kOld); | 11913 Heap::kOld); |
11865 NoGCScope no_gc; | 11914 NoGCScope no_gc; |
11866 result ^= raw; | 11915 result ^= raw; |
11867 } | 11916 } |
11868 result.set_function(caller_function); | 11917 result.set_owner(owner); |
11869 result.set_target_name(target_name); | 11918 result.set_target_name(target_name); |
11870 result.set_arguments_descriptor(arguments_descriptor); | 11919 result.set_arguments_descriptor(arguments_descriptor); |
11871 result.set_deopt_id(deopt_id); | 11920 result.set_deopt_id(deopt_id); |
11872 result.set_num_args_tested(num_args_tested); | 11921 result.set_state_bits(0); |
11873 result.set_deopt_reason(kDeoptUnknown); | 11922 result.SetNumArgsTested(num_args_tested); |
11874 result.set_is_closure_call(false); | |
11875 // Number of array elements in one test entry. | 11923 // Number of array elements in one test entry. |
11876 intptr_t len = result.TestEntryLength(); | 11924 intptr_t len = result.TestEntryLength(); |
11877 // IC data array must be null terminated (sentinel entry). | 11925 // IC data array must be null terminated (sentinel entry). |
11878 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); | 11926 const Array& ic_data = Array::Handle(Array::New(len, Heap::kOld)); |
11879 result.set_ic_data(ic_data); | 11927 result.set_ic_data(ic_data); |
11880 result.WriteSentinel(ic_data); | 11928 result.WriteSentinel(ic_data); |
11881 return result.raw(); | 11929 return result.raw(); |
11882 } | 11930 } |
11883 | 11931 |
11884 | 11932 |
(...skipping 6706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
18591 return tag_label.ToCString(); | 18639 return tag_label.ToCString(); |
18592 } | 18640 } |
18593 | 18641 |
18594 | 18642 |
18595 void UserTag::PrintToJSONStream(JSONStream* stream, bool ref) const { | 18643 void UserTag::PrintToJSONStream(JSONStream* stream, bool ref) const { |
18596 Instance::PrintToJSONStream(stream, ref); | 18644 Instance::PrintToJSONStream(stream, ref); |
18597 } | 18645 } |
18598 | 18646 |
18599 | 18647 |
18600 } // namespace dart | 18648 } // namespace dart |
OLD | NEW |