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

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

Issue 2734883002: ICData::NumberOfChecks is O(n) so don't call it in loops (Closed)
Patch Set: Add const Created 3 years, 9 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
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/become.h" 10 #include "vm/become.h"
(...skipping 12976 matching lines...) Expand 10 before | Expand all | Expand 10 after
12987 for (intptr_t i = 0; i < length; i++) { 12987 for (intptr_t i = 0; i < length; i++) {
12988 if (IsSentinelAt(i)) { 12988 if (IsSentinelAt(i)) {
12989 return i; 12989 return i;
12990 } 12990 }
12991 } 12991 }
12992 UNREACHABLE(); 12992 UNREACHABLE();
12993 return -1; 12993 return -1;
12994 } 12994 }
12995 12995
12996 12996
12997 bool ICData::NumberOfChecksIs(intptr_t n) const {
12998 const intptr_t length = Length();
12999 for (intptr_t i = 0; i < length; i++) {
13000 if (i == n) {
13001 return IsSentinelAt(i);
13002 } else {
13003 if (IsSentinelAt(i)) return false;
13004 }
13005 }
13006 return n == length;
13007 }
13008
13009
12997 // Discounts any checks with usage of zero. 13010 // Discounts any checks with usage of zero.
12998 intptr_t ICData::NumberOfUsedChecks() const { 13011 intptr_t ICData::NumberOfUsedChecks() const {
12999 intptr_t n = NumberOfChecks(); 13012 intptr_t n = NumberOfChecks();
13000 if (n == 0) { 13013 if (n == 0) {
13001 return 0; 13014 return 0;
13002 } 13015 }
13003 intptr_t count = 0; 13016 intptr_t count = 0;
13004 for (intptr_t i = 0; i < n; i++) { 13017 for (intptr_t i = 0; i < n; i++) {
13005 if (GetCountAt(i) > 0) { 13018 if (GetCountAt(i) > 0) {
13006 count++; 13019 count++;
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
13049 Array& data = Array::Handle(ic_data()); 13062 Array& data = Array::Handle(ic_data());
13050 const intptr_t start = index * TestEntryLength(); 13063 const intptr_t start = index * TestEntryLength();
13051 const intptr_t end = start + TestEntryLength(); 13064 const intptr_t end = start + TestEntryLength();
13052 for (intptr_t i = start; i < end; i++) { 13065 for (intptr_t i = start; i < end; i++) {
13053 data.SetAt(i, smi_illegal_cid()); 13066 data.SetAt(i, smi_illegal_cid());
13054 } 13067 }
13055 } 13068 }
13056 13069
13057 13070
13058 void ICData::ClearCountAt(intptr_t index) const { 13071 void ICData::ClearCountAt(intptr_t index) const {
13059 const intptr_t len = NumberOfChecks();
13060 ASSERT(index >= 0); 13072 ASSERT(index >= 0);
13061 ASSERT(index < len); 13073 ASSERT(index < NumberOfChecks());
13062 SetCountAt(index, 0); 13074 SetCountAt(index, 0);
13063 } 13075 }
13064 13076
13065 13077
13066 void ICData::ClearWithSentinel() const { 13078 void ICData::ClearWithSentinel() const {
13067 if (IsImmutable()) { 13079 if (IsImmutable()) {
13068 return; 13080 return;
13069 } 13081 }
13070 // Write the sentinel value into all entries except the first one. 13082 // Write the sentinel value into all entries except the first one.
13071 const intptr_t len = Length(); 13083 const intptr_t len = Length();
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
13150 // Add an initial Smi/Smi check with count 0. 13162 // Add an initial Smi/Smi check with count 0.
13151 bool ICData::AddSmiSmiCheckForFastSmiStubs() const { 13163 bool ICData::AddSmiSmiCheckForFastSmiStubs() const {
13152 bool is_smi_two_args_op = false; 13164 bool is_smi_two_args_op = false;
13153 13165
13154 ASSERT(NumArgsTested() == 2); 13166 ASSERT(NumArgsTested() == 2);
13155 const String& name = String::Handle(target_name()); 13167 const String& name = String::Handle(target_name());
13156 const Class& smi_class = Class::Handle(Smi::Class()); 13168 const Class& smi_class = Class::Handle(Smi::Class());
13157 Zone* zone = Thread::Current()->zone(); 13169 Zone* zone = Thread::Current()->zone();
13158 const Function& smi_op_target = 13170 const Function& smi_op_target =
13159 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name)); 13171 Function::Handle(Resolver::ResolveDynamicAnyArgs(zone, smi_class, name));
13160 if (NumberOfChecks() == 0) { 13172 if (NumberOfChecksIs(0)) {
13161 GrowableArray<intptr_t> class_ids(2); 13173 GrowableArray<intptr_t> class_ids(2);
13162 class_ids.Add(kSmiCid); 13174 class_ids.Add(kSmiCid);
13163 class_ids.Add(kSmiCid); 13175 class_ids.Add(kSmiCid);
13164 AddCheck(class_ids, smi_op_target); 13176 AddCheck(class_ids, smi_op_target);
13165 // 'AddCheck' sets the initial count to 1. 13177 // 'AddCheck' sets the initial count to 1.
13166 SetCountAt(0, 0); 13178 SetCountAt(0, 0);
13167 is_smi_two_args_op = true; 13179 is_smi_two_args_op = true;
13168 } else if (NumberOfChecks() == 1) { 13180 } else if (NumberOfChecksIs(1)) {
13169 GrowableArray<intptr_t> class_ids(2); 13181 GrowableArray<intptr_t> class_ids(2);
13170 Function& target = Function::Handle(); 13182 Function& target = Function::Handle();
13171 GetCheckAt(0, &class_ids, &target); 13183 GetCheckAt(0, &class_ids, &target);
13172 if ((target.raw() == smi_op_target.raw()) && (class_ids[0] == kSmiCid) && 13184 if ((target.raw() == smi_op_target.raw()) && (class_ids[0] == kSmiCid) &&
13173 (class_ids[1] == kSmiCid)) { 13185 (class_ids[1] == kSmiCid)) {
13174 is_smi_two_args_op = true; 13186 is_smi_two_args_op = true;
13175 } 13187 }
13176 } 13188 }
13177 return is_smi_two_args_op; 13189 return is_smi_two_args_op;
13178 } 13190 }
(...skipping 465 matching lines...) Expand 10 before | Expand all | Expand 10 after
13644 } 13656 }
13645 } 13657 }
13646 if (!found) { 13658 if (!found) {
13647 aggregate.Add( 13659 aggregate.Add(
13648 CidCount(class_id, count, &Function::ZoneHandle(GetTargetAt(i)))); 13660 CidCount(class_id, count, &Function::ZoneHandle(GetTargetAt(i))));
13649 } 13661 }
13650 } 13662 }
13651 aggregate.Sort(CidCount::HighestCountFirst); 13663 aggregate.Sort(CidCount::HighestCountFirst);
13652 13664
13653 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested)); 13665 ICData& result = ICData::Handle(ICData::NewFrom(*this, kNumArgsTested));
13654 ASSERT(result.NumberOfChecks() == 0); 13666 ASSERT(result.NumberOfChecksIs(0));
13655 // Room for all entries and the sentinel. 13667 // Room for all entries and the sentinel.
13656 const intptr_t data_len = result.TestEntryLength() * (aggregate.length() + 1); 13668 const intptr_t data_len = result.TestEntryLength() * (aggregate.length() + 1);
13657 // Allocate the array but do not assign it to result until we have populated 13669 // Allocate the array but do not assign it to result until we have populated
13658 // it with the aggregate data and the terminating sentinel. 13670 // it with the aggregate data and the terminating sentinel.
13659 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld)); 13671 const Array& data = Array::Handle(Array::New(data_len, Heap::kOld));
13660 intptr_t pos = 0; 13672 intptr_t pos = 0;
13661 for (intptr_t i = 0; i < aggregate.length(); i++) { 13673 for (intptr_t i = 0; i < aggregate.length(); i++) {
13662 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid))); 13674 data.SetAt(pos + 0, Smi::Handle(Smi::New(aggregate[i].cid)));
13663 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function); 13675 data.SetAt(pos + TargetIndexFor(1), *aggregate[i].function);
13664 data.SetAt(pos + CountIndexFor(1), 13676 data.SetAt(pos + CountIndexFor(1),
13665 Smi::Handle(Smi::New(aggregate[i].count))); 13677 Smi::Handle(Smi::New(aggregate[i].count)));
13666 13678
13667 pos += result.TestEntryLength(); 13679 pos += result.TestEntryLength();
13668 } 13680 }
13669 WriteSentinel(data, result.TestEntryLength()); 13681 WriteSentinel(data, result.TestEntryLength());
13670 result.set_ic_data_array(data); 13682 result.set_ic_data_array(data);
13671 ASSERT(result.NumberOfChecks() == aggregate.length()); 13683 ASSERT(result.NumberOfChecksIs(aggregate.length()));
13672 return result.raw(); 13684 return result.raw();
13673 } 13685 }
13674 13686
13675 13687
13676 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const { 13688 bool ICData::AllTargetsHaveSameOwner(intptr_t owner_cid) const {
13677 if (NumberOfChecks() == 0) return false; 13689 if (NumberOfChecksIs(0)) return false;
13678 Class& cls = Class::Handle(); 13690 Class& cls = Class::Handle();
13679 const intptr_t len = NumberOfChecks(); 13691 const intptr_t len = NumberOfChecks();
13680 for (intptr_t i = 0; i < len; i++) { 13692 for (intptr_t i = 0; i < len; i++) {
13681 if (IsUsedAt(i)) { 13693 if (IsUsedAt(i)) {
13682 cls = Function::Handle(GetTargetAt(i)).Owner(); 13694 cls = Function::Handle(GetTargetAt(i)).Owner();
13683 if (cls.id() != owner_cid) { 13695 if (cls.id() != owner_cid) {
13684 return false; 13696 return false;
13685 } 13697 }
13686 } 13698 }
13687 } 13699 }
(...skipping 12 matching lines...) Expand all
13700 } 13712 }
13701 } 13713 }
13702 } 13714 }
13703 return false; 13715 return false;
13704 } 13716 }
13705 13717
13706 13718
13707 // Returns true if all targets are the same. 13719 // Returns true if all targets are the same.
13708 // TODO(srdjan): if targets are native use their C_function to compare. 13720 // TODO(srdjan): if targets are native use their C_function to compare.
13709 bool ICData::HasOneTarget() const { 13721 bool ICData::HasOneTarget() const {
13710 ASSERT(NumberOfChecks() > 0); 13722 ASSERT(!NumberOfChecksIs(0));
13711 const Function& first_target = Function::Handle(GetTargetAt(0)); 13723 const Function& first_target = Function::Handle(GetTargetAt(0));
13712 const intptr_t len = NumberOfChecks(); 13724 const intptr_t len = NumberOfChecks();
13713 for (intptr_t i = 1; i < len; i++) { 13725 for (intptr_t i = 1; i < len; i++) {
13714 if (IsUsedAt(i) && (GetTargetAt(i) != first_target.raw())) { 13726 if (IsUsedAt(i) && (GetTargetAt(i) != first_target.raw())) {
13715 return false; 13727 return false;
13716 } 13728 }
13717 } 13729 }
13718 return true; 13730 return true;
13719 } 13731 }
13720 13732
(...skipping 9206 matching lines...) Expand 10 before | Expand all | Expand 10 after
22927 return UserTag::null(); 22939 return UserTag::null();
22928 } 22940 }
22929 22941
22930 22942
22931 const char* UserTag::ToCString() const { 22943 const char* UserTag::ToCString() const {
22932 const String& tag_label = String::Handle(label()); 22944 const String& tag_label = String::Handle(label());
22933 return tag_label.ToCString(); 22945 return tag_label.ToCString();
22934 } 22946 }
22935 22947
22936 } // namespace dart 22948 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698