Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 23823) |
+++ runtime/vm/object.cc (working copy) |
@@ -50,6 +50,8 @@ |
"Huge method cutoff in tokens: Disables optimizations for huge methods."); |
DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000, |
"Huge method cutoff in unoptimized code size (in bytes)."); |
+DEFINE_FLAG(bool, report_incorrect_const_objects, true, |
hausner
2013/06/11 23:29:24
Why do we need the flag?
srdjan
2013/06/12 00:22:22
Removing. It is easy to disable the error reportin
|
+ "Report if a const object has incorrect fields."); |
DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, |
"Throw an exception when integer arithmetic exceeds 53 bits."); |
DECLARE_FLAG(bool, trace_compiler); |
@@ -9094,13 +9096,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()); |
+ if (cls.id() >= kNumPredefinedCids) { |
hausner
2013/06/11 23:29:24
As discussed offline, this excludes arrays.
srdjan
2013/06/12 00:22:22
Added arrays.
|
+ // 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 { |
+ if (FLAG_report_incorrect_const_objects) { |
+ 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 |
@@ -11448,7 +11480,7 @@ |
} |
-RawInstance* String::Canonicalize() const { |
+RawInstance* String::CheckAndCanonicalize(const char** error_str) const { |
if (IsCanonical()) { |
return this->raw(); |
} |