• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 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 #ifndef V8_WASM_MODULE_COMPILER_H_
6 #define V8_WASM_MODULE_COMPILER_H_
7 
8 #include <atomic>
9 #include <functional>
10 #include <memory>
11 
12 #include "src/cancelable-task.h"
13 #include "src/globals.h"
14 #include "src/wasm/wasm-features.h"
15 #include "src/wasm/wasm-module.h"
16 
17 namespace v8 {
18 namespace internal {
19 
20 class JSArrayBuffer;
21 class JSPromise;
22 class Counters;
23 class WasmModuleObject;
24 class WasmInstanceObject;
25 
26 template <typename T>
27 class Vector;
28 
29 namespace wasm {
30 
31 class CompilationResultResolver;
32 class CompilationState;
33 class ErrorThrower;
34 class ModuleCompiler;
35 class NativeModule;
36 class WasmCode;
37 struct ModuleEnv;
38 struct WasmModule;
39 
40 struct CompilationStateDeleter {
41   void operator()(CompilationState* compilation_state) const;
42 };
43 
44 // Wrapper to create a CompilationState exists in order to avoid having
45 // the CompilationState in the header file.
46 std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
47     Isolate* isolate, const ModuleEnv& env);
48 
49 ModuleEnv* GetModuleEnv(CompilationState* compilation_state);
50 
51 MaybeHandle<WasmModuleObject> CompileToModuleObject(
52     Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower,
53     std::shared_ptr<const WasmModule> module, const ModuleWireBytes& wire_bytes,
54     Handle<Script> asm_js_script, Vector<const byte> asm_js_offset_table_bytes);
55 
56 MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
57     Isolate* isolate, ErrorThrower* thrower,
58     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
59     MaybeHandle<JSArrayBuffer> memory);
60 
61 V8_EXPORT_PRIVATE
62 void CompileJsToWasmWrappers(Isolate* isolate,
63                              Handle<WasmModuleObject> module_object);
64 
65 V8_EXPORT_PRIVATE Handle<Script> CreateWasmScript(
66     Isolate* isolate, const ModuleWireBytes& wire_bytes);
67 
68 // Triggered by the WasmCompileLazy builtin.
69 // Returns the instruction start of the compiled code object.
70 Address CompileLazy(Isolate*, NativeModule*, uint32_t func_index);
71 
72 // Encapsulates all the state and steps of an asynchronous compilation.
73 // An asynchronous compile job consists of a number of tasks that are executed
74 // as foreground and background tasks. Any phase that touches the V8 heap or
75 // allocates on the V8 heap (e.g. creating the module object) must be a
76 // foreground task. All other tasks (e.g. decoding and validating, the majority
77 // of the work of compilation) can be background tasks.
78 // TODO(wasm): factor out common parts of this with the synchronous pipeline.
79 class AsyncCompileJob {
80  public:
81   AsyncCompileJob(Isolate* isolate, const WasmFeatures& enabled_features,
82                   std::unique_ptr<byte[]> bytes_copy, size_t length,
83                   Handle<Context> context,
84                   std::shared_ptr<CompilationResultResolver> resolver);
85   ~AsyncCompileJob();
86 
87   void Start();
88 
89   std::shared_ptr<StreamingDecoder> CreateStreamingDecoder();
90 
91   void Abort();
92   void CancelPendingForegroundTask();
93 
isolate()94   Isolate* isolate() const { return isolate_; }
95 
96  private:
97   class CompileTask;
98   class CompileStep;
99 
100   // States of the AsyncCompileJob.
101   class DecodeModule;            // Step 1  (async)
102   class DecodeFail;              // Step 1b (sync)
103   class PrepareAndStartCompile;  // Step 2  (sync)
104   class CompileFailed;           // Step 4b (sync)
105   class CompileWrappers;         // Step 5  (sync)
106   class FinishModule;            // Step 6  (sync)
107 
async_counters()108   const std::shared_ptr<Counters>& async_counters() const {
109     return async_counters_;
110   }
counters()111   Counters* counters() const { return async_counters().get(); }
112 
113   void FinishCompile();
114 
115   void AsyncCompileFailed(Handle<Object> error_reason);
116 
117   void AsyncCompileSucceeded(Handle<WasmModuleObject> result);
118 
119   void StartForegroundTask();
120   void ExecuteForegroundTaskImmediately();
121 
122   void StartBackgroundTask();
123 
124   // Switches to the compilation step {Step} and starts a foreground task to
125   // execute it.
126   template <typename Step, typename... Args>
127   void DoSync(Args&&... args);
128 
129   // Switches to the compilation step {Step} and immediately executes that step.
130   template <typename Step, typename... Args>
131   void DoImmediately(Args&&... args);
132 
133   // Switches to the compilation step {Step} and starts a background task to
134   // execute it.
135   template <typename Step, typename... Args>
136   void DoAsync(Args&&... args);
137 
138   // Switches to the compilation step {Step} but does not start a task to
139   // execute it.
140   template <typename Step, typename... Args>
141   void NextStep(Args&&... args);
142 
143   friend class AsyncStreamingProcessor;
144 
145   Isolate* isolate_;
146   const WasmFeatures enabled_features_;
147   const std::shared_ptr<Counters> async_counters_;
148   // Copy of the module wire bytes, moved into the {native_module_} on its
149   // creation.
150   std::unique_ptr<byte[]> bytes_copy_;
151   // Reference to the wire bytes (hold in {bytes_copy_} or as part of
152   // {native_module_}).
153   ModuleWireBytes wire_bytes_;
154   Handle<Context> native_context_;
155   std::shared_ptr<CompilationResultResolver> resolver_;
156 
157   std::vector<DeferredHandles*> deferred_handles_;
158   Handle<WasmModuleObject> module_object_;
159   NativeModule* native_module_ = nullptr;
160 
161   std::unique_ptr<CompileStep> step_;
162   CancelableTaskManager background_task_manager_;
163 
164   std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
165 
166   // For async compilation the AsyncCompileJob is the only finisher. For
167   // streaming compilation also the AsyncStreamingProcessor has to finish before
168   // compilation can be finished.
169   std::atomic<int32_t> outstanding_finishers_{1};
170 
171   // Decrements the number of outstanding finishers. The last caller of this
172   // function should finish the asynchronous compilation, see the comment on
173   // {outstanding_finishers_}.
DecrementAndCheckFinisherCount()174   V8_WARN_UNUSED_RESULT bool DecrementAndCheckFinisherCount() {
175     return outstanding_finishers_.fetch_sub(1) == 1;
176   }
177 
178   // A reference to a pending foreground task, or {nullptr} if none is pending.
179   CompileTask* pending_foreground_task_ = nullptr;
180 
181   // The AsyncCompileJob owns the StreamingDecoder because the StreamingDecoder
182   // contains data which is needed by the AsyncCompileJob for streaming
183   // compilation. The AsyncCompileJob does not actively use the
184   // StreamingDecoder.
185   std::shared_ptr<StreamingDecoder> stream_;
186 
187   bool tiering_completed_ = false;
188 };
189 }  // namespace wasm
190 }  // namespace internal
191 }  // namespace v8
192 
193 #endif  // V8_WASM_MODULE_COMPILER_H_
194