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

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