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

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

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

Powered by Google App Engine
This is Rietveld 408576698