Commit 1a482540 authored by Clemens Hammacher's avatar Clemens Hammacher Committed by Commit Bot

[wasm] Move code logging management to engine

This moves the vector of {WasmCode} to log (per isolate) from the
{LogCodesTask} to the {WasmEngine}, where lifetime is more clear.
This makes it harder to mess up the ref count of the stored {WasmCode}
objects.

R=mstarzinger@chromium.org

Bug: v8:8217
Change-Id: I07131f95391bfabee3c376378179d8bcdc1555b0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1566518
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Reviewed-by: 's avatarMichael Starzinger <mstarzinger@chromium.org>
Cr-Commit-Position: refs/heads/master@{#60869}
parent 9e9fb65e
...@@ -23,12 +23,17 @@ namespace internal { ...@@ -23,12 +23,17 @@ namespace internal {
namespace wasm { namespace wasm {
namespace { namespace {
// A task to log a set of {WasmCode} objects in an isolate. Explicitly manages // A task to log a set of {WasmCode} objects in an isolate. It does not own any
// ref counts of the contained code objects. // data itself, since it is owned by the platform, so lifetime is not really
// bound to the wasm engine.
class LogCodesTask : public Task { class LogCodesTask : public Task {
public: public:
LogCodesTask(base::Mutex* mutex, LogCodesTask** task_slot, Isolate* isolate) LogCodesTask(base::Mutex* mutex, LogCodesTask** task_slot, Isolate* isolate,
: mutex_(mutex), task_slot_(task_slot), isolate_(isolate) { WasmEngine* engine)
: mutex_(mutex),
task_slot_(task_slot),
isolate_(isolate),
engine_(engine) {
DCHECK_NOT_NULL(task_slot); DCHECK_NOT_NULL(task_slot);
DCHECK_NOT_NULL(isolate); DCHECK_NOT_NULL(isolate);
} }
...@@ -37,33 +42,18 @@ class LogCodesTask : public Task { ...@@ -37,33 +42,18 @@ class LogCodesTask : public Task {
// If the platform deletes this task before executing it, we also deregister // If the platform deletes this task before executing it, we also deregister
// it to avoid use-after-free from still-running background threads. // it to avoid use-after-free from still-running background threads.
if (!cancelled()) DeregisterTask(); if (!cancelled()) DeregisterTask();
// TODO(clemensh): Move ref-count management to WasmEngine, i.e. store
// std::vector<WasmCode> there instead of in this task.
clear();
}
// Hold the {mutex_} when calling this method.
void AddCode(WasmCode* code) {
code_to_log_.push_back(code);
code->IncRef();
} }
void Run() override { void Run() override {
if (cancelled()) return; if (cancelled()) return;
DeregisterTask(); DeregisterTask();
// If by now we should not log code any more, do not log it. engine_->LogOutstandingCodesForIsolate(isolate_);
if (!WasmCode::ShouldBeLogged(isolate_)) return;
for (WasmCode* code : code_to_log_) {
code->LogCode(isolate_);
}
clear();
} }
void Cancel() { void Cancel() {
// Cancel will only be called on Isolate shutdown, which happens on the // Cancel will only be called on Isolate shutdown, which happens on the
// Isolate's foreground thread. Thus no synchronization needed. // Isolate's foreground thread. Thus no synchronization needed.
isolate_ = nullptr; isolate_ = nullptr;
clear();
} }
bool cancelled() const { return isolate_ == nullptr; } bool cancelled() const { return isolate_ == nullptr; }
...@@ -82,18 +72,13 @@ class LogCodesTask : public Task { ...@@ -82,18 +72,13 @@ class LogCodesTask : public Task {
} }
private: private:
void clear() {
WasmCode::DecrementRefCount(VectorOf(code_to_log_));
code_to_log_.clear();
}
// The mutex of the WasmEngine. // The mutex of the WasmEngine.
base::Mutex* const mutex_; base::Mutex* const mutex_;
// The slot in the WasmEngine where this LogCodesTask is stored. This is // The slot in the WasmEngine where this LogCodesTask is stored. This is
// cleared by this task before execution or on task destruction. // cleared by this task before execution or on task destruction.
LogCodesTask** task_slot_; LogCodesTask** task_slot_;
Isolate* isolate_; Isolate* isolate_;
std::vector<WasmCode*> code_to_log_; WasmEngine* const engine_;
}; };
class WasmGCForegroundTask : public Task { class WasmGCForegroundTask : public Task {
...@@ -136,6 +121,14 @@ struct WasmEngine::IsolateInfo { ...@@ -136,6 +121,14 @@ struct WasmEngine::IsolateInfo {
foreground_task_runner = platform->GetForegroundTaskRunner(v8_isolate); foreground_task_runner = platform->GetForegroundTaskRunner(v8_isolate);
} }
#ifdef DEBUG
~IsolateInfo() {
// Before destructing, the {WasmEngine} must have cleared outstanding code
// to log.
DCHECK_EQ(0, code_to_log.size());
}
#endif
// All native modules that are being used by this Isolate (currently only // All native modules that are being used by this Isolate (currently only
// grows, never shrinks). // grows, never shrinks).
std::set<NativeModule*> native_modules; std::set<NativeModule*> native_modules;
...@@ -146,6 +139,9 @@ struct WasmEngine::IsolateInfo { ...@@ -146,6 +139,9 @@ struct WasmEngine::IsolateInfo {
// The currently scheduled LogCodesTask. // The currently scheduled LogCodesTask.
LogCodesTask* log_codes_task = nullptr; LogCodesTask* log_codes_task = nullptr;
// The vector of code objects that still need to be logged in this isolate.
std::vector<WasmCode*> code_to_log;
// The foreground task runner of the isolate (can be called from background). // The foreground task runner of the isolate (can be called from background).
std::shared_ptr<v8::TaskRunner> foreground_task_runner; std::shared_ptr<v8::TaskRunner> foreground_task_runner;
}; };
...@@ -514,7 +510,9 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) { ...@@ -514,7 +510,9 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) {
base::MutexGuard guard(&mutex_); base::MutexGuard guard(&mutex_);
auto it = isolates_.find(isolate); auto it = isolates_.find(isolate);
DCHECK_NE(isolates_.end(), it); DCHECK_NE(isolates_.end(), it);
for (NativeModule* native_module : it->second->native_modules) { std::unique_ptr<IsolateInfo> info = std::move(it->second);
isolates_.erase(it);
for (NativeModule* native_module : info->native_modules) {
DCHECK_EQ(1, native_modules_.count(native_module)); DCHECK_EQ(1, native_modules_.count(native_module));
DCHECK_EQ(1, native_modules_[native_module]->isolates.count(isolate)); DCHECK_EQ(1, native_modules_[native_module]->isolates.count(isolate));
auto* info = native_modules_[native_module].get(); auto* info = native_modules_[native_module].get();
...@@ -522,7 +520,7 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) { ...@@ -522,7 +520,7 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) {
if (current_gc_info_) { if (current_gc_info_) {
auto it = current_gc_info_->outstanding_isolates.find(isolate); auto it = current_gc_info_->outstanding_isolates.find(isolate);
if (it != current_gc_info_->outstanding_isolates.end()) { if (it != current_gc_info_->outstanding_isolates.end()) {
if (it->second) it->second->Cancel(); if (auto* gc_task = it->second) gc_task->Cancel();
current_gc_info_->outstanding_isolates.erase(it); current_gc_info_->outstanding_isolates.erase(it);
} }
for (WasmCode* code : info->potentially_dead_code) { for (WasmCode* code : info->potentially_dead_code) {
...@@ -530,8 +528,11 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) { ...@@ -530,8 +528,11 @@ void WasmEngine::RemoveIsolate(Isolate* isolate) {
} }
} }
} }
if (auto* task = it->second->log_codes_task) task->Cancel(); if (auto* task = info->log_codes_task) task->Cancel();
isolates_.erase(it); if (!info->code_to_log.empty()) {
WasmCode::DecrementRefCount(VectorOf(info->code_to_log));
info->code_to_log.clear();
}
} }
void WasmEngine::LogCode(WasmCode* code) { void WasmEngine::LogCode(WasmCode* code) {
...@@ -544,11 +545,12 @@ void WasmEngine::LogCode(WasmCode* code) { ...@@ -544,11 +545,12 @@ void WasmEngine::LogCode(WasmCode* code) {
if (info->log_codes == false) continue; if (info->log_codes == false) continue;
if (info->log_codes_task == nullptr) { if (info->log_codes_task == nullptr) {
auto new_task = base::make_unique<LogCodesTask>( auto new_task = base::make_unique<LogCodesTask>(
&mutex_, &info->log_codes_task, isolate); &mutex_, &info->log_codes_task, isolate, this);
info->log_codes_task = new_task.get(); info->log_codes_task = new_task.get();
info->foreground_task_runner->PostTask(std::move(new_task)); info->foreground_task_runner->PostTask(std::move(new_task));
} }
info->log_codes_task->AddCode(code); info->code_to_log.push_back(code);
code->IncRef();
} }
} }
...@@ -559,6 +561,21 @@ void WasmEngine::EnableCodeLogging(Isolate* isolate) { ...@@ -559,6 +561,21 @@ void WasmEngine::EnableCodeLogging(Isolate* isolate) {
it->second->log_codes = true; it->second->log_codes = true;
} }
void WasmEngine::LogOutstandingCodesForIsolate(Isolate* isolate) {
// If by now we should not log code any more, do not log it.
if (!WasmCode::ShouldBeLogged(isolate)) return;
base::MutexGuard guard(&mutex_);
DCHECK_EQ(1, isolates_.count(isolate));
IsolateInfo* info = isolates_[isolate].get();
if (info->code_to_log.empty()) return;
for (WasmCode* code : info->code_to_log) {
code->LogCode(isolate);
}
WasmCode::DecrementRefCount(VectorOf(info->code_to_log));
info->code_to_log.clear();
}
std::shared_ptr<NativeModule> WasmEngine::NewNativeModule( std::shared_ptr<NativeModule> WasmEngine::NewNativeModule(
Isolate* isolate, const WasmFeatures& enabled, size_t code_size_estimate, Isolate* isolate, const WasmFeatures& enabled, size_t code_size_estimate,
bool can_request_more, std::shared_ptr<const WasmModule> module) { bool can_request_more, std::shared_ptr<const WasmModule> module) {
......
...@@ -163,6 +163,10 @@ class V8_EXPORT_PRIVATE WasmEngine { ...@@ -163,6 +163,10 @@ class V8_EXPORT_PRIVATE WasmEngine {
// {AddIsolate}. // {AddIsolate}.
void EnableCodeLogging(Isolate*); void EnableCodeLogging(Isolate*);
// This is called from the foreground thread of the Isolate to log all
// outstanding code objects (added via {LogCode}).
void LogOutstandingCodesForIsolate(Isolate*);
// Create a new NativeModule. The caller is responsible for its // Create a new NativeModule. The caller is responsible for its
// lifetime. The native module will be given some memory for code, // lifetime. The native module will be given some memory for code,
// which will be page size aligned. The size of the initial memory // which will be page size aligned. The size of the initial memory
......
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