• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #if !V8_ENABLE_WEBASSEMBLY
6 #error This header should only be included if WebAssembly is enabled.
7 #endif  // !V8_ENABLE_WEBASSEMBLY
8 
9 #ifndef V8_WASM_COMPILATION_ENVIRONMENT_H_
10 #define V8_WASM_COMPILATION_ENVIRONMENT_H_
11 
12 #include <memory>
13 
14 #include "src/wasm/wasm-features.h"
15 #include "src/wasm/wasm-limits.h"
16 #include "src/wasm/wasm-module.h"
17 #include "src/wasm/wasm-tier.h"
18 
19 namespace v8 {
20 
21 class JobHandle;
22 
23 namespace internal {
24 
25 class Counters;
26 
27 namespace wasm {
28 
29 class NativeModule;
30 class WasmCode;
31 class WasmEngine;
32 class WasmError;
33 
34 enum RuntimeExceptionSupport : bool {
35   kRuntimeExceptionSupport = true,
36   kNoRuntimeExceptionSupport = false
37 };
38 
39 enum BoundsCheckStrategy : int8_t {
40   // Emit protected instructions, use the trap handler for OOB detection.
41   kTrapHandler,
42   // Emit explicit bounds checks.
43   kExplicitBoundsChecks,
44   // Emit no bounds checks at all (for testing only).
45   kNoBoundsChecks
46 };
47 
48 enum class DynamicTiering { kEnabled, kDisabled };
49 
50 // The {CompilationEnv} encapsulates the module data that is used during
51 // compilation. CompilationEnvs are shareable across multiple compilations.
52 struct CompilationEnv {
53   // A pointer to the decoded module's static representation.
54   const WasmModule* const module;
55 
56   // The bounds checking strategy to use.
57   const BoundsCheckStrategy bounds_checks;
58 
59   // If the runtime doesn't support exception propagation,
60   // we won't generate stack checks, and trap handling will also
61   // be generated differently.
62   const RuntimeExceptionSupport runtime_exception_support;
63 
64   // The smallest size of any memory that could be used with this module, in
65   // bytes.
66   const uintptr_t min_memory_size;
67 
68   // The largest size of any memory that could be used with this module, in
69   // bytes.
70   const uintptr_t max_memory_size;
71 
72   // Features enabled for this compilation.
73   const WasmFeatures enabled_features;
74 
75   const DynamicTiering dynamic_tiering;
76 
CompilationEnvCompilationEnv77   constexpr CompilationEnv(const WasmModule* module,
78                            BoundsCheckStrategy bounds_checks,
79                            RuntimeExceptionSupport runtime_exception_support,
80                            const WasmFeatures& enabled_features,
81                            DynamicTiering dynamic_tiering)
82       : module(module),
83         bounds_checks(bounds_checks),
84         runtime_exception_support(runtime_exception_support),
85         // During execution, the memory can never be bigger than what fits in a
86         // uintptr_t.
87         min_memory_size(
88             std::min(kV8MaxWasmMemoryPages,
89                      uintptr_t{module ? module->initial_pages : 0}) *
90             kWasmPageSize),
91         max_memory_size((module && module->has_maximum_pages
92                              ? std::min(kV8MaxWasmMemoryPages,
93                                         uintptr_t{module->maximum_pages})
94                              : kV8MaxWasmMemoryPages) *
95                         kWasmPageSize),
96         enabled_features(enabled_features),
97         dynamic_tiering(dynamic_tiering) {}
98 };
99 
100 // The wire bytes are either owned by the StreamingDecoder, or (after streaming)
101 // by the NativeModule. This class abstracts over the storage location.
102 class WireBytesStorage {
103  public:
104   virtual ~WireBytesStorage() = default;
105   virtual base::Vector<const uint8_t> GetCode(WireBytesRef) const = 0;
106   // Returns the ModuleWireBytes corresponding to the underlying module if
107   // available. Not supported if the wire bytes are owned by a StreamingDecoder.
108   virtual base::Optional<ModuleWireBytes> GetModuleBytes() const = 0;
109 };
110 
111 // Callbacks will receive either {kFailedCompilation} or both
112 // {kFinishedBaselineCompilation} and {kFinishedTopTierCompilation}, in that
113 // order. If tier up is off, both events are delivered right after each other.
114 enum class CompilationEvent : uint8_t {
115   kFinishedBaselineCompilation,
116   kFinishedExportWrappers,
117   kFinishedCompilationChunk,
118   kFinishedTopTierCompilation,
119   kFailedCompilation,
120   kFinishedRecompilation
121 };
122 
123 class V8_EXPORT_PRIVATE CompilationEventCallback {
124  public:
125   virtual ~CompilationEventCallback() = default;
126 
127   virtual void call(CompilationEvent event) = 0;
128 
129   enum class ReleaseAfterFinalEvent { kRelease, kKeep };
130 
131   // Tells the module compiler whether to keep or to release a callback when the
132   // compilation state finishes all compilation units. Most callbacks should be
133   // released, that's why there is a default implementation, but the callback
134   // for code caching with dynamic tiering has to stay alive.
release_after_final_event()135   virtual ReleaseAfterFinalEvent release_after_final_event() {
136     return ReleaseAfterFinalEvent::kRelease;
137   }
138 };
139 
140 // The implementation of {CompilationState} lives in module-compiler.cc.
141 // This is the PIMPL interface to that private class.
142 class V8_EXPORT_PRIVATE CompilationState {
143  public:
144   ~CompilationState();
145 
146   void InitCompileJob();
147 
148   void CancelCompilation();
149 
150   void CancelInitialCompilation();
151 
152   void SetError();
153 
154   void SetWireBytesStorage(std::shared_ptr<WireBytesStorage>);
155 
156   std::shared_ptr<WireBytesStorage> GetWireBytesStorage() const;
157 
158   void AddCallback(std::unique_ptr<CompilationEventCallback> callback);
159 
160   void InitializeAfterDeserialization(
161       base::Vector<const int> lazy_functions,
162       base::Vector<const int> liftoff_functions);
163 
164   // Wait until top tier compilation finished, or compilation failed.
165   void WaitForTopTierFinished();
166 
167   // Set a higher priority for the compilation job.
168   void SetHighPriority();
169 
170   bool failed() const;
171   bool baseline_compilation_finished() const;
172   bool top_tier_compilation_finished() const;
173   bool recompilation_finished() const;
174 
175   void set_compilation_id(int compilation_id);
176 
177   DynamicTiering dynamic_tiering() const;
178 
179   // Override {operator delete} to avoid implicit instantiation of {operator
180   // delete} with {size_t} argument. The {size_t} argument would be incorrect.
delete(void * ptr)181   void operator delete(void* ptr) { ::operator delete(ptr); }
182 
183   CompilationState() = delete;
184 
185  private:
186   // NativeModule is allowed to call the static {New} method.
187   friend class NativeModule;
188 
189   // The CompilationState keeps a {std::weak_ptr} back to the {NativeModule}
190   // such that it can keep it alive (by regaining a {std::shared_ptr}) in
191   // certain scopes.
192   static std::unique_ptr<CompilationState> New(
193       const std::shared_ptr<NativeModule>&, std::shared_ptr<Counters>,
194       DynamicTiering dynamic_tiering);
195 };
196 
197 }  // namespace wasm
198 }  // namespace internal
199 }  // namespace v8
200 
201 #endif  // V8_WASM_COMPILATION_ENVIRONMENT_H_
202