From 9daa67967f3b602b042e98bf200b526804ba270d Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Sat, 25 Mar 2023 01:33:07 +0000 Subject: [PATCH] [vm/reload] Ensure we only morph instantiated classes and enums. Fixes https://github.com/dart-lang/sdk/issues/51835 TEST=IsolateReload_EnumInMainLibraryModified Change-Id: I4a8993cb44619a552866430b92f3941d49afbae6 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/291051 Reviewed-by: Ryan Macnak Commit-Queue: Alexander Aprelev --- runtime/vm/isolate_reload.cc | 1 + runtime/vm/isolate_reload_test.cc | 29 +++++++++++++++++++++++++++++ runtime/vm/object_reload.cc | 5 +++++ 3 files changed, 35 insertions(+) diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc index 1fa9aee4e5d..225113af4e4 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -319,6 +319,7 @@ void InstanceMorpher::CreateMorphedCopies(Become* become) { // We also forward Enum.values. No filler is needed because arrays never // change shape. + ASSERT(old_values.ptr() != new_values.ptr()); become->Add(old_values, new_values); #if defined(DEBUG) diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc index 829d4d6d148..0fd416dcb23 100644 --- a/runtime/vm/isolate_reload_test.cc +++ b/runtime/vm/isolate_reload_test.cc @@ -5196,6 +5196,35 @@ TEST_CASE(IsolateReload_ImplicitGetterWithLoadGuard) { EXPECT_STREQ("y: 3, z: 8208", SimpleInvokeStr(lib1, "main")); } +// Regression test for https://github.com/dart-lang/sdk/issues/51835 +TEST_CASE(IsolateReload_EnumInMainLibraryModified) { + const char* kScript = + "enum Bar { bar }\n" + "class Foo { int? a; toString() => 'foo'; }" + "main() {\n" + " return Foo().toString();\n" + "}\n"; + + Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); + EXPECT_VALID(lib); + EXPECT_VALID(Dart_FinalizeAllClasses()); + EXPECT_STREQ("foo", SimpleInvokeStr(lib, "main")); + + const char* kReloadScript = + "enum Bar { bar }\n" + "class Foo { int? a; String? b; toString() => 'foo'; }" + "main() {\n" + " return Foo().toString();\n" + "}\n"; + + lib = TestCase::ReloadTestScript(kReloadScript); + EXPECT_VALID(lib); + Dart_SetFileModifiedCallback(NULL); + + // Modification of an imported library propagates to the importing library. + EXPECT_STREQ("foo", SimpleInvokeStr(lib, "main")); +} + #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) } // namespace dart diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc index 4ca1846d45f..ea79b675629 100644 --- a/runtime/vm/object_reload.cc +++ b/runtime/vm/object_reload.cc @@ -610,6 +610,11 @@ void Class::MarkFieldBoxedDuringReload(ClassTable* class_table, bool Class::RequiresInstanceMorphing(ClassTable* class_table, const Class& replacement) const { + if (!is_allocate_finalized()) { + // No instances of this class exists on the heap - nothing to morph. + return false; + } + if (replacement.is_enum_class()) { return true; }