Skip to content

Commit af270e4

Browse files
derekxu16Commit Queue
authored andcommitted
[VM] Replace usages of Function::EnsureHasCompiledUnoptimizedCode in ProgramReloadContext with a non-throwing version
TEST=CI Issue: flutter/flutter#150550 Change-Id: I424e43d6d11237f18fa8e91bf183299c7f1ea0ac Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/373560 Commit-Queue: Derek Xu <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
1 parent 829b9f4 commit af270e4

File tree

4 files changed

+78
-25
lines changed

4 files changed

+78
-25
lines changed

runtime/vm/isolate_reload.cc

Lines changed: 55 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,14 @@ bool IsolateGroupReloadContext::Reload(bool force_reload,
817817
// assumptions from field guards or CHA or deferred library prefixes.
818818
// TODO(johnmccutchan): Deoptimizing dependent code here (before the reload)
819819
// is paranoid. This likely can be moved to the commit phase.
820-
IG->program_reload_context()->EnsuredUnoptimizedCodeForStack();
820+
const Error& error = Error::Handle(
821+
IG->program_reload_context()->EnsuredUnoptimizedCodeForStack());
822+
if (!error.IsNull()) {
823+
AddReasonForCancelling(new Aborted(Z, error));
824+
ReportReasonsForCancelling();
825+
CommonFinalizeTail(num_old_libs_);
826+
return false;
827+
}
821828
IG->program_reload_context()->DeoptimizeDependentCode();
822829
IG->program_reload_context()->ReloadPhase1AllocateStorageMapsAndCheckpoint();
823830

@@ -963,9 +970,14 @@ bool IsolateGroupReloadContext::Reload(bool force_reload,
963970
if (discard_class_tables) {
964971
IG->DropOriginalClassTable();
965972
}
966-
isolate_group_->program_reload_context()->ReloadPhase4CommitFinish();
967-
TIR_Print("---- DONE COMMIT\n");
968-
isolate_group_->set_last_reload_timestamp(reload_timestamp_);
973+
const Error& error = Error::Handle(
974+
isolate_group_->program_reload_context()->ReloadPhase4CommitFinish());
975+
if (error.IsNull()) {
976+
TIR_Print("---- DONE COMMIT\n");
977+
isolate_group_->set_last_reload_timestamp(reload_timestamp_);
978+
} else {
979+
AddReasonForCancelling(new Aborted(Z, error));
980+
}
969981
} else {
970982
TIR_Print("---- ROLLING BACK");
971983
isolate_group_->program_reload_context()->ReloadPhase4Rollback();
@@ -1233,9 +1245,9 @@ void ProgramReloadContext::ReloadPhase4CommitPrepare() {
12331245
CommitBeforeInstanceMorphing();
12341246
}
12351247

1236-
void ProgramReloadContext::ReloadPhase4CommitFinish() {
1248+
ErrorPtr ProgramReloadContext::ReloadPhase4CommitFinish() {
12371249
CommitAfterInstanceMorphing();
1238-
PostCommit();
1250+
return PostCommit();
12391251
}
12401252

12411253
void ProgramReloadContext::ReloadPhase4Rollback() {
@@ -1318,10 +1330,17 @@ void IsolateGroupReloadContext::ReportOnJSON(JSONStream* stream,
13181330
}
13191331
}
13201332

1321-
void ProgramReloadContext::EnsuredUnoptimizedCodeForStack() {
1333+
ErrorPtr ProgramReloadContext::EnsuredUnoptimizedCodeForStack() {
13221334
TIMELINE_SCOPE(EnsuredUnoptimizedCodeForStack);
13231335

1324-
IG->ForEachIsolate([](Isolate* isolate) {
1336+
Error& error = Error::Handle();
1337+
IG->ForEachIsolate([&error](Isolate* isolate) {
1338+
if (!error.IsNull()) {
1339+
// An error occurred the previous time this callback was called, but
1340+
// |ForEachIsolate| does not support stopping iteration early, so we
1341+
// return here.
1342+
return;
1343+
}
13251344
auto thread = isolate->mutator_thread();
13261345
if (thread == nullptr) {
13271346
return;
@@ -1338,11 +1357,16 @@ void ProgramReloadContext::EnsuredUnoptimizedCodeForStack() {
13381357
// Force-optimized functions don't need unoptimized code because their
13391358
// optimized code cannot deopt.
13401359
if (!func.ForceOptimize()) {
1341-
func.EnsureHasCompiledUnoptimizedCode();
1360+
error = func.EnsureHasCompiledUnoptimizedCodeNoThrow();
1361+
if (!error.IsNull()) {
1362+
return;
1363+
}
13421364
}
13431365
}
13441366
}
13451367
});
1368+
1369+
return error.ptr();
13461370
}
13471371

13481372
void ProgramReloadContext::DeoptimizeDependentCode() {
@@ -1772,11 +1796,11 @@ bool ProgramReloadContext::IsDirty(const Library& lib) {
17721796
return library_infos_[index].dirty;
17731797
}
17741798

1775-
void ProgramReloadContext::PostCommit() {
1799+
ErrorPtr ProgramReloadContext::PostCommit() {
17761800
TIMELINE_SCOPE(PostCommit);
17771801
saved_root_library_ = Library::null();
17781802
saved_libraries_ = GrowableObjectArray::null();
1779-
InvalidateWorld();
1803+
return InvalidateWorld();
17801804
}
17811805

17821806
void IsolateGroupReloadContext::AddReasonForCancelling(
@@ -1984,7 +2008,7 @@ class InvalidationCollector : public ObjectVisitor {
19842008
GrowableArray<const Instance*>* const instances_;
19852009
};
19862010

1987-
void ProgramReloadContext::RunInvalidationVisitors() {
2011+
ErrorPtr ProgramReloadContext::RunInvalidationVisitors() {
19882012
TIR_Print("---- RUNNING INVALIDATION HEAP VISITORS\n");
19892013
Thread* thread = Thread::Current();
19902014
StackZone stack_zone(thread);
@@ -2005,12 +2029,20 @@ void ProgramReloadContext::RunInvalidationVisitors() {
20052029
}
20062030

20072031
InvalidateKernelInfos(zone, kernel_infos);
2008-
InvalidateSuspendStates(zone, suspend_states);
2032+
2033+
const Error& error =
2034+
Error::Handle(InvalidateSuspendStates(zone, suspend_states));
2035+
if (!error.IsNull()) {
2036+
return error.ptr();
2037+
}
2038+
20092039
InvalidateFields(zone, fields, instances);
20102040

20112041
// After InvalidateFields in order to invalidate
20122042
// implicit getters which need load guards.
20132043
InvalidateFunctions(zone, functions);
2044+
2045+
return Error::null();
20142046
}
20152047

20162048
void ProgramReloadContext::InvalidateKernelInfos(
@@ -2114,7 +2146,7 @@ void ProgramReloadContext::InvalidateFunctions(
21142146
}
21152147
}
21162148

2117-
void ProgramReloadContext::InvalidateSuspendStates(
2149+
ErrorPtr ProgramReloadContext::InvalidateSuspendStates(
21182150
Zone* zone,
21192151
const GrowableArray<const SuspendState*>& suspend_states) {
21202152
TIMELINE_SCOPE(InvalidateSuspendStates);
@@ -2124,6 +2156,7 @@ void ProgramReloadContext::InvalidateSuspendStates(
21242156
CallSiteResetter resetter(zone);
21252157
Code& code = Code::Handle(zone);
21262158
Function& function = Function::Handle(zone);
2159+
Error& error = Error::Handle(zone);
21272160

21282161
SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock());
21292162
for (intptr_t i = 0, n = suspend_states.length(); i < n; ++i) {
@@ -2156,11 +2189,16 @@ void ProgramReloadContext::InvalidateSuspendStates(
21562189
// can be cleared along with the code in InvalidateFunctions
21572190
// during previous hot reloads.
21582191
// Rebuild an unoptimized code in order to recreate ICData array.
2159-
function.EnsureHasCompiledUnoptimizedCode();
2192+
error = function.EnsureHasCompiledUnoptimizedCodeNoThrow();
2193+
if (!error.IsNull()) {
2194+
return error.ptr();
2195+
}
21602196
resetter.ResetSwitchableCalls(code);
21612197
resetter.ResetCaches(code);
21622198
}
21632199
}
2200+
2201+
return Error::null();
21642202
}
21652203

21662204
// Finds fields that are initialized or have a value that does not conform to
@@ -2404,7 +2442,7 @@ void ProgramReloadContext::InvalidateFields(
24042442
invalidator.CheckInstances(instances);
24052443
}
24062444

2407-
void ProgramReloadContext::InvalidateWorld() {
2445+
ErrorPtr ProgramReloadContext::InvalidateWorld() {
24082446
TIMELINE_SCOPE(InvalidateWorld);
24092447
TIR_Print("---- INVALIDATING WORLD\n");
24102448
ResetMegamorphicCaches();
@@ -2413,7 +2451,7 @@ void ProgramReloadContext::InvalidateWorld() {
24132451
}
24142452
DeoptimizeFunctionsOnStack();
24152453
ResetUnoptimizedICsOnStack();
2416-
RunInvalidationVisitors();
2454+
return RunInvalidationVisitors();
24172455
}
24182456

24192457
ClassPtr ProgramReloadContext::OldClassOrNull(const Class& replacement_or_new) {

runtime/vm/isolate_reload.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ class ProgramReloadContext {
319319
IsolateGroup* isolate_group() { return isolate_group_; }
320320
ObjectStore* object_store();
321321

322-
void EnsuredUnoptimizedCodeForStack();
322+
ErrorPtr EnsuredUnoptimizedCodeForStack();
323323
void DeoptimizeDependentCode();
324324

325325
void ReloadPhase1AllocateStorageMapsAndCheckpoint();
@@ -328,7 +328,7 @@ class ProgramReloadContext {
328328
const String& root_lib_url);
329329
void ReloadPhase3FinalizeLoading();
330330
void ReloadPhase4CommitPrepare();
331-
void ReloadPhase4CommitFinish();
331+
ErrorPtr ReloadPhase4CommitFinish();
332332
void ReloadPhase4Rollback();
333333

334334
void CheckpointLibraries();
@@ -341,23 +341,23 @@ class ProgramReloadContext {
341341

342342
void CommitBeforeInstanceMorphing();
343343
void CommitAfterInstanceMorphing();
344-
void PostCommit();
344+
ErrorPtr PostCommit();
345345

346-
void RunInvalidationVisitors();
346+
ErrorPtr RunInvalidationVisitors();
347347
void InvalidateKernelInfos(
348348
Zone* zone,
349349
const GrowableArray<const KernelProgramInfo*>& kernel_infos);
350350
void InvalidateFunctions(Zone* zone,
351351
const GrowableArray<const Function*>& functions);
352-
void InvalidateSuspendStates(
352+
ErrorPtr InvalidateSuspendStates(
353353
Zone* zone,
354354
const GrowableArray<const SuspendState*>& suspend_states);
355355
void InvalidateFields(Zone* zone,
356356
const GrowableArray<const Field*>& fields,
357357
const GrowableArray<const Instance*>& instances);
358358
void ResetUnoptimizedICsOnStack();
359359
void ResetMegamorphicCaches();
360-
void InvalidateWorld();
360+
ErrorPtr InvalidateWorld();
361361

362362
struct LibraryInfo {
363363
bool dirty;

runtime/vm/object.cc

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7977,16 +7977,24 @@ void Function::EnsureHasCompiledUnoptimizedCode() const {
79777977
ASSERT(!ForceOptimize());
79787978
Thread* thread = Thread::Current();
79797979
ASSERT(thread->IsDartMutatorThread());
7980-
// TODO(35224): DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
7980+
DEBUG_ASSERT(thread->TopErrorHandlerIsExitFrame());
79817981
Zone* zone = thread->zone();
79827982

79837983
const Error& error =
7984-
Error::Handle(zone, Compiler::EnsureUnoptimizedCode(thread, *this));
7984+
Error::Handle(zone, EnsureHasCompiledUnoptimizedCodeNoThrow());
79857985
if (!error.IsNull()) {
79867986
Exceptions::PropagateError(error);
79877987
}
79887988
}
79897989

7990+
ErrorPtr Function::EnsureHasCompiledUnoptimizedCodeNoThrow() const {
7991+
ASSERT(!ForceOptimize());
7992+
Thread* thread = Thread::Current();
7993+
ASSERT(thread->IsDartMutatorThread());
7994+
7995+
return Compiler::EnsureUnoptimizedCode(thread, *this);
7996+
}
7997+
79907998
void Function::SwitchToUnoptimizedCode() const {
79917999
ASSERT(HasOptimizedCode());
79928000
ASSERT(!ForceOptimize());

runtime/vm/object.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3181,8 +3181,15 @@ class Function : public Object {
31813181
void SwitchToLazyCompiledUnoptimizedCode() const;
31823182

31833183
// Compiles unoptimized code (if necessary) and attaches it to the function.
3184+
// If an error occurs during compilation, |Exceptions::PropagateError| will be
3185+
// called to propagate it.
31843186
void EnsureHasCompiledUnoptimizedCode() const;
31853187

3188+
// Compiles unoptimized code (if necessary) and attaches it to the function.
3189+
// If an error occurs during compilation, the error is returned. Otherwise,
3190+
// |Error::null()| is returned.
3191+
ErrorPtr EnsureHasCompiledUnoptimizedCodeNoThrow() const;
3192+
31863193
// Return the most recently compiled and installed code for this function.
31873194
// It is not the only Code object that points to this function.
31883195
CodePtr CurrentCode() const { return CurrentCodeOf(ptr()); }

0 commit comments

Comments
 (0)