chromium/v8/src/wasm/wasm-engine.cc

// 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 <optional>

#include "src/base/functional.h"
#include "src/base/platform/time.h"
#include "src/base/small-vector.h"
#include "src/common/assert-scope.h"
#include "src/common/globals.h"
#include "src/debug/debug.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/managed-inl.h"
#include "src/objects/objects-inl.h"
#include "src/objects/objects.h"
#include "src/objects/primitive-heap-object.h"
#include "src/utils/ostreams.h"
#include "src/wasm/function-compiler.h"
#include "src/wasm/module-compiler.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/module-instantiate.h"
#include "src/wasm/pgo.h"
#include "src/wasm/stacks.h"
#include "src/wasm/std-object-sizes.h"
#include "src/wasm/streaming-decoder.h"
#include "src/wasm/wasm-code-pointer-table.h"
#include "src/wasm/wasm-debug.h"
#include "src/wasm/wasm-limits.h"
#include "src/wasm/wasm-objects-inl.h"

#if V8_ENABLE_DRUMBRAKE
#include "src/wasm/interpreter/wasm-interpreter-inl.h"
#endif  // V8_ENABLE_DRUMBRAKE

#ifdef V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING
#include "src/debug/wasm/gdb-server/gdb-server.h"
#endif  // V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING

namespace v8::internal::wasm {

#define TRACE_CODE_GC

// This class exists in order to solve a shutdown ordering problem.
// The basic situation is that the process-global WasmEngine has, for each
// Isolate that it knows about, a map from NativeModule to Script, using
// WeakScriptHandles to make sure that the NativeModules, which are shared
// across the process, don't keep the (Isolate-specific) Scripts alive.
// In the other direction, the Scripts keep the NativeModule alive, IOW
// usually the Scripts die first, and the WeakScriptHandles are cleared
// before being freed.
// In case of asm.js modules and in case of Isolate shutdown, it can happen
// that the NativeModule dies first, so the WeakScriptHandles are no longer
// needed and should be destroyed. That can only happen on the main thread of
// the Isolate they belong to, whereas the last thread that releases a
// NativeModule might be any other thread, so we post a
// ClearWeakScriptHandleTask to that isolate's foreground task runner.
// In case of Isolate shutdown at an inconvenient moment, this task runner can
// destroy all waiting tasks; and *afterwards* global handles are freed, which
// writes to the memory location backing the handle, so this bit of memory must
// not be owned by (and die with) the ClearWeakScriptHandleTask.
// The solution is this class here: its instances form a linked list owned by
// the Isolate to which the referenced Scripts belong. Its name refers to the
// fact that it stores global handles that used to have a purpose but are now
// just waiting for the right thread to destroy them.
// If the ClearWeakScriptHandleTask gets to run (i.e. in the regular case),
// it destroys the weak global handle and then the WasmOrphanedGlobalHandle
// container, removing it from the isolate's list.
// If the ClearWeakScriptHandleTask is destroyed before it runs, the isolate's
// list of WasmOrphanedGlobalHandles isn't modified, so the indirection cell
// is still around when all remaining global handles are freed; nevertheless
// it won't leak because the Isolate owns it and will free it.
class WasmOrphanedGlobalHandle {};

// static
WasmOrphanedGlobalHandle* WasmEngine::NewOrphanedGlobalHandle(
    WasmOrphanedGlobalHandle** pointer) {}

// static
void WasmEngine::FreeAllOrphanedGlobalHandles(WasmOrphanedGlobalHandle* start) {}

// 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 WasmEngine::LogCodesTask : public CancelableTask {};

namespace {
void CheckNoArchivedThreads(Isolate* isolate) {}

class WasmGCForegroundTask : public CancelableTask {};

class ClearWeakScriptHandleTask : public CancelableTask {};

class WeakScriptHandle {};

// If PGO data is being collected, keep all native modules alive, so repeated
// runs of a benchmark (with different configuration) all use the same module.
// This vector is protected by the global WasmEngine's mutex, but not defined in
// the header because it's a private implementation detail.
std::vector<std::shared_ptr<NativeModule>>* native_modules_kept_alive_for_pgo;

}  // namespace

std::shared_ptr<NativeModule> NativeModuleCache::MaybeGetNativeModule(
    ModuleOrigin origin, base::Vector<const uint8_t> wire_bytes,
    const CompileTimeImports& compile_imports) {}

bool NativeModuleCache::GetStreamingCompilationOwnership(
    size_t prefix_hash, const CompileTimeImports& compile_imports) {}

void NativeModuleCache::StreamingCompilationFailed(
    size_t prefix_hash, const CompileTimeImports& compile_imports) {}

std::shared_ptr<NativeModule> NativeModuleCache::Update(
    std::shared_ptr<NativeModule> native_module, bool error) {}

void NativeModuleCache::Erase(NativeModule* native_module) {}

// static
size_t NativeModuleCache::PrefixHash(base::Vector<const uint8_t> wire_bytes) {}

struct WasmEngine::CurrentGCInfo {};

struct WasmEngine::IsolateInfo {};

void WasmEngine::ClearWeakScriptHandle(Isolate* isolate,
                                       std::unique_ptr<Address*> location) {}

struct WasmEngine::NativeModuleInfo {};

WasmEngine::WasmEngine() :{}

WasmEngine::~WasmEngine() {}

bool WasmEngine::SyncValidate(Isolate* isolate, WasmEnabledFeatures enabled,
                              CompileTimeImports compile_imports,
                              ModuleWireBytes bytes) {}

MaybeHandle<AsmWasmData> WasmEngine::SyncCompileTranslatedAsmJs(
    Isolate* isolate, ErrorThrower* thrower, ModuleWireBytes bytes,
    DirectHandle<Script> script,
    base::Vector<const uint8_t> asm_js_offset_table_bytes,
    DirectHandle<HeapNumber> uses_bitset, LanguageMode language_mode) {}

Handle<WasmModuleObject> WasmEngine::FinalizeTranslatedAsmJs(
    Isolate* isolate, DirectHandle<AsmWasmData> asm_wasm_data,
    DirectHandle<Script> script) {}

MaybeHandle<WasmModuleObject> WasmEngine::SyncCompile(
    Isolate* isolate, WasmEnabledFeatures enabled,
    CompileTimeImports compile_imports, ErrorThrower* thrower,
    ModuleWireBytes bytes) {}

MaybeHandle<WasmInstanceObject> WasmEngine::SyncInstantiate(
    Isolate* isolate, ErrorThrower* thrower,
    Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
    MaybeHandle<JSArrayBuffer> memory) {}

void WasmEngine::AsyncInstantiate(
    Isolate* isolate, std::unique_ptr<InstantiationResultResolver> resolver,
    Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports) {}

void WasmEngine::AsyncCompile(
    Isolate* isolate, WasmEnabledFeatures enabled,
    CompileTimeImports compile_imports,
    std::shared_ptr<CompilationResultResolver> resolver, ModuleWireBytes bytes,
    bool is_shared, const char* api_method_name_for_errors) {}

std::shared_ptr<StreamingDecoder> WasmEngine::StartStreamingCompilation(
    Isolate* isolate, WasmEnabledFeatures enabled,
    CompileTimeImports compile_imports, Handle<Context> context,
    const char* api_method_name,
    std::shared_ptr<CompilationResultResolver> resolver) {}

void WasmEngine::CompileFunction(Counters* counters,
                                 NativeModule* native_module,
                                 uint32_t function_index, ExecutionTier tier) {}

void WasmEngine::EnterDebuggingForIsolate(Isolate* isolate) {}

void WasmEngine::LeaveDebuggingForIsolate(Isolate* isolate) {}

namespace {
Handle<Script> CreateWasmScript(Isolate* isolate,
                                std::shared_ptr<NativeModule> native_module,
                                base::Vector<const char> source_url) {}
}  // namespace

Handle<WasmModuleObject> WasmEngine::ImportNativeModule(
    Isolate* isolate, std::shared_ptr<NativeModule> shared_native_module,
    base::Vector<const char> source_url) {}

std::pair<size_t, size_t> WasmEngine::FlushLiftoffCode() {}

size_t WasmEngine::GetLiftoffCodeSizeForTesting() {}

std::shared_ptr<CompilationStatistics>
WasmEngine::GetOrCreateTurboStatistics() {}

void WasmEngine::DumpAndResetTurboStatistics() {}

void WasmEngine::DumpTurboStatistics() {}

CodeTracer* WasmEngine::GetCodeTracer() {}

AsyncCompileJob* WasmEngine::CreateAsyncCompileJob(
    Isolate* isolate, WasmEnabledFeatures enabled,
    CompileTimeImports compile_imports, base::OwnedVector<const uint8_t> bytes,
    DirectHandle<Context> context, const char* api_method_name,
    std::shared_ptr<CompilationResultResolver> resolver, int compilation_id) {}

std::unique_ptr<AsyncCompileJob> WasmEngine::RemoveCompileJob(
    AsyncCompileJob* job) {}

bool WasmEngine::HasRunningCompileJob(Isolate* isolate) {}

void WasmEngine::DeleteCompileJobsOnContext(Handle<Context> context) {}

void WasmEngine::DeleteCompileJobsOnIsolate(Isolate* isolate) {}

OperationsBarrier::Token WasmEngine::StartWrapperCompilation(Isolate* isolate) {}

void WasmEngine::AddIsolate(Isolate* isolate) {}

void WasmEngine::RemoveIsolate(Isolate* isolate) {}

void WasmEngine::LogCode(base::Vector<WasmCode*> code_vec) {}

void WasmEngine::LogWrapperCode(base::Vector<WasmCode*> code_vec) {}

void WasmEngine::EnableCodeLogging(Isolate* isolate) {}

void WasmEngine::LogOutstandingCodesForIsolate(Isolate* isolate) {}

std::shared_ptr<NativeModule> WasmEngine::NewNativeModule(
    Isolate* isolate, WasmEnabledFeatures enabled,
    CompileTimeImports compile_imports,
    std::shared_ptr<const WasmModule> module, size_t code_size_estimate) {}

std::shared_ptr<NativeModule> WasmEngine::MaybeGetNativeModule(
    ModuleOrigin origin, base::Vector<const uint8_t> wire_bytes,
    const CompileTimeImports& compile_imports, Isolate* isolate) {}

std::shared_ptr<NativeModule> WasmEngine::UpdateNativeModuleCache(
    bool has_error, std::shared_ptr<NativeModule> native_module,
    Isolate* isolate) {}

bool WasmEngine::GetStreamingCompilationOwnership(
    size_t prefix_hash, const CompileTimeImports& compile_imports) {}

void WasmEngine::StreamingCompilationFailed(
    size_t prefix_hash, const CompileTimeImports& compile_imports) {}

void WasmEngine::FreeNativeModule(NativeModule* native_module) {}

void WasmEngine::ReportLiveCodeForGC(Isolate* isolate,
                                     base::Vector<WasmCode*> live_code) {}

namespace {
void ReportLiveCodeFromFrameForGC(
    Isolate* isolate, StackFrame* frame,
    std::unordered_set<wasm::WasmCode*>& live_wasm_code) {}
}  // namespace

void WasmEngine::ReportLiveCodeFromStackForGC(Isolate* isolate) {}

bool WasmEngine::AddPotentiallyDeadCode(WasmCode* code) {}

void WasmEngine::FreeDeadCode(const DeadCodeMap& dead_code,
                              std::vector<WasmCode*>& dead_wrappers) {}

void WasmEngine::FreeDeadCodeLocked(const DeadCodeMap& dead_code,
                                    std::vector<WasmCode*>& dead_wrappers) {}

Handle<Script> WasmEngine::GetOrCreateScript(
    Isolate* isolate, const std::shared_ptr<NativeModule>& native_module,
    base::Vector<const char> source_url) {}

std::shared_ptr<OperationsBarrier>
WasmEngine::GetBarrierForBackgroundCompile() {}

void WasmEngine::TriggerGC(int8_t gc_sequence_index) {}

bool WasmEngine::RemoveIsolateFromCurrentGC(Isolate* isolate) {}

void WasmEngine::PotentiallyFinishCurrentGC() {}

size_t WasmEngine::EstimateCurrentMemoryConsumption() const {}

int WasmEngine::GetDeoptsExecutedCount() const {}

int WasmEngine::IncrementDeoptsExecutedCount() {}

namespace {

struct GlobalWasmState {};

GlobalWasmState* global_wasm_state =;

}  // namespace

// static
void WasmEngine::InitializeOncePerProcess() {}

// static
void WasmEngine::GlobalTearDown() {}

WasmEngine* GetWasmEngine() {}

WasmCodeManager* GetWasmCodeManager() {}

WasmImportWrapperCache* GetWasmImportWrapperCache() {}

// {max_mem_pages} is declared in wasm-limits.h.
uint32_t max_mem32_pages() {}

uint32_t max_mem64_pages() {}

// {max_table_init_entries} is declared in wasm-limits.h.
uint32_t max_table_init_entries() {}

// {max_module_size} is declared in wasm-limits.h.
size_t max_module_size() {}

#undef TRACE_CODE_GC

}  // namespace v8::internal::wasm