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