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

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

Issue 2160953002: Add a verification step which iterates over the heap and verifies that all canonical objects are co… (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address code review comments. Created 4 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
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | 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 15289 matching lines...) Expand 10 before | Expand all | Expand 10 after
15300 } else { 15300 } else {
15301 result ^= this->raw(); 15301 result ^= this->raw();
15302 } 15302 }
15303 ASSERT(result.IsOld()); 15303 ASSERT(result.IsOld());
15304 result.SetCanonical(); 15304 result.SetCanonical();
15305 return cls.InsertCanonicalConstant(zone, result); 15305 return cls.InsertCanonicalConstant(zone, result);
15306 } 15306 }
15307 } 15307 }
15308 15308
15309 15309
15310 #if defined(DEBUG)
15311 bool Instance::CheckIsCanonical(Thread* thread) const {
15312 Zone* zone = thread->zone();
15313 Isolate* isolate = thread->isolate();
15314 Instance& result = Instance::Handle(zone);
15315 const Class& cls = Class::Handle(zone, this->clazz());
15316 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
15317 result ^= cls.LookupCanonicalInstance(zone, *this);
15318 return (result.raw() == this->raw());
15319 }
15320 #endif // DEBUG
15321
15322
15310 RawAbstractType* Instance::GetType() const { 15323 RawAbstractType* Instance::GetType() const {
15311 if (IsNull()) { 15324 if (IsNull()) {
15312 return Type::NullType(); 15325 return Type::NullType();
15313 } 15326 }
15314 const Class& cls = Class::Handle(clazz()); 15327 const Class& cls = Class::Handle(clazz());
15315 if (cls.IsClosureClass()) { 15328 if (cls.IsClosureClass()) {
15316 const Function& signature = 15329 const Function& signature =
15317 Function::Handle(Closure::Cast(*this).function()); 15330 Function::Handle(Closure::Cast(*this).function());
15318 Type& type = Type::Handle(signature.SignatureType()); 15331 Type& type = Type::Handle(signature.SignatureType());
15319 if (type.type_class() == cls.raw()) { 15332 if (type.type_class() == cls.raw()) {
(...skipping 1788 matching lines...) Expand 10 before | Expand all | Expand 10 after
17108 type.SetCanonical(); // Mark object as being canonical. 17121 type.SetCanonical(); // Mark object as being canonical.
17109 bool present = table.Insert(type); 17122 bool present = table.Insert(type);
17110 ASSERT(!present); 17123 ASSERT(!present);
17111 } 17124 }
17112 object_store->set_canonical_types(table.Release()); 17125 object_store->set_canonical_types(table.Release());
17113 } 17126 }
17114 return type.raw(); 17127 return type.raw();
17115 } 17128 }
17116 17129
17117 17130
17131 #if defined(DEBUG)
17132 bool Type::CheckIsCanonical(Thread* thread) const {
17133 if (IsMalformed()) {
17134 return true;
17135 }
17136 if (type_class() == Object::dynamic_class()) {
17137 return (raw() == Object::dynamic_type().raw());
17138 }
17139 Zone* zone = thread->zone();
17140 Isolate* isolate = thread->isolate();
17141 AbstractType& type = Type::Handle(zone);
17142 const Class& cls = Class::Handle(zone, type_class());
17143
17144 // Fast canonical lookup/registry for simple types.
17145 if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
17146 ASSERT(!IsFunctionType());
17147 type = cls.CanonicalType();
17148 return (raw() == type.raw());
17149 }
17150
17151 ObjectStore* object_store = isolate->object_store();
17152 {
17153 SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
17154 CanonicalTypeSet table(zone, object_store->canonical_types());
17155 type ^= table.GetOrNull(CanonicalTypeKey(*this));
17156 object_store->set_canonical_types(table.Release());
17157 }
17158 return (raw() == type.raw());
17159 }
17160 #endif // DEBUG
17161
17162
17118 RawString* Type::EnumerateURIs() const { 17163 RawString* Type::EnumerateURIs() const {
17119 if (IsDynamicType() || IsVoidType()) { 17164 if (IsDynamicType() || IsVoidType()) {
17120 return Symbols::Empty().raw(); 17165 return Symbols::Empty().raw();
17121 } 17166 }
17122 Thread* thread = Thread::Current(); 17167 Thread* thread = Thread::Current();
17123 Zone* zone = thread->zone(); 17168 Zone* zone = thread->zone();
17124 GrowableHandlePtrArray<const String> pieces(zone, 6); 17169 GrowableHandlePtrArray<const String> pieces(zone, 6);
17125 if (IsFunctionType()) { 17170 if (IsFunctionType()) {
17126 // The scope class and type arguments do not appear explicitly in the user 17171 // The scope class and type arguments do not appear explicitly in the user
17127 // visible name. The type arguments were used to instantiate the function 17172 // visible name. The type arguments were used to instantiate the function
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
17370 } 17415 }
17371 // TODO(regis): Try to reduce the number of nodes required to represent the 17416 // TODO(regis): Try to reduce the number of nodes required to represent the
17372 // referenced recursive type. 17417 // referenced recursive type.
17373 AbstractType& ref_type = AbstractType::Handle(type()); 17418 AbstractType& ref_type = AbstractType::Handle(type());
17374 ref_type = ref_type.Canonicalize(trail); 17419 ref_type = ref_type.Canonicalize(trail);
17375 set_type(ref_type); 17420 set_type(ref_type);
17376 return raw(); 17421 return raw();
17377 } 17422 }
17378 17423
17379 17424
17425 #if defined(DEBUG)
17426 bool TypeRef::CheckIsCanonical(Thread* thread) const {
17427 AbstractType& ref_type = AbstractType::Handle(type());
17428 return ref_type.CheckIsCanonical(thread);
17429 }
17430 #endif // DEBUG
17431
17432
17380 RawString* TypeRef::EnumerateURIs() const { 17433 RawString* TypeRef::EnumerateURIs() const {
17381 Thread* thread = Thread::Current(); 17434 Thread* thread = Thread::Current();
17382 Zone* zone = thread->zone(); 17435 Zone* zone = thread->zone();
17383 const AbstractType& ref_type = AbstractType::Handle(zone, type()); 17436 const AbstractType& ref_type = AbstractType::Handle(zone, type());
17384 ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType()); 17437 ASSERT(!ref_type.IsDynamicType() && !ref_type.IsVoidType());
17385 GrowableHandlePtrArray<const String> pieces(zone, 6); 17438 GrowableHandlePtrArray<const String> pieces(zone, 6);
17386 const Class& cls = Class::Handle(zone, ref_type.type_class()); 17439 const Class& cls = Class::Handle(zone, ref_type.type_class());
17387 pieces.Add(Symbols::TwoSpaces()); 17440 pieces.Add(Symbols::TwoSpaces());
17388 pieces.Add(String::Handle(zone, cls.UserVisibleName())); 17441 pieces.Add(String::Handle(zone, cls.UserVisibleName()));
17389 // Break cycle by not printing type arguments, but '<optimized out>' instead. 17442 // Break cycle by not printing type arguments, but '<optimized out>' instead.
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
18033 const char** error_str) const { 18086 const char** error_str) const {
18034 intptr_t cid = GetClassId(); 18087 intptr_t cid = GetClassId();
18035 switch (cid) { 18088 switch (cid) {
18036 case kSmiCid: 18089 case kSmiCid:
18037 return reinterpret_cast<RawSmi*>(raw_value()); 18090 return reinterpret_cast<RawSmi*>(raw_value());
18038 case kMintCid: 18091 case kMintCid:
18039 return Mint::NewCanonical(Mint::Cast(*this).value()); 18092 return Mint::NewCanonical(Mint::Cast(*this).value());
18040 case kDoubleCid: 18093 case kDoubleCid:
18041 return Double::NewCanonical(Double::Cast(*this).value()); 18094 return Double::NewCanonical(Double::Cast(*this).value());
18042 case kBigintCid: { 18095 case kBigintCid: {
18096 if (this->IsCanonical()) {
18097 return this->raw();
18098 }
18043 Zone* zone = thread->zone(); 18099 Zone* zone = thread->zone();
18044 Isolate* isolate = thread->isolate(); 18100 Isolate* isolate = thread->isolate();
18045 if (!CheckAndCanonicalizeFields(thread, error_str)) {
18046 return Instance::null();
18047 }
18048 Bigint& result = Bigint::Handle(zone); 18101 Bigint& result = Bigint::Handle(zone);
18049 const Class& cls = Class::Handle(zone, this->clazz()); 18102 const Class& cls = Class::Handle(zone, this->clazz());
18050 intptr_t index = 0; 18103 intptr_t index = 0;
18051 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index); 18104 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &index);
18052 if (!result.IsNull()) { 18105 if (!result.IsNull()) {
18053 return result.raw(); 18106 return result.raw();
18054 } 18107 }
18055 { 18108 {
18056 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex()); 18109 SafepointMutexLocker ml(isolate->constant_canonicalization_mutex());
18057 // Retry lookup. 18110 // Retry lookup.
(...skipping 19 matching lines...) Expand all
18077 return result.raw(); 18130 return result.raw();
18078 } 18131 }
18079 } 18132 }
18080 default: 18133 default:
18081 UNREACHABLE(); 18134 UNREACHABLE();
18082 } 18135 }
18083 return Instance::null(); 18136 return Instance::null();
18084 } 18137 }
18085 18138
18086 18139
18140 #if defined(DEBUG)
18141 bool Number::CheckIsCanonical(Thread* thread) const {
18142 intptr_t cid = GetClassId();
18143 intptr_t idx = 0;
18144 Zone* zone = thread->zone();
18145 const Class& cls = Class::Handle(zone, this->clazz());
18146 switch (cid) {
18147 case kSmiCid:
18148 return true;
18149 case kMintCid: {
18150 Mint& result = Mint::Handle(zone);
18151 result ^= cls.LookupCanonicalMint(zone, Mint::Cast(*this).value(), &idx);
18152 return (result.raw() == this->raw());
18153 }
18154 case kDoubleCid: {
18155 Double& dbl = Double::Handle(zone);
18156 dbl ^= cls.LookupCanonicalDouble(zone, Double::Cast(*this).value(), &idx);
18157 return (dbl.raw() == this->raw());
18158 }
18159 case kBigintCid: {
18160 Bigint& result = Bigint::Handle(zone);
18161 result ^= cls.LookupCanonicalBigint(zone, Bigint::Cast(*this), &idx);
18162 return (result.raw() == this->raw());
18163 }
18164 default:
18165 UNREACHABLE();
18166 }
18167 return false;
18168 }
18169 #endif // DEBUG
18170
18171
18087 const char* Number::ToCString() const { 18172 const char* Number::ToCString() const {
18088 // Number is an interface. No instances of Number should exist. 18173 // Number is an interface. No instances of Number should exist.
18089 UNREACHABLE(); 18174 UNREACHABLE();
18090 return "Number"; 18175 return "Number";
18091 } 18176 }
18092 18177
18093 18178
18094 const char* Integer::ToCString() const { 18179 const char* Integer::ToCString() const {
18095 // Integer is an interface. No instances of Integer should exist except null. 18180 // Integer is an interface. No instances of Integer should exist except null.
18096 ASSERT(IsNull()); 18181 ASSERT(IsNull());
(...skipping 1680 matching lines...) Expand 10 before | Expand all | Expand 10 after
19777 19862
19778 RawInstance* String::CheckAndCanonicalize(Thread* thread, 19863 RawInstance* String::CheckAndCanonicalize(Thread* thread,
19779 const char** error_str) const { 19864 const char** error_str) const {
19780 if (IsCanonical()) { 19865 if (IsCanonical()) {
19781 return this->raw(); 19866 return this->raw();
19782 } 19867 }
19783 return Symbols::New(Thread::Current(), *this); 19868 return Symbols::New(Thread::Current(), *this);
19784 } 19869 }
19785 19870
19786 19871
19872 #if defined(DEBUG)
19873 bool String::CheckIsCanonical(Thread* thread) const {
19874 Zone* zone = thread->zone();
19875 const String& str = String::Handle(zone, Symbols::Lookup(thread, *this));
19876 return (str.raw() == this->raw());
19877 }
19878 #endif // DEBUG
19879
19880
19787 RawString* String::New(const char* cstr, Heap::Space space) { 19881 RawString* String::New(const char* cstr, Heap::Space space) {
19788 ASSERT(cstr != NULL); 19882 ASSERT(cstr != NULL);
19789 intptr_t array_len = strlen(cstr); 19883 intptr_t array_len = strlen(cstr);
19790 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr); 19884 const uint8_t* utf8_array = reinterpret_cast<const uint8_t*>(cstr);
19791 return String::FromUTF8(utf8_array, array_len, space); 19885 return String::FromUTF8(utf8_array, array_len, space);
19792 } 19886 }
19793 19887
19794 19888
19795 RawString* String::FromUTF8(const uint8_t* utf8_array, 19889 RawString* String::FromUTF8(const uint8_t* utf8_array,
19796 intptr_t array_len, 19890 intptr_t array_len,
(...skipping 1500 matching lines...) Expand 10 before | Expand all | Expand 10 after
21297 if (with_type_argument) { 21391 if (with_type_argument) {
21298 dest.SetTypeArguments(TypeArguments::Handle(GetTypeArguments())); 21392 dest.SetTypeArguments(TypeArguments::Handle(GetTypeArguments()));
21299 } 21393 }
21300 21394
21301 return dest.raw(); 21395 return dest.raw();
21302 } 21396 }
21303 21397
21304 21398
21305 void Array::MakeImmutable() const { 21399 void Array::MakeImmutable() const {
21306 if (IsImmutable()) return; 21400 if (IsImmutable()) return;
21401 ASSERT(!IsCanonical());
21307 NoSafepointScope no_safepoint; 21402 NoSafepointScope no_safepoint;
21308 uword tags = raw_ptr()->tags_; 21403 uword tags = raw_ptr()->tags_;
21309 uword old_tags; 21404 uword old_tags;
21310 do { 21405 do {
21311 old_tags = tags; 21406 old_tags = tags;
21312 uword new_tags = RawObject::ClassIdTag::update(kImmutableArrayCid, 21407 uword new_tags = RawObject::ClassIdTag::update(kImmutableArrayCid,
21313 old_tags); 21408 old_tags);
21314 tags = CompareAndSwapTags(old_tags, new_tags); 21409 tags = CompareAndSwapTags(old_tags, new_tags);
21315 } while (tags != old_tags); 21410 } while (tags != old_tags);
21316 } 21411 }
(...skipping 1294 matching lines...) Expand 10 before | Expand all | Expand 10 after
22611 return UserTag::null(); 22706 return UserTag::null();
22612 } 22707 }
22613 22708
22614 22709
22615 const char* UserTag::ToCString() const { 22710 const char* UserTag::ToCString() const {
22616 const String& tag_label = String::Handle(label()); 22711 const String& tag_label = String::Handle(label());
22617 return tag_label.ToCString(); 22712 return tag_label.ToCString();
22618 } 22713 }
22619 22714
22620 } // namespace dart 22715 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/raw_object.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698