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

Side by Side Diff: runtime/vm/object.cc

Issue 50243004: Fix bug with guarded fields and deserialization. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 1 month 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
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 1721 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | runtime/vm/snapshot.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698