[wasm][gc] Fix potential deadlock
This fixes a deadlock that was detected by layout tests executing with --future (hence enabling wasm code gc). It did not fail anywhere in v8 because GC is only triggered once we have > 1MB potentially dead code. I plan to add a '--stress-wasm-code-gc' flag, which lowers this limit to zero, thereby triggering GC when finding a single potentially dead code. This mode found this issue, but also finds more, so I need to fix other issues before enabling these stress tests. R=mstarzinger@chromium.org Bug: v8:8217 Change-Id: I373955b90c8b79d7b9e16184729f45db947eeeab Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1583728 Reviewed-by: Michael Starzinger <mstarzinger@chromium.org> Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Cr-Commit-Position: refs/heads/master@{#61034}
This commit is contained in:
parent
f5124b42a1
commit
34554ec00e
@ -665,29 +665,35 @@ void WasmEngine::SampleTopTierCodeSizeInAllIsolates(
|
||||
|
||||
void WasmEngine::ReportLiveCodeForGC(Isolate* isolate,
|
||||
Vector<WasmCode*> live_code) {
|
||||
base::MutexGuard guard(&mutex_);
|
||||
DCHECK_NOT_NULL(current_gc_info_);
|
||||
auto outstanding_isolate_it =
|
||||
current_gc_info_->outstanding_isolates.find(isolate);
|
||||
DCHECK_NE(current_gc_info_->outstanding_isolates.end(),
|
||||
outstanding_isolate_it);
|
||||
auto* fg_task = outstanding_isolate_it->second;
|
||||
if (fg_task) fg_task->Cancel();
|
||||
current_gc_info_->outstanding_isolates.erase(outstanding_isolate_it);
|
||||
for (WasmCode* code : live_code) current_gc_info_->dead_code.erase(code);
|
||||
// Get the set of dead code under the mutex, but decrement the ref count after
|
||||
// releasing the mutex to avoid deadlocks.
|
||||
OwnedVector<WasmCode*> dead_code;
|
||||
{
|
||||
base::MutexGuard guard(&mutex_);
|
||||
DCHECK_NOT_NULL(current_gc_info_);
|
||||
auto outstanding_isolate_it =
|
||||
current_gc_info_->outstanding_isolates.find(isolate);
|
||||
DCHECK_NE(current_gc_info_->outstanding_isolates.end(),
|
||||
outstanding_isolate_it);
|
||||
auto* fg_task = outstanding_isolate_it->second;
|
||||
if (fg_task) fg_task->Cancel();
|
||||
current_gc_info_->outstanding_isolates.erase(outstanding_isolate_it);
|
||||
for (WasmCode* code : live_code) current_gc_info_->dead_code.erase(code);
|
||||
|
||||
if (current_gc_info_->outstanding_isolates.empty()) {
|
||||
// All remaining code in {current_gc_info->dead_code} is really dead. Remove
|
||||
// it from the set of potentially dead code, and decrement its ref count.
|
||||
auto dead_code = OwnedVector<WasmCode*>::Of(current_gc_info_->dead_code);
|
||||
for (WasmCode* code : dead_code) {
|
||||
auto* native_module_info = native_modules_[code->native_module()].get();
|
||||
DCHECK_EQ(1, native_module_info->potentially_dead_code.count(code));
|
||||
native_module_info->potentially_dead_code.erase(code);
|
||||
if (current_gc_info_->outstanding_isolates.empty()) {
|
||||
// All remaining code in {current_gc_info->dead_code} is really dead.
|
||||
// Remove it from the set of potentially dead code, and decrement its ref
|
||||
// count.
|
||||
dead_code = OwnedVector<WasmCode*>::Of(current_gc_info_->dead_code);
|
||||
for (WasmCode* code : dead_code) {
|
||||
auto* native_module_info = native_modules_[code->native_module()].get();
|
||||
DCHECK_EQ(1, native_module_info->potentially_dead_code.count(code));
|
||||
native_module_info->potentially_dead_code.erase(code);
|
||||
}
|
||||
current_gc_info_.reset();
|
||||
}
|
||||
WasmCode::DecrementRefCount(dead_code.as_vector());
|
||||
current_gc_info_.reset();
|
||||
}
|
||||
if (!dead_code.empty()) WasmCode::DecrementRefCount(dead_code.as_vector());
|
||||
}
|
||||
|
||||
bool WasmEngine::AddPotentiallyDeadCode(WasmCode* code) {
|
||||
|
Loading…
Reference in New Issue
Block a user