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

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
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(-1);
Florian Schneider 2014/05/28 14:57:36 s/-1/kUnknownLengthOffset/
Vyacheslav Egorov (Google) 2014/05/29 17:36:51 Done.
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_;
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_ = list_length_offset;
6835 }
6836
6837
6825 bool Field::IsUnboxedField() const { 6838 bool Field::IsUnboxedField() const {
6826 bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() && 6839 bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() &&
6827 (guarded_cid() == kDoubleCid)) || 6840 (guarded_cid() == kDoubleCid)) ||
6828 (FlowGraphCompiler::SupportsUnboxedSimd128() && 6841 (FlowGraphCompiler::SupportsUnboxedSimd128() &&
6829 (guarded_cid() == kFloat32x4Cid)) || 6842 (guarded_cid() == kFloat32x4Cid)) ||
6830 (FlowGraphCompiler::SupportsUnboxedSimd128() && 6843 (FlowGraphCompiler::SupportsUnboxedSimd128() &&
6831 (guarded_cid() == kFloat64x2Cid)); 6844 (guarded_cid() == kFloat64x2Cid));
6832 return is_unboxing_candidate() && !is_final() && !is_nullable() && 6845 return is_unboxing_candidate() && !is_final() && !is_nullable() &&
6833 valid_class; 6846 valid_class;
6834 } 6847 }
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
6976 6989
6977 6990
6978 bool Field::IsUninitialized() const { 6991 bool Field::IsUninitialized() const {
6979 const Instance& value = Instance::Handle(raw_ptr()->value_); 6992 const Instance& value = Instance::Handle(raw_ptr()->value_);
6980 ASSERT(value.raw() != Object::transition_sentinel().raw()); 6993 ASSERT(value.raw() != Object::transition_sentinel().raw());
6981 return value.raw() == Object::sentinel().raw(); 6994 return value.raw() == Object::sentinel().raw();
6982 } 6995 }
6983 6996
6984 6997
6985 static intptr_t GetListLength(const Object& value) { 6998 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()) { 6999 if (value.IsTypedData()) {
6990 const TypedData& list = TypedData::Cast(value); 7000 const TypedData& list = TypedData::Cast(value);
6991 return list.Length(); 7001 return list.Length();
6992 } else if (value.IsArray()) { 7002 } else if (value.IsArray()) {
6993 const Array& list = Array::Cast(value); 7003 const Array& list = Array::Cast(value);
6994 return list.Length(); 7004 return list.Length();
6995 } else if (value.IsGrowableObjectArray()) { 7005 } else if (value.IsGrowableObjectArray()) {
6996 // List length is variable. 7006 // List length is variable.
6997 return Field::kNoFixedLength; 7007 return Field::kNoFixedLength;
6998 } else if (value.IsExternalTypedData()) { 7008 } else if (value.IsExternalTypedData()) {
6999 // TODO(johnmccutchan): Enable for external typed data. 7009 // TODO(johnmccutchan): Enable for external typed data.
7000 return Field::kNoFixedLength; 7010 return Field::kNoFixedLength;
7001 } else if (RawObject::IsTypedDataViewClassId(cid)) { 7011 } else if (RawObject::IsTypedDataViewClassId(value.GetClassId())) {
7002 // TODO(johnmccutchan): Enable for typed data views. 7012 // TODO(johnmccutchan): Enable for typed data views.
7003 return Field::kNoFixedLength; 7013 return Field::kNoFixedLength;
7004 } 7014 }
7005 UNIMPLEMENTED();
7006 return Field::kNoFixedLength; 7015 return Field::kNoFixedLength;
7007 } 7016 }
7008 7017
7009 7018
7019 static intptr_t GetListLengthOffset(const Object& value) {
7020 if (value.IsTypedData()) {
7021 return TypedData::length_offset();
7022 } else if (value.IsArray()) {
7023 return Array::length_offset();
7024 } else if (value.IsGrowableObjectArray()) {
7025 // List length is variable.
7026 return Field::kUnknownLengthOffset;
7027 } else if (value.IsExternalTypedData()) {
7028 // TODO(johnmccutchan): Enable for external typed data.
7029 return Field::kUnknownLengthOffset;
7030 } else if (RawObject::IsTypedDataViewClassId(value.GetClassId())) {
7031 // TODO(johnmccutchan): Enable for typed data views.
7032 return Field::kUnknownLengthOffset;
7033 }
7034 return Field::kUnknownLengthOffset;
7035 }
7036
7037
7038 const char* Field::GuardedPropertiesAsCString() const {
7039 if (guarded_cid() == kIllegalCid) {
7040 return "<?>";
7041 } else if (guarded_cid() == kDynamicCid) {
7042 return "<*>";
7043 }
7044
7045 const Class& cls = Class::Handle(
7046 Isolate::Current()->class_table()->At(guarded_cid()));
7047 const char* class_name = String::Handle(cls.Name()).ToCString();
7048
7049 if (RawObject::IsBuiltinListClassId(guarded_cid()) &&
7050 !is_nullable() &&
7051 is_final()) {
7052 ASSERT(guarded_list_length() != kUnknownFixedLength);
7053 if (guarded_list_length() == kNoFixedLength) {
7054 return Isolate::Current()->current_zone()->PrintToString(
7055 "<%s [*]>", class_name);
7056 } else {
7057 return Isolate::Current()->current_zone()->PrintToString("<%s [%d @%d]>",
7058 class_name,
7059 guarded_list_length(),
7060 guarded_list_length_in_object_offset());
7061 }
7062 }
7063
7064 return Isolate::Current()->current_zone()->PrintToString("<%s %s>",
7065 is_nullable() ? "nullable" : "not-nullable",
7066 class_name);
7067 }
7068
7069
7010 bool Field::UpdateGuardedCidAndLength(const Object& value) const { 7070 bool Field::UpdateGuardedCidAndLength(const Object& value) const {
7011 const intptr_t cid = value.GetClassId(); 7071 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 7072
7025
7026 bool Field::UpdateCid(intptr_t cid) const {
7027 if (guarded_cid() == kIllegalCid) { 7073 if (guarded_cid() == kIllegalCid) {
7028 // Field is assigned first time. 7074 // Field is assigned first time.
7029 set_guarded_cid(cid); 7075 set_guarded_cid(cid);
7030 set_is_nullable(cid == kNullCid); 7076 set_is_nullable(cid == kNullCid);
7077
7078 // Start tracking length if needed.
7079 ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
7080 (guarded_list_length() == Field::kNoFixedLength));
7081 if (needs_length_check()) {
7082 ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
7083 set_guarded_list_length(GetListLength(value));
7084 set_guarded_list_length_in_object_offset(GetListLengthOffset(value));
7085 }
7086
7031 return false; 7087 return false;
7032 } 7088 }
7033 7089
7034 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) { 7090 if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
7035 // Class id of the assigned value matches expected class id and nullability. 7091 // Class id of the assigned value matches expected class id and nullability.
7092
7093 // If we are tracking length check if it has matches.
7094 if (needs_length_check() &&
7095 (guarded_list_length() != GetListLength(value))) {
7096 ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
7097 set_guarded_list_length(Field::kNoFixedLength);
7098 set_guarded_list_length_in_object_offset(-1);
Florian Schneider 2014/05/28 14:57:36 s/-1/kUnknownLengthOffset/
Vyacheslav Egorov (Google) 2014/05/29 17:36:51 Done.
7099 return true;
7100 }
7101
7102 // Everything matches.
7036 return false; 7103 return false;
7037 } 7104 }
7038 7105
7039 if ((cid == kNullCid) && !is_nullable()) { 7106 if ((cid == kNullCid) && !is_nullable()) {
7040 // Assigning null value to a non-nullable field makes it nullable. 7107 // Assigning null value to a non-nullable field makes it nullable.
7041 set_is_nullable(true); 7108 set_is_nullable(true);
7042 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) { 7109 } else if ((cid != kNullCid) && (guarded_cid() == kNullCid)) {
7043 // Assigning non-null value to a field that previously contained only null 7110 // Assigning non-null value to a field that previously contained only null
7044 // turns it into a nullable field with the given class id. 7111 // turns it into a nullable field with the given class id.
7045 ASSERT(is_nullable()); 7112 ASSERT(is_nullable());
7046 set_guarded_cid(cid); 7113 set_guarded_cid(cid);
7047 } else { 7114 } else {
7048 // Give up on tracking class id of values contained in this field. 7115 // Give up on tracking class id of values contained in this field.
7049 ASSERT(guarded_cid() != cid); 7116 ASSERT(guarded_cid() != cid);
7050 set_guarded_cid(kDynamicCid); 7117 set_guarded_cid(kDynamicCid);
7051 set_is_nullable(true); 7118 set_is_nullable(true);
7052 } 7119 }
7053 7120
7121 // If we were tracking length drop collected feedback.
7122 if (needs_length_check()) {
7123 ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
7124 set_guarded_list_length(Field::kNoFixedLength);
7125 set_guarded_list_length_in_object_offset(-1);
Florian Schneider 2014/05/28 14:57:36 s/-1/kUnknownLengthOffset/
Vyacheslav Egorov (Google) 2014/05/29 17:36:51 Done.
7126 }
7127
7054 // Expected class id or nullability of the field changed. 7128 // Expected class id or nullability of the field changed.
7055 return true; 7129 return true;
7056 } 7130 }
7057 7131
7058 7132
7059 bool Field::UpdateLength(intptr_t list_length) const { 7133 void Field::RecordStore(const Object& value) const {
7060 ASSERT(is_final() || (!is_final() && 7134 if (FLAG_trace_field_guards) {
7061 (list_length < Field::kUnknownFixedLength))); 7135 OS::Print("Store %s %s <- %s\n",
7062 ASSERT((list_length == Field::kNoFixedLength) || 7136 ToCString(),
7063 (list_length > Field::kUnknownFixedLength)); 7137 GuardedPropertiesAsCString(),
7064 ASSERT(guarded_cid() != kIllegalCid); 7138 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 } 7139 }
7078 7140
7079 if (!list_length_changed && !force_invalidate) { 7141 if (UpdateGuardedCidAndLength(value)) {
7080 // List length unchanged. 7142 if (FLAG_trace_field_guards) {
7081 return false; 7143 OS::Print(" => %s\n", GuardedPropertiesAsCString());
7144 }
7145
7146 DeoptimizeDependentCode();
7082 } 7147 }
7083 // Multiple list lengths assigned here, stop tracking length.
7084 set_guarded_list_length(Field::kNoFixedLength);
7085 return true;
7086 } 7148 }
7087 7149
7088 7150
7089 void LiteralToken::set_literal(const String& literal) const { 7151 void LiteralToken::set_literal(const String& literal) const {
7090 StorePointer(&raw_ptr()->literal_, literal.raw()); 7152 StorePointer(&raw_ptr()->literal_, literal.raw());
7091 } 7153 }
7092 7154
7093 7155
7094 void LiteralToken::set_value(const Object& value) const { 7156 void LiteralToken::set_value(const Object& value) const {
7095 StorePointer(&raw_ptr()->value_, value.raw()); 7157 StorePointer(&raw_ptr()->value_, value.raw());
(...skipping 11803 matching lines...) Expand 10 before | Expand all | Expand 10 after
18899 return tag_label.ToCString(); 18961 return tag_label.ToCString();
18900 } 18962 }
18901 18963
18902 18964
18903 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 18965 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
18904 Instance::PrintJSONImpl(stream, ref); 18966 Instance::PrintJSONImpl(stream, ref);
18905 } 18967 }
18906 18968
18907 18969
18908 } // namespace dart 18970 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698