text: // Copyright 2017 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.
  
  #ifndef V8_WASM_WASM_ENGINE_H_
  #define V8_WASM_WASM_ENGINE_H_
  
  #include <memory>
  
  #include "src/wasm/wasm-code-manager.h"
  #include "src/wasm/wasm-memory.h"
  #include "src/wasm/wasm-tier.h"
  #include "src/zone/accounting-allocator.h"
  
  namespace v8 {
  namespace internal {
  
  class CodeTracer;
  class CompilationStatistics;
  class WasmModuleObject;
  class WasmInstanceObject;
  
  namespace wasm {
  
  class ErrorThrower;
  struct WasmFeatures;
  struct ModuleWireBytes;
  
  class V8_EXPORT_PRIVATE CompilationResultResolver {
   public:
    virtual void OnCompilationSucceeded(Handle<WasmModuleObject> result) = 0;
    virtual void OnCompilationFailed(Handle<Object> error_reason) = 0;
    virtual ~CompilationResultResolver() {}
  };
  
  class V8_EXPORT_PRIVATE InstantiationResultResolver {
   public:
    virtual void OnInstantiationSucceeded(Handle<WasmInstanceObject> result) = 0;
    virtual void OnInstantiationFailed(Handle<Object> error_reason) = 0;
    virtual ~InstantiationResultResolver() {}
  };
  
  // The central data structure that represents an engine instance capable of
  // loading, instantiating, and executing WASM code.
  class V8_EXPORT_PRIVATE WasmEngine {
   public:
    WasmEngine();
    ~WasmEngine();
  
    // Synchronously validates the given bytes that represent an encoded WASM
    // module.
    bool SyncValidate(Isolate* isolate, const WasmFeatures& enabled,
                      const ModuleWireBytes& bytes);
  
    // Synchronously compiles the given bytes that represent a translated
    // asm.js module.
    MaybeHandle<WasmModuleObject> SyncCompileTranslatedAsmJs(
        Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
        Handle<Script> asm_js_script,
        Vector<const byte> asm_js_offset_table_bytes);
  
    // Synchronously compiles the given bytes that represent an encoded WASM
    // module.
    MaybeHandle<WasmModuleObject> SyncCompile(Isolate* isolate,
                                              const WasmFeatures& enabled,
                                              ErrorThrower* thrower,
                                              const ModuleWireBytes& bytes);
  
    // Synchronously instantiate the given WASM module with the given imports.
    // If the module represents an asm.js module, then the supplied {memory}
    // should be used as the memory of the instance.
    MaybeHandle<WasmInstanceObject> SyncInstantiate(
        Isolate* isolate, ErrorThrower* thrower,
        Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
        MaybeHandle<JSArrayBuffer> memory);
  
    // Begin an asynchronous compilation of the given bytes that represent an
    // encoded WASM module.
    // The {is_shared} flag indicates if the bytes backing the module could
    // be shared across threads, i.e. could be concurrently modified.
    void AsyncCompile(Isolate* isolate, const WasmFeatures& enabled,
                      std::shared_ptr<CompilationResultResolver> resolver,
                      const ModuleWireBytes& bytes, bool is_shared);
  
    // Begin an asynchronous instantiation of the given WASM module.
    void AsyncInstantiate(Isolate* isolate,
                          std::unique_ptr<InstantiationResultResolver> resolver,
                          Handle<WasmModuleObject> module_object,
                          MaybeHandle<JSReceiver> imports);
  
    std::shared_ptr<StreamingDecoder> StartStreamingCompilation(
        Isolate* isolate, const WasmFeatures& enabled, Handle<Context> context,
        std::shared_ptr<CompilationResultResolver> resolver);
  
    // Compiles the function with the given index at a specific compilation tier
    // and returns true on success, false (and pending exception) otherwise. This
    // is mostly used for testing to force a function into a specific tier.
    bool CompileFunction(Isolate* isolate, NativeModule* native_module,
                         uint32_t function_index, ExecutionTier tier);
  
    // Exports the sharable parts of the given module object so that they can be
    // transferred to a different Context/Isolate using the same engine.
    std::shared_ptr<NativeModule> ExportNativeModule(
        Handle<WasmModuleObject> module_object);
  
    // Imports the shared part of a module from a different Context/Isolate using
    // the the same engine, recreating a full module object in the given Isolate.
    Handle<WasmModuleObject> ImportNativeModule(
        Isolate* isolate, std::shared_ptr<NativeModule> shared_module);
  
    WasmCodeManager* code_manager() { return &code_manager_; }
  
    WasmMemoryTracker* memory_tracker() { return &memory_tracker_; }
  
    AccountingAllocator* allocator() { return &allocator_; }
  
    // Compilation statistics for TurboFan compilations.
    CompilationStatistics* GetOrCreateTurboStatistics();
  
    // Prints the gathered compilation statistics, then resets them.
    void DumpAndResetTurboStatistics();
  
    // Used to redirect tracing output from {stdout} to a file.
    CodeTracer* GetCodeTracer();
  
    // Remove {job} from the list of active compile jobs.
    std::unique_ptr<AsyncCompileJob> RemoveCompileJob(AsyncCompileJob* job);
  
    // Returns true if at least one AsyncCompileJob that belongs to the given
    // Isolate is currently running.
    bool HasRunningCompileJob(Isolate* isolate);
  
    // Deletes all AsyncCompileJobs that belong to the given Isolate. All
    // compilation is aborted, no more callbacks will be triggered. This is used
    // for tearing down an isolate, or to clean it up to be reused.
    void DeleteCompileJobsOnIsolate(Isolate* isolate);
  
    // Call on process start and exit.
    static void InitializeOncePerProcess();
    static void GlobalTearDown();
  
    // Constructs a WasmEngine instance. Depending on whether we are sharing
    // engines this might be a pointer to a new instance or to a shared one.
    static std::shared_ptr<WasmEngine> GetWasmEngine();
  
   private:
    AsyncCompileJob* CreateAsyncCompileJob(
        Isolate* isolate, const WasmFeatures& enabled,
        std::unique_ptr<byte[]> bytes_copy, size_t length,
        Handle<Context> context,
        std::shared_ptr<CompilationResultResolver> resolver);
  
    WasmMemoryTracker memory_tracker_;
    WasmCodeManager code_manager_;
    AccountingAllocator allocator_;
  
    // This mutex protects all information which is mutated concurrently or
    // fields that are initialized lazily on the first access.
    base::Mutex mutex_;
  
    //////////////////////////////////////////////////////////////////////////////
    // Protected by {mutex_}:
  
    // We use an AsyncCompileJob as the key for itself so that we can delete the
    // job from the map when it is finished.
    std::unordered_map<AsyncCompileJob*, std::unique_ptr<AsyncCompileJob>> jobs_;
  
    std::unique_ptr<CompilationStatistics> compilation_stats_;
    std::unique_ptr<CodeTracer> code_tracer_;
  
    // End of fields protected by {mutex_}.
    //////////////////////////////////////////////////////////////////////////////
  
    DISALLOW_COPY_AND_ASSIGN(WasmEngine);
  };
  
  }  // namespace wasm
  }  // namespace internal
  }  // namespace v8
  
  #endif  // V8_WASM_WASM_ENGINE_H_
  