11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#if !V8_ENABLE_WEBASSEMBLY 61cb0ef41Sopenharmony_ci#error This header should only be included if WebAssembly is enabled. 71cb0ef41Sopenharmony_ci#endif // !V8_ENABLE_WEBASSEMBLY 81cb0ef41Sopenharmony_ci 91cb0ef41Sopenharmony_ci#ifndef V8_WASM_MODULE_COMPILER_H_ 101cb0ef41Sopenharmony_ci#define V8_WASM_MODULE_COMPILER_H_ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include <atomic> 131cb0ef41Sopenharmony_ci#include <functional> 141cb0ef41Sopenharmony_ci#include <memory> 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#include "include/v8-metrics.h" 171cb0ef41Sopenharmony_ci#include "src/base/optional.h" 181cb0ef41Sopenharmony_ci#include "src/common/globals.h" 191cb0ef41Sopenharmony_ci#include "src/logging/metrics.h" 201cb0ef41Sopenharmony_ci#include "src/tasks/cancelable-task.h" 211cb0ef41Sopenharmony_ci#include "src/wasm/compilation-environment.h" 221cb0ef41Sopenharmony_ci#include "src/wasm/wasm-features.h" 231cb0ef41Sopenharmony_ci#include "src/wasm/wasm-import-wrapper-cache.h" 241cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h" 251cb0ef41Sopenharmony_ci 261cb0ef41Sopenharmony_cinamespace v8 { 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_cinamespace base { 291cb0ef41Sopenharmony_citemplate <typename T> 301cb0ef41Sopenharmony_ciclass Vector; 311cb0ef41Sopenharmony_ci} // namespace base 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_cinamespace internal { 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciclass JSArrayBuffer; 361cb0ef41Sopenharmony_ciclass JSPromise; 371cb0ef41Sopenharmony_ciclass Counters; 381cb0ef41Sopenharmony_ciclass WasmModuleObject; 391cb0ef41Sopenharmony_ciclass WasmInstanceObject; 401cb0ef41Sopenharmony_ci 411cb0ef41Sopenharmony_cinamespace wasm { 421cb0ef41Sopenharmony_ci 431cb0ef41Sopenharmony_cistruct CompilationEnv; 441cb0ef41Sopenharmony_ciclass CompilationResultResolver; 451cb0ef41Sopenharmony_ciclass ErrorThrower; 461cb0ef41Sopenharmony_ciclass ModuleCompiler; 471cb0ef41Sopenharmony_ciclass NativeModule; 481cb0ef41Sopenharmony_ciclass StreamingDecoder; 491cb0ef41Sopenharmony_ciclass WasmCode; 501cb0ef41Sopenharmony_cistruct WasmModule; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE 531cb0ef41Sopenharmony_cistd::shared_ptr<NativeModule> CompileToNativeModule( 541cb0ef41Sopenharmony_ci Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower, 551cb0ef41Sopenharmony_ci std::shared_ptr<const WasmModule> module, const ModuleWireBytes& wire_bytes, 561cb0ef41Sopenharmony_ci Handle<FixedArray>* export_wrappers_out, int compilation_id, 571cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id); 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_civoid RecompileNativeModule(NativeModule* native_module, 601cb0ef41Sopenharmony_ci TieringState new_tiering_state); 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE 631cb0ef41Sopenharmony_civoid CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module, 641cb0ef41Sopenharmony_ci Handle<FixedArray>* export_wrappers_out); 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci// Compiles the wrapper for this (kind, sig) pair and sets the corresponding 671cb0ef41Sopenharmony_ci// cache entry. Assumes the key already exists in the cache but has not been 681cb0ef41Sopenharmony_ci// compiled yet. 691cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE 701cb0ef41Sopenharmony_ciWasmCode* CompileImportWrapper( 711cb0ef41Sopenharmony_ci NativeModule* native_module, Counters* counters, 721cb0ef41Sopenharmony_ci compiler::WasmImportCallKind kind, const FunctionSig* sig, 731cb0ef41Sopenharmony_ci int expected_arity, Suspend suspend, 741cb0ef41Sopenharmony_ci WasmImportWrapperCache::ModificationScope* cache_scope); 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_ci// Triggered by the WasmCompileLazy builtin. The return value indicates whether 771cb0ef41Sopenharmony_ci// compilation was successful. Lazy compilation can fail only if validation is 781cb0ef41Sopenharmony_ci// also lazy. 791cb0ef41Sopenharmony_cibool CompileLazy(Isolate*, Handle<WasmInstanceObject>, int func_index); 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE void TriggerTierUp(Isolate*, NativeModule*, int func_index, 821cb0ef41Sopenharmony_ci Handle<WasmInstanceObject> instance); 831cb0ef41Sopenharmony_ci 841cb0ef41Sopenharmony_citemplate <typename Key, typename Hash> 851cb0ef41Sopenharmony_ciclass WrapperQueue { 861cb0ef41Sopenharmony_ci public: 871cb0ef41Sopenharmony_ci // Removes an arbitrary key from the queue and returns it. 881cb0ef41Sopenharmony_ci // If the queue is empty, returns nullopt. 891cb0ef41Sopenharmony_ci // Thread-safe. 901cb0ef41Sopenharmony_ci base::Optional<Key> pop() { 911cb0ef41Sopenharmony_ci base::Optional<Key> key = base::nullopt; 921cb0ef41Sopenharmony_ci base::MutexGuard lock(&mutex_); 931cb0ef41Sopenharmony_ci auto it = queue_.begin(); 941cb0ef41Sopenharmony_ci if (it != queue_.end()) { 951cb0ef41Sopenharmony_ci key = *it; 961cb0ef41Sopenharmony_ci queue_.erase(it); 971cb0ef41Sopenharmony_ci } 981cb0ef41Sopenharmony_ci return key; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_ci // Add the given key to the queue and returns true iff the insert was 1021cb0ef41Sopenharmony_ci // successful. 1031cb0ef41Sopenharmony_ci // Not thread-safe. 1041cb0ef41Sopenharmony_ci bool insert(const Key& key) { return queue_.insert(key).second; } 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci size_t size() { 1071cb0ef41Sopenharmony_ci base::MutexGuard lock(&mutex_); 1081cb0ef41Sopenharmony_ci return queue_.size(); 1091cb0ef41Sopenharmony_ci } 1101cb0ef41Sopenharmony_ci 1111cb0ef41Sopenharmony_ci private: 1121cb0ef41Sopenharmony_ci base::Mutex mutex_; 1131cb0ef41Sopenharmony_ci std::unordered_set<Key, Hash> queue_; 1141cb0ef41Sopenharmony_ci}; 1151cb0ef41Sopenharmony_ci 1161cb0ef41Sopenharmony_ci// Encapsulates all the state and steps of an asynchronous compilation. 1171cb0ef41Sopenharmony_ci// An asynchronous compile job consists of a number of tasks that are executed 1181cb0ef41Sopenharmony_ci// as foreground and background tasks. Any phase that touches the V8 heap or 1191cb0ef41Sopenharmony_ci// allocates on the V8 heap (e.g. creating the module object) must be a 1201cb0ef41Sopenharmony_ci// foreground task. All other tasks (e.g. decoding and validating, the majority 1211cb0ef41Sopenharmony_ci// of the work of compilation) can be background tasks. 1221cb0ef41Sopenharmony_ci// TODO(wasm): factor out common parts of this with the synchronous pipeline. 1231cb0ef41Sopenharmony_ciclass AsyncCompileJob { 1241cb0ef41Sopenharmony_ci public: 1251cb0ef41Sopenharmony_ci AsyncCompileJob(Isolate* isolate, const WasmFeatures& enabled_features, 1261cb0ef41Sopenharmony_ci std::unique_ptr<byte[]> bytes_copy, size_t length, 1271cb0ef41Sopenharmony_ci Handle<Context> context, Handle<Context> incumbent_context, 1281cb0ef41Sopenharmony_ci const char* api_method_name, 1291cb0ef41Sopenharmony_ci std::shared_ptr<CompilationResultResolver> resolver, 1301cb0ef41Sopenharmony_ci int compilation_id); 1311cb0ef41Sopenharmony_ci ~AsyncCompileJob(); 1321cb0ef41Sopenharmony_ci 1331cb0ef41Sopenharmony_ci void Start(); 1341cb0ef41Sopenharmony_ci 1351cb0ef41Sopenharmony_ci std::shared_ptr<StreamingDecoder> CreateStreamingDecoder(); 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci void Abort(); 1381cb0ef41Sopenharmony_ci void CancelPendingForegroundTask(); 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci Isolate* isolate() const { return isolate_; } 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci Handle<NativeContext> context() const { return native_context_; } 1431cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id() const { return context_id_; } 1441cb0ef41Sopenharmony_ci 1451cb0ef41Sopenharmony_ci private: 1461cb0ef41Sopenharmony_ci class CompileTask; 1471cb0ef41Sopenharmony_ci class CompileStep; 1481cb0ef41Sopenharmony_ci class CompilationStateCallback; 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci // States of the AsyncCompileJob. 1511cb0ef41Sopenharmony_ci class DecodeModule; // Step 1 (async) 1521cb0ef41Sopenharmony_ci class DecodeFail; // Step 1b (sync) 1531cb0ef41Sopenharmony_ci class PrepareAndStartCompile; // Step 2 (sync) 1541cb0ef41Sopenharmony_ci class CompileFailed; // Step 3a (sync) 1551cb0ef41Sopenharmony_ci class CompileFinished; // Step 3b (sync) 1561cb0ef41Sopenharmony_ci 1571cb0ef41Sopenharmony_ci friend class AsyncStreamingProcessor; 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ci // Decrements the number of outstanding finishers. The last caller of this 1601cb0ef41Sopenharmony_ci // function should finish the asynchronous compilation, see the comment on 1611cb0ef41Sopenharmony_ci // {outstanding_finishers_}. 1621cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT bool DecrementAndCheckFinisherCount() { 1631cb0ef41Sopenharmony_ci DCHECK_LT(0, outstanding_finishers_.load()); 1641cb0ef41Sopenharmony_ci return outstanding_finishers_.fetch_sub(1) == 1; 1651cb0ef41Sopenharmony_ci } 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci void CreateNativeModule(std::shared_ptr<const WasmModule> module, 1681cb0ef41Sopenharmony_ci size_t code_size_estimate); 1691cb0ef41Sopenharmony_ci // Return true for cache hit, false for cache miss. 1701cb0ef41Sopenharmony_ci bool GetOrCreateNativeModule(std::shared_ptr<const WasmModule> module, 1711cb0ef41Sopenharmony_ci size_t code_size_estimate); 1721cb0ef41Sopenharmony_ci void PrepareRuntimeObjects(); 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci void FinishCompile(bool is_after_cache_hit); 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci void DecodeFailed(const WasmError&); 1771cb0ef41Sopenharmony_ci void AsyncCompileFailed(); 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci void AsyncCompileSucceeded(Handle<WasmModuleObject> result); 1801cb0ef41Sopenharmony_ci 1811cb0ef41Sopenharmony_ci void FinishModule(); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci void StartForegroundTask(); 1841cb0ef41Sopenharmony_ci void ExecuteForegroundTaskImmediately(); 1851cb0ef41Sopenharmony_ci 1861cb0ef41Sopenharmony_ci void StartBackgroundTask(); 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci enum UseExistingForegroundTask : bool { 1891cb0ef41Sopenharmony_ci kUseExistingForegroundTask = true, 1901cb0ef41Sopenharmony_ci kAssertNoExistingForegroundTask = false 1911cb0ef41Sopenharmony_ci }; 1921cb0ef41Sopenharmony_ci // Switches to the compilation step {Step} and starts a foreground task to 1931cb0ef41Sopenharmony_ci // execute it. Most of the time we know that there cannot be a running 1941cb0ef41Sopenharmony_ci // foreground task. If there might be one, then pass 1951cb0ef41Sopenharmony_ci // kUseExistingForegroundTask to avoid spawning a second one. 1961cb0ef41Sopenharmony_ci template <typename Step, 1971cb0ef41Sopenharmony_ci UseExistingForegroundTask = kAssertNoExistingForegroundTask, 1981cb0ef41Sopenharmony_ci typename... Args> 1991cb0ef41Sopenharmony_ci void DoSync(Args&&... args); 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ci // Switches to the compilation step {Step} and immediately executes that step. 2021cb0ef41Sopenharmony_ci template <typename Step, typename... Args> 2031cb0ef41Sopenharmony_ci void DoImmediately(Args&&... args); 2041cb0ef41Sopenharmony_ci 2051cb0ef41Sopenharmony_ci // Switches to the compilation step {Step} and starts a background task to 2061cb0ef41Sopenharmony_ci // execute it. 2071cb0ef41Sopenharmony_ci template <typename Step, typename... Args> 2081cb0ef41Sopenharmony_ci void DoAsync(Args&&... args); 2091cb0ef41Sopenharmony_ci 2101cb0ef41Sopenharmony_ci // Switches to the compilation step {Step} but does not start a task to 2111cb0ef41Sopenharmony_ci // execute it. 2121cb0ef41Sopenharmony_ci template <typename Step, typename... Args> 2131cb0ef41Sopenharmony_ci void NextStep(Args&&... args); 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci Isolate* const isolate_; 2161cb0ef41Sopenharmony_ci const char* const api_method_name_; 2171cb0ef41Sopenharmony_ci const WasmFeatures enabled_features_; 2181cb0ef41Sopenharmony_ci const DynamicTiering dynamic_tiering_; 2191cb0ef41Sopenharmony_ci const bool wasm_lazy_compilation_; 2201cb0ef41Sopenharmony_ci base::TimeTicks start_time_; 2211cb0ef41Sopenharmony_ci // Copy of the module wire bytes, moved into the {native_module_} on its 2221cb0ef41Sopenharmony_ci // creation. 2231cb0ef41Sopenharmony_ci std::unique_ptr<byte[]> bytes_copy_; 2241cb0ef41Sopenharmony_ci // Reference to the wire bytes (held in {bytes_copy_} or as part of 2251cb0ef41Sopenharmony_ci // {native_module_}). 2261cb0ef41Sopenharmony_ci ModuleWireBytes wire_bytes_; 2271cb0ef41Sopenharmony_ci Handle<NativeContext> native_context_; 2281cb0ef41Sopenharmony_ci Handle<Context> incumbent_context_; 2291cb0ef41Sopenharmony_ci v8::metrics::Recorder::ContextId context_id_; 2301cb0ef41Sopenharmony_ci v8::metrics::WasmModuleDecoded metrics_event_; 2311cb0ef41Sopenharmony_ci const std::shared_ptr<CompilationResultResolver> resolver_; 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object_; 2341cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> native_module_; 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci std::unique_ptr<CompileStep> step_; 2371cb0ef41Sopenharmony_ci CancelableTaskManager background_task_manager_; 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci std::shared_ptr<v8::TaskRunner> foreground_task_runner_; 2401cb0ef41Sopenharmony_ci 2411cb0ef41Sopenharmony_ci // For async compilation the AsyncCompileJob is the only finisher. For 2421cb0ef41Sopenharmony_ci // streaming compilation also the AsyncStreamingProcessor has to finish before 2431cb0ef41Sopenharmony_ci // compilation can be finished. 2441cb0ef41Sopenharmony_ci std::atomic<int32_t> outstanding_finishers_{1}; 2451cb0ef41Sopenharmony_ci 2461cb0ef41Sopenharmony_ci // A reference to a pending foreground task, or {nullptr} if none is pending. 2471cb0ef41Sopenharmony_ci CompileTask* pending_foreground_task_ = nullptr; 2481cb0ef41Sopenharmony_ci 2491cb0ef41Sopenharmony_ci // The AsyncCompileJob owns the StreamingDecoder because the StreamingDecoder 2501cb0ef41Sopenharmony_ci // contains data which is needed by the AsyncCompileJob for streaming 2511cb0ef41Sopenharmony_ci // compilation. The AsyncCompileJob does not actively use the 2521cb0ef41Sopenharmony_ci // StreamingDecoder. 2531cb0ef41Sopenharmony_ci std::shared_ptr<StreamingDecoder> stream_; 2541cb0ef41Sopenharmony_ci 2551cb0ef41Sopenharmony_ci // The compilation id to identify trace events linked to this compilation. 2561cb0ef41Sopenharmony_ci const int compilation_id_; 2571cb0ef41Sopenharmony_ci}; 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci} // namespace wasm 2601cb0ef41Sopenharmony_ci} // namespace internal 2611cb0ef41Sopenharmony_ci} // namespace v8 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci#endif // V8_WASM_MODULE_COMPILER_H_ 264