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