Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(68)

Side by Side Diff: runtime/vm/object.cc

Issue 254723003: Remember all deopt reasons in ic_data, not just the last one. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW
« runtime/vm/object.h ('K') | « runtime/vm/object.h ('k') | runtime/vm/object_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698