| 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 |