diff --git a/runtime/vm/isolate_reload_test.cc b/runtime/vm/isolate_reload_test.cc index 4f300d641d6..d30886b35d0 100644 --- a/runtime/vm/isolate_reload_test.cc +++ b/runtime/vm/isolate_reload_test.cc @@ -6815,6 +6815,74 @@ abstract class A5 { } check_class_hierarchy_state(); } +// https://github.com/flutter/flutter/issues/153536 +TEST_CASE(IsolateReload_ClosureHashStablity) { + const char* kScript = + "var retained;\n" + "var retainedHashes;\n" + "static1() {} \n" + "static2() {} \n" + "static3() {} \n" + "class Foo {\n" + " method1() {}\n" + " method2() {}\n" + " method3() {}\n" + "}\n" + "extension Ext on Foo {\n" + " extensionMethod1() {}\n" + " extensionMethod2() {}\n" + " extensionMethod3() {}\n" + "}\n" + "main() {\n" + " local1() {}\n" + " local2() {}\n" + " local3() {}\n" + " var f = new Foo();\n" + " retained = [ static1, static2, static3,\n" + " f.method1, f.method2, f.method3,\n" + " f.extensionMethod1, f.extensionMethod2,\n" + " f.extensionMethod3,\n" + " local1, local2, local3 ];\n" + " retainedHashes = retained.map((c) => c.hashCode).toList();\n" + " return 'Setup';\n" + "}\n"; + + Dart_Handle lib = TestCase::LoadTestScript(kScript, nullptr); + EXPECT_VALID(lib); + EXPECT_VALID(Dart_FinalizeAllClasses()); + EXPECT_STREQ("Setup", SimpleInvokeStr(lib, "main")); + + const char* kReloadScript = + "extraFunctionShiftingDownAllTokenPositions() {}\n" + "var retained;\n" + "var retainedHashes;\n" + "static1() {} \n" + "static2() {} \n" + "static3() {} \n" + "class Foo {\n" + " method1() {}\n" + " method2() {}\n" + " method3() {}\n" + "}\n" + "extension Ext on Foo {\n" + " extensionMethod1() {}\n" + " extensionMethod2() {}\n" + " extensionMethod3() {}\n" + "}\n" + "main() {\n" + " for (var i = 0; i < retained.length; i++) {\n" + " if (retained[i].hashCode != retainedHashes[i]){\n" + " return 'Changed: ${retained[i]}';\n" + " }\n" + " }\n" + " return 'Okay';\n" + "}\n"; + + lib = TestCase::ReloadTestScript(kReloadScript); + EXPECT_VALID(lib); + EXPECT_STREQ("Okay", SimpleInvokeStr(lib, "main")); +} + #endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME) } // namespace dart diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index bfd7450343d..5ff31ebc662 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -8067,12 +8067,12 @@ void PatchClass::set_script(const Script& value) const { } uword Function::Hash() const { - uword hash = String::HashRawSymbol(name()); - if (IsClosureFunction()) { - hash = hash ^ token_pos().Hash(); + uint32_t hash = String::HashRawSymbol(name()); + if (IsNonImplicitClosureFunction()) { + hash = CombineHashes(hash, token_pos().Hash()); } if (Owner()->IsClass()) { - hash = hash ^ Class::Hash(Class::RawCast(Owner())); + hash = CombineHashes(hash, Class::Hash(Class::RawCast(Owner()))); } return hash; }