Skip to content

Commit 134b2dc

Browse files
alexmarkovCommit Queue
authored and
Commit Queue
committed
Revert "[vm] Account for changes in the implicit getters due to load guards"
This reverts commit 8781007. Reason for revert: breaks hot reload test case in Flutter, reverting as temporary workaround to flutter/flutter#120091. Original change's description: > [vm] Account for changes in the implicit getters due to load guards > > Hot reload may mark certain fields as 'needs_load_guard', meaning > types of their values should be checked on access, in the implicit > getters. > > Unoptimized code for implicit getters of such fields should be > forcefully recompiled during hot reload in order to update their > code. This ensures that optimized code in future can deoptimize > into the updated unoptimized code of implicit getters. > > TEST=vm/cc/IsolateReload_ImplicitGetterWithLoadGuard > TEST=corelib/string_fromcharcodes_test, lib/convert/json_utf8_chunk_test > and vm/dart/string_equals_test on vm-reload-linux-{debug,release}-x64 > configurations. > > Fixes #51215 > Fixes flutter/flutter#103268 > > Change-Id: I1afbeabb4a60b7a5f69ed055f40beeb6d3dcf359 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/280401 > Reviewed-by: Martin Kustermann <[email protected]> > Commit-Queue: Alexander Markov <[email protected]> > Reviewed-by: Ryan Macnak <[email protected]> # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: Ia7dba382547cceb38524707f9ecef892016108de Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/281220 Reviewed-by: Alexander Markov <[email protected]> Bot-Commit: Rubber Stamper <[email protected]> Reviewed-by: Zach Anderson <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
1 parent 5b09a3d commit 134b2dc

File tree

4 files changed

+49
-123
lines changed

4 files changed

+49
-123
lines changed

runtime/vm/compiler/frontend/kernel_to_il.cc

Lines changed: 35 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -3862,44 +3862,44 @@ FlowGraph* FlowGraphBuilder::BuildGraphOfFieldAccessor(
38623862
}
38633863
}
38643864
body += NullConstant();
3865-
} else {
3866-
ASSERT(is_getter);
3867-
if (is_method) {
3868-
body += LoadLocal(parsed_function_->ParameterVariable(0));
3869-
body += LoadField(
3870-
field, /*calls_initializer=*/field.NeedsInitializationCheckOnLoad());
3871-
} else if (field.is_const()) {
3872-
const auto& value = Object::Handle(Z, field.StaticConstFieldValue());
3873-
if (value.IsError()) {
3874-
Report::LongJump(Error::Cast(value));
3875-
}
3876-
body += Constant(Instance::ZoneHandle(Z, Instance::RawCast(value.ptr())));
3877-
} else {
3878-
// Static fields
3879-
// - with trivial initializer
3880-
// - without initializer if they are not late
3881-
// are initialized eagerly and do not have implicit getters.
3882-
// Static fields with non-trivial initializer need getter to perform
3883-
// lazy initialization. Late fields without initializer need getter
3884-
// to make sure they are already initialized.
3885-
ASSERT(field.has_nontrivial_initializer() ||
3886-
(field.is_late() && !field.has_initializer()));
3887-
body += LoadStaticField(field, /*calls_initializer=*/true);
3865+
} else if (is_getter && is_method) {
3866+
ASSERT(!field.needs_load_guard()
3867+
NOT_IN_PRODUCT(|| IG->HasAttemptedReload()));
3868+
body += LoadLocal(parsed_function_->ParameterVariable(0));
3869+
body += LoadField(
3870+
field, /*calls_initializer=*/field.NeedsInitializationCheckOnLoad());
3871+
if (field.needs_load_guard()) {
3872+
#if defined(PRODUCT)
3873+
UNREACHABLE();
3874+
#else
3875+
body += CheckAssignable(AbstractType::Handle(Z, field.type()),
3876+
Symbols::FunctionResult());
3877+
#endif
38883878
}
3889-
3890-
if (is_method || !field.is_const()) {
3879+
} else if (field.is_const()) {
3880+
const auto& value = Object::Handle(Z, field.StaticConstFieldValue());
3881+
if (value.IsError()) {
3882+
Report::LongJump(Error::Cast(value));
3883+
}
3884+
body += Constant(Instance::ZoneHandle(Z, Instance::RawCast(value.ptr())));
3885+
} else {
3886+
// Static fields
3887+
// - with trivial initializer
3888+
// - without initializer if they are not late
3889+
// are initialized eagerly and do not have implicit getters.
3890+
// Static fields with non-trivial initializer need getter to perform
3891+
// lazy initialization. Late fields without initializer need getter
3892+
// to make sure they are already initialized.
3893+
ASSERT(field.has_nontrivial_initializer() ||
3894+
(field.is_late() && !field.has_initializer()));
3895+
body += LoadStaticField(field, /*calls_initializer=*/true);
3896+
if (field.needs_load_guard()) {
38913897
#if defined(PRODUCT)
3892-
RELEASE_ASSERT(!field.needs_load_guard());
3898+
UNREACHABLE();
38933899
#else
3894-
// Always build fragment for load guard to maintain stable deopt_id
3895-
// numbering, but link it into the graph only if field actually
3896-
// needs load guard.
3897-
Fragment load_guard = CheckAssignable(
3898-
AbstractType::Handle(Z, field.type()), Symbols::FunctionResult());
3899-
if (field.needs_load_guard()) {
3900-
ASSERT(IG->HasAttemptedReload());
3901-
body += load_guard;
3902-
}
3900+
ASSERT(IsolateGroup::Current()->HasAttemptedReload());
3901+
body += CheckAssignable(AbstractType::Handle(Z, field.type()),
3902+
Symbols::FunctionResult());
39033903
#endif
39043904
}
39053905
}

runtime/vm/isolate_reload.cc

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2005,11 +2005,8 @@ void ProgramReloadContext::RunInvalidationVisitors() {
20052005

20062006
InvalidateKernelInfos(zone, kernel_infos);
20072007
InvalidateSuspendStates(zone, suspend_states);
2008-
InvalidateFields(zone, fields, instances);
2009-
2010-
// After InvalidateFields in order to invalidate
2011-
// implicit getters which need load guards.
20122008
InvalidateFunctions(zone, functions);
2009+
InvalidateFields(zone, fields, instances);
20132010
}
20142011

20152012
void ProgramReloadContext::InvalidateKernelInfos(
@@ -2054,7 +2051,6 @@ void ProgramReloadContext::InvalidateFunctions(
20542051
Class& owning_class = Class::Handle(zone);
20552052
Library& owning_lib = Library::Handle(zone);
20562053
Code& code = Code::Handle(zone);
2057-
Field& field = Field::Handle(zone);
20582054
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
20592055
for (intptr_t i = 0; i < functions.length(); i++) {
20602056
const Function& func = *functions[i];
@@ -2066,20 +2062,9 @@ void ProgramReloadContext::InvalidateFunctions(
20662062
code = func.CurrentCode();
20672063
ASSERT(!code.IsNull());
20682064

2069-
// Force recompilation of unoptimized code of implicit getters
2070-
// in order to add load guards. This is needed for future
2071-
// deoptimizations which will expect load guard in the unoptimized code.
2072-
bool recompile_for_load_guard = false;
2073-
if (func.IsImplicitGetterFunction() ||
2074-
func.IsImplicitStaticGetterFunction()) {
2075-
field = func.accessor_field();
2076-
recompile_for_load_guard = field.needs_load_guard();
2077-
}
2078-
20792065
owning_class = func.Owner();
20802066
owning_lib = owning_class.library();
2081-
const bool clear_unoptimized_code =
2082-
IsDirty(owning_lib) || recompile_for_load_guard;
2067+
const bool clear_code = IsDirty(owning_lib);
20832068
const bool stub_code = code.IsStubCode();
20842069

20852070
// Zero edge counters, before clearing the ICDataArray, since that's where
@@ -2088,7 +2073,7 @@ void ProgramReloadContext::InvalidateFunctions(
20882073

20892074
if (stub_code) {
20902075
// Nothing to reset.
2091-
} else if (clear_unoptimized_code) {
2076+
} else if (clear_code) {
20922077
VTIR_Print("Marking %s for recompilation, clearing code\n",
20932078
func.ToCString());
20942079
// Null out the ICData array and code.

runtime/vm/isolate_reload_test.cc

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -5007,63 +5007,6 @@ TEST_CASE(IsolateReload_GenericConstructorTearOff) {
50075007
EXPECT_STREQ("okay", SimpleInvokeStr(lib, "main"));
50085008
}
50095009

5010-
// Regression test for https://github.com/dart-lang/sdk/issues/51215.
5011-
TEST_CASE(IsolateReload_ImplicitGetterWithLoadGuard) {
5012-
const char* kLibScript = R"(
5013-
import 'file:///test:isolate_reload_helper';
5014-
5015-
class A {
5016-
int x;
5017-
A(this.x);
5018-
A.withUinitializedObject(int Function() callback) : x = callback();
5019-
}
5020-
5021-
A a = A(3);
5022-
5023-
main() {
5024-
int sum = 0;
5025-
// Trigger OSR and optimize this function.
5026-
for (int i = 0; i < 30000; ++i) {
5027-
sum += i;
5028-
}
5029-
// Make sure A.get:x is compiled.
5030-
int y = a.x;
5031-
// Reload while having an uninitialized
5032-
// object A on the stack. This should result in
5033-
// a load guard for A.x.
5034-
A.withUinitializedObject(() {
5035-
reloadTest();
5036-
return 4;
5037-
});
5038-
// Trigger OSR and optimize this function once again.
5039-
for (int i = 0; i < 30000; ++i) {
5040-
sum += i;
5041-
}
5042-
// Trigger deoptimization in A.get:x.
5043-
// It should correctly deoptimize into an implicit
5044-
// getter with a load guard.
5045-
a.x = 0x8070605040302010;
5046-
int z = a.x & 0xffff;
5047-
return "y: $y, z: $z";
5048-
}
5049-
)";
5050-
5051-
Dart_Handle lib1 =
5052-
TestCase::LoadTestLibrary("test_lib1.dart", kLibScript, nullptr);
5053-
EXPECT_VALID(lib1);
5054-
5055-
const char* kMainScript = R"(
5056-
main() {}
5057-
)";
5058-
5059-
// Trigger hot reload during execution of 'main' from test_lib1
5060-
// without reloading test_lib1, so its unoptimized code is retained.
5061-
EXPECT_VALID(TestCase::LoadTestScript(kMainScript, nullptr));
5062-
EXPECT_VALID(TestCase::SetReloadTestScript(kMainScript));
5063-
5064-
EXPECT_STREQ("y: 3, z: 8208", SimpleInvokeStr(lib1, "main"));
5065-
}
5066-
50675010
#endif // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
50685011

50695012
} // namespace dart

runtime/vm/unit_test.cc

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -284,18 +284,12 @@ void FUNCTION_NAME(Test_CollectOldSpace)(Dart_NativeArguments native_args) {
284284
GCTestHelper::CollectOldSpace();
285285
}
286286

287-
#endif // !PRODUCT
288-
289-
static void LoadIsolateReloadTestLibIfNeeded(const char* script) {
290-
#ifndef PRODUCT
291-
if (strstr(script, IsolateReloadTestLibUri()) != nullptr) {
292-
Dart_Handle result = TestCase::LoadTestLibrary(
293-
IsolateReloadTestLibUri(), kIsolateReloadTestLibSource,
294-
IsolateReloadTestNativeResolver);
295-
EXPECT_VALID(result);
296-
}
297-
#endif // ifndef PRODUCT
287+
static Dart_Handle LoadIsolateReloadTestLib() {
288+
return TestCase::LoadTestLibrary(IsolateReloadTestLibUri(),
289+
kIsolateReloadTestLibSource,
290+
IsolateReloadTestNativeResolver);
298291
}
292+
#endif // !PRODUCT
299293

300294
char* TestCase::CompileTestScriptWithDFE(const char* url,
301295
const char* source,
@@ -424,7 +418,12 @@ Dart_Handle TestCase::LoadTestScript(const char* script,
424418
const char* lib_url,
425419
bool finalize_classes,
426420
bool allow_compile_errors) {
427-
LoadIsolateReloadTestLibIfNeeded(script);
421+
#ifndef PRODUCT
422+
if (strstr(script, IsolateReloadTestLibUri()) != NULL) {
423+
Dart_Handle result = LoadIsolateReloadTestLib();
424+
EXPECT_VALID(result);
425+
}
426+
#endif // ifndef PRODUCT
428427
Dart_SourceFile* sourcefiles = NULL;
429428
intptr_t num_sources = BuildSourceFilesArray(&sourcefiles, script, lib_url);
430429
Dart_Handle result =
@@ -441,7 +440,6 @@ static void MallocFinalizer(void* isolate_callback_data, void* peer) {
441440
Dart_Handle TestCase::LoadTestLibrary(const char* lib_uri,
442441
const char* script,
443442
Dart_NativeEntryResolver resolver) {
444-
LoadIsolateReloadTestLibIfNeeded(script);
445443
const char* prefixed_lib_uri =
446444
OS::SCreate(Thread::Current()->zone(), "file:///%s", lib_uri);
447445
Dart_SourceFile sourcefiles[] = {{prefixed_lib_uri, script}};

0 commit comments

Comments
 (0)