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 15289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |