diff --git a/runtime/tests/vm/vm.status b/runtime/tests/vm/vm.status index 8270ee15ca9..505c06f5fcc 100644 --- a/runtime/tests/vm/vm.status +++ b/runtime/tests/vm/vm.status @@ -333,6 +333,7 @@ cc/IsolateReload_RunNewFieldInitializersMutateStaticField: Skip cc/IsolateReload_RunNewFieldInitializersReferenceStaticField: Skip cc/IsolateReload_RunNewFieldInitializersSyntaxError3: Fail cc/IsolateReload_RunNewFieldInitializersThrows: Skip +cc/IsolateReload_RunNewFieldInitializersWithConsts: Skip cc/IsolateReload_ShapeChangeRetainsHash: Skip cc/IsolateReload_SmiFastPathStubs: Fail cc/IsolateReload_TearOff_AddArguments2: Fail diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc index bc50f850133..982a00e80b9 100644 --- a/runtime/vm/isolate_reload.cc +++ b/runtime/vm/isolate_reload.cc @@ -1288,8 +1288,19 @@ void IsolateReloadContext::Commit() { Become::ElementsForwardIdentity(before, after); } - // Run the initializers for new instance fields. - RunNewFieldInitializers(); + // Rehash constants map for all classes. Constants are hashed by address, and + // addresses may change during a become operation. + RehashConstants(); + +#ifdef DEBUG + // Verify that all canonical instances are correctly setup in the + // corresponding canonical tables. + Thread* thread = Thread::Current(); + I->heap()->CollectAllGarbage(); + HeapIterationScope iteration(thread); + VerifyCanonicalVisitor check_canonical(thread); + iteration.IterateObjects(&check_canonical); +#endif // DEBUG if (FLAG_identity_reload) { if (saved_num_cids_ != I->class_table()->NumCids()) { @@ -1306,18 +1317,8 @@ void IsolateReloadContext::Commit() { } } - // Rehash constants map for all classes. - RehashConstants(); - -#ifdef DEBUG - // Verify that all canonical instances are correctly setup in the - // corresponding canonical tables. - Thread* thread = Thread::Current(); - I->heap()->CollectAllGarbage(); - HeapIterationScope iteration(thread); - VerifyCanonicalVisitor check_canonical(thread); - iteration.IterateObjects(&check_canonical); -#endif // DEBUG + // Run the initializers for new instance fields. + RunNewFieldInitializers(); } void IsolateReloadContext::RehashConstants() { diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc index ef331deac0f..ed3195864cb 100644 --- a/runtime/vm/isolate_reload_test.cc +++ b/runtime/vm/isolate_reload_test.cc @@ -3542,6 +3542,57 @@ TEST_CASE(IsolateReload_RunNewFieldInitialiazersSuperClass) { EXPECT_STREQ("right", SimpleInvokeStr(lib, "main")); } +TEST_CASE(IsolateReload_RunNewFieldInitializersWithConsts) { + const char* kScript = + "class C {\n" + " final x;\n" + " const C(this.x);\n" + "}\n" + "var a = const C(const C(1));\n" + "var b = const C(const C(2));\n" + "var c = const C(const C(3));\n" + "var d = const C(const C(4));\n" + "class Foo {\n" + "}\n" + "Foo value;\n" + "main() {\n" + " value = new Foo();\n" + " a; b; c; d;\n" + " return 'Okay';\n" + "}\n"; + + Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL); + EXPECT_VALID(lib); + EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main")); + + const char* kReloadScript = + "class C {\n" + " final x;\n" + " const C(this.x);\n" + "}\n" + "var a = const C(const C(1));\n" + "var b = const C(const C(2));\n" + "var c = const C(const C(3));\n" + "var d = const C(const C(4));\n" + "class Foo {\n" + " var d = const C(const C(4));\n" + " var c = const C(const C(3));\n" + " var b = const C(const C(2));\n" + " var a = const C(const C(1));\n" + "}\n" + "Foo value;\n" + "main() {\n" + " return '${identical(a, value.a)} ${identical(b, value.b)}'" + " ' ${identical(c, value.c)} ${identical(d, value.d)}';\n" + "}\n"; + + lib = TestCase::ReloadTestScript(kReloadScript); + EXPECT_VALID(lib); + // Verify that we ran field initializers on existing instances and the const + // expressions were properly canonicalized. + EXPECT_STREQ("true true true true", SimpleInvokeStr(lib, "main")); +} + TEST_CASE(IsolateReload_TypedefToNotTypedef) { const char* kScript = "typedef bool Predicate(dynamic x);\n"