Commit 0820ee1a authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm][gc] Fix several minor issues

This CL fixes some issues with GC.
1) It removes dead code from the set of potentially dead code to avoid
   considering the same code for GC again and again.
2) It resets the {new_potentially_dead_code_size_} counter to avoid
   triggering too many GCs.
3) When code becomes dead after GC, do not unconditionally free it; just
   decrement its ref count (there might still be {WasmCodeRefScope}s
   holding the code alive).
4) Update the comment of the ref count to be more accurate.

R=titzer@chromium.org

Bug: v8:8217
Change-Id: I28e5a1fed74411b8473bb66ddbad3ffe7643f266
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1574518
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarBen Titzer <titzer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60949}
parent e453f722
...@@ -219,6 +219,9 @@ class OwnedVector { ...@@ -219,6 +219,9 @@ class OwnedVector {
return data_.get(); return data_.get();
} }
constexpr T* begin() const { return start(); }
constexpr T* end() const { return start() + size(); }
// Returns a {Vector<T>} view of the data in this vector. // Returns a {Vector<T>} view of the data in this vector.
Vector<T> as_vector() const { return Vector<T>(start(), size()); } Vector<T> as_vector() const { return Vector<T>(start(), size()); }
......
...@@ -1333,6 +1333,7 @@ void NativeModule::SampleCodeSize( ...@@ -1333,6 +1333,7 @@ void NativeModule::SampleCodeSize(
histogram = counters->wasm_module_code_size_mb(); histogram = counters->wasm_module_code_size_mb();
// Also, add a sample of freed code size, absolute and relative. // Also, add a sample of freed code size, absolute and relative.
size_t freed_size = freed_code_size_.load(std::memory_order_relaxed); size_t freed_size = freed_code_size_.load(std::memory_order_relaxed);
DCHECK_LE(freed_size, generated_code_size_);
int total_freed_mb = static_cast<int>(freed_size / MB); int total_freed_mb = static_cast<int>(freed_size / MB);
counters->wasm_module_freed_code_size_mb()->AddSample(total_freed_mb); counters->wasm_module_freed_code_size_mb()->AddSample(total_freed_mb);
int freed_percent = int freed_percent =
......
...@@ -248,15 +248,15 @@ class V8_EXPORT_PRIVATE WasmCode final { ...@@ -248,15 +248,15 @@ class V8_EXPORT_PRIVATE WasmCode final {
ExecutionTier tier_; ExecutionTier tier_;
// WasmCode is ref counted. Counters are held by: // WasmCode is ref counted. Counters are held by:
// 1) The jump table. // 1) The jump table / code table.
// 2) Function tables. // 2) {WasmCodeRefScope}s.
// 3) {WasmCodeRefScope}s. // 3) The set of potentially dead code in the {WasmEngine}.
// 4) The set of potentially dead code in the {WasmEngine}. // If a decrement of (1) would drop the ref count to 0, that code becomes a
// If a decrement of (1) or (2) would drop the ref count to 0, that code // candidate for garbage collection. At that point, we add a ref count for (3)
// becomes a candidate for garbage collection. At that point, we add // *before* decrementing the counter to ensure the code stays alive as long as
// ref counts for (4) *before* decrementing the counter to ensure the code // it's being used. Once the ref count drops to zero (i.e. after being removed
// stays alive as long as it's being used. Once the ref count drops to zero, // from (3) and all (2)), the code object is deleted and the memory for the
// the code object is deleted and the memory for the machine code is freed. // machine code is freed.
std::atomic<int> ref_count_{1}; std::atomic<int> ref_count_{1};
DISALLOW_COPY_AND_ASSIGN(WasmCode); DISALLOW_COPY_AND_ASSIGN(WasmCode);
......
...@@ -675,14 +675,15 @@ void WasmEngine::ReportLiveCodeForGC(Isolate* isolate, ...@@ -675,14 +675,15 @@ void WasmEngine::ReportLiveCodeForGC(Isolate* isolate,
for (WasmCode* code : live_code) current_gc_info_->dead_code.erase(code); for (WasmCode* code : live_code) current_gc_info_->dead_code.erase(code);
if (current_gc_info_->outstanding_isolates.empty()) { if (current_gc_info_->outstanding_isolates.empty()) {
std::unordered_map<NativeModule*, std::vector<WasmCode*>> // All remaining code in {current_gc_info->dead_code} is really dead. Remove
dead_code_per_native_module; // it from the set of potentially dead code, and decrement its ref count.
for (WasmCode* code : current_gc_info_->dead_code) { auto dead_code = OwnedVector<WasmCode*>::Of(current_gc_info_->dead_code);
dead_code_per_native_module[code->native_module()].push_back(code); for (WasmCode* code : dead_code) {
} auto* native_module_info = native_modules_[code->native_module()].get();
for (auto& entry : dead_code_per_native_module) { DCHECK_EQ(1, native_module_info->potentially_dead_code.count(code));
entry.first->FreeCode(VectorOf(entry.second)); native_module_info->potentially_dead_code.erase(code);
} }
WasmCode::DecrementRefCount(dead_code.as_vector());
current_gc_info_.reset(); current_gc_info_.reset();
} }
} }
...@@ -698,6 +699,7 @@ bool WasmEngine::AddPotentiallyDeadCode(WasmCode* code) { ...@@ -698,6 +699,7 @@ bool WasmEngine::AddPotentiallyDeadCode(WasmCode* code) {
size_t dead_code_limit = 1 * MB + code_manager_.committed_code_space() / 10; size_t dead_code_limit = 1 * MB + code_manager_.committed_code_space() / 10;
if (FLAG_wasm_code_gc && new_potentially_dead_code_size_ > dead_code_limit && if (FLAG_wasm_code_gc && new_potentially_dead_code_size_ > dead_code_limit &&
!current_gc_info_) { !current_gc_info_) {
new_potentially_dead_code_size_ = 0;
TriggerGC(); TriggerGC();
} }
return true; return true;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment