mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 23:29:47 +00:00
[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:
parent
946175cbd0
commit
bb9583bf99
|
@ -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) {
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue