Index: runtime/vm/object.cc |
=================================================================== |
--- runtime/vm/object.cc (revision 29540) |
+++ runtime/vm/object.cc (working copy) |
@@ -1739,6 +1739,31 @@ |
} |
+RawArray* Class::OffsetToFieldMap() const { |
+ Array& array = Array::Handle(raw_ptr()->offset_in_words_to_field_); |
+ if (array.IsNull()) { |
+ ASSERT(is_finalized()); |
+ const intptr_t length = raw_ptr()->instance_size_in_words_; |
+ array = Array::New(length); |
Ivan Posva
2013/11/01 04:50:05
This array should be allocated in old space. It wi
Florian Schneider
2013/11/01 10:39:27
Done.
|
+ Class& cls = Class::Handle(this->raw()); |
+ Array& fields = Array::Handle(); |
+ Field& f = Field::Handle(); |
+ while (!cls.IsNull()) { |
+ fields = cls.fields(); |
+ for (intptr_t i = 0; i < fields.Length(); ++i) { |
+ f ^= fields.At(i); |
+ if (!f.is_static()) { |
+ array.SetAt(f.Offset() / kWordSize, f); |
Ivan Posva
2013/11/01 04:50:05
f.Offset() >> kWordSizeLog2
Florian Schneider
2013/11/01 10:39:27
Done.
|
+ } |
+ } |
+ cls = cls.SuperClass(); |
+ } |
+ StorePointer(&raw_ptr()->offset_in_words_to_field_, array.raw()); |
+ } |
+ return array.raw(); |
+} |
+ |
+ |
bool Class::HasInstanceFields() const { |
const Array& field_array = Array::Handle(fields()); |
Field& field = Field::Handle(); |
@@ -5960,17 +5985,58 @@ |
} |
-void Field::UpdateCid(intptr_t cid) const { |
+static intptr_t GetListLength(const Object& value) { |
+ const intptr_t cid = value.GetClassId(); |
+ ASSERT(RawObject::IsBuiltinListClassId(cid)); |
+ // Extract list length. |
+ if (value.IsTypedData()) { |
+ const TypedData& list = TypedData::Cast(value); |
+ return list.Length(); |
+ } else if (value.IsArray()) { |
+ const Array& list = Array::Cast(value); |
+ return list.Length(); |
+ } else if (value.IsGrowableObjectArray()) { |
+ // List length is variable. |
+ return Field::kNoFixedLength; |
+ } else if (value.IsExternalTypedData()) { |
+ // TODO(johnmccutchan): Enable for external typed data. |
+ return Field::kNoFixedLength; |
+ } else if (RawObject::IsTypedDataViewClassId(cid)) { |
+ // TODO(johnmccutchan): Enable for typed data views. |
+ return Field::kNoFixedLength; |
+ } |
+ UNIMPLEMENTED(); |
+ return Field::kNoFixedLength; |
+} |
+ |
+ |
+bool Field::UpdateGuardedCidAndLength(const Object& value) const { |
+ const intptr_t cid = value.GetClassId(); |
+ bool deoptimize = UpdateCid(cid); |
+ intptr_t list_length = Field::kNoFixedLength; |
+ if ((guarded_cid() != kDynamicCid) && |
+ is_final() && RawObject::IsBuiltinListClassId(cid)) { |
+ list_length = GetListLength(value); |
+ } |
+ deoptimize = UpdateLength(list_length) || deoptimize; |
+ if (deoptimize) { |
+ DeoptimizeDependentCode(); |
+ } |
+ return deoptimize; |
+} |
+ |
+ |
+bool Field::UpdateCid(intptr_t cid) const { |
if (guarded_cid() == kIllegalCid) { |
// Field is assigned first time. |
set_guarded_cid(cid); |
set_is_nullable(cid == kNullCid); |
- return; |
+ return false; |
} |
if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { |
// Class id of the assigned value matches expected class id and nullability. |
- return; |
+ return false; |
} |
if ((cid == kNullCid) && !is_nullable()) { |
@@ -5989,11 +6055,11 @@ |
} |
// Expected class id or nullability of the field changed. |
- DeoptimizeDependentCode(); |
+ return true; |
} |
-void Field::UpdateLength(intptr_t list_length) const { |
+bool Field::UpdateLength(intptr_t list_length) const { |
ASSERT(is_final() || (!is_final() && |
(list_length < Field::kUnknownFixedLength))); |
ASSERT((list_length == Field::kNoFixedLength) || |
@@ -6010,16 +6076,16 @@ |
if (list_length_unknown && list_length_changed && !force_invalidate) { |
// List length set for first time. |
set_guarded_list_length(list_length); |
- return; |
+ return false; |
} |
if (!list_length_changed && !force_invalidate) { |
// List length unchanged. |
- return; |
+ return false; |
} |
// Multiple list lengths assigned here, stop tracking length. |
set_guarded_list_length(Field::kNoFixedLength); |
- DeoptimizeDependentCode(); |
+ return true; |
} |