1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- 2 * vim: set ts=8 sts=2 et sw=2 tw=80: 3 * 4 * Copyright 2021 Mozilla Foundation 5 * 6 * Licensed under the Apache License, Version 2.0 (the "License"); 7 * you may not use this file except in compliance with the License. 8 * You may obtain a copy of the License at 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 12 * Unless required by applicable law or agreed to in writing, software 13 * distributed under the License is distributed on an "AS IS" BASIS, 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 * See the License for the specific language governing permissions and 16 * limitations under the License. 17 */ 18 19 #ifndef wasm_compile_args_h 20 #define wasm_compile_args_h 21 22 #include "mozilla/RefPtr.h" 23 24 #include "js/Utility.h" 25 #include "js/WasmFeatures.h" 26 #include "wasm/WasmConstants.h" 27 #include "wasm/WasmShareable.h" 28 29 namespace js { 30 namespace wasm { 31 32 enum class Shareable { False, True }; 33 34 // Code can be compiled either with the Baseline compiler or the Ion compiler, 35 // and tier-variant data are tagged with the Tier value. 36 // 37 // A tier value is used to request tier-variant aspects of code, metadata, or 38 // linkdata. The tiers are normally explicit (Baseline and Ion); implicit tiers 39 // can be obtained through accessors on Code objects (eg, stableTier). 40 41 enum class Tier { 42 Baseline, 43 Debug = Baseline, 44 Optimized, 45 Serialized = Optimized 46 }; 47 48 // Iterator over tiers present in a tiered data structure. 49 50 class Tiers { 51 Tier t_[2]; 52 uint32_t n_; 53 54 public: Tiers()55 explicit Tiers() { n_ = 0; } Tiers(Tier t)56 explicit Tiers(Tier t) { 57 t_[0] = t; 58 n_ = 1; 59 } Tiers(Tier t,Tier u)60 explicit Tiers(Tier t, Tier u) { 61 MOZ_ASSERT(t != u); 62 t_[0] = t; 63 t_[1] = u; 64 n_ = 2; 65 } 66 begin()67 Tier* begin() { return t_; } end()68 Tier* end() { return t_ + n_; } 69 }; 70 71 // Describes per-compilation settings that are controlled by an options bag 72 // passed to compilation and validation functions. (Nonstandard extension 73 // available under prefs.) 74 75 struct FeatureOptions { FeatureOptionsFeatureOptions76 FeatureOptions() : simdWormhole(false) {} 77 78 // May be set if javascript.options.wasm_simd_wormhole==true. 79 bool simdWormhole; 80 }; 81 82 // Describes the features that control wasm compilation. 83 84 struct FeatureArgs { FeatureArgsFeatureArgs85 FeatureArgs() 86 : 87 #define WASM_FEATURE(NAME, LOWER_NAME, ...) LOWER_NAME(false), 88 JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE) 89 #undef WASM_FEATURE 90 sharedMemory(Shareable::False), 91 hugeMemory(false), 92 simdWormhole(false) { 93 } 94 FeatureArgs(const FeatureArgs&) = default; 95 FeatureArgs& operator=(const FeatureArgs&) = default; 96 FeatureArgs(FeatureArgs&&) = default; 97 98 static FeatureArgs build(JSContext* cx, const FeatureOptions& options); 99 100 #define WASM_FEATURE(NAME, LOWER_NAME, ...) bool LOWER_NAME; 101 JS_FOR_WASM_FEATURES(WASM_FEATURE, WASM_FEATURE) 102 #undef WASM_FEATURE 103 104 Shareable sharedMemory; 105 bool hugeMemory; 106 bool simdWormhole; 107 }; 108 109 // Describes the JS scripted caller of a request to compile a wasm module. 110 111 struct ScriptedCaller { 112 UniqueChars filename; 113 bool filenameIsURL; 114 unsigned line; 115 ScriptedCallerScriptedCaller116 ScriptedCaller() : filenameIsURL(false), line(0) {} 117 }; 118 119 // Describes all the parameters that control wasm compilation. 120 121 struct CompileArgs; 122 using MutableCompileArgs = RefPtr<CompileArgs>; 123 using SharedCompileArgs = RefPtr<const CompileArgs>; 124 125 struct CompileArgs : ShareableBase<CompileArgs> { 126 ScriptedCaller scriptedCaller; 127 UniqueChars sourceMapURL; 128 129 bool baselineEnabled; 130 bool ionEnabled; 131 bool craneliftEnabled; 132 bool debugEnabled; 133 bool forceTiering; 134 135 FeatureArgs features; 136 137 // CompileArgs has two constructors: 138 // 139 // - one through a factory function `build`, which checks that flags are 140 // consistent with each other. 141 // - one that gives complete access to underlying fields. 142 // 143 // You should use the first one in general, unless you have a very good 144 // reason (i.e. no JSContext around and you know which flags have been used). 145 146 static SharedCompileArgs build(JSContext* cx, ScriptedCaller&& scriptedCaller, 147 const FeatureOptions& options); 148 CompileArgsCompileArgs149 explicit CompileArgs(ScriptedCaller&& scriptedCaller) 150 : scriptedCaller(std::move(scriptedCaller)), 151 baselineEnabled(false), 152 ionEnabled(false), 153 craneliftEnabled(false), 154 debugEnabled(false), 155 forceTiering(false) {} 156 }; 157 158 // CompilerEnvironment holds any values that will be needed to compute 159 // compilation parameters once the module's feature opt-in sections have been 160 // parsed. 161 // 162 // Subsequent to construction a computeParameters() call will compute the final 163 // compilation parameters, and the object can then be queried for their values. 164 165 struct CompileArgs; 166 class Decoder; 167 168 struct CompilerEnvironment { 169 // The object starts in one of two "initial" states; computeParameters moves 170 // it into the "computed" state. 171 enum State { InitialWithArgs, InitialWithModeTierDebug, Computed }; 172 173 State state_; 174 union { 175 // Value if the state_ == InitialWithArgs. 176 const CompileArgs* args_; 177 178 // Value in the other two states. 179 struct { 180 CompileMode mode_; 181 Tier tier_; 182 OptimizedBackend optimizedBackend_; 183 DebugEnabled debug_; 184 }; 185 }; 186 187 public: 188 // Retain a reference to the CompileArgs. A subsequent computeParameters() 189 // will compute all parameters from the CompileArgs and additional values. 190 explicit CompilerEnvironment(const CompileArgs& args); 191 192 // Save the provided values for mode, tier, and debug, and the initial value 193 // for gc/refTypes. A subsequent computeParameters() will compute the 194 // final value of gc/refTypes. 195 CompilerEnvironment(CompileMode mode, Tier tier, 196 OptimizedBackend optimizedBackend, 197 DebugEnabled debugEnabled); 198 199 // Compute any remaining compilation parameters. 200 void computeParameters(Decoder& d); 201 202 // Compute any remaining compilation parameters. Only use this method if 203 // the CompilerEnvironment was created with values for mode, tier, and 204 // debug. 205 void computeParameters(); 206 isComputedCompilerEnvironment207 bool isComputed() const { return state_ == Computed; } modeCompilerEnvironment208 CompileMode mode() const { 209 MOZ_ASSERT(isComputed()); 210 return mode_; 211 } tierCompilerEnvironment212 Tier tier() const { 213 MOZ_ASSERT(isComputed()); 214 return tier_; 215 } optimizedBackendCompilerEnvironment216 OptimizedBackend optimizedBackend() const { 217 MOZ_ASSERT(isComputed()); 218 return optimizedBackend_; 219 } debugCompilerEnvironment220 DebugEnabled debug() const { 221 MOZ_ASSERT(isComputed()); 222 return debug_; 223 } debugEnabledCompilerEnvironment224 bool debugEnabled() const { return debug() == DebugEnabled::True; } 225 }; 226 227 } // namespace wasm 228 } // namespace js 229 230 #endif // wasm_compile_args_h 231