| Index: runtime/vm/object.cc
|
| ===================================================================
|
| --- runtime/vm/object.cc (revision 23933)
|
| +++ runtime/vm/object.cc (working copy)
|
| @@ -9209,13 +9209,43 @@
|
| }
|
|
|
|
|
| -RawInstance* Instance::Canonicalize() const {
|
| +RawInstance* Instance::CheckAndCanonicalize(const char** error_str) const {
|
| ASSERT(!IsNull());
|
| if (this->IsCanonical()) {
|
| return this->raw();
|
| }
|
| Instance& result = Instance::Handle();
|
| const Class& cls = Class::Handle(this->clazz());
|
| + // TODO(srdjan): Check that predefined classes do not have fields that need
|
| + // to be checked/canonicalized as well.
|
| + if ((cls.id() >= kNumPredefinedCids) || cls.IsArray()) {
|
| + // Iterate over all fields, canonicalize numbers and strings, expect all
|
| + // other instances to be canonical otherwise report error (return
|
| + // Instance::null()).
|
| + Object& obj = Object::Handle();
|
| + const intptr_t end_field_offset = cls.instance_size() - kWordSize;
|
| + for (intptr_t field_offset = 0;
|
| + field_offset <= end_field_offset;
|
| + field_offset += kWordSize) {
|
| + obj = *this->FieldAddrAtOffset(field_offset);
|
| + if (obj.IsInstance() && !obj.IsSmi() && !obj.IsCanonical()) {
|
| + if (obj.IsNumber() || obj.IsString()) {
|
| + obj = Instance::Cast(obj).CheckAndCanonicalize(NULL);
|
| + ASSERT(!obj.IsNull());
|
| + this->SetFieldAtOffset(field_offset, obj);
|
| + } else {
|
| + ASSERT(error_str != NULL);
|
| + const char* kFormat = "field: %s\n";
|
| + const intptr_t len =
|
| + OS::SNPrint(NULL, 0, kFormat, obj.ToCString()) + 1;
|
| + char* chars = Isolate::Current()->current_zone()->Alloc<char>(len);
|
| + OS::SNPrint(chars, len, kFormat, obj.ToCString());
|
| + *error_str = chars;
|
| + return Instance::null();
|
| + }
|
| + }
|
| + }
|
| + }
|
| Array& constants = Array::Handle(cls.constants());
|
| const intptr_t constants_len = constants.Length();
|
| // Linear search to see whether this value is already present in the
|
| @@ -11563,7 +11593,7 @@
|
| }
|
|
|
|
|
| -RawInstance* String::Canonicalize() const {
|
| +RawInstance* String::CheckAndCanonicalize(const char** error_str) const {
|
| if (IsCanonical()) {
|
| return this->raw();
|
| }
|
|
|