From f3520ff11bbee30233cdff582abaaa7df7afad8e Mon Sep 17 00:00:00 2001 From: Alexander Aprelev Date: Mon, 19 Apr 2021 16:03:18 +0000 Subject: [PATCH] [vm/concurrency] Ensure field unboxed->boxed deoptimization runs with stopped mutators. In lightweight isolate mode if some isolate or background compiler decides to deopt unboxed field, we need to bring to stop all other isolates to prevent to-be-deoptimized code from running. If isolates are not stopped they might continue running the code that still assumes the field is unboxed(reusable mutable box), overwriting (now immutable) boxed value. Issue https://github.com/dart-lang/sdk/issues/36097 TEST=ci Change-Id: I5d2492650b8aa00491a1bd6ba2a7fb4817460f14 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/195662 Commit-Queue: Alexander Aprelev Reviewed-by: Martin Kustermann --- runtime/vm/object.cc | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc index 08b8d078f16..42566464602 100644 --- a/runtime/vm/object.cc +++ b/runtime/vm/object.cc @@ -10148,19 +10148,25 @@ const Object* Field::CloneForUnboxed(const Object& value) const { } void Field::DisableFieldUnboxing() const { - Thread* thread = Thread::Current(); ASSERT(!IsOriginal()); const Field& original = Field::Handle(Original()); if (!original.is_unboxing_candidate()) { return; } + auto thread = Thread::Current(); SafepointWriteRwLocker ml(thread, thread->isolate_group()->program_lock()); if (!original.is_unboxing_candidate()) { return; } - original.set_is_unboxing_candidate(false); - set_is_unboxing_candidate(false); - original.DeoptimizeDependentCode(); + + // Ensures that to-be-disabled existing code won't continue running as we + // update field properties as it might write into now boxed field thinking + // it still holds unboxed(reusable box) value. + thread->isolate_group()->RunWithStoppedMutators([&]() { + original.set_is_unboxing_candidate(false); + set_is_unboxing_candidate(false); + original.DeoptimizeDependentCode(); + }); } intptr_t Field::guarded_cid() const {