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

Unified 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, 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index 5b358b5f2f5d96834d7a794622d46730f361069a..98f32601cc41c3469758be91c6473f60271574ff 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -64,6 +64,7 @@ DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
"fit into a javascript integer.");
DEFINE_FLAG(bool, use_field_guards, true, "Guard field cids.");
DEFINE_FLAG(bool, use_lib_cache, true, "Use library name cache");
+DEFINE_FLAG(bool, trace_field_guards, false, "Trace changes in field's cids.");
DECLARE_FLAG(bool, enable_type_checks);
DECLARE_FLAG(bool, error_on_bad_override);
@@ -6774,6 +6775,7 @@ RawField* Field::New(const String& name,
result.set_is_unboxing_candidate(true);
result.set_guarded_cid(FLAG_use_field_guards ? kIllegalCid : kDynamicCid);
result.set_is_nullable(FLAG_use_field_guards ? false : true);
+ result.set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
// Presently, we only attempt to remember the list length for final fields.
if (is_final && FLAG_use_field_guards) {
result.set_guarded_list_length(Field::kUnknownFixedLength);
@@ -6822,6 +6824,19 @@ void Field::set_guarded_list_length(intptr_t list_length) const {
}
+intptr_t Field::guarded_list_length_in_object_offset() const {
+ return raw_ptr()->guarded_list_length_in_object_offset_ + kHeapObjectTag;
+}
+
+
+void Field::set_guarded_list_length_in_object_offset(
+ intptr_t list_length_offset) const {
+ raw_ptr()->guarded_list_length_in_object_offset_ =
+ static_cast<int8_t>(list_length_offset - kHeapObjectTag);
+ ASSERT(guarded_list_length_in_object_offset() == list_length_offset);
+}
+
+
bool Field::IsUnboxedField() const {
bool valid_class = (FlowGraphCompiler::SupportsUnboxedDoubles() &&
(guarded_cid() == kDoubleCid)) ||
@@ -6983,9 +6998,6 @@ bool Field::IsUninitialized() 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();
@@ -6998,41 +7010,115 @@ static intptr_t GetListLength(const Object& value) {
} else if (value.IsExternalTypedData()) {
// TODO(johnmccutchan): Enable for external typed data.
return Field::kNoFixedLength;
- } else if (RawObject::IsTypedDataViewClassId(cid)) {
+ } else if (RawObject::IsTypedDataViewClassId(value.GetClassId())) {
// 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();
+static intptr_t GetListLengthOffset(intptr_t cid) {
+ if (RawObject::IsTypedDataClassId(cid)) {
+ return TypedData::length_offset();
+ } else if (cid == kArrayCid || cid == kImmutableArrayCid) {
+ return Array::length_offset();
+ } else if (cid == kGrowableObjectArrayCid) {
+ // List length is variable.
+ return Field::kUnknownLengthOffset;
+ } else if (RawObject::IsExternalTypedDataClassId(cid)) {
+ // TODO(johnmccutchan): Enable for external typed data.
+ return Field::kUnknownLengthOffset;
+ } else if (RawObject::IsTypedDataViewClassId(cid)) {
+ // TODO(johnmccutchan): Enable for typed data views.
+ return Field::kUnknownLengthOffset;
}
- return deoptimize;
+ return Field::kUnknownLengthOffset;
}
-bool Field::UpdateCid(intptr_t cid) const {
+const char* Field::GuardedPropertiesAsCString() const {
+ if (guarded_cid() == kIllegalCid) {
+ return "<?>";
+ } else if (guarded_cid() == kDynamicCid) {
+ return "<*>";
+ }
+
+ const Class& cls = Class::Handle(
+ Isolate::Current()->class_table()->At(guarded_cid()));
+ const char* class_name = String::Handle(cls.Name()).ToCString();
+
+ if (RawObject::IsBuiltinListClassId(guarded_cid()) &&
+ !is_nullable() &&
+ is_final()) {
+ ASSERT(guarded_list_length() != kUnknownFixedLength);
+ if (guarded_list_length() == kNoFixedLength) {
+ return Isolate::Current()->current_zone()->PrintToString(
+ "<%s [*]>", class_name);
+ } else {
+ return Isolate::Current()->current_zone()->PrintToString(
+ "<%s [%" Pd " @%" Pd "]>",
+ class_name,
+ guarded_list_length(),
+ guarded_list_length_in_object_offset());
+ }
+ }
+
+ return Isolate::Current()->current_zone()->PrintToString("<%s %s>",
+ is_nullable() ? "nullable" : "not-nullable",
+ class_name);
+}
+
+
+void Field::InitializeGuardedListLengthInObjectOffset() const {
+ if (needs_length_check() &&
+ (guarded_list_length() != Field::kUnknownFixedLength)) {
+ const intptr_t offset = GetListLengthOffset(guarded_cid());
+ set_guarded_list_length_in_object_offset(offset);
+ ASSERT(offset != Field::kUnknownLengthOffset);
+ } else {
+ set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+ }
+}
+
+
+bool Field::UpdateGuardedCidAndLength(const Object& value) const {
+ const intptr_t cid = value.GetClassId();
+
if (guarded_cid() == kIllegalCid) {
// Field is assigned first time.
set_guarded_cid(cid);
set_is_nullable(cid == kNullCid);
+
+ // Start tracking length if needed.
+ ASSERT((guarded_list_length() == Field::kUnknownFixedLength) ||
+ (guarded_list_length() == Field::kNoFixedLength));
+ if (needs_length_check()) {
+ ASSERT(guarded_list_length() == Field::kUnknownFixedLength);
+ set_guarded_list_length(GetListLength(value));
+ InitializeGuardedListLengthInObjectOffset();
+ }
+
+ if (FLAG_trace_field_guards) {
+ OS::Print(" => %s\n", GuardedPropertiesAsCString());
+ }
+
return false;
}
if ((cid == guarded_cid()) || ((cid == kNullCid) && is_nullable())) {
// Class id of the assigned value matches expected class id and nullability.
+
+ // If we are tracking length check if it has matches.
+ if (needs_length_check() &&
+ (guarded_list_length() != GetListLength(value))) {
+ ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
+ set_guarded_list_length(Field::kNoFixedLength);
+ set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+ return true;
+ }
+
+ // Everything matches.
return false;
}
@@ -7051,38 +7137,33 @@ bool Field::UpdateCid(intptr_t cid) const {
set_is_nullable(true);
}
+ // If we were tracking length drop collected feedback.
+ if (needs_length_check()) {
+ ASSERT(guarded_list_length() != Field::kUnknownFixedLength);
+ set_guarded_list_length(Field::kNoFixedLength);
+ set_guarded_list_length_in_object_offset(Field::kUnknownLengthOffset);
+ }
+
// Expected class id or nullability of the field changed.
return true;
}
-bool Field::UpdateLength(intptr_t list_length) const {
- ASSERT(is_final() || (!is_final() &&
- (list_length < Field::kUnknownFixedLength)));
- ASSERT((list_length == Field::kNoFixedLength) ||
- (list_length > Field::kUnknownFixedLength));
- ASSERT(guarded_cid() != kIllegalCid);
-
- const bool force_invalidate = (guarded_cid() == kDynamicCid) &&
- (list_length != Field::kNoFixedLength);
-
- const bool list_length_unknown =
- (guarded_list_length() == Field::kUnknownFixedLength);
- const bool list_length_changed = (guarded_list_length() != list_length);
-
- if (list_length_unknown && list_length_changed && !force_invalidate) {
- // List length set for first time.
- set_guarded_list_length(list_length);
- return false;
+void Field::RecordStore(const Object& value) const {
+ if (FLAG_trace_field_guards) {
+ OS::Print("Store %s %s <- %s\n",
+ ToCString(),
+ GuardedPropertiesAsCString(),
+ value.ToCString());
}
- if (!list_length_changed && !force_invalidate) {
- // List length unchanged.
- return false;
+ if (UpdateGuardedCidAndLength(value)) {
+ if (FLAG_trace_field_guards) {
+ OS::Print(" => %s\n", GuardedPropertiesAsCString());
+ }
+
+ DeoptimizeDependentCode();
}
- // Multiple list lengths assigned here, stop tracking length.
- set_guarded_list_length(Field::kNoFixedLength);
- return true;
}
« 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