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_WASM_ENGINE_H_ 101cb0ef41Sopenharmony_ci#define V8_WASM_WASM_ENGINE_H_ 111cb0ef41Sopenharmony_ci 121cb0ef41Sopenharmony_ci#include <algorithm> 131cb0ef41Sopenharmony_ci#include <map> 141cb0ef41Sopenharmony_ci#include <memory> 151cb0ef41Sopenharmony_ci#include <unordered_map> 161cb0ef41Sopenharmony_ci#include <unordered_set> 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ci#include "src/base/platform/condition-variable.h" 191cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h" 201cb0ef41Sopenharmony_ci#include "src/tasks/cancelable-task.h" 211cb0ef41Sopenharmony_ci#include "src/tasks/operations-barrier.h" 221cb0ef41Sopenharmony_ci#include "src/wasm/canonical-types.h" 231cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h" 241cb0ef41Sopenharmony_ci#include "src/wasm/wasm-tier.h" 251cb0ef41Sopenharmony_ci#include "src/zone/accounting-allocator.h" 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cinamespace v8 { 281cb0ef41Sopenharmony_cinamespace internal { 291cb0ef41Sopenharmony_ci 301cb0ef41Sopenharmony_ciclass AsmWasmData; 311cb0ef41Sopenharmony_ciclass CodeTracer; 321cb0ef41Sopenharmony_ciclass CompilationStatistics; 331cb0ef41Sopenharmony_ciclass HeapNumber; 341cb0ef41Sopenharmony_ciclass WasmInstanceObject; 351cb0ef41Sopenharmony_ciclass WasmModuleObject; 361cb0ef41Sopenharmony_ciclass JSArrayBuffer; 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cinamespace wasm { 391cb0ef41Sopenharmony_ci 401cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING 411cb0ef41Sopenharmony_cinamespace gdb_server { 421cb0ef41Sopenharmony_ciclass GdbServer; 431cb0ef41Sopenharmony_ci} // namespace gdb_server 441cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_ciclass AsyncCompileJob; 471cb0ef41Sopenharmony_ciclass ErrorThrower; 481cb0ef41Sopenharmony_cistruct ModuleWireBytes; 491cb0ef41Sopenharmony_ciclass StreamingDecoder; 501cb0ef41Sopenharmony_ciclass WasmFeatures; 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CompilationResultResolver { 531cb0ef41Sopenharmony_ci public: 541cb0ef41Sopenharmony_ci virtual void OnCompilationSucceeded(Handle<WasmModuleObject> result) = 0; 551cb0ef41Sopenharmony_ci virtual void OnCompilationFailed(Handle<Object> error_reason) = 0; 561cb0ef41Sopenharmony_ci virtual ~CompilationResultResolver() = default; 571cb0ef41Sopenharmony_ci}; 581cb0ef41Sopenharmony_ci 591cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE InstantiationResultResolver { 601cb0ef41Sopenharmony_ci public: 611cb0ef41Sopenharmony_ci virtual void OnInstantiationSucceeded(Handle<WasmInstanceObject> result) = 0; 621cb0ef41Sopenharmony_ci virtual void OnInstantiationFailed(Handle<Object> error_reason) = 0; 631cb0ef41Sopenharmony_ci virtual ~InstantiationResultResolver() = default; 641cb0ef41Sopenharmony_ci}; 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ci// Native modules cached by their wire bytes. 671cb0ef41Sopenharmony_ciclass NativeModuleCache { 681cb0ef41Sopenharmony_ci public: 691cb0ef41Sopenharmony_ci struct Key { 701cb0ef41Sopenharmony_ci // Store the prefix hash as part of the key for faster lookup, and to 711cb0ef41Sopenharmony_ci // quickly check existing prefixes for streaming compilation. 721cb0ef41Sopenharmony_ci size_t prefix_hash; 731cb0ef41Sopenharmony_ci base::Vector<const uint8_t> bytes; 741cb0ef41Sopenharmony_ci 751cb0ef41Sopenharmony_ci bool operator==(const Key& other) const { 761cb0ef41Sopenharmony_ci bool eq = bytes == other.bytes; 771cb0ef41Sopenharmony_ci DCHECK_IMPLIES(eq, prefix_hash == other.prefix_hash); 781cb0ef41Sopenharmony_ci return eq; 791cb0ef41Sopenharmony_ci } 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci bool operator<(const Key& other) const { 821cb0ef41Sopenharmony_ci if (prefix_hash != other.prefix_hash) { 831cb0ef41Sopenharmony_ci DCHECK_IMPLIES(!bytes.empty() && !other.bytes.empty(), 841cb0ef41Sopenharmony_ci bytes != other.bytes); 851cb0ef41Sopenharmony_ci return prefix_hash < other.prefix_hash; 861cb0ef41Sopenharmony_ci } 871cb0ef41Sopenharmony_ci if (bytes.size() != other.bytes.size()) { 881cb0ef41Sopenharmony_ci return bytes.size() < other.bytes.size(); 891cb0ef41Sopenharmony_ci } 901cb0ef41Sopenharmony_ci // Fast path when the base pointers are the same. 911cb0ef41Sopenharmony_ci // Also handles the {nullptr} case which would be UB for memcmp. 921cb0ef41Sopenharmony_ci if (bytes.begin() == other.bytes.begin()) { 931cb0ef41Sopenharmony_ci DCHECK_EQ(prefix_hash, other.prefix_hash); 941cb0ef41Sopenharmony_ci return false; 951cb0ef41Sopenharmony_ci } 961cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(bytes.begin()); 971cb0ef41Sopenharmony_ci DCHECK_NOT_NULL(other.bytes.begin()); 981cb0ef41Sopenharmony_ci return memcmp(bytes.begin(), other.bytes.begin(), bytes.size()) < 0; 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci }; 1011cb0ef41Sopenharmony_ci 1021cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> MaybeGetNativeModule( 1031cb0ef41Sopenharmony_ci ModuleOrigin origin, base::Vector<const uint8_t> wire_bytes); 1041cb0ef41Sopenharmony_ci bool GetStreamingCompilationOwnership(size_t prefix_hash); 1051cb0ef41Sopenharmony_ci void StreamingCompilationFailed(size_t prefix_hash); 1061cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> Update( 1071cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> native_module, bool error); 1081cb0ef41Sopenharmony_ci void Erase(NativeModule* native_module); 1091cb0ef41Sopenharmony_ci 1101cb0ef41Sopenharmony_ci bool empty() { return map_.empty(); } 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci static size_t WireBytesHash(base::Vector<const uint8_t> bytes); 1131cb0ef41Sopenharmony_ci 1141cb0ef41Sopenharmony_ci // Hash the wire bytes up to the code section header. Used as a heuristic to 1151cb0ef41Sopenharmony_ci // avoid streaming compilation of modules that are likely already in the 1161cb0ef41Sopenharmony_ci // cache. See {GetStreamingCompilationOwnership}. Assumes that the bytes have 1171cb0ef41Sopenharmony_ci // already been validated. 1181cb0ef41Sopenharmony_ci static size_t PrefixHash(base::Vector<const uint8_t> wire_bytes); 1191cb0ef41Sopenharmony_ci 1201cb0ef41Sopenharmony_ci private: 1211cb0ef41Sopenharmony_ci // Each key points to the corresponding native module's wire bytes, so they 1221cb0ef41Sopenharmony_ci // should always be valid as long as the native module is alive. When 1231cb0ef41Sopenharmony_ci // the native module dies, {FreeNativeModule} deletes the entry from the 1241cb0ef41Sopenharmony_ci // map, so that we do not leave any dangling key pointing to an expired 1251cb0ef41Sopenharmony_ci // weak_ptr. This also serves as a way to regularly clean up the map, which 1261cb0ef41Sopenharmony_ci // would otherwise accumulate expired entries. 1271cb0ef41Sopenharmony_ci // A {nullopt} value is inserted to indicate that this native module is 1281cb0ef41Sopenharmony_ci // currently being created in some thread, and that other threads should wait 1291cb0ef41Sopenharmony_ci // before trying to get it from the cache. 1301cb0ef41Sopenharmony_ci // By contrast, an expired {weak_ptr} indicates that the native module died 1311cb0ef41Sopenharmony_ci // and will soon be cleaned up from the cache. 1321cb0ef41Sopenharmony_ci std::map<Key, base::Optional<std::weak_ptr<NativeModule>>> map_; 1331cb0ef41Sopenharmony_ci 1341cb0ef41Sopenharmony_ci base::Mutex mutex_; 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_ci // This condition variable is used to synchronize threads compiling the same 1371cb0ef41Sopenharmony_ci // module. Only one thread will create the {NativeModule}. Other threads 1381cb0ef41Sopenharmony_ci // will wait on this variable until the first thread wakes them up. 1391cb0ef41Sopenharmony_ci base::ConditionVariable cache_cv_; 1401cb0ef41Sopenharmony_ci}; 1411cb0ef41Sopenharmony_ci 1421cb0ef41Sopenharmony_ci// The central data structure that represents an engine instance capable of 1431cb0ef41Sopenharmony_ci// loading, instantiating, and executing Wasm code. 1441cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE WasmEngine { 1451cb0ef41Sopenharmony_ci public: 1461cb0ef41Sopenharmony_ci WasmEngine(); 1471cb0ef41Sopenharmony_ci WasmEngine(const WasmEngine&) = delete; 1481cb0ef41Sopenharmony_ci WasmEngine& operator=(const WasmEngine&) = delete; 1491cb0ef41Sopenharmony_ci ~WasmEngine(); 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_ci // Synchronously validates the given bytes that represent an encoded Wasm 1521cb0ef41Sopenharmony_ci // module. If validation fails and {error_msg} is present, it is set to the 1531cb0ef41Sopenharmony_ci // validation error. 1541cb0ef41Sopenharmony_ci bool SyncValidate(Isolate* isolate, const WasmFeatures& enabled, 1551cb0ef41Sopenharmony_ci const ModuleWireBytes& bytes, 1561cb0ef41Sopenharmony_ci std::string* error_message = nullptr); 1571cb0ef41Sopenharmony_ci 1581cb0ef41Sopenharmony_ci // Synchronously compiles the given bytes that represent a translated 1591cb0ef41Sopenharmony_ci // asm.js module. 1601cb0ef41Sopenharmony_ci MaybeHandle<AsmWasmData> SyncCompileTranslatedAsmJs( 1611cb0ef41Sopenharmony_ci Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes, 1621cb0ef41Sopenharmony_ci base::Vector<const byte> asm_js_offset_table_bytes, 1631cb0ef41Sopenharmony_ci Handle<HeapNumber> uses_bitset, LanguageMode language_mode); 1641cb0ef41Sopenharmony_ci Handle<WasmModuleObject> FinalizeTranslatedAsmJs( 1651cb0ef41Sopenharmony_ci Isolate* isolate, Handle<AsmWasmData> asm_wasm_data, 1661cb0ef41Sopenharmony_ci Handle<Script> script); 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ci // Synchronously compiles the given bytes that represent an encoded Wasm 1691cb0ef41Sopenharmony_ci // module. 1701cb0ef41Sopenharmony_ci MaybeHandle<WasmModuleObject> SyncCompile(Isolate* isolate, 1711cb0ef41Sopenharmony_ci const WasmFeatures& enabled, 1721cb0ef41Sopenharmony_ci ErrorThrower* thrower, 1731cb0ef41Sopenharmony_ci const ModuleWireBytes& bytes); 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_ci // Synchronously instantiate the given Wasm module with the given imports. 1761cb0ef41Sopenharmony_ci // If the module represents an asm.js module, then the supplied {memory} 1771cb0ef41Sopenharmony_ci // should be used as the memory of the instance. 1781cb0ef41Sopenharmony_ci MaybeHandle<WasmInstanceObject> SyncInstantiate( 1791cb0ef41Sopenharmony_ci Isolate* isolate, ErrorThrower* thrower, 1801cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports, 1811cb0ef41Sopenharmony_ci MaybeHandle<JSArrayBuffer> memory); 1821cb0ef41Sopenharmony_ci 1831cb0ef41Sopenharmony_ci // Begin an asynchronous compilation of the given bytes that represent an 1841cb0ef41Sopenharmony_ci // encoded Wasm module. 1851cb0ef41Sopenharmony_ci // The {is_shared} flag indicates if the bytes backing the module could 1861cb0ef41Sopenharmony_ci // be shared across threads, i.e. could be concurrently modified. 1871cb0ef41Sopenharmony_ci void AsyncCompile(Isolate* isolate, const WasmFeatures& enabled, 1881cb0ef41Sopenharmony_ci std::shared_ptr<CompilationResultResolver> resolver, 1891cb0ef41Sopenharmony_ci const ModuleWireBytes& bytes, bool is_shared, 1901cb0ef41Sopenharmony_ci const char* api_method_name_for_errors); 1911cb0ef41Sopenharmony_ci 1921cb0ef41Sopenharmony_ci // Begin an asynchronous instantiation of the given Wasm module. 1931cb0ef41Sopenharmony_ci void AsyncInstantiate(Isolate* isolate, 1941cb0ef41Sopenharmony_ci std::unique_ptr<InstantiationResultResolver> resolver, 1951cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object, 1961cb0ef41Sopenharmony_ci MaybeHandle<JSReceiver> imports); 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ci std::shared_ptr<StreamingDecoder> StartStreamingCompilation( 1991cb0ef41Sopenharmony_ci Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context, 2001cb0ef41Sopenharmony_ci const char* api_method_name, 2011cb0ef41Sopenharmony_ci std::shared_ptr<CompilationResultResolver> resolver); 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci // Compiles the function with the given index at a specific compilation tier. 2041cb0ef41Sopenharmony_ci // Errors are stored internally in the CompilationState. 2051cb0ef41Sopenharmony_ci // This is mostly used for testing to force a function into a specific tier. 2061cb0ef41Sopenharmony_ci void CompileFunction(Isolate* isolate, NativeModule* native_module, 2071cb0ef41Sopenharmony_ci uint32_t function_index, ExecutionTier tier); 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ci void TierDownAllModulesPerIsolate(Isolate* isolate); 2101cb0ef41Sopenharmony_ci void TierUpAllModulesPerIsolate(Isolate* isolate); 2111cb0ef41Sopenharmony_ci 2121cb0ef41Sopenharmony_ci // Exports the sharable parts of the given module object so that they can be 2131cb0ef41Sopenharmony_ci // transferred to a different Context/Isolate using the same engine. 2141cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> ExportNativeModule( 2151cb0ef41Sopenharmony_ci Handle<WasmModuleObject> module_object); 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci // Imports the shared part of a module from a different Context/Isolate using 2181cb0ef41Sopenharmony_ci // the the same engine, recreating a full module object in the given Isolate. 2191cb0ef41Sopenharmony_ci Handle<WasmModuleObject> ImportNativeModule( 2201cb0ef41Sopenharmony_ci Isolate* isolate, std::shared_ptr<NativeModule> shared_module, 2211cb0ef41Sopenharmony_ci base::Vector<const char> source_url); 2221cb0ef41Sopenharmony_ci 2231cb0ef41Sopenharmony_ci AccountingAllocator* allocator() { return &allocator_; } 2241cb0ef41Sopenharmony_ci 2251cb0ef41Sopenharmony_ci // Compilation statistics for TurboFan compilations. 2261cb0ef41Sopenharmony_ci CompilationStatistics* GetOrCreateTurboStatistics(); 2271cb0ef41Sopenharmony_ci 2281cb0ef41Sopenharmony_ci // Prints the gathered compilation statistics, then resets them. 2291cb0ef41Sopenharmony_ci void DumpAndResetTurboStatistics(); 2301cb0ef41Sopenharmony_ci // Same, but no reset. 2311cb0ef41Sopenharmony_ci void DumpTurboStatistics(); 2321cb0ef41Sopenharmony_ci 2331cb0ef41Sopenharmony_ci // Used to redirect tracing output from {stdout} to a file. 2341cb0ef41Sopenharmony_ci CodeTracer* GetCodeTracer(); 2351cb0ef41Sopenharmony_ci 2361cb0ef41Sopenharmony_ci // Remove {job} from the list of active compile jobs. 2371cb0ef41Sopenharmony_ci std::unique_ptr<AsyncCompileJob> RemoveCompileJob(AsyncCompileJob* job); 2381cb0ef41Sopenharmony_ci 2391cb0ef41Sopenharmony_ci // Returns true if at least one AsyncCompileJob that belongs to the given 2401cb0ef41Sopenharmony_ci // Isolate is currently running. 2411cb0ef41Sopenharmony_ci bool HasRunningCompileJob(Isolate* isolate); 2421cb0ef41Sopenharmony_ci 2431cb0ef41Sopenharmony_ci // Deletes all AsyncCompileJobs that belong to the given context. All 2441cb0ef41Sopenharmony_ci // compilation is aborted, no more callbacks will be triggered. This is used 2451cb0ef41Sopenharmony_ci // when a context is disposed, e.g. because of browser navigation. 2461cb0ef41Sopenharmony_ci void DeleteCompileJobsOnContext(Handle<Context> context); 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ci // Deletes all AsyncCompileJobs that belong to the given Isolate. All 2491cb0ef41Sopenharmony_ci // compilation is aborted, no more callbacks will be triggered. This is used 2501cb0ef41Sopenharmony_ci // for tearing down an isolate, or to clean it up to be reused. 2511cb0ef41Sopenharmony_ci void DeleteCompileJobsOnIsolate(Isolate* isolate); 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci // Get a token for compiling wrappers for an Isolate. The token is used to 2541cb0ef41Sopenharmony_ci // synchronize background tasks on isolate shutdown. The caller should only 2551cb0ef41Sopenharmony_ci // hold the token while compiling export wrappers. If the isolate is already 2561cb0ef41Sopenharmony_ci // shutting down, this method will return an invalid token. 2571cb0ef41Sopenharmony_ci OperationsBarrier::Token StartWrapperCompilation(Isolate*); 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci // Manage the set of Isolates that use this WasmEngine. 2601cb0ef41Sopenharmony_ci void AddIsolate(Isolate* isolate); 2611cb0ef41Sopenharmony_ci void RemoveIsolate(Isolate* isolate); 2621cb0ef41Sopenharmony_ci 2631cb0ef41Sopenharmony_ci // Trigger code logging for the given code objects in all Isolates which have 2641cb0ef41Sopenharmony_ci // access to the NativeModule containing this code. This method can be called 2651cb0ef41Sopenharmony_ci // from background threads. 2661cb0ef41Sopenharmony_ci void LogCode(base::Vector<WasmCode*>); 2671cb0ef41Sopenharmony_ci 2681cb0ef41Sopenharmony_ci // Enable code logging for the given Isolate. Initially, code logging is 2691cb0ef41Sopenharmony_ci // enabled if {WasmCode::ShouldBeLogged(Isolate*)} returns true during 2701cb0ef41Sopenharmony_ci // {AddIsolate}. 2711cb0ef41Sopenharmony_ci void EnableCodeLogging(Isolate*); 2721cb0ef41Sopenharmony_ci 2731cb0ef41Sopenharmony_ci // This is called from the foreground thread of the Isolate to log all 2741cb0ef41Sopenharmony_ci // outstanding code objects (added via {LogCode}). 2751cb0ef41Sopenharmony_ci void LogOutstandingCodesForIsolate(Isolate*); 2761cb0ef41Sopenharmony_ci 2771cb0ef41Sopenharmony_ci // Create a new NativeModule. The caller is responsible for its 2781cb0ef41Sopenharmony_ci // lifetime. The native module will be given some memory for code, 2791cb0ef41Sopenharmony_ci // which will be page size aligned. The size of the initial memory 2801cb0ef41Sopenharmony_ci // is determined by {code_size_estimate}. The native module may later request 2811cb0ef41Sopenharmony_ci // more memory. 2821cb0ef41Sopenharmony_ci // TODO(wasm): isolate is only required here for CompilationState. 2831cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> NewNativeModule( 2841cb0ef41Sopenharmony_ci Isolate* isolate, const WasmFeatures& enabled_features, 2851cb0ef41Sopenharmony_ci std::shared_ptr<const WasmModule> module, size_t code_size_estimate); 2861cb0ef41Sopenharmony_ci 2871cb0ef41Sopenharmony_ci // Try getting a cached {NativeModule}, or get ownership for its creation. 2881cb0ef41Sopenharmony_ci // Return {nullptr} if no {NativeModule} exists for these bytes. In this case, 2891cb0ef41Sopenharmony_ci // a {nullopt} entry is added to let other threads know that a {NativeModule} 2901cb0ef41Sopenharmony_ci // for these bytes is currently being created. The caller should eventually 2911cb0ef41Sopenharmony_ci // call {UpdateNativeModuleCache} to update the entry and wake up other 2921cb0ef41Sopenharmony_ci // threads. The {wire_bytes}' underlying array should be valid at least until 2931cb0ef41Sopenharmony_ci // the call to {UpdateNativeModuleCache}. 2941cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule> MaybeGetNativeModule( 2951cb0ef41Sopenharmony_ci ModuleOrigin origin, base::Vector<const uint8_t> wire_bytes, 2961cb0ef41Sopenharmony_ci Isolate* isolate); 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci // Replace the temporary {nullopt} with the new native module, or 2991cb0ef41Sopenharmony_ci // erase it if any error occurred. Wake up blocked threads waiting for this 3001cb0ef41Sopenharmony_ci // module. 3011cb0ef41Sopenharmony_ci // To avoid a deadlock on the main thread between synchronous and streaming 3021cb0ef41Sopenharmony_ci // compilation, two compilation jobs might compile the same native module at 3031cb0ef41Sopenharmony_ci // the same time. In this case the first call to {UpdateNativeModuleCache} 3041cb0ef41Sopenharmony_ci // will insert the native module in the cache, and the last call will discard 3051cb0ef41Sopenharmony_ci // its {native_module} argument and replace it with the existing entry. 3061cb0ef41Sopenharmony_ci // Return true in the former case, and false in the latter. 3071cb0ef41Sopenharmony_ci bool UpdateNativeModuleCache(bool error, 3081cb0ef41Sopenharmony_ci std::shared_ptr<NativeModule>* native_module, 3091cb0ef41Sopenharmony_ci Isolate* isolate); 3101cb0ef41Sopenharmony_ci 3111cb0ef41Sopenharmony_ci // Register this prefix hash for a streaming compilation job. 3121cb0ef41Sopenharmony_ci // If the hash is not in the cache yet, the function returns true and the 3131cb0ef41Sopenharmony_ci // caller owns the compilation of this module. 3141cb0ef41Sopenharmony_ci // Otherwise another compilation job is currently preparing or has already 3151cb0ef41Sopenharmony_ci // prepared a module with the same prefix hash. The caller should wait until 3161cb0ef41Sopenharmony_ci // the stream is finished and call {MaybeGetNativeModule} to either get the 3171cb0ef41Sopenharmony_ci // module from the cache or get ownership for the compilation of these bytes. 3181cb0ef41Sopenharmony_ci bool GetStreamingCompilationOwnership(size_t prefix_hash); 3191cb0ef41Sopenharmony_ci 3201cb0ef41Sopenharmony_ci // Remove the prefix hash from the cache when compilation failed. If 3211cb0ef41Sopenharmony_ci // compilation succeeded, {UpdateNativeModuleCache} should be called instead. 3221cb0ef41Sopenharmony_ci void StreamingCompilationFailed(size_t prefix_hash); 3231cb0ef41Sopenharmony_ci 3241cb0ef41Sopenharmony_ci void FreeNativeModule(NativeModule*); 3251cb0ef41Sopenharmony_ci 3261cb0ef41Sopenharmony_ci // Sample the code size of the given {NativeModule} in all isolates that have 3271cb0ef41Sopenharmony_ci // access to it. Call this after top-tier compilation finished. 3281cb0ef41Sopenharmony_ci // This will spawn foreground tasks that do *not* keep the NativeModule alive. 3291cb0ef41Sopenharmony_ci void SampleTopTierCodeSizeInAllIsolates(const std::shared_ptr<NativeModule>&); 3301cb0ef41Sopenharmony_ci 3311cb0ef41Sopenharmony_ci // Called by each Isolate to report its live code for a GC cycle. First 3321cb0ef41Sopenharmony_ci // version reports an externally determined set of live code (might be empty), 3331cb0ef41Sopenharmony_ci // second version gets live code from the execution stack of that isolate. 3341cb0ef41Sopenharmony_ci void ReportLiveCodeForGC(Isolate*, base::Vector<WasmCode*>); 3351cb0ef41Sopenharmony_ci void ReportLiveCodeFromStackForGC(Isolate*); 3361cb0ef41Sopenharmony_ci 3371cb0ef41Sopenharmony_ci // Add potentially dead code. The occurrence in the set of potentially dead 3381cb0ef41Sopenharmony_ci // code counts as a reference, and is decremented on the next GC. 3391cb0ef41Sopenharmony_ci // Returns {true} if the code was added to the set of potentially dead code, 3401cb0ef41Sopenharmony_ci // {false} if an entry already exists. The ref count is *unchanged* in any 3411cb0ef41Sopenharmony_ci // case. 3421cb0ef41Sopenharmony_ci V8_WARN_UNUSED_RESULT bool AddPotentiallyDeadCode(WasmCode*); 3431cb0ef41Sopenharmony_ci 3441cb0ef41Sopenharmony_ci // Free dead code. 3451cb0ef41Sopenharmony_ci using DeadCodeMap = std::unordered_map<NativeModule*, std::vector<WasmCode*>>; 3461cb0ef41Sopenharmony_ci void FreeDeadCode(const DeadCodeMap&); 3471cb0ef41Sopenharmony_ci void FreeDeadCodeLocked(const DeadCodeMap&); 3481cb0ef41Sopenharmony_ci 3491cb0ef41Sopenharmony_ci Handle<Script> GetOrCreateScript(Isolate*, 3501cb0ef41Sopenharmony_ci const std::shared_ptr<NativeModule>&, 3511cb0ef41Sopenharmony_ci base::Vector<const char> source_url); 3521cb0ef41Sopenharmony_ci 3531cb0ef41Sopenharmony_ci // Returns a barrier allowing background compile operations if valid and 3541cb0ef41Sopenharmony_ci // preventing this object from being destroyed. 3551cb0ef41Sopenharmony_ci std::shared_ptr<OperationsBarrier> GetBarrierForBackgroundCompile(); 3561cb0ef41Sopenharmony_ci 3571cb0ef41Sopenharmony_ci void SampleThrowEvent(Isolate*); 3581cb0ef41Sopenharmony_ci void SampleRethrowEvent(Isolate*); 3591cb0ef41Sopenharmony_ci void SampleCatchEvent(Isolate*); 3601cb0ef41Sopenharmony_ci 3611cb0ef41Sopenharmony_ci TypeCanonicalizer* type_canonicalizer() { return &type_canonicalizer_; } 3621cb0ef41Sopenharmony_ci 3631cb0ef41Sopenharmony_ci // Call on process start and exit. 3641cb0ef41Sopenharmony_ci static void InitializeOncePerProcess(); 3651cb0ef41Sopenharmony_ci static void GlobalTearDown(); 3661cb0ef41Sopenharmony_ci 3671cb0ef41Sopenharmony_ci private: 3681cb0ef41Sopenharmony_ci struct CurrentGCInfo; 3691cb0ef41Sopenharmony_ci struct IsolateInfo; 3701cb0ef41Sopenharmony_ci struct NativeModuleInfo; 3711cb0ef41Sopenharmony_ci 3721cb0ef41Sopenharmony_ci AsyncCompileJob* CreateAsyncCompileJob( 3731cb0ef41Sopenharmony_ci Isolate* isolate, const WasmFeatures& enabled, 3741cb0ef41Sopenharmony_ci std::unique_ptr<byte[]> bytes_copy, size_t length, 3751cb0ef41Sopenharmony_ci Handle<Context> context, const char* api_method_name, 3761cb0ef41Sopenharmony_ci std::shared_ptr<CompilationResultResolver> resolver, int compilation_id); 3771cb0ef41Sopenharmony_ci 3781cb0ef41Sopenharmony_ci void TriggerGC(int8_t gc_sequence_index); 3791cb0ef41Sopenharmony_ci 3801cb0ef41Sopenharmony_ci // Remove an isolate from the outstanding isolates of the current GC. Returns 3811cb0ef41Sopenharmony_ci // true if the isolate was still outstanding, false otherwise. Hold {mutex_} 3821cb0ef41Sopenharmony_ci // when calling this method. 3831cb0ef41Sopenharmony_ci bool RemoveIsolateFromCurrentGC(Isolate*); 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci // Finish a GC if there are no more outstanding isolates. Hold {mutex_} when 3861cb0ef41Sopenharmony_ci // calling this method. 3871cb0ef41Sopenharmony_ci void PotentiallyFinishCurrentGC(); 3881cb0ef41Sopenharmony_ci 3891cb0ef41Sopenharmony_ci AccountingAllocator allocator_; 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci#ifdef V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING 3921cb0ef41Sopenharmony_ci // Implements a GDB-remote stub for WebAssembly debugging. 3931cb0ef41Sopenharmony_ci std::unique_ptr<gdb_server::GdbServer> gdb_server_; 3941cb0ef41Sopenharmony_ci#endif // V8_ENABLE_WASM_GDB_REMOTE_DEBUGGING 3951cb0ef41Sopenharmony_ci 3961cb0ef41Sopenharmony_ci std::atomic<int> next_compilation_id_{0}; 3971cb0ef41Sopenharmony_ci 3981cb0ef41Sopenharmony_ci TypeCanonicalizer type_canonicalizer_; 3991cb0ef41Sopenharmony_ci 4001cb0ef41Sopenharmony_ci // This mutex protects all information which is mutated concurrently or 4011cb0ef41Sopenharmony_ci // fields that are initialized lazily on the first access. 4021cb0ef41Sopenharmony_ci base::Mutex mutex_; 4031cb0ef41Sopenharmony_ci 4041cb0ef41Sopenharmony_ci ////////////////////////////////////////////////////////////////////////////// 4051cb0ef41Sopenharmony_ci // Protected by {mutex_}: 4061cb0ef41Sopenharmony_ci 4071cb0ef41Sopenharmony_ci // We use an AsyncCompileJob as the key for itself so that we can delete the 4081cb0ef41Sopenharmony_ci // job from the map when it is finished. 4091cb0ef41Sopenharmony_ci std::unordered_map<AsyncCompileJob*, std::unique_ptr<AsyncCompileJob>> 4101cb0ef41Sopenharmony_ci async_compile_jobs_; 4111cb0ef41Sopenharmony_ci 4121cb0ef41Sopenharmony_ci std::unique_ptr<CompilationStatistics> compilation_stats_; 4131cb0ef41Sopenharmony_ci std::unique_ptr<CodeTracer> code_tracer_; 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci // Set of isolates which use this WasmEngine. 4161cb0ef41Sopenharmony_ci std::unordered_map<Isolate*, std::unique_ptr<IsolateInfo>> isolates_; 4171cb0ef41Sopenharmony_ci 4181cb0ef41Sopenharmony_ci // Set of native modules managed by this engine. 4191cb0ef41Sopenharmony_ci std::unordered_map<NativeModule*, std::unique_ptr<NativeModuleInfo>> 4201cb0ef41Sopenharmony_ci native_modules_; 4211cb0ef41Sopenharmony_ci 4221cb0ef41Sopenharmony_ci std::shared_ptr<OperationsBarrier> operations_barrier_{ 4231cb0ef41Sopenharmony_ci std::make_shared<OperationsBarrier>()}; 4241cb0ef41Sopenharmony_ci 4251cb0ef41Sopenharmony_ci // Size of code that became dead since the last GC. If this exceeds a certain 4261cb0ef41Sopenharmony_ci // threshold, a new GC is triggered. 4271cb0ef41Sopenharmony_ci size_t new_potentially_dead_code_size_ = 0; 4281cb0ef41Sopenharmony_ci 4291cb0ef41Sopenharmony_ci // If an engine-wide GC is currently running, this pointer stores information 4301cb0ef41Sopenharmony_ci // about that. 4311cb0ef41Sopenharmony_ci std::unique_ptr<CurrentGCInfo> current_gc_info_; 4321cb0ef41Sopenharmony_ci 4331cb0ef41Sopenharmony_ci NativeModuleCache native_module_cache_; 4341cb0ef41Sopenharmony_ci 4351cb0ef41Sopenharmony_ci // End of fields protected by {mutex_}. 4361cb0ef41Sopenharmony_ci ////////////////////////////////////////////////////////////////////////////// 4371cb0ef41Sopenharmony_ci}; 4381cb0ef41Sopenharmony_ci 4391cb0ef41Sopenharmony_ci// Returns a reference to the WasmEngine shared by the entire process. 4401cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE WasmEngine* GetWasmEngine(); 4411cb0ef41Sopenharmony_ci 4421cb0ef41Sopenharmony_ci// Returns a reference to the WasmCodeManager shared by the entire process. 4431cb0ef41Sopenharmony_ciV8_EXPORT_PRIVATE WasmCodeManager* GetWasmCodeManager(); 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci} // namespace wasm 4461cb0ef41Sopenharmony_ci} // namespace internal 4471cb0ef41Sopenharmony_ci} // namespace v8 4481cb0ef41Sopenharmony_ci 4491cb0ef41Sopenharmony_ci#endif // V8_WASM_WASM_ENGINE_H_ 450