Skip to content

Commit ccaf6c6

Browse files
RELOAD: Maintain identity of static tear-offs.
[email protected] Review URL: https://codereview.chromium.org/2194333002 .
1 parent e76ad03 commit ccaf6c6

File tree

4 files changed

+111
-9
lines changed

4 files changed

+111
-9
lines changed

runtime/vm/isolate_reload.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -970,25 +970,25 @@ void IsolateReloadContext::Commit() {
970970
// Copy static field values from the old classes to the new classes.
971971
// Patch fields and functions in the old classes so that they retain
972972
// the old script.
973-
Class& cls = Class::Handle();
973+
Class& old_cls = Class::Handle();
974974
Class& new_cls = Class::Handle();
975-
976975
UnorderedHashMap<ClassMapTraits> class_map(class_map_storage_);
977976

978977
{
979978
UnorderedHashMap<ClassMapTraits>::Iterator it(&class_map);
980979
while (it.MoveNext()) {
981980
const intptr_t entry = it.Current();
982981
new_cls = Class::RawCast(class_map.GetKey(entry));
983-
cls = Class::RawCast(class_map.GetPayload(entry, 0));
984-
if (new_cls.raw() != cls.raw()) {
985-
ASSERT(new_cls.is_enum_class() == cls.is_enum_class());
982+
old_cls = Class::RawCast(class_map.GetPayload(entry, 0));
983+
if (new_cls.raw() != old_cls.raw()) {
984+
ASSERT(new_cls.is_enum_class() == old_cls.is_enum_class());
986985
if (new_cls.is_enum_class() && new_cls.is_finalized()) {
987-
new_cls.ReplaceEnum(cls);
986+
new_cls.ReplaceEnum(old_cls);
988987
} else {
989-
new_cls.CopyStaticFieldValues(cls);
988+
new_cls.CopyStaticFieldValues(old_cls);
990989
}
991-
cls.PatchFieldsAndFunctions();
990+
old_cls.PatchFieldsAndFunctions();
991+
old_cls.MigrateImplicitStaticClosures(this, new_cls);
992992
}
993993
}
994994
}

runtime/vm/isolate_reload_test.cc

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1310,7 +1310,7 @@ TEST_CASE(IsolateReload_PendingSuperCall) {
13101310
}
13111311

13121312

1313-
TEST_CASE(IsolateReload_TearOff_Equality) {
1313+
TEST_CASE(IsolateReload_TearOff_Instance_Equality) {
13141314
const char* kScript =
13151315
"import 'test:isolate_reload_helper';\n"
13161316
"class C {\n"
@@ -1349,6 +1349,80 @@ TEST_CASE(IsolateReload_TearOff_Equality) {
13491349
}
13501350

13511351

1352+
TEST_CASE(IsolateReload_TearOff_Class_Identity) {
1353+
const char* kScript =
1354+
"import 'test:isolate_reload_helper';\n"
1355+
"class C {\n"
1356+
" static foo() => 'old';\n"
1357+
"}\n"
1358+
"getFoo() => C.foo;\n"
1359+
"main() {\n"
1360+
" var f1 = getFoo();\n"
1361+
" reloadTest();\n"
1362+
" var f2 = getFoo();\n"
1363+
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
1364+
"}\n";
1365+
1366+
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1367+
EXPECT_VALID(lib);
1368+
1369+
const char* kReloadScript =
1370+
"import 'test:isolate_reload_helper';\n"
1371+
"class C {\n"
1372+
" static foo() => 'new';\n"
1373+
"}\n"
1374+
"getFoo() => C.foo;\n"
1375+
"main() {\n"
1376+
" var f1 = getFoo();\n"
1377+
" reloadTest();\n"
1378+
" var f2 = getFoo();\n"
1379+
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
1380+
"}\n";
1381+
1382+
TestCase::SetReloadTestScript(kReloadScript);
1383+
1384+
EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
1385+
1386+
lib = TestCase::GetReloadErrorOrRootLibrary();
1387+
EXPECT_VALID(lib);
1388+
}
1389+
1390+
1391+
TEST_CASE(IsolateReload_TearOff_Library_Identity) {
1392+
const char* kScript =
1393+
"import 'test:isolate_reload_helper';\n"
1394+
"foo() => 'old';\n"
1395+
"getFoo() => foo;\n"
1396+
"main() {\n"
1397+
" var f1 = getFoo();\n"
1398+
" reloadTest();\n"
1399+
" var f2 = getFoo();\n"
1400+
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
1401+
"}\n";
1402+
1403+
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
1404+
EXPECT_VALID(lib);
1405+
1406+
const char* kReloadScript =
1407+
"import 'test:isolate_reload_helper';\n"
1408+
"foo() => 'new';\n"
1409+
"getFoo() => foo;\n"
1410+
"main() {\n"
1411+
" var f1 = getFoo();\n"
1412+
" reloadTest();\n"
1413+
" var f2 = getFoo();\n"
1414+
" return '${f1()} ${f2()} ${f1 == f2} ${identical(f1, f2)}';\n"
1415+
"}\n";
1416+
1417+
TestCase::SetReloadTestScript(kReloadScript);
1418+
1419+
EXPECT_STREQ("new new true true", SimpleInvokeStr(lib, "main"));
1420+
1421+
lib = TestCase::GetReloadErrorOrRootLibrary();
1422+
EXPECT_VALID(lib);
1423+
}
1424+
1425+
13521426
TEST_CASE(IsolateReload_TearOff_List_Set) {
13531427
const char* kScript =
13541428
"import 'test:isolate_reload_helper';\n"

runtime/vm/object.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,6 +1401,8 @@ class Class : public Object {
14011401
void ReplaceEnum(const Class& old_enum) const;
14021402
void CopyStaticFieldValues(const Class& old_cls) const;
14031403
void PatchFieldsAndFunctions() const;
1404+
void MigrateImplicitStaticClosures(IsolateReloadContext* context,
1405+
const Class& new_cls) const;
14041406
void CopyCanonicalConstants(const Class& old_cls) const;
14051407
void CopyCanonicalType(const Class& old_cls) const;
14061408
void CheckReload(const Class& replacement,

runtime/vm/object_reload.cc

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,32 @@ void Class::PatchFieldsAndFunctions() const {
363363
}
364364

365365

366+
void Class::MigrateImplicitStaticClosures(IsolateReloadContext* irc,
367+
const Class& new_cls) const {
368+
const Array& funcs = Array::Handle(functions());
369+
Function& old_func = Function::Handle();
370+
String& selector = String::Handle();
371+
Function& new_func = Function::Handle();
372+
Instance& old_closure = Instance::Handle();
373+
Instance& new_closure = Instance::Handle();
374+
for (intptr_t i = 0; i < funcs.Length(); i++) {
375+
old_func ^= funcs.At(i);
376+
if (old_func.is_static() &&
377+
old_func.HasImplicitClosureFunction()) {
378+
selector = old_func.name();
379+
new_func = new_cls.LookupFunction(selector);
380+
if (!new_func.IsNull() && new_func.is_static()) {
381+
old_func = old_func.ImplicitClosureFunction();
382+
old_closure = old_func.ImplicitStaticClosure();
383+
new_func = new_func.ImplicitClosureFunction();
384+
new_closure = new_func.ImplicitStaticClosure();
385+
irc->AddBecomeMapping(old_closure, new_closure);
386+
}
387+
}
388+
}
389+
}
390+
391+
366392
class EnumClassConflict : public ClassReasonForCancelling {
367393
public:
368394
EnumClassConflict(const Class& from, const Class& to)

0 commit comments

Comments
 (0)