| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |