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