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