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