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_FUNCTION_COMPILER_H_ 10 #define V8_WASM_FUNCTION_COMPILER_H_ 11 12 #include <memory> 13 14 #include "src/codegen/assembler.h" 15 #include "src/codegen/code-desc.h" 16 #include "src/trap-handler/trap-handler.h" 17 #include "src/wasm/compilation-environment.h" 18 #include "src/wasm/function-body-decoder.h" 19 #include "src/wasm/wasm-limits.h" 20 #include "src/wasm/wasm-module.h" 21 #include "src/wasm/wasm-tier.h" 22 23 namespace v8 { 24 namespace internal { 25 26 class Counters; 27 class TurbofanCompilationJob; 28 29 namespace wasm { 30 31 class NativeModule; 32 class WasmCode; 33 class WasmEngine; 34 struct WasmFunction; 35 36 struct WasmCompilationResult { 37 public: 38 MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmCompilationResult); 39 40 enum Kind : int8_t { 41 kFunction, 42 kWasmToJsWrapper, 43 }; 44 succeededWasmCompilationResult45 bool succeeded() const { return code_desc.buffer != nullptr; } failedWasmCompilationResult46 bool failed() const { return !succeeded(); } 47 operator bool() const { return succeeded(); } 48 49 CodeDesc code_desc; 50 std::unique_ptr<AssemblerBuffer> instr_buffer; 51 uint32_t frame_slot_count = 0; 52 uint32_t tagged_parameter_slots = 0; 53 base::OwnedVector<byte> source_positions; 54 base::OwnedVector<byte> protected_instructions_data; 55 int func_index = kAnonymousFuncIndex; 56 ExecutionTier requested_tier; 57 ExecutionTier result_tier; 58 Kind kind = kFunction; 59 ForDebugging for_debugging = kNoDebugging; 60 int feedback_vector_slots = 0; 61 }; 62 63 class V8_EXPORT_PRIVATE WasmCompilationUnit final { 64 public: 65 static ExecutionTier GetBaselineExecutionTier(const WasmModule*); 66 WasmCompilationUnit(int index,ExecutionTier tier,ForDebugging for_debugging)67 WasmCompilationUnit(int index, ExecutionTier tier, ForDebugging for_debugging) 68 : func_index_(index), tier_(tier), for_debugging_(for_debugging) {} 69 70 WasmCompilationResult ExecuteCompilation(CompilationEnv*, 71 const WireBytesStorage*, Counters*, 72 WasmFeatures* detected); 73 tier()74 ExecutionTier tier() const { return tier_; } for_debugging()75 ForDebugging for_debugging() const { return for_debugging_; } func_index()76 int func_index() const { return func_index_; } 77 78 static void CompileWasmFunction(Isolate*, NativeModule*, 79 WasmFeatures* detected, const WasmFunction*, 80 ExecutionTier); 81 82 private: 83 WasmCompilationResult ExecuteFunctionCompilation(CompilationEnv*, 84 const WireBytesStorage*, 85 Counters*, 86 WasmFeatures* detected); 87 88 WasmCompilationResult ExecuteImportWrapperCompilation(CompilationEnv*); 89 90 int func_index_; 91 ExecutionTier tier_; 92 ForDebugging for_debugging_; 93 }; 94 95 // {WasmCompilationUnit} should be trivially copyable and small enough so we can 96 // efficiently pass it by value. 97 ASSERT_TRIVIALLY_COPYABLE(WasmCompilationUnit); 98 STATIC_ASSERT(sizeof(WasmCompilationUnit) <= 2 * kSystemPointerSize); 99 100 class V8_EXPORT_PRIVATE JSToWasmWrapperCompilationUnit final { 101 public: 102 // A flag to mark whether the compilation unit can skip the compilation 103 // and return the builtin (generic) wrapper, when available. 104 enum AllowGeneric : bool { kAllowGeneric = true, kDontAllowGeneric = false }; 105 106 JSToWasmWrapperCompilationUnit(Isolate* isolate, const FunctionSig* sig, 107 const wasm::WasmModule* module, bool is_import, 108 const WasmFeatures& enabled_features, 109 AllowGeneric allow_generic); 110 ~JSToWasmWrapperCompilationUnit(); 111 isolate()112 Isolate* isolate() const { return isolate_; } 113 114 void Execute(); 115 Handle<Code> Finalize(); 116 is_import()117 bool is_import() const { return is_import_; } sig()118 const FunctionSig* sig() const { return sig_; } 119 120 // Run a compilation unit synchronously. 121 static Handle<Code> CompileJSToWasmWrapper(Isolate* isolate, 122 const FunctionSig* sig, 123 const WasmModule* module, 124 bool is_import); 125 126 // Run a compilation unit synchronously, but ask for the specific 127 // wrapper. 128 static Handle<Code> CompileSpecificJSToWasmWrapper(Isolate* isolate, 129 const FunctionSig* sig, 130 const WasmModule* module); 131 132 private: 133 // Wrapper compilation is bound to an isolate. Concurrent accesses to the 134 // isolate (during the "Execute" phase) must be audited carefully, i.e. we 135 // should only access immutable information (like the root table). The isolate 136 // is guaranteed to be alive when this unit executes. 137 Isolate* isolate_; 138 bool is_import_; 139 const FunctionSig* sig_; 140 bool use_generic_wrapper_; 141 std::unique_ptr<TurbofanCompilationJob> job_; 142 }; 143 144 } // namespace wasm 145 } // namespace internal 146 } // namespace v8 147 148 #endif // V8_WASM_FUNCTION_COMPILER_H_ 149