// Copyright 2018 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "src/wasm/wasm-engine.h" #include "src/base/functional.h" #include "src/base/platform/time.h" #include "src/common/globals.h" #include "src/diagnostics/code-tracer.h" #include "src/diagnostics/compilation-statistics.h" #include "src/execution/frames.h" #include "src/execution/v8threads.h" #include "src/handles/global-handles-inl.h" #include "src/logging/counters.h" #include "src/logging/metrics.h" #include "src/objects/heap-number.h" #include "src/objects/js-promise.h" #include "src/objects/managed-inl.h" #include "src/objects/objects-inl.h" #include "src/strings/string-hasher-inl.h" #include "src/utils/ostreams.h" #include "src/wasm/function-compiler.h" #include "src/wasm/memory-protection-key.h" #include "src/wasm/module-compiler.h" #include "src/wasm/module-decoder.h" #include "src/wasm/module-instantiate.h" #include "src/wasm/streaming-decoder.h" #include "src/wasm/wasm-debug.h" #include "src/wasm/wasm-limits.h" #include "src/wasm/wasm-objects-inl.h" #ifdef V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING #include "src/base/platform/wrappers.h" #include "src/debug/wasm/gdb-server/gdb-server.h" #endif // V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING namespace v8 { namespace internal { namespace wasm { #define TRACE_CODE_GC(...) \ do { \ if (FLAG_trace_wasm_code_gc) PrintF("[wasm-gc] " __VA_ARGS__); \ } while (false) namespace { // A task to log a set of {WasmCode} objects in an isolate. It does not own any // data itself, since it is owned by the platform, so lifetime is not really // bound to the wasm engine. class LogCodesTask : public Task { public: LogCodesTask(base::Mutex* mutex, LogCodesTask** task_slot, Isolate* isolate, WasmEngine* engine) : mutex_(mutex), task_slot_(task_slot), isolate_(isolate), engine_(engine) { DCHECK_NOT_NULL(task_slot); DCHECK_NOT_NULL(isolate); } ~LogCodesTask() override { // If the platform deletes this task before executing it, we also deregister // it to avoid use-after-free from still-running background threads. if (!cancelled()) DeregisterTask(); } void Run() override { if (cancelled()) return; DeregisterTask(); engine_->LogOutstandingCodesForIsolate(isolate_); } void Cancel() { // Cancel will only be called on Isolate shutdown, which happens on the // Isolate's foreground thread. Thus no synchronization needed. isolate_ = nullptr; } bool cancelled() const { return isolate_ == nullptr; } void DeregisterTask() { // The task will only be deregistered from the foreground thread (executing // this task or calling its destructor), thus we do not need synchronization // on this field access. if (task_slot_ == nullptr) return; // already deregistered. // Remove this task from the {IsolateInfo} in the engine. The next // logging request will allocate and schedule a new task. base::MutexGuard guard(mutex_); DCHECK_EQ(this, *task_slot_); *task_slot_ = nullptr; task_slot_ = nullptr; } private: // The mutex of the WasmEngine. base::Mutex* const mutex_; // The slot in the WasmEngine where this LogCodesTask is stored. This is // cleared by this task before execution or on task destruction. LogCodesTask** task_slot_; Isolate* isolate_; WasmEngine* const engine_; }; void CheckNoArchivedThreads(Isolate* isolate) { class ArchivedThreadsVisitor : public ThreadVisitor { void VisitThread(Isolate* isolate, ThreadLocalTop* top) override { // Archived threads are rarely used, and not combined with Wasm at the // moment. Implement this and test it properly once we have a use case for // that. FATAL("archived threads in combination with wasm not supported"); } } archived_threads_visitor; isolate->thread_manager()->IterateArchivedThreads(&archived_threads_visitor); } class WasmGCForegroundTask : public CancelableTask { public: explicit WasmGCForegroundTask(Isolate* isolate) : CancelableTask(isolate->cancelable_task_manager()), isolate_(isolate) {} void RunInternal() final { // The stack can contain live frames, for instance when this is invoked // during a pause or a breakpoint. GetWasmEngine()->ReportLiveCodeFromStackForGC(isolate_); } private: Isolate* isolate_; }; class WeakScriptHandle { public: explicit WeakScriptHandle(Handle