mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 22:31:50 +00:00
[vm, reload] Eagerly assign static field initializers a PatchClass owner.
Static field initializers are not added as members of their owning class, so they must be pre-emptively given a patch class to avoid the meaning of their kernel/token position changing during a reload. Member functions and fields have their owner changed to patch class only when the class is changed during a reload. Curiously, this was originally done in the C++ front end before hot reload: https://codereview.chromium.org//1317753004 Bug: https://github.com/dart-lang/sdk/issues/32497 Change-Id: I236c188a4b9e05a1e3c011d27e123979db1ca2e5 Reviewed-on: https://dart-review.googlesource.com/46124 Commit-Queue: Ryan Macnak <rmacnak@google.com> Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
parent
3c8d3b6870
commit
66af0113de
|
@ -17,9 +17,6 @@ namespace dart {
|
|||
|
||||
#if !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
// TODO(johnmccutchan):
|
||||
// - Tests involving generics.
|
||||
|
||||
int64_t SimpleInvoke(Dart_Handle lib, const char* method) {
|
||||
Dart_Handle result = Dart_Invoke(lib, NewString(method), 0, NULL);
|
||||
EXPECT_VALID(result);
|
||||
|
@ -3500,6 +3497,31 @@ TEST_CASE(IsolateReload_TypedefAddParameter) {
|
|||
EXPECT_STREQ("false", SimpleInvokeStr(lib, "main"));
|
||||
}
|
||||
|
||||
TEST_CASE(IsolateReload_PatchStaticInitializerWithClosure) {
|
||||
const char* kScript =
|
||||
"dynamic field = (a) => 'a$a';\n"
|
||||
"main() {\n"
|
||||
" dynamic f = field;\n"
|
||||
" return f('b');\n"
|
||||
"}\n";
|
||||
|
||||
Dart_Handle lib = TestCase::LoadTestScript(kScript, NULL);
|
||||
EXPECT_VALID(lib);
|
||||
EXPECT_STREQ("ab", SimpleInvokeStr(lib, "main"));
|
||||
|
||||
const char* kReloadScript =
|
||||
"extraFunction() => 'Just here to change kernel offsets';\n"
|
||||
"dynamic field = (_, __) => 'Not executed';\n"
|
||||
"main() {\n"
|
||||
" dynamic f = field;\n"
|
||||
" return f('c');\n"
|
||||
"}\n";
|
||||
|
||||
lib = TestCase::ReloadTestScript(kReloadScript);
|
||||
EXPECT_VALID(lib);
|
||||
EXPECT_STREQ("ac", SimpleInvokeStr(lib, "main"));
|
||||
}
|
||||
|
||||
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
|
||||
|
||||
} // namespace dart
|
||||
|
|
|
@ -1607,8 +1607,22 @@ RawFunction* CreateFieldInitializerFunction(Thread* thread,
|
|||
String& init_name = String::Handle(zone, field.name());
|
||||
init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
|
||||
|
||||
// Static field initializers are not added as members of their owning class,
|
||||
// so they must be pre-emptively given a patch class to avoid the meaning of
|
||||
// their kernel/token position changing during a reload. Compare
|
||||
// Class::PatchFieldsAndFunctions().
|
||||
// This might also be necessary for lazy computation of local var descriptors.
|
||||
// Compare https://codereview.chromium.org//1317753004
|
||||
const Script& script = Script::Handle(zone, field.Script());
|
||||
const Class& field_owner = Class::Handle(zone, field.Owner());
|
||||
const PatchClass& initializer_owner =
|
||||
PatchClass::Handle(zone, PatchClass::New(field_owner, script));
|
||||
const Library& lib = Library::Handle(zone, field_owner.library());
|
||||
initializer_owner.set_library_kernel_data(
|
||||
TypedData::Handle(zone, lib.kernel_data()));
|
||||
initializer_owner.set_library_kernel_offset(lib.kernel_offset());
|
||||
|
||||
// Create a static initializer.
|
||||
const Object& owner = Object::Handle(field.RawOwner());
|
||||
const Function& initializer_fun = Function::Handle(
|
||||
zone, Function::New(init_name,
|
||||
// TODO(alexmarkov): Consider creating a separate
|
||||
|
@ -1619,7 +1633,7 @@ RawFunction* CreateFieldInitializerFunction(Thread* thread,
|
|||
false, // is_abstract
|
||||
false, // is_external
|
||||
false, // is_native
|
||||
owner, TokenPosition::kNoSource));
|
||||
initializer_owner, TokenPosition::kNoSource));
|
||||
initializer_fun.set_kernel_offset(field.kernel_offset());
|
||||
initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
|
||||
initializer_fun.set_is_debuggable(false);
|
||||
|
|
Loading…
Reference in a new issue