11cb0ef41Sopenharmony_ci// Copyright 2018 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_COMPILATION_ENVIRONMENT_H_
101cb0ef41Sopenharmony_ci#define V8_WASM_COMPILATION_ENVIRONMENT_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include <memory>
131cb0ef41Sopenharmony_ci
141cb0ef41Sopenharmony_ci#include "src/wasm/wasm-features.h"
151cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h"
161cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
171cb0ef41Sopenharmony_ci#include "src/wasm/wasm-tier.h"
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_cinamespace v8 {
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciclass JobHandle;
221cb0ef41Sopenharmony_ci
231cb0ef41Sopenharmony_cinamespace internal {
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ciclass Counters;
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_cinamespace wasm {
281cb0ef41Sopenharmony_ci
291cb0ef41Sopenharmony_ciclass NativeModule;
301cb0ef41Sopenharmony_ciclass WasmCode;
311cb0ef41Sopenharmony_ciclass WasmEngine;
321cb0ef41Sopenharmony_ciclass WasmError;
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_cienum RuntimeExceptionSupport : bool {
351cb0ef41Sopenharmony_ci  kRuntimeExceptionSupport = true,
361cb0ef41Sopenharmony_ci  kNoRuntimeExceptionSupport = false
371cb0ef41Sopenharmony_ci};
381cb0ef41Sopenharmony_ci
391cb0ef41Sopenharmony_cienum BoundsCheckStrategy : int8_t {
401cb0ef41Sopenharmony_ci  // Emit protected instructions, use the trap handler for OOB detection.
411cb0ef41Sopenharmony_ci  kTrapHandler,
421cb0ef41Sopenharmony_ci  // Emit explicit bounds checks.
431cb0ef41Sopenharmony_ci  kExplicitBoundsChecks,
441cb0ef41Sopenharmony_ci  // Emit no bounds checks at all (for testing only).
451cb0ef41Sopenharmony_ci  kNoBoundsChecks
461cb0ef41Sopenharmony_ci};
471cb0ef41Sopenharmony_ci
481cb0ef41Sopenharmony_cienum class DynamicTiering { kEnabled, kDisabled };
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci// The {CompilationEnv} encapsulates the module data that is used during
511cb0ef41Sopenharmony_ci// compilation. CompilationEnvs are shareable across multiple compilations.
521cb0ef41Sopenharmony_cistruct CompilationEnv {
531cb0ef41Sopenharmony_ci  // A pointer to the decoded module's static representation.
541cb0ef41Sopenharmony_ci  const WasmModule* const module;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  // The bounds checking strategy to use.
571cb0ef41Sopenharmony_ci  const BoundsCheckStrategy bounds_checks;
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_ci  // If the runtime doesn't support exception propagation,
601cb0ef41Sopenharmony_ci  // we won't generate stack checks, and trap handling will also
611cb0ef41Sopenharmony_ci  // be generated differently.
621cb0ef41Sopenharmony_ci  const RuntimeExceptionSupport runtime_exception_support;
631cb0ef41Sopenharmony_ci
641cb0ef41Sopenharmony_ci  // The smallest size of any memory that could be used with this module, in
651cb0ef41Sopenharmony_ci  // bytes.
661cb0ef41Sopenharmony_ci  const uintptr_t min_memory_size;
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  // The largest size of any memory that could be used with this module, in
691cb0ef41Sopenharmony_ci  // bytes.
701cb0ef41Sopenharmony_ci  const uintptr_t max_memory_size;
711cb0ef41Sopenharmony_ci
721cb0ef41Sopenharmony_ci  // Features enabled for this compilation.
731cb0ef41Sopenharmony_ci  const WasmFeatures enabled_features;
741cb0ef41Sopenharmony_ci
751cb0ef41Sopenharmony_ci  const DynamicTiering dynamic_tiering;
761cb0ef41Sopenharmony_ci
771cb0ef41Sopenharmony_ci  constexpr CompilationEnv(const WasmModule* module,
781cb0ef41Sopenharmony_ci                           BoundsCheckStrategy bounds_checks,
791cb0ef41Sopenharmony_ci                           RuntimeExceptionSupport runtime_exception_support,
801cb0ef41Sopenharmony_ci                           const WasmFeatures& enabled_features,
811cb0ef41Sopenharmony_ci                           DynamicTiering dynamic_tiering)
821cb0ef41Sopenharmony_ci      : module(module),
831cb0ef41Sopenharmony_ci        bounds_checks(bounds_checks),
841cb0ef41Sopenharmony_ci        runtime_exception_support(runtime_exception_support),
851cb0ef41Sopenharmony_ci        // During execution, the memory can never be bigger than what fits in a
861cb0ef41Sopenharmony_ci        // uintptr_t.
871cb0ef41Sopenharmony_ci        min_memory_size(
881cb0ef41Sopenharmony_ci            std::min(kV8MaxWasmMemoryPages,
891cb0ef41Sopenharmony_ci                     uintptr_t{module ? module->initial_pages : 0}) *
901cb0ef41Sopenharmony_ci            kWasmPageSize),
911cb0ef41Sopenharmony_ci        max_memory_size((module && module->has_maximum_pages
921cb0ef41Sopenharmony_ci                             ? std::min(kV8MaxWasmMemoryPages,
931cb0ef41Sopenharmony_ci                                        uintptr_t{module->maximum_pages})
941cb0ef41Sopenharmony_ci                             : kV8MaxWasmMemoryPages) *
951cb0ef41Sopenharmony_ci                        kWasmPageSize),
961cb0ef41Sopenharmony_ci        enabled_features(enabled_features),
971cb0ef41Sopenharmony_ci        dynamic_tiering(dynamic_tiering) {}
981cb0ef41Sopenharmony_ci};
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci// The wire bytes are either owned by the StreamingDecoder, or (after streaming)
1011cb0ef41Sopenharmony_ci// by the NativeModule. This class abstracts over the storage location.
1021cb0ef41Sopenharmony_ciclass WireBytesStorage {
1031cb0ef41Sopenharmony_ci public:
1041cb0ef41Sopenharmony_ci  virtual ~WireBytesStorage() = default;
1051cb0ef41Sopenharmony_ci  virtual base::Vector<const uint8_t> GetCode(WireBytesRef) const = 0;
1061cb0ef41Sopenharmony_ci  // Returns the ModuleWireBytes corresponding to the underlying module if
1071cb0ef41Sopenharmony_ci  // available. Not supported if the wire bytes are owned by a StreamingDecoder.
1081cb0ef41Sopenharmony_ci  virtual base::Optional<ModuleWireBytes> GetModuleBytes() const = 0;
1091cb0ef41Sopenharmony_ci};
1101cb0ef41Sopenharmony_ci
1111cb0ef41Sopenharmony_ci// Callbacks will receive either {kFailedCompilation} or both
1121cb0ef41Sopenharmony_ci// {kFinishedBaselineCompilation} and {kFinishedTopTierCompilation}, in that
1131cb0ef41Sopenharmony_ci// order. If tier up is off, both events are delivered right after each other.
1141cb0ef41Sopenharmony_cienum class CompilationEvent : uint8_t {
1151cb0ef41Sopenharmony_ci  kFinishedBaselineCompilation,
1161cb0ef41Sopenharmony_ci  kFinishedExportWrappers,
1171cb0ef41Sopenharmony_ci  kFinishedCompilationChunk,
1181cb0ef41Sopenharmony_ci  kFinishedTopTierCompilation,
1191cb0ef41Sopenharmony_ci  kFailedCompilation,
1201cb0ef41Sopenharmony_ci  kFinishedRecompilation
1211cb0ef41Sopenharmony_ci};
1221cb0ef41Sopenharmony_ci
1231cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CompilationEventCallback {
1241cb0ef41Sopenharmony_ci public:
1251cb0ef41Sopenharmony_ci  virtual ~CompilationEventCallback() = default;
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  virtual void call(CompilationEvent event) = 0;
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci  enum class ReleaseAfterFinalEvent { kRelease, kKeep };
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ci  // Tells the module compiler whether to keep or to release a callback when the
1321cb0ef41Sopenharmony_ci  // compilation state finishes all compilation units. Most callbacks should be
1331cb0ef41Sopenharmony_ci  // released, that's why there is a default implementation, but the callback
1341cb0ef41Sopenharmony_ci  // for code caching with dynamic tiering has to stay alive.
1351cb0ef41Sopenharmony_ci  virtual ReleaseAfterFinalEvent release_after_final_event() {
1361cb0ef41Sopenharmony_ci    return ReleaseAfterFinalEvent::kRelease;
1371cb0ef41Sopenharmony_ci  }
1381cb0ef41Sopenharmony_ci};
1391cb0ef41Sopenharmony_ci
1401cb0ef41Sopenharmony_ci// The implementation of {CompilationState} lives in module-compiler.cc.
1411cb0ef41Sopenharmony_ci// This is the PIMPL interface to that private class.
1421cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE CompilationState {
1431cb0ef41Sopenharmony_ci public:
1441cb0ef41Sopenharmony_ci  ~CompilationState();
1451cb0ef41Sopenharmony_ci
1461cb0ef41Sopenharmony_ci  void InitCompileJob();
1471cb0ef41Sopenharmony_ci
1481cb0ef41Sopenharmony_ci  void CancelCompilation();
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  void CancelInitialCompilation();
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  void SetError();
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>);
1551cb0ef41Sopenharmony_ci
1561cb0ef41Sopenharmony_ci  std::shared_ptr<WireBytesStorage> GetWireBytesStorage() const;
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ci  void AddCallback(std::unique_ptr<CompilationEventCallback> callback);
1591cb0ef41Sopenharmony_ci
1601cb0ef41Sopenharmony_ci  void InitializeAfterDeserialization(
1611cb0ef41Sopenharmony_ci      base::Vector<const int> lazy_functions,
1621cb0ef41Sopenharmony_ci      base::Vector<const int> liftoff_functions);
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ci  // Wait until top tier compilation finished, or compilation failed.
1651cb0ef41Sopenharmony_ci  void WaitForTopTierFinished();
1661cb0ef41Sopenharmony_ci
1671cb0ef41Sopenharmony_ci  // Set a higher priority for the compilation job.
1681cb0ef41Sopenharmony_ci  void SetHighPriority();
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci  bool failed() const;
1711cb0ef41Sopenharmony_ci  bool baseline_compilation_finished() const;
1721cb0ef41Sopenharmony_ci  bool top_tier_compilation_finished() const;
1731cb0ef41Sopenharmony_ci  bool recompilation_finished() const;
1741cb0ef41Sopenharmony_ci
1751cb0ef41Sopenharmony_ci  void set_compilation_id(int compilation_id);
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  DynamicTiering dynamic_tiering() const;
1781cb0ef41Sopenharmony_ci
1791cb0ef41Sopenharmony_ci  // Override {operator delete} to avoid implicit instantiation of {operator
1801cb0ef41Sopenharmony_ci  // delete} with {size_t} argument. The {size_t} argument would be incorrect.
1811cb0ef41Sopenharmony_ci  void operator delete(void* ptr) { ::operator delete(ptr); }
1821cb0ef41Sopenharmony_ci
1831cb0ef41Sopenharmony_ci  CompilationState() = delete;
1841cb0ef41Sopenharmony_ci
1851cb0ef41Sopenharmony_ci private:
1861cb0ef41Sopenharmony_ci  // NativeModule is allowed to call the static {New} method.
1871cb0ef41Sopenharmony_ci  friend class NativeModule;
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  // The CompilationState keeps a {std::weak_ptr} back to the {NativeModule}
1901cb0ef41Sopenharmony_ci  // such that it can keep it alive (by regaining a {std::shared_ptr}) in
1911cb0ef41Sopenharmony_ci  // certain scopes.
1921cb0ef41Sopenharmony_ci  static std::unique_ptr<CompilationState> New(
1931cb0ef41Sopenharmony_ci      const std::shared_ptr<NativeModule>&, std::shared_ptr<Counters>,
1941cb0ef41Sopenharmony_ci      DynamicTiering dynamic_tiering);
1951cb0ef41Sopenharmony_ci};
1961cb0ef41Sopenharmony_ci
1971cb0ef41Sopenharmony_ci}  // namespace wasm
1981cb0ef41Sopenharmony_ci}  // namespace internal
1991cb0ef41Sopenharmony_ci}  // namespace v8
2001cb0ef41Sopenharmony_ci
2011cb0ef41Sopenharmony_ci#endif  // V8_WASM_COMPILATION_ENVIRONMENT_H_
202