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

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

Powered by Google App Engine
This is Rietveld 408576698