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

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