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

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

Issue 304703002: Split GuardField into GuardFieldType and GuardFieldLength instructions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 6 months 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
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
57 DEFINE_FLAG(bool, show_internal_names, false, 57 DEFINE_FLAG(bool, show_internal_names, false,
58 "Show names of internal classes (e.g. \"OneByteString\") in error messages " 58 "Show names of internal classes (e.g. \"OneByteString\") in error messages "
59 "instead of showing the corresponding interface names (e.g. \"String\")"); 59 "instead of showing the corresponding interface names (e.g. \"String\")");
60 DEFINE_FLAG(bool, trace_disabling_optimized_code, false, 60 DEFINE_FLAG(bool, trace_disabling_optimized_code, false,
61 "Trace disabling optimized code."); 61 "Trace disabling optimized code.");
62 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false, 62 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
63 "Throw an exception when the result of an integer calculation will not " 63 "Throw an exception when the result of an integer calculation will not "
64 "fit into a javascript integer."); 64 "fit into a javascript integer.");
65 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids."); 65 DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
66 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache"); 66 DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
67 DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
67 68
68 DECLARE_FLAG(bool, enable_type_checks); 69 DECLARE_FLAG(bool, enable_type_checks);
69 DECLARE_FLAG(bool, error_on_bad_override); 70 DECLARE_FLAG(bool, error_on_bad_override);
70 DECLARE_FLAG(bool, trace_compiler); 71 DECLARE_FLAG(bool, trace_compiler);
71 DECLARE_FLAG(bool, trace_deoptimization); 72 DECLARE_FLAG(bool, trace_deoptimization);
72 DECLARE_FLAG(bool, trace_deoptimization_verbose); 73 DECLARE_FLAG(bool, trace_deoptimization_verbose);
73 DECLARE_FLAG(bool, verbose_stacktrace); 74 DECLARE_FLAG(bool, verbose_stacktrace);
74 DECLARE_FLAG(charp, coverage_dir); 75 DECLARE_FLAG(charp, coverage_dir);
75 DECLARE_FLAG(bool, write_protect_code); 76 DECLARE_FLAG(bool, write_protect_code);
76 77
(...skipping 6690 matching lines...) Expand 10 before | Expand all | Expand 10 after
6767 result.SetOffset(0); 6768 result.SetOffset(0);
6768 } 6769 }
6769 result.set_is_final(is_final); 6770 result.set_is_final(is_final);
6770 result.set_is_const(is_const); 6771 result.set_is_const(is_const);
6771 result.set_owner(owner); 6772 result.set_owner(owner);
6772 result.set_token_pos(token_pos); 6773 result.set_token_pos(token_pos);
6773 result.set_has_initializer(false); 6774 result.set_has_initializer(false);
6774 result.set_is_unboxing_candidate(true); 6775 result.set_is_unboxing_candidate(true);
6775 result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid); 6776 result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid);
6776 result.set_is_nullable(FLAG_use_field_guards ? false : true); 6777 result.set_is_nullable(FLAG_use_field_guards ? false : true);
6778 result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
6777 // Presently, we only attempt to remember the list length for final fields. 6779 // Presently, we only attempt to remember the list length for final fields.
6778 if (is_final && FLAG_use_field_guards) { 6780 if (is_final && FLAG_use_field_guards) {
6779 result.set_guarded_list_length(Field::kUnknownFixedLength); 6781 result.set_guarded_list_length(Field::kUnknownFixedLength);
6780 } else { 6782 } else {
6781 result.set_guarded_list_length(Field::kNoFixedLength); 6783 result.set_guarded_list_length(Field::kNoFixedLength);
6782 } 6784 }
6783 result.set_dependent_code(Object::null_array()); 6785 result.set_dependent_code(Object::null_array());
6784 return result.raw(); 6786 return result.raw();
6785 } 6787 }
6786 6788
(...skipping 28 matching lines...) Expand all
6815 intptr_t Field::guarded_list_length() const { 6817 intptr_t Field::guarded_list_length() const {
6816 return Smi::Value(raw_ptr()->guarded_list_length_); 6818 return Smi::Value(raw_ptr()->guarded_list_length_);
6817 } 6819 }
6818 6820
6819 6821
6820 void Field::set_guarded_list_length(intptr_t list_length) const { 6822 void Field::set_guarded_list_length(intptr_t list_length) const {
6821 raw_ptr()->guarded_list_length_ = Smi::New(list_length); 6823 raw_ptr()->guarded_list_length_ = Smi::New(list_length);
6822 } 6824 }
6823 6825
6824 6826
6827 intptr_t Field::guarded_list_length_in_object_offset() const {
6828 return raw_ptr()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
6829 }
6830
6831
6832 void Field::set_guarded_list_length_in_object_offset(
6833 intptr_t list_length_offset) const {
6834 raw_ptr()->guarded_list_length_in_object_offset_ =
6835 static_cast<int8_t>(list_length_offset - kHeapObjectTag);
6836 ASSERT(guarded_list_length_in_object_offset() == list_length_offset);
6837 }
6838
6839
6825 bool Field::IsUnboxedField() const { 6840 bool Field::IsUnboxedField() const {
6826 bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() && 6841 bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() &&
6827 (guarded_cid() == kDoubleCid)) || 6842 (guarded_cid() == kDoubleCid)) ||
6828 (FlowGraphCompiler::SupportsUnboxedSimd128() && 6843 (FlowGraphCompiler::SupportsUnboxedSimd128() &&
6829 (guarded_cid() == kFloat32x4Cid)) || 6844 (guarded_cid() == kFloat32x4Cid)) ||
6830 (FlowGraphCompiler::SupportsUnboxedSimd128() && 6845 (FlowGraphCompiler::SupportsUnboxedSimd128() &&
6831 (guarded_cid() == kFloat64x2Cid)); 6846 (guarded_cid() == kFloat64x2Cid));
6832 return is_unboxing_candidate() && !is_final() && !is_nullable() && 6847 return is_unboxing_candidate() && !is_final() && !is_nullable() &&
6833 valid_class; 6848 valid_class;
6834 } 6849 }
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
6976 6991
6977 6992
6978 bool Field::IsUninitialized() const { 6993 bool Field::IsUninitialized() const {
6979 const Instance& value = Instance::Handle(raw_ptr()->value_); 6994 const Instance& value = Instance::Handle(raw_ptr()->value_);
6980 ASSERT(value.raw() != Object::transition_sentinel().raw()); 6995 ASSERT(value.raw() != Object::transition_sentinel().raw());
6981 return value.raw() == Object::sentinel().raw(); 6996 return value.raw() == Object::sentinel().raw();
6982 } 6997 }
6983 6998
6984 6999
6985 static intptr_t GetListLength(const Object& value) { 7000 static intptr_t GetListLength(const Object& value) {
6986 const intptr_t cid = value.GetClassId();
6987 ASSERT(RawObject::IsBuiltinListClassId(cid));
6988 // Extract list length.
6989 if (value.IsTypedData()) { 7001 if (value.IsTypedData()) {
6990 const TypedData& list = TypedData::Cast(value); 7002 const TypedData& list = TypedData::Cast(value);
6991 return list.Length(); 7003 return list.Length();
6992 } else if (value.IsArray()) { 7004 } else if (value.IsArray()) {
6993 const Array& list = Array::Cast(value); 7005 const Array& list = Array::Cast(value);
6994 return list.Length(); 7006 return list.Length();
6995 } else if (value.IsGrowableObjectArray()) { 7007 } else if (value.IsGrowableObjectArray()) {
6996 // List length is variable. 7008 // List length is variable.
6997 return Field::kNoFixedLength; 7009 return Field::kNoFixedLength;
6998 } else if (value.IsExternalTypedData()) { 7010 } else if (value.IsExternalTypedData()) {
6999 // TODO(johnmccutchan): Enable for external typed data. 7011 // TODO(johnmccutchan): Enable for external typed data.
7000 return Field::kNoFixedLength; 7012 return Field::kNoFixedLength;
7001 } else if (RawObject::IsTypedDataViewClassId(cid)) { 7013 } else if (RawObject::IsTypedDataViewClassId(value.GetClassId())) {
7002 // TODO(johnmccutchan): Enable for typed data views. 7014 // TODO(johnmccutchan): Enable for typed data views.
7003 return Field::kNoFixedLength; 7015 return Field::kNoFixedLength;
7004 } 7016 }
7005 UNIMPLEMENTED();
7006 return Field::kNoFixedLength; 7017 return Field::kNoFixedLength;
7007 } 7018 }
7008 7019
7009 7020
7021 static intptr_t GetListLengthOffset(intptr_t cid) {
7022 if (RawObject::IsTypedDataClassId(cid)) {
7023 return TypedData::length_offset();
7024 } else if (cid == kArrayCid || cid == kImmutableArrayCid) {
7025 return Array::length_offset();
7026 } else if (cid == kGrowableObjectArrayCid) {
7027 // List length is variable.
7028 return Field::kUnknownLengthOffset;
7029 } else if (RawObject::IsExternalTypedDataClassId(cid)) {
7030 // TODO(johnmccutchan): Enable for external typed data.
7031 return Field::kUnknownLengthOffset;
7032 } else if (RawObject::IsTypedDataViewClassId(cid)) {
7033 // TODO(johnmccutchan): Enable for typed data views.
7034 return Field::kUnknownLengthOffset;
7035 }
7036 return Field::kUnknownLengthOffset;
7037 }
7038
7039
7040 const char* Field::GuardedPropertiesAsCString() const {
7041 if (guarded_cid() == kIllegalCid) {
7042 return "<?>";
7043 } else if (guarded_cid() == kDynamicCid) {
7044 return "<*>";
7045 }
7046
7047 const Class& cls = Class::Handle(
7048 Isolate::Current()->class_table()->At(guarded_cid()));
7049 const char* class_name = String::Handle(cls.Name()).ToCString();
7050
7051 if (RawObject::IsBuiltinListClassId(guarded_cid()) &&
7052 !is_nullable() &&
7053 is_final()) {
7054 ASSERT(guarded_list_length() != kUnknownFixedLength);
7055 if (guarded_list_length() == kNoFixedLength) {
7056 return Isolate::Current()->current_zone()->PrintToString(
7057 "<%s [*]>", class_name);
7058 } else {
7059 return Isolate::Current()->current_zone()->PrintToString(
7060 "<%s [%" Pd " @%" Pd "]>",
7061 class_name,
7062 guarded_list_length(),
7063 guarded_list_length_in_object_offset());
7064 }
7065 }
7066
7067 return Isolate::Current()->current_zone()->PrintToString("<%s %s>",
7068 is_nullable() ? "nullable" : "not-nullable",
7069 class_name);
7070 }
7071
7072
7073 void Field::InitializeGuardedListLengthInObjectOffset() const {
7074 if (needs_length_check() &&
7075 (guarded_list_length() != Field::kUnknownFixedLength)) {
7076 const intptr_t offset = GetListLengthOffset(guarded_cid());
7077 set_guarded_list_length_in_object_offset(offset);
7078 ASSERT(offset != Field::kUnknownLengthOffset);
7079 } else {
7080 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
7081 }
7082 }
7083
7084
7010 bool Field::UpdateGuardedCidAndLength(const Object& value) const { 7085 bool Field::UpdateGuardedCidAndLength(const Object& value) const {
7011 const intptr_t cid = value.GetClassId(); 7086 const intptr_t cid = value.GetClassId();
7012 bool deoptimize = UpdateCid(cid);
7013 intptr_t list_length = Field::kNoFixedLength;
7014 if ((guarded_cid() != kDynamicCid) &&
7015 is_final() && RawObject::IsBuiltinListClassId(cid)) {
7016 list_length = GetListLength(value);
7017 }
7018 deoptimize = UpdateLength(list_length) || deoptimize;
7019 if (deoptimize) {
7020 DeoptimizeDependentCode();
7021 }
7022 return deoptimize;
7023 }
7024 7087
7025
7026 bool Field::UpdateCid(intptr_t cid) const {
7027 if (guarded_cid() == kIllegalCid) { 7088 if (guarded_cid() == kIllegalCid) {
7028 // Field is assigned first time. 7089 // Field is assigned first time.
7029 set_guarded_cid(cid); 7090 set_guarded_cid(cid);
7030 set_is_nullable(cid == kNullCid); 7091 set_is_nullable(cid == kNullCid);
7092
7093 // Start tracking length if needed.
7094 ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
7095 (guarded_list_length() == Field::kNoFixedLength));
7096 if (needs_length_check()) {
7097 ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
7098 set_guarded_list_length(GetListLength(value));
7099 InitializeGuardedListLengthInObjectOffset();
7100 }
7101
7102 if (FLAG_trace_field_guards) {
7103 OS::Print(" => %s\n", GuardedPropertiesAsCString());
7104 }
7105
7031 return false; 7106 return false;
7032 } 7107 }
7033 7108
7034 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { 7109 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
7035 // Class id of the assigned value matches expected class id and nullability. 7110 // Class id of the assigned value matches expected class id and nullability.
7111
7112 // If we are tracking length check if it has matches.
7113 if (needs_length_check() &&
7114 (guarded_list_length() != GetListLength(value))) {
7115 ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
7116 set_guarded_list_length(Field::kNoFixedLength);
7117 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
7118 return true;
7119 }
7120
7121 // Everything matches.
7036 return false; 7122 return false;
7037 } 7123 }
7038 7124
7039 if ((cid == kNullCid) && !is_nullable()) { 7125 if ((cid == kNullCid) && !is_nullable()) {
7040 // Assigning null value to a non-nullable field makes it nullable. 7126 // Assigning null value to a non-nullable field makes it nullable.
7041 set_is_nullable(true); 7127 set_is_nullable(true);
7042 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) { 7128 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) {
7043 // Assigning non-null value to a field that previously contained only null 7129 // Assigning non-null value to a field that previously contained only null
7044 // turns it into a nullable field with the given class id. 7130 // turns it into a nullable field with the given class id.
7045 ASSERT(is_nullable()); 7131 ASSERT(is_nullable());
7046 set_guarded_cid(cid); 7132 set_guarded_cid(cid);
7047 } else { 7133 } else {
7048 // Give up on tracking class id of values contained in this field. 7134 // Give up on tracking class id of values contained in this field.
7049 ASSERT(guarded_cid() != cid); 7135 ASSERT(guarded_cid() != cid);
7050 set_guarded_cid(kDynamicCid); 7136 set_guarded_cid(kDynamicCid);
7051 set_is_nullable(true); 7137 set_is_nullable(true);
7052 } 7138 }
7053 7139
7140 // If we were tracking length drop collected feedback.
7141 if (needs_length_check()) {
7142 ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
7143 set_guarded_list_length(Field::kNoFixedLength);
7144 set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
7145 }
7146
7054 // Expected class id or nullability of the field changed. 7147 // Expected class id or nullability of the field changed.
7055 return true; 7148 return true;
7056 } 7149 }
7057 7150
7058 7151
7059 bool Field::UpdateLength(intptr_t list_length) const { 7152 void Field::RecordStore(const Object& value) const {
7060 ASSERT(is_final() || (!is_final() && 7153 if (FLAG_trace_field_guards) {
7061 (list_length < Field::kUnknownFixedLength))); 7154 OS::Print("Store %s %s <- %s\n",
7062 ASSERT((list_length == Field::kNoFixedLength) || 7155 ToCString(),
7063 (list_length > Field::kUnknownFixedLength)); 7156 GuardedPropertiesAsCString(),
7064 ASSERT(guarded_cid() != kIllegalCid); 7157 value.ToCString());
7065
7066 const bool force_invalidate = (guarded_cid() == kDynamicCid) &&
7067 (list_length != Field::kNoFixedLength);
7068
7069 const bool list_length_unknown =
7070 (guarded_list_length() == Field::kUnknownFixedLength);
7071 const bool list_length_changed = (guarded_list_length() != list_length);
7072
7073 if (list_length_unknown && list_length_changed && !force_invalidate) {
7074 // List length set for first time.
7075 set_guarded_list_length(list_length);
7076 return false;
7077 } 7158 }
7078 7159
7079 if (!list_length_changed && !force_invalidate) { 7160 if (UpdateGuardedCidAndLength(value)) {
7080 // List length unchanged. 7161 if (FLAG_trace_field_guards) {
7081 return false; 7162 OS::Print(" => %s\n", GuardedPropertiesAsCString());
7163 }
7164
7165 DeoptimizeDependentCode();
7082 } 7166 }
7083 // Multiple list lengths assigned here, stop tracking length.
7084 set_guarded_list_length(Field::kNoFixedLength);
7085 return true;
7086 } 7167 }
7087 7168
7088 7169
7089 void LiteralToken::set_literal(const String& literal) const { 7170 void LiteralToken::set_literal(const String& literal) const {
7090 StorePointer(&raw_ptr()->literal_, literal.raw()); 7171 StorePointer(&raw_ptr()->literal_, literal.raw());
7091 } 7172 }
7092 7173
7093 7174
7094 void LiteralToken::set_value(const Object& value) const { 7175 void LiteralToken::set_value(const Object& value) const {
7095 StorePointer(&raw_ptr()->value_, value.raw()); 7176 StorePointer(&raw_ptr()->value_, value.raw());
(...skipping 11803 matching lines...) Expand 10 before | Expand all | Expand 10 after
18899 return tag_label.ToCString(); 18980 return tag_label.ToCString();
18900 } 18981 }
18901 18982
18902 18983
18903 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 18984 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
18904 Instance::PrintJSONImpl(stream, ref); 18985 Instance::PrintJSONImpl(stream, ref);
18905 } 18986 }
18906 18987
18907 18988
18908 } // namespace dart 18989 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698