[vm, reload] Debugging code for become conflict.
TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/56583
Change-Id: I8afba7689c91ebbd03ec4fcee22782205dc7959f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/383540
Reviewed-by: Alexander Aprelev <aam@google.com>
Commit-Queue: Ryan Macnak <rmacnak@google.com>
diff --git a/runtime/vm/heap/become.cc b/runtime/vm/heap/become.cc
index 732375b..f1be403 100644
--- a/runtime/vm/heap/become.cc
+++ b/runtime/vm/heap/become.cc
@@ -228,9 +228,12 @@
Thread::Current()->isolate_group()->set_become(nullptr);
}
-void Become::Add(const Object& before, const Object& after) {
+void Become::Add(const Object& before,
+ const Object& after,
+ const char* whence) {
pointers_.Add(before.ptr());
pointers_.Add(after.ptr());
+ whence_.Add(whence);
}
void Become::VisitObjectPointers(ObjectPointerVisitor* visitor) {
@@ -272,11 +275,77 @@
FATAL("become: %s", message);
}
+struct PtrIntTrait {
+ typedef ObjectPtr Key;
+ typedef intptr_t Value;
+ typedef struct {
+ ObjectPtr key;
+ intptr_t value;
+ } Pair;
+
+ static Key KeyOf(Pair kv) { return kv.key; }
+ static Value ValueOf(Pair kv) { return kv.value; }
+ static uword Hash(Key key) {
+ return (static_cast<uword>(key) * 92821) ^ (static_cast<uword>(key) >> 8);
+ }
+ static bool IsKeyEqual(Pair kv, Key key) { return kv.key == key; }
+};
+
void Become::Forward() {
if (pointers_.length() == 0) {
return;
}
+ {
+ intptr_t conflicts = 0;
+ MallocDirectChainedHashMap<PtrIntTrait> map(pointers_.length() / 2);
+ for (intptr_t i = 0; i < pointers_.length(); i += 2) {
+ ObjectPtr before = pointers_[i];
+ auto* pair = map.Lookup(before);
+ if (pair == nullptr) {
+ map.Insert({before, i + 1}); // 0 value is sentinel.
+ } else {
+ intptr_t j = pair->value - 1; // 0 value is sentinel.
+ ObjectPtr before1 = pointers_[j];
+ ObjectPtr after1 = pointers_[j + 1];
+ ObjectPtr before2 = pointers_[i];
+ ObjectPtr after2 = pointers_[i + 1];
+ const char* whence1 = whence_[j / 2];
+ const char* whence2 = whence_[i / 2];
+
+ OS::PrintErr("become conflict:\n");
+ OS::PrintErr("whence1 = %s\n", whence1);
+ OS::PrintErr("whence2 = %s\n", whence2);
+
+ OS::PrintErr("before1 cid = %" Pd "\n", before1.GetClassId());
+ OS::PrintErr(" after1 cid = %" Pd "\n", after1.GetClassId());
+ OS::PrintErr("before2 cid = %" Pd "\n", before2.GetClassId());
+ OS::PrintErr(" after2 cid = %" Pd "\n", after2.GetClassId());
+
+ OS::PrintErr("before1 size = %" Pd "\n", before1.untag()->HeapSize());
+ OS::PrintErr(" after1 size = %" Pd "\n", after1.untag()->HeapSize());
+ OS::PrintErr("before2 size = %" Pd "\n", before2.untag()->HeapSize());
+ OS::PrintErr(" after2 size = %" Pd "\n", after2.untag()->HeapSize());
+
+#ifndef PRODUCT
+ ClassTable* class_table = IsolateGroup::Current()->class_table();
+ OS::PrintErr("before1 cls = %s\n",
+ class_table->UserVisibleNameFor(before1.GetClassId()));
+ OS::PrintErr(" after1 cls = %s\n",
+ class_table->UserVisibleNameFor(after1.GetClassId()));
+ OS::PrintErr("before2 cls = %s\n",
+ class_table->UserVisibleNameFor(before2.GetClassId()));
+ OS::PrintErr(" after2 cls = %s\n",
+ class_table->UserVisibleNameFor(after2.GetClassId()));
+#endif
+ conflicts++;
+ }
+ }
+ if (conflicts != 0) {
+ FATAL("%" Pd " become conflicts", conflicts);
+ }
+ }
+
Thread* thread = Thread::Current();
auto heap = thread->isolate_group()->heap();
@@ -325,6 +394,7 @@
}
#endif
pointers_.Clear();
+ whence_.Clear();
}
void Become::FollowForwardingPointers(Thread* thread) {
diff --git a/runtime/vm/heap/become.h b/runtime/vm/heap/become.h
index 1d4bb3b..940e8da 100644
--- a/runtime/vm/heap/become.h
+++ b/runtime/vm/heap/become.h
@@ -98,7 +98,7 @@
Become();
~Become();
- void Add(const Object& before, const Object& after);
+ void Add(const Object& before, const Object& after, const char* whence);
void Forward();
void Exchange() { UNIMPLEMENTED(); }
@@ -115,6 +115,7 @@
private:
MallocGrowableArray<ObjectPtr> pointers_;
+ MallocGrowableArray<const char*> whence_;
DISALLOW_COPY_AND_ASSIGN(Become);
};
diff --git a/runtime/vm/heap/become_test.cc b/runtime/vm/heap/become_test.cc
index e83fbf1..152cfd5 100644
--- a/runtime/vm/heap/become_test.cc
+++ b/runtime/vm/heap/become_test.cc
@@ -22,7 +22,7 @@
EXPECT(before_obj.ptr() != after_obj.ptr());
Become become;
- become.Add(before_obj, after_obj);
+ become.Add(before_obj, after_obj, "test");
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
@@ -64,7 +64,7 @@
EXPECT_EQ(no_peer, heap->GetPeer(after_obj.ptr()));
Become become;
- become.Add(before_obj, after_obj);
+ become.Add(before_obj, after_obj, "test");
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
@@ -86,7 +86,7 @@
EXPECT_EQ(no_id, heap->GetObjectId(after_obj.ptr()));
Become become;
- become.Add(before_obj, after_obj);
+ become.Add(before_obj, after_obj, "test");
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
@@ -112,7 +112,7 @@
isolate->forward_table_old()->GetValueExclusive(after_obj.ptr()));
Become become;
- become.Add(before_obj, after_obj);
+ become.Add(before_obj, after_obj, "test");
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
@@ -138,7 +138,7 @@
EXPECT(before_obj.ptr() != after_obj.ptr());
Become become;
- become.Add(before_obj, after_obj);
+ become.Add(before_obj, after_obj, "test");
become.Forward();
EXPECT(before_obj.ptr() == after_obj.ptr());
@@ -167,7 +167,7 @@
}
Become become;
- become.Add(old_element, new_element);
+ become.Add(old_element, new_element, "test");
become.Forward();
EXPECT(old_element.ptr() == new_element.ptr());
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 792bfa6..0f04c1a 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -992,7 +992,7 @@
}
if (old_value.ptr() != new_value.ptr()) {
- become->Add(old_value, new_value);
+ become->Add(old_value, new_value, "enum forwarding");
}
if (new_value.IsCanonical()) {
cls.InsertCanonicalConstant(zone, new_value);
@@ -1009,7 +1009,7 @@
} else {
new_value = old_value.Canonicalize(thread);
if (old_value.ptr() != new_value.ptr()) {
- become->Add(old_value, new_value);
+ become->Add(old_value, new_value, "constant forwarding");
}
}
}
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 65cc2ae..504880f 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -357,7 +357,9 @@
// instances of any class with the old size.
Become::MakeDummyObject(before);
- become->Add(before, after);
+ become->Add(
+ before, after,
+ is_canonical ? "instance morphing canonical" : "instance morphing");
}
}
@@ -1279,7 +1281,7 @@
IG->class_table()->SetAt(old_cls.id(), new_cls.ptr());
new_cls.CopyCanonicalConstants(old_cls);
new_cls.CopyDeclarationType(old_cls);
- AddBecomeMapping(old_cls, new_cls);
+ AddBecomeMapping(old_cls, new_cls, "class forwarding");
AddClassMapping(new_cls, old_cls);
}
@@ -2555,7 +2557,7 @@
// Replaced class.
AddLibraryMapping(replacement_or_new, old);
- AddBecomeMapping(old, replacement_or_new);
+ AddBecomeMapping(old, replacement_or_new, "library forwarding");
}
}
}
@@ -2664,12 +2666,13 @@
const Field& new_field) {
ASSERT(old_field.is_static());
ASSERT(new_field.is_static());
- AddBecomeMapping(old_field, new_field);
+ AddBecomeMapping(old_field, new_field, "static field");
}
void ProgramReloadContext::AddBecomeMapping(const Object& old,
- const Object& neu) {
- become_.Add(old, neu);
+ const Object& neu,
+ const char* whence) {
+ become_.Add(old, neu, whence);
}
void ProgramReloadContext::RestoreClassHierarchyInvariants() {
diff --git a/runtime/vm/isolate_reload.h b/runtime/vm/isolate_reload.h
index d4b5e66..263b486 100644
--- a/runtime/vm/isolate_reload.h
+++ b/runtime/vm/isolate_reload.h
@@ -381,7 +381,9 @@
void AddLibraryMapping(const Library& replacement_or_new,
const Library& original);
void AddStaticFieldMapping(const Field& old_field, const Field& new_field);
- void AddBecomeMapping(const Object& old, const Object& neu);
+ void AddBecomeMapping(const Object& old,
+ const Object& neu,
+ const char* whence);
void RestoreClassHierarchyInvariants();
Become become_;
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 8a6545e..24a468b 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -338,7 +338,7 @@
if (old_closure.IsCanonical()) {
new_closure.SetCanonical();
}
- irc->AddBecomeMapping(old_closure, new_closure);
+ irc->AddBecomeMapping(old_closure, new_closure, "static tear-off");
}
}
}
@@ -758,7 +758,7 @@
// The replacement of the old prefix with the new prefix
// in Isolate::loaded_prefixes_set_ implicitly carried
// the loaded state over to the new prefix.
- context->AddBecomeMapping(original_prefix, prefix);
+ context->AddBecomeMapping(original_prefix, prefix, "library prefix");
}
}
}