no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / js / src / wasm / WasmGenerator.h
blob775366e215651017e4cbd55fe42917f21afcba8d
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:
4 * Copyright 2015 Mozilla Foundation
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #ifndef wasm_generator_h
20 #define wasm_generator_h
22 #include "mozilla/Attributes.h"
23 #include "mozilla/MemoryReporting.h"
25 #include "jit/MacroAssembler.h"
26 #include "threading/ProtectedData.h"
27 #include "vm/HelperThreadTask.h"
28 #include "wasm/WasmCompile.h"
29 #include "wasm/WasmModule.h"
30 #include "wasm/WasmValidate.h"
32 namespace JS {
33 class OptimizedEncodingListener;
36 namespace js {
37 namespace wasm {
39 struct CompileTask;
40 using CompileTaskPtrVector = Vector<CompileTask*, 0, SystemAllocPolicy>;
42 // FuncCompileInput contains the input for compiling a single function.
44 struct FuncCompileInput {
45 const uint8_t* begin;
46 const uint8_t* end;
47 uint32_t index;
48 uint32_t lineOrBytecode;
49 Uint32Vector callSiteLineNums;
51 FuncCompileInput(uint32_t index, uint32_t lineOrBytecode,
52 const uint8_t* begin, const uint8_t* end,
53 Uint32Vector&& callSiteLineNums)
54 : begin(begin),
55 end(end),
56 index(index),
57 lineOrBytecode(lineOrBytecode),
58 callSiteLineNums(std::move(callSiteLineNums)) {}
61 using FuncCompileInputVector = Vector<FuncCompileInput, 8, SystemAllocPolicy>;
63 // CompiledCode contains the resulting code and metadata for a set of compiled
64 // input functions or stubs.
66 struct CompiledCode {
67 CompiledCode() : featureUsage(FeatureUsage::None) {}
69 Bytes bytes;
70 CodeRangeVector codeRanges;
71 CallSiteVector callSites;
72 CallSiteTargetVector callSiteTargets;
73 TrapSiteVectorArray trapSites;
74 SymbolicAccessVector symbolicAccesses;
75 jit::CodeLabelVector codeLabels;
76 StackMaps stackMaps;
77 TryNoteVector tryNotes;
78 CodeRangeUnwindInfoVector codeRangeUnwindInfos;
79 FeatureUsage featureUsage;
81 [[nodiscard]] bool swap(jit::MacroAssembler& masm);
83 void clear() {
84 bytes.clear();
85 codeRanges.clear();
86 callSites.clear();
87 callSiteTargets.clear();
88 trapSites.clear();
89 symbolicAccesses.clear();
90 codeLabels.clear();
91 stackMaps.clear();
92 tryNotes.clear();
93 codeRangeUnwindInfos.clear();
94 featureUsage = FeatureUsage::None;
95 MOZ_ASSERT(empty());
98 bool empty() {
99 return bytes.empty() && codeRanges.empty() && callSites.empty() &&
100 callSiteTargets.empty() && trapSites.empty() &&
101 symbolicAccesses.empty() && codeLabels.empty() && tryNotes.empty() &&
102 stackMaps.empty() && codeRangeUnwindInfos.empty() &&
103 featureUsage == FeatureUsage::None;
106 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
109 // The CompileTaskState of a ModuleGenerator contains the mutable state shared
110 // between helper threads executing CompileTasks. Each CompileTask started on a
111 // helper thread eventually either ends up in the 'finished' list or increments
112 // 'numFailed'.
114 struct CompileTaskState {
115 HelperThreadLockData<CompileTaskPtrVector> finished_;
116 HelperThreadLockData<uint32_t> numFailed_;
117 HelperThreadLockData<UniqueChars> errorMessage_;
118 HelperThreadLockData<ConditionVariable> condVar_;
120 CompileTaskState() : numFailed_(0) {}
121 ~CompileTaskState() {
122 MOZ_ASSERT(finished_.refNoCheck().empty());
123 MOZ_ASSERT(!numFailed_.refNoCheck());
126 CompileTaskPtrVector& finished() { return finished_.ref(); }
127 uint32_t& numFailed() { return numFailed_.ref(); }
128 UniqueChars& errorMessage() { return errorMessage_.ref(); }
129 ConditionVariable& condVar() { return condVar_.ref(); }
132 // A CompileTask holds a batch of input functions that are to be compiled on a
133 // helper thread as well as, eventually, the results of compilation.
135 struct CompileTask : public HelperThreadTask {
136 const ModuleEnvironment& moduleEnv;
137 const CompilerEnvironment& compilerEnv;
139 CompileTaskState& state;
140 LifoAlloc lifo;
141 FuncCompileInputVector inputs;
142 CompiledCode output;
144 CompileTask(const ModuleEnvironment& moduleEnv,
145 const CompilerEnvironment& compilerEnv, CompileTaskState& state,
146 size_t defaultChunkSize)
147 : moduleEnv(moduleEnv),
148 compilerEnv(compilerEnv),
149 state(state),
150 lifo(defaultChunkSize) {}
152 virtual ~CompileTask() = default;
154 size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
156 void runHelperThreadTask(AutoLockHelperThreadState& locked) override;
157 ThreadType threadType() override;
160 // A ModuleGenerator encapsulates the creation of a wasm module. During the
161 // lifetime of a ModuleGenerator, a sequence of FunctionGenerators are created
162 // and destroyed to compile the individual function bodies. After generating all
163 // functions, ModuleGenerator::finish() must be called to complete the
164 // compilation and extract the resulting wasm module.
166 class MOZ_STACK_CLASS ModuleGenerator {
167 using CompileTaskVector = Vector<CompileTask, 0, SystemAllocPolicy>;
168 using CodeOffsetVector = Vector<jit::CodeOffset, 0, SystemAllocPolicy>;
169 struct CallFarJump {
170 uint32_t funcIndex;
171 jit::CodeOffset jump;
172 CallFarJump(uint32_t fi, jit::CodeOffset j) : funcIndex(fi), jump(j) {}
174 using CallFarJumpVector = Vector<CallFarJump, 0, SystemAllocPolicy>;
176 // Constant parameters
177 SharedCompileArgs const compileArgs_;
178 UniqueChars* const error_;
179 UniqueCharsVector* const warnings_;
180 const Atomic<bool>* const cancelled_;
181 ModuleEnvironment* const moduleEnv_;
182 CompilerEnvironment* const compilerEnv_;
184 // Data that is moved into the result of finish()
185 UniqueLinkData linkData_;
186 UniqueMetadataTier metadataTier_;
187 MutableMetadata metadata_;
189 // Data scoped to the ModuleGenerator's lifetime
190 CompileTaskState taskState_;
191 LifoAlloc lifo_;
192 jit::TempAllocator masmAlloc_;
193 jit::WasmMacroAssembler masm_;
194 Uint32Vector funcToCodeRange_;
195 uint32_t debugTrapCodeOffset_;
196 CallFarJumpVector callFarJumps_;
197 CallSiteTargetVector callSiteTargets_;
198 uint32_t lastPatchedCallSite_;
199 uint32_t startOfUnpatchedCallsites_;
201 // Parallel compilation
202 bool parallel_;
203 uint32_t outstanding_;
204 CompileTaskVector tasks_;
205 CompileTaskPtrVector freeTasks_;
206 CompileTask* currentTask_;
207 uint32_t batchedBytecode_;
209 // Assertions
210 DebugOnly<bool> finishedFuncDefs_;
212 bool allocateInstanceDataBytes(uint32_t bytes, uint32_t align,
213 uint32_t* instanceDataOffset);
214 bool allocateInstanceDataBytesN(uint32_t bytes, uint32_t align,
215 uint32_t count, uint32_t* instanceDataOffset);
217 bool funcIsCompiled(uint32_t funcIndex) const;
218 const CodeRange& funcCodeRange(uint32_t funcIndex) const;
219 bool linkCallSites();
220 void noteCodeRange(uint32_t codeRangeIndex, const CodeRange& codeRange);
221 bool linkCompiledCode(CompiledCode& code);
222 bool locallyCompileCurrentTask();
223 bool finishTask(CompileTask* task);
224 bool launchBatchCompile();
225 bool finishOutstandingTask();
226 bool finishCodegen();
227 bool finishMetadataTier();
228 UniqueCodeTier finishCodeTier();
229 SharedMetadata finishMetadata(const Bytes& bytecode);
231 bool isAsmJS() const { return moduleEnv_->isAsmJS(); }
232 Tier tier() const { return compilerEnv_->tier(); }
233 CompileMode mode() const { return compilerEnv_->mode(); }
234 bool debugEnabled() const { return compilerEnv_->debugEnabled(); }
236 void warnf(const char* msg, ...) MOZ_FORMAT_PRINTF(2, 3);
238 public:
239 ModuleGenerator(const CompileArgs& args, ModuleEnvironment* moduleEnv,
240 CompilerEnvironment* compilerEnv,
241 const Atomic<bool>* cancelled, UniqueChars* error,
242 UniqueCharsVector* warnings);
243 ~ModuleGenerator();
244 [[nodiscard]] bool init(Metadata* maybeAsmJSMetadata = nullptr);
246 // Before finishFuncDefs() is called, compileFuncDef() must be called once
247 // for each funcIndex in the range [0, env->numFuncDefs()).
249 [[nodiscard]] bool compileFuncDef(
250 uint32_t funcIndex, uint32_t lineOrBytecode, const uint8_t* begin,
251 const uint8_t* end, Uint32Vector&& callSiteLineNums = Uint32Vector());
253 // Must be called after the last compileFuncDef() and before finishModule()
254 // or finishTier2().
256 [[nodiscard]] bool finishFuncDefs();
258 // If env->mode is Once or Tier1, finishModule() must be called to generate
259 // a new Module. Otherwise, if env->mode is Tier2, finishTier2() must be
260 // called to augment the given Module with tier 2 code.
262 SharedModule finishModule(
263 const ShareableBytes& bytecode,
264 JS::OptimizedEncodingListener* maybeTier2Listener = nullptr);
265 [[nodiscard]] bool finishTier2(const Module& module);
268 } // namespace wasm
269 } // namespace js
271 #endif // wasm_generator_h