| 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/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 9185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 9196 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != | 9196 if ((*reinterpret_cast<RawObject**>(this_addr + offset)) != |
| 9197 (*reinterpret_cast<RawObject**>(other_addr + offset))) { | 9197 (*reinterpret_cast<RawObject**>(other_addr + offset))) { |
| 9198 return false; | 9198 return false; |
| 9199 } | 9199 } |
| 9200 } | 9200 } |
| 9201 } | 9201 } |
| 9202 return true; | 9202 return true; |
| 9203 } | 9203 } |
| 9204 | 9204 |
| 9205 | 9205 |
| 9206 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { | 9206 #if defined(DEBUG) |
| 9207 ASSERT(!IsNull()); | 9207 class CheckForPointers : public ObjectPointerVisitor { |
| 9208 if (this->IsCanonical()) { | 9208 public: |
| 9209 return this->raw(); | 9209 explicit CheckForPointers(Isolate* isolate) |
| 9210 : ObjectPointerVisitor(isolate), has_pointers_(false) {} |
| 9211 |
| 9212 bool has_pointers() const { return has_pointers_; } |
| 9213 |
| 9214 void VisitPointers(RawObject** first, RawObject** last) { |
| 9215 if (first != last) { |
| 9216 has_pointers_ = true; |
| 9217 } |
| 9210 } | 9218 } |
| 9211 Instance& result = Instance::Handle(); | 9219 |
| 9220 private: |
| 9221 bool has_pointers_; |
| 9222 |
| 9223 DISALLOW_COPY_AND_ASSIGN(CheckForPointers); |
| 9224 }; |
| 9225 #endif // DEBUG |
| 9226 |
| 9227 |
| 9228 bool Instance::CheckAndCanonicalizeFields(const char** error_str) const { |
| 9212 const Class& cls = Class::Handle(this->clazz()); | 9229 const Class& cls = Class::Handle(this->clazz()); |
| 9213 // TODO(srdjan): Check that predefined classes do not have fields that need | 9230 if ((cls.id() >= kNumPredefinedCids)) { |
| 9214 // to be checked/canonicalized as well. | |
| 9215 if ((cls.id() >= kNumPredefinedCids) || cls.IsArray()) { | |
| 9216 // Iterate over all fields, canonicalize numbers and strings, expect all | 9231 // Iterate over all fields, canonicalize numbers and strings, expect all |
| 9217 // other instances to be canonical otherwise report error (return | 9232 // other instances to be canonical otherwise report error (return false). |
| 9218 // Instance::null()). | |
| 9219 Object& obj = Object::Handle(); | 9233 Object& obj = Object::Handle(); |
| 9220 const intptr_t end_field_offset = cls.instance_size() - kWordSize; | 9234 intptr_t end_field_offset = cls.instance_size() - kWordSize; |
| 9221 for (intptr_t field_offset = 0; | 9235 for (intptr_t field_offset = 0; |
| 9222 field_offset <= end_field_offset; | 9236 field_offset <= end_field_offset; |
| 9223 field_offset += kWordSize) { | 9237 field_offset += kWordSize) { |
| 9224 obj = *this->FieldAddrAtOffset(field_offset); | 9238 obj = *this->FieldAddrAtOffset(field_offset); |
| 9225 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { | 9239 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
| 9226 if (obj.IsNumber() || obj.IsString()) { | 9240 if (obj.IsNumber() || obj.IsString()) { |
| 9227 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); | 9241 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
| 9228 ASSERT(!obj.IsNull()); | 9242 ASSERT(!obj.IsNull()); |
| 9229 this->SetFieldAtOffset(field_offset, obj); | 9243 this->SetFieldAtOffset(field_offset, obj); |
| 9230 } else { | 9244 } else { |
| 9231 ASSERT(error_str != NULL); | 9245 ASSERT(error_str != NULL); |
| 9232 const char* kFormat = "field: %s\n"; | 9246 const char* kFormat = "field: %s\n"; |
| 9233 const intptr_t len = | 9247 const intptr_t len = |
| 9234 OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1; | 9248 OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1; |
| 9235 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); | 9249 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 9236 OS::SNPrint(chars, len, kFormat, obj.ToCString()); | 9250 OS::SNPrint(chars, len, kFormat, obj.ToCString()); |
| 9237 *error_str = chars; | 9251 *error_str = chars; |
| 9238 return Instance::null(); | 9252 return false; |
| 9239 } | 9253 } |
| 9240 } | 9254 } |
| 9241 } | 9255 } |
| 9256 } else { |
| 9257 #if defined(DEBUG) |
| 9258 // Make sure that we are not missing any fields. |
| 9259 CheckForPointers has_pointers(Isolate::Current()); |
| 9260 this->raw()->VisitPointers(&has_pointers); |
| 9261 ASSERT(!has_pointers.has_pointers()); |
| 9262 #endif // DEBUG |
| 9242 } | 9263 } |
| 9264 return true; |
| 9265 } |
| 9266 |
| 9267 |
| 9268 RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const { |
| 9269 ASSERT(!IsNull()); |
| 9270 if (this->IsCanonical()) { |
| 9271 return this->raw(); |
| 9272 } |
| 9273 if (!CheckAndCanonicalizeFields(error_str)) { |
| 9274 return Instance::null(); |
| 9275 } |
| 9276 Instance& result = Instance::Handle(); |
| 9277 const Class& cls = Class::Handle(this->clazz()); |
| 9243 Array& constants = Array::Handle(cls.constants()); | 9278 Array& constants = Array::Handle(cls.constants()); |
| 9244 const intptr_t constants_len = constants.Length(); | 9279 const intptr_t constants_len = constants.Length(); |
| 9245 // Linear search to see whether this value is already present in the | 9280 // Linear search to see whether this value is already present in the |
| 9246 // list of canonicalized constants. | 9281 // list of canonicalized constants. |
| 9247 intptr_t index = 0; | 9282 intptr_t index = 0; |
| 9248 while (index < constants_len) { | 9283 while (index < constants_len) { |
| 9249 result ^= constants.At(index); | 9284 result ^= constants.At(index); |
| 9250 if (result.IsNull()) { | 9285 if (result.IsNull()) { |
| 9251 break; | 9286 break; |
| 9252 } | 9287 } |
| (...skipping 3499 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 12752 | 12787 |
| 12753 // If there is any left over space fill it with either an Array object or | 12788 // If there is any left over space fill it with either an Array object or |
| 12754 // just a plain object (depending on the amount of left over space) so | 12789 // just a plain object (depending on the amount of left over space) so |
| 12755 // that it can be traversed over successfully during garbage collection. | 12790 // that it can be traversed over successfully during garbage collection. |
| 12756 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); | 12791 Object::MakeUnusedSpaceTraversable(array, capacity_size, used_size); |
| 12757 | 12792 |
| 12758 return array.raw(); | 12793 return array.raw(); |
| 12759 } | 12794 } |
| 12760 | 12795 |
| 12761 | 12796 |
| 12797 bool Array::CheckAndCanonicalizeFields(const char** error_str) const { |
| 12798 Object& obj = Object::Handle(); |
| 12799 // Iterate over all elements, canonicalize numbers and strings, expect all |
| 12800 // other instances to be canonical otherwise report error (return false). |
| 12801 for (intptr_t i = 0; i < Length(); i++) { |
| 12802 obj = At(i); |
| 12803 if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) { |
| 12804 if (obj.IsNumber() || obj.IsString()) { |
| 12805 obj = Instance::Cast(obj).CheckAndCanonicalize(NULL); |
| 12806 ASSERT(!obj.IsNull()); |
| 12807 this->SetAt(i, obj); |
| 12808 } else { |
| 12809 ASSERT(error_str != NULL); |
| 12810 const char* kFormat = "element at index %"Pd": %s\n"; |
| 12811 const intptr_t len = |
| 12812 OS::SNPrint(NULL, 0, kFormat, i, obj.ToCString()) + 1; |
| 12813 char* chars = Isolate::Current()->current_zone()->Alloc<char>(len); |
| 12814 OS::SNPrint(chars, len, kFormat, i, obj.ToCString()); |
| 12815 *error_str = chars; |
| 12816 return false; |
| 12817 } |
| 12818 } |
| 12819 } |
| 12820 return true; |
| 12821 } |
| 12822 |
| 12823 |
| 12762 RawImmutableArray* ImmutableArray::New(intptr_t len, | 12824 RawImmutableArray* ImmutableArray::New(intptr_t len, |
| 12763 Heap::Space space) { | 12825 Heap::Space space) { |
| 12764 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != | 12826 ASSERT(Isolate::Current()->object_store()->immutable_array_class() != |
| 12765 Class::null()); | 12827 Class::null()); |
| 12766 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); | 12828 return reinterpret_cast<RawImmutableArray*>(Array::New(kClassId, len, space)); |
| 12767 } | 12829 } |
| 12768 | 12830 |
| 12769 | 12831 |
| 12770 void GrowableObjectArray::Add(const Object& value, Heap::Space space) const { | 12832 void GrowableObjectArray::Add(const Object& value, Heap::Space space) const { |
| 12771 ASSERT(!IsNull()); | 12833 ASSERT(!IsNull()); |
| (...skipping 768 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 13540 space); | 13602 space); |
| 13541 return reinterpret_cast<RawWeakProperty*>(raw); | 13603 return reinterpret_cast<RawWeakProperty*>(raw); |
| 13542 } | 13604 } |
| 13543 | 13605 |
| 13544 | 13606 |
| 13545 const char* WeakProperty::ToCString() const { | 13607 const char* WeakProperty::ToCString() const { |
| 13546 return "_WeakProperty"; | 13608 return "_WeakProperty"; |
| 13547 } | 13609 } |
| 13548 | 13610 |
| 13549 } // namespace dart | 13611 } // namespace dart |
| OLD | NEW |