[vm, reload] Fix assertion failure when instance morphing encounters a field value that is an already morphed instance.

TEST=ci
Change-Id: I0d04b92fafc7ccb655e67e1fa3805d00e92a7e4b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/316488
Commit-Queue: Ryan Macnak <rmacnak@google.com>
Reviewed-by: Ben Konyi <bkonyi@google.com>
This commit is contained in:
Ryan Macnak 2023-07-26 20:47:25 +00:00 committed by Commit Queue
parent 946175cbd0
commit bb9583bf99
3 changed files with 48 additions and 2 deletions

View file

@ -388,8 +388,10 @@ void InstanceMorpher::CreateMorphedCopies(Become* become) {
if (from.box_cid == kIllegalCid) {
// Boxed to boxed field migration.
ASSERT(to.box_cid == kIllegalCid);
value = before.RawGetFieldAtOffset(from.offset);
after.RawSetFieldAtOffset(to.offset, value);
// No handle: raw_value might be a ForwardingCorpse for an object
// processed earlier in instance morphing
ObjectPtr raw_value = before.RawGetFieldAtOffset(from.offset);
after.RawSetFieldAtOffset(to.offset, raw_value);
} else if (to.box_cid == kIllegalCid) {
// Unboxed to boxed field migration.
switch (from.box_cid) {

View file

@ -3934,6 +3934,47 @@ TEST_CASE(IsolateReload_ChangeInstanceFormat9) {
EXPECT_ERROR(lib, "type parameters have changed");
}
TEST_CASE(IsolateReload_ShapeChangeMutualReference) {
const char* kScript =
"class A{\n"
" var x;\n"
" get yourself => this;\n"
"}\n"
"var retained1;\n"
"var retained2;\n"
"main() {\n"
" retained1 = new A();\n"
" retained2 = new A();\n"
" retained1.x = retained2;\n"
" retained2.x = retained1;\n"
" return '${identical(retained1.x.yourself, retained2)}'\n"
" '${identical(retained2.x.yourself, retained1)}';\n"
"}\n";
Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr);
EXPECT_VALID(lib);
EXPECT_STREQ("truetrue", SimpleInvokeStr(lib, "main"));
const char* kReloadScript =
"class A{\n"
" var x;\n"
" var y;\n"
" var z;\n"
" var w;\n"
" get yourself => this;\n"
"}\n"
"var retained1;\n"
"var retained2;\n"
"main() {\n"
" return '${identical(retained1.x.yourself, retained2)}'\n"
" '${identical(retained2.x.yourself, retained1)}';\n"
"}\n";
lib = TestCase::ReloadTestScript(kReloadScript);
EXPECT_VALID(lib);
EXPECT_STREQ("truetrue", SimpleInvokeStr(lib, "main"));
}
TEST_CASE(IsolateReload_ShapeChangeRetainsHash) {
const char* kScript =
"class A{\n"

View file

@ -8294,6 +8294,9 @@ class Instance : public Object {
void RawSetFieldAtOffset(intptr_t offset, const Object& value) const {
StoreCompressedPointer(RawFieldAddrAtOffset(offset), value.ptr());
}
void RawSetFieldAtOffset(intptr_t offset, ObjectPtr value) const {
StoreCompressedPointer(RawFieldAddrAtOffset(offset), value);
}
template <typename T>
T* RawUnboxedFieldAddrAtOffset(intptr_t offset) const {