Commit fab754ff authored by Clemens Backes's avatar Clemens Backes Committed by Commit Bot

[wasm][debug] Cache debugging code

This adds a little cache for debugging code, including stepping code.
Especially in stepping, we are currently repeatedly recompiling the same
function, because whenever we pause (after every step) we clear
stepping, only to reinstantiate it if the user continues stepping.
Especially in source-level stepping this is wasteful, because stepping
over a single line of C++ code can execute hundreds or thousands of
steps in wasm.

R=thibaudm@chromium.org

Bug: chromium:1172299
Change-Id: Id59a26cc67a5bf4a2d3cf6b1e8f14a8b1c73712c
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2732015Reviewed-by: 's avatarThibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#73162}
parent ba0269b8
......@@ -219,6 +219,20 @@ class DebugInfoImpl {
Vector<const int> offsets,
int dead_breakpoint) {
DCHECK(!mutex_.TryLock()); // Mutex is held externally.
// Check the cache first.
for (auto begin = cached_debugging_code_.begin(), it = begin,
end = cached_debugging_code_.end();
it != end; ++it) {
if (it->func_index == func_index &&
it->breakpoint_offsets.as_vector() == offsets &&
it->dead_breakpoint == dead_breakpoint) {
// Rotate the cache entry to the front (for LRU).
for (; it != begin; --it) std::iter_swap(it, it - 1);
return it->code;
}
}
// Recompile the function with Liftoff, setting the new breakpoints.
// Not thread-safe. The caller is responsible for locking {mutex_}.
CompilationEnv env = native_module_->CreateCompilationEnv();
......@@ -255,6 +269,21 @@ class DebugInfoImpl {
debug_side_tables_.emplace(new_code, std::move(debug_sidetable));
}
// Insert new code into the cache. Insert before existing elements for LRU.
cached_debugging_code_.insert(
cached_debugging_code_.begin(),
CachedDebuggingCode{func_index, OwnedVector<int>::Of(offsets),
dead_breakpoint, new_code});
// Increase the ref count (for the cache entry).
new_code->IncRef();
// Remove exceeding element.
if (cached_debugging_code_.size() > kMaxCachedDebuggingCode) {
WasmCode::DecrementRefCount(
VectorOf({cached_debugging_code_.back().code}));
cached_debugging_code_.pop_back();
}
DCHECK_GE(kMaxCachedDebuggingCode, cached_debugging_code_.size());
return new_code;
}
......@@ -649,6 +678,19 @@ class DebugInfoImpl {
// {mutex_} protects all fields below.
mutable base::Mutex mutex_;
// Cache a fixed number of WasmCode objects that were generated for debugging.
// This is useful especially in stepping, because stepping code is cleared on
// every pause and re-installed on the next step.
// This is a LRU cache (most recently used entries first).
static constexpr size_t kMaxCachedDebuggingCode = 3;
struct CachedDebuggingCode {
int func_index;
OwnedVector<const int> breakpoint_offsets;
int dead_breakpoint;
WasmCode* code;
};
std::vector<CachedDebuggingCode> cached_debugging_code_;
// Names of exports, lazily derived from the exports table.
std::unique_ptr<std::map<ImportExportKey, wasm::WireBytesRef>> export_names_;
......
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