OLD | NEW |
---|---|
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 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1732 StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw()); | 1732 StorePointer(&raw_ptr()->interfaces_, Object::empty_array().raw()); |
1733 StorePointer(&raw_ptr()->constants_, Object::empty_array().raw()); | 1733 StorePointer(&raw_ptr()->constants_, Object::empty_array().raw()); |
1734 StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw()); | 1734 StorePointer(&raw_ptr()->canonical_types_, Object::empty_array().raw()); |
1735 StorePointer(&raw_ptr()->functions_, Object::empty_array().raw()); | 1735 StorePointer(&raw_ptr()->functions_, Object::empty_array().raw()); |
1736 StorePointer(&raw_ptr()->fields_, Object::empty_array().raw()); | 1736 StorePointer(&raw_ptr()->fields_, Object::empty_array().raw()); |
1737 StorePointer(&raw_ptr()->invocation_dispatcher_cache_, | 1737 StorePointer(&raw_ptr()->invocation_dispatcher_cache_, |
1738 Object::empty_array().raw()); | 1738 Object::empty_array().raw()); |
1739 } | 1739 } |
1740 | 1740 |
1741 | 1741 |
1742 RawArray* Class::OffsetToFieldMap() const { | |
1743 Array& array = Array::Handle(raw_ptr()->offset_in_words_to_field_); | |
1744 if (array.IsNull()) { | |
1745 ASSERT(is_finalized()); | |
1746 const intptr_t length = raw_ptr()->instance_size_in_words_; | |
1747 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.
| |
1748 Class& cls = Class::Handle(this->raw()); | |
1749 Array& fields = Array::Handle(); | |
1750 Field& f = Field::Handle(); | |
1751 while (!cls.IsNull()) { | |
1752 fields = cls.fields(); | |
1753 for (intptr_t i = 0; i < fields.Length(); ++i) { | |
1754 f ^= fields.At(i); | |
1755 if (!f.is_static()) { | |
1756 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.
| |
1757 } | |
1758 } | |
1759 cls = cls.SuperClass(); | |
1760 } | |
1761 StorePointer(&raw_ptr()->offset_in_words_to_field_, array.raw()); | |
1762 } | |
1763 return array.raw(); | |
1764 } | |
1765 | |
1766 | |
1742 bool Class::HasInstanceFields() const { | 1767 bool Class::HasInstanceFields() const { |
1743 const Array& field_array = Array::Handle(fields()); | 1768 const Array& field_array = Array::Handle(fields()); |
1744 Field& field = Field::Handle(); | 1769 Field& field = Field::Handle(); |
1745 for (intptr_t i = 0; i < field_array.Length(); ++i) { | 1770 for (intptr_t i = 0; i < field_array.Length(); ++i) { |
1746 field ^= field_array.At(i); | 1771 field ^= field_array.At(i); |
1747 if (!field.is_static()) { | 1772 if (!field.is_static()) { |
1748 return true; | 1773 return true; |
1749 } | 1774 } |
1750 } | 1775 } |
1751 return false; | 1776 return false; |
(...skipping 4201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5953 } | 5978 } |
5954 | 5979 |
5955 | 5980 |
5956 bool Field::IsUninitialized() const { | 5981 bool Field::IsUninitialized() const { |
5957 const Instance& value = Instance::Handle(raw_ptr()->value_); | 5982 const Instance& value = Instance::Handle(raw_ptr()->value_); |
5958 ASSERT(value.raw() != Object::transition_sentinel().raw()); | 5983 ASSERT(value.raw() != Object::transition_sentinel().raw()); |
5959 return value.raw() == Object::sentinel().raw(); | 5984 return value.raw() == Object::sentinel().raw(); |
5960 } | 5985 } |
5961 | 5986 |
5962 | 5987 |
5963 void Field::UpdateCid(intptr_t cid) const { | 5988 static intptr_t GetListLength(const Object& value) { |
5989 const intptr_t cid = value.GetClassId(); | |
5990 ASSERT(RawObject::IsBuiltinListClassId(cid)); | |
5991 // Extract list length. | |
5992 if (value.IsTypedData()) { | |
5993 const TypedData& list = TypedData::Cast(value); | |
5994 return list.Length(); | |
5995 } else if (value.IsArray()) { | |
5996 const Array& list = Array::Cast(value); | |
5997 return list.Length(); | |
5998 } else if (value.IsGrowableObjectArray()) { | |
5999 // List length is variable. | |
6000 return Field::kNoFixedLength; | |
6001 } else if (value.IsExternalTypedData()) { | |
6002 // TODO(johnmccutchan): Enable for external typed data. | |
6003 return Field::kNoFixedLength; | |
6004 } else if (RawObject::IsTypedDataViewClassId(cid)) { | |
6005 // TODO(johnmccutchan): Enable for typed data views. | |
6006 return Field::kNoFixedLength; | |
6007 } | |
6008 UNIMPLEMENTED(); | |
6009 return Field::kNoFixedLength; | |
6010 } | |
6011 | |
6012 | |
6013 bool Field::UpdateGuardedCidAndLength(const Object& value) const { | |
6014 const intptr_t cid = value.GetClassId(); | |
6015 bool deoptimize = UpdateCid(cid); | |
6016 intptr_t list_length = Field::kNoFixedLength; | |
6017 if ((guarded_cid() != kDynamicCid) && | |
6018 is_final() && RawObject::IsBuiltinListClassId(cid)) { | |
6019 list_length = GetListLength(value); | |
6020 } | |
6021 deoptimize = UpdateLength(list_length) || deoptimize; | |
6022 if (deoptimize) { | |
6023 DeoptimizeDependentCode(); | |
6024 } | |
6025 return deoptimize; | |
6026 } | |
6027 | |
6028 | |
6029 bool Field::UpdateCid(intptr_t cid) const { | |
5964 if (guarded_cid() == kIllegalCid) { | 6030 if (guarded_cid() == kIllegalCid) { |
5965 // Field is assigned first time. | 6031 // Field is assigned first time. |
5966 set_guarded_cid(cid); | 6032 set_guarded_cid(cid); |
5967 set_is_nullable(cid == kNullCid); | 6033 set_is_nullable(cid == kNullCid); |
5968 return; | 6034 return false; |
5969 } | 6035 } |
5970 | 6036 |
5971 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { | 6037 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { |
5972 // Class id of the assigned value matches expected class id and nullability. | 6038 // Class id of the assigned value matches expected class id and nullability. |
5973 return; | 6039 return false; |
5974 } | 6040 } |
5975 | 6041 |
5976 if ((cid == kNullCid) && !is_nullable()) { | 6042 if ((cid == kNullCid) && !is_nullable()) { |
5977 // Assigning null value to a non-nullable field makes it nullable. | 6043 // Assigning null value to a non-nullable field makes it nullable. |
5978 set_is_nullable(true); | 6044 set_is_nullable(true); |
5979 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) { | 6045 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) { |
5980 // Assigning non-null value to a field that previously contained only null | 6046 // Assigning non-null value to a field that previously contained only null |
5981 // turns it into a nullable field with the given class id. | 6047 // turns it into a nullable field with the given class id. |
5982 ASSERT(is_nullable()); | 6048 ASSERT(is_nullable()); |
5983 set_guarded_cid(cid); | 6049 set_guarded_cid(cid); |
5984 } else { | 6050 } else { |
5985 // Give up on tracking class id of values contained in this field. | 6051 // Give up on tracking class id of values contained in this field. |
5986 ASSERT(guarded_cid() != cid); | 6052 ASSERT(guarded_cid() != cid); |
5987 set_guarded_cid(kDynamicCid); | 6053 set_guarded_cid(kDynamicCid); |
5988 set_is_nullable(true); | 6054 set_is_nullable(true); |
5989 } | 6055 } |
5990 | 6056 |
5991 // Expected class id or nullability of the field changed. | 6057 // Expected class id or nullability of the field changed. |
5992 DeoptimizeDependentCode(); | 6058 return true; |
5993 } | 6059 } |
5994 | 6060 |
5995 | 6061 |
5996 void Field::UpdateLength(intptr_t list_length) const { | 6062 bool Field::UpdateLength(intptr_t list_length) const { |
5997 ASSERT(is_final() || (!is_final() && | 6063 ASSERT(is_final() || (!is_final() && |
5998 (list_length < Field::kUnknownFixedLength))); | 6064 (list_length < Field::kUnknownFixedLength))); |
5999 ASSERT((list_length == Field::kNoFixedLength) || | 6065 ASSERT((list_length == Field::kNoFixedLength) || |
6000 (list_length > Field::kUnknownFixedLength)); | 6066 (list_length > Field::kUnknownFixedLength)); |
6001 ASSERT(guarded_cid() != kIllegalCid); | 6067 ASSERT(guarded_cid() != kIllegalCid); |
6002 | 6068 |
6003 const bool force_invalidate = (guarded_cid() == kDynamicCid) && | 6069 const bool force_invalidate = (guarded_cid() == kDynamicCid) && |
6004 (list_length != Field::kNoFixedLength); | 6070 (list_length != Field::kNoFixedLength); |
6005 | 6071 |
6006 const bool list_length_unknown = | 6072 const bool list_length_unknown = |
6007 (guarded_list_length() == Field::kUnknownFixedLength); | 6073 (guarded_list_length() == Field::kUnknownFixedLength); |
6008 const bool list_length_changed = (guarded_list_length() != list_length); | 6074 const bool list_length_changed = (guarded_list_length() != list_length); |
6009 | 6075 |
6010 if (list_length_unknown && list_length_changed && !force_invalidate) { | 6076 if (list_length_unknown && list_length_changed && !force_invalidate) { |
6011 // List length set for first time. | 6077 // List length set for first time. |
6012 set_guarded_list_length(list_length); | 6078 set_guarded_list_length(list_length); |
6013 return; | 6079 return false; |
6014 } | 6080 } |
6015 | 6081 |
6016 if (!list_length_changed && !force_invalidate) { | 6082 if (!list_length_changed && !force_invalidate) { |
6017 // List length unchanged. | 6083 // List length unchanged. |
6018 return; | 6084 return false; |
6019 } | 6085 } |
6020 // Multiple list lengths assigned here, stop tracking length. | 6086 // Multiple list lengths assigned here, stop tracking length. |
6021 set_guarded_list_length(Field::kNoFixedLength); | 6087 set_guarded_list_length(Field::kNoFixedLength); |
6022 DeoptimizeDependentCode(); | 6088 return true; |
6023 } | 6089 } |
6024 | 6090 |
6025 | 6091 |
6026 void LiteralToken::set_literal(const String& literal) const { | 6092 void LiteralToken::set_literal(const String& literal) const { |
6027 StorePointer(&raw_ptr()->literal_, literal.raw()); | 6093 StorePointer(&raw_ptr()->literal_, literal.raw()); |
6028 } | 6094 } |
6029 | 6095 |
6030 | 6096 |
6031 void LiteralToken::set_value(const Object& value) const { | 6097 void LiteralToken::set_value(const Object& value) const { |
6032 StorePointer(&raw_ptr()->value_, value.raw()); | 6098 StorePointer(&raw_ptr()->value_, value.raw()); |
(...skipping 9563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15596 return "_MirrorReference"; | 15662 return "_MirrorReference"; |
15597 } | 15663 } |
15598 | 15664 |
15599 | 15665 |
15600 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { | 15666 void MirrorReference::PrintToJSONStream(JSONStream* stream, bool ref) const { |
15601 JSONObject jsobj(stream); | 15667 JSONObject jsobj(stream); |
15602 } | 15668 } |
15603 | 15669 |
15604 | 15670 |
15605 } // namespace dart | 15671 } // namespace dart |
OLD | NEW |