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

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

Issue 17104002: Fix a bug in instance canonicalization and add debug mode checks that we are not missing any fields. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | 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/cpu.h" 10 #include "vm/cpu.h"
(...skipping 9185 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698