File: | var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h |
Warning: | line 579, column 17 Value stored to 'what' during its initialization is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
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 | * This Source Code Form is subject to the terms of the Mozilla Public |
4 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | |
7 | /* |
8 | * Everything needed to build actual MIR instructions: the actual opcodes and |
9 | * instructions, the instruction interface, and use chains. |
10 | */ |
11 | |
12 | #ifndef jit_MIR_wasm_h |
13 | #define jit_MIR_wasm_h |
14 | |
15 | #include "mozilla/Array.h" |
16 | #include "mozilla/HashFunctions.h" |
17 | #ifdef JS_JITSPEW1 |
18 | # include "mozilla/Sprintf.h" |
19 | # include "mozilla/Vector.h" |
20 | #endif |
21 | |
22 | #include <algorithm> |
23 | #include <initializer_list> |
24 | |
25 | #include "jit/MIR.h" |
26 | |
27 | namespace js { |
28 | |
29 | class WasmInstanceObject; |
30 | |
31 | namespace wasm { |
32 | class FuncExport; |
33 | extern uint32_t MIRTypeToABIResultSize(jit::MIRType); |
34 | } // namespace wasm |
35 | |
36 | namespace jit { |
37 | |
38 | class MWasmNullConstant : public MNullaryInstruction { |
39 | explicit MWasmNullConstant() : MNullaryInstruction(classOpcode) { |
40 | setResultType(MIRType::WasmAnyRef); |
41 | setMovable(); |
42 | } |
43 | |
44 | public: |
45 | INSTRUCTION_HEADER(WasmNullConstant) |
46 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
47 | |
48 | HashNumber valueHash() const override; |
49 | bool congruentTo(const MDefinition* ins) const override { |
50 | return ins->isWasmNullConstant(); |
51 | } |
52 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
53 | |
54 | ALLOW_CLONE(MWasmNullConstant)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmNullConstant (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
55 | }; |
56 | |
57 | // Floating-point value as created by wasm. Just a constant value, used to |
58 | // effectively inhibit all the MIR optimizations. This uses the same LIR nodes |
59 | // as a MConstant of the same type would. |
60 | class MWasmFloatConstant : public MNullaryInstruction { |
61 | union { |
62 | float f32_; |
63 | double f64_; |
64 | #ifdef ENABLE_WASM_SIMD1 |
65 | int8_t s128_[16]; |
66 | uint64_t bits_[2]; |
67 | #else |
68 | uint64_t bits_[1]; |
69 | #endif |
70 | } u; |
71 | |
72 | explicit MWasmFloatConstant(MIRType type) : MNullaryInstruction(classOpcode) { |
73 | u.bits_[0] = 0; |
74 | #ifdef ENABLE_WASM_SIMD1 |
75 | u.bits_[1] = 0; |
76 | #endif |
77 | setResultType(type); |
78 | } |
79 | |
80 | public: |
81 | INSTRUCTION_HEADER(WasmFloatConstant) |
82 | |
83 | static MWasmFloatConstant* NewDouble(TempAllocator& alloc, double d) { |
84 | auto* ret = new (alloc) MWasmFloatConstant(MIRType::Double); |
85 | ret->u.f64_ = d; |
86 | return ret; |
87 | } |
88 | |
89 | static MWasmFloatConstant* NewFloat32(TempAllocator& alloc, float f) { |
90 | auto* ret = new (alloc) MWasmFloatConstant(MIRType::Float32); |
91 | ret->u.f32_ = f; |
92 | return ret; |
93 | } |
94 | |
95 | #ifdef ENABLE_WASM_SIMD1 |
96 | static MWasmFloatConstant* NewSimd128(TempAllocator& alloc, |
97 | const SimdConstant& s) { |
98 | auto* ret = new (alloc) MWasmFloatConstant(MIRType::Simd128); |
99 | memcpy(ret->u.s128_, s.bytes(), 16); |
100 | return ret; |
101 | } |
102 | #endif |
103 | |
104 | HashNumber valueHash() const override; |
105 | bool congruentTo(const MDefinition* ins) const override; |
106 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
107 | |
108 | const double& toDouble() const { |
109 | MOZ_ASSERT(type() == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type() == MIRType::Double)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type() == MIRType::Double))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Double" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 109); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Double" ")"); do { *((volatile int*)__null) = 109; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
110 | return u.f64_; |
111 | } |
112 | const float& toFloat32() const { |
113 | MOZ_ASSERT(type() == MIRType::Float32)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type() == MIRType::Float32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type() == MIRType::Float32)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Float32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 113); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Float32" ")"); do { *((volatile int*)__null) = 113; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
114 | return u.f32_; |
115 | } |
116 | #ifdef ENABLE_WASM_SIMD1 |
117 | const SimdConstant toSimd128() const { |
118 | MOZ_ASSERT(type() == MIRType::Simd128)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type() == MIRType::Simd128)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(type() == MIRType::Simd128)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Simd128" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Simd128" ")"); do { *((volatile int*)__null) = 118; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
119 | return SimdConstant::CreateX16(u.s128_); |
120 | } |
121 | #endif |
122 | #ifdef JS_JITSPEW1 |
123 | void getExtras(ExtrasCollector* extras) const override { |
124 | char buf[64]; |
125 | switch (type()) { |
126 | case MIRType::Float32: |
127 | SprintfLiteral(buf, "f32{%e}", (double)u.f32_); |
128 | break; |
129 | case MIRType::Double: |
130 | SprintfLiteral(buf, "f64{%e}", u.f64_); |
131 | break; |
132 | # ifdef ENABLE_WASM_SIMD1 |
133 | case MIRType::Simd128: |
134 | SprintfLiteral(buf, "v128{[1]=%016llx:[0]=%016llx}", |
135 | (unsigned long long int)u.bits_[1], |
136 | (unsigned long long int)u.bits_[0]); |
137 | break; |
138 | # endif |
139 | default: |
140 | SprintfLiteral(buf, "!!getExtras: missing case!!"); |
141 | break; |
142 | } |
143 | extras->add(buf); |
144 | } |
145 | #endif |
146 | }; |
147 | |
148 | // Converts a uint32 to a float32 (coming from wasm). |
149 | class MWasmUnsignedToFloat32 : public MUnaryInstruction, |
150 | public NoTypePolicy::Data { |
151 | explicit MWasmUnsignedToFloat32(MDefinition* def) |
152 | : MUnaryInstruction(classOpcode, def) { |
153 | setResultType(MIRType::Float32); |
154 | setMovable(); |
155 | } |
156 | |
157 | public: |
158 | INSTRUCTION_HEADER(WasmUnsignedToFloat32) |
159 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
160 | |
161 | MDefinition* foldsTo(TempAllocator& alloc) override; |
162 | bool congruentTo(const MDefinition* ins) const override { |
163 | return congruentIfOperandsEqual(ins); |
164 | } |
165 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
166 | |
167 | bool canProduceFloat32() const override { return true; } |
168 | }; |
169 | |
170 | // The same as MWasmTruncateToInt64 but with the Instance dependency. |
171 | // It used only for arm now because on arm we need to call builtin to truncate |
172 | // to i64. |
173 | class MWasmBuiltinTruncateToInt64 : public MAryInstruction<2>, |
174 | public NoTypePolicy::Data { |
175 | TruncFlags flags_; |
176 | wasm::BytecodeOffset bytecodeOffset_; |
177 | |
178 | MWasmBuiltinTruncateToInt64(MDefinition* def, MDefinition* instance, |
179 | TruncFlags flags, |
180 | wasm::BytecodeOffset bytecodeOffset) |
181 | : MAryInstruction(classOpcode), |
182 | flags_(flags), |
183 | bytecodeOffset_(bytecodeOffset) { |
184 | initOperand(0, def); |
185 | initOperand(1, instance); |
186 | |
187 | setResultType(MIRType::Int64); |
188 | setGuard(); // neither removable nor movable because of possible |
189 | // side-effects. |
190 | } |
191 | |
192 | public: |
193 | INSTRUCTION_HEADER(WasmBuiltinTruncateToInt64) |
194 | NAMED_OPERANDS((0, input), (1, instance))MDefinition* input() const { return getOperand(0); } MDefinition * instance() const { return getOperand(1); }; |
195 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
196 | |
197 | bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; } |
198 | bool isSaturating() const { return flags_ & TRUNC_SATURATING; } |
199 | TruncFlags flags() const { return flags_; } |
200 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
201 | |
202 | bool congruentTo(const MDefinition* ins) const override { |
203 | return congruentIfOperandsEqual(ins) && |
204 | ins->toWasmBuiltinTruncateToInt64()->flags() == flags_; |
205 | } |
206 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
207 | }; |
208 | |
209 | class MWasmTruncateToInt64 : public MUnaryInstruction, |
210 | public NoTypePolicy::Data { |
211 | TruncFlags flags_; |
212 | wasm::BytecodeOffset bytecodeOffset_; |
213 | |
214 | MWasmTruncateToInt64(MDefinition* def, TruncFlags flags, |
215 | wasm::BytecodeOffset bytecodeOffset) |
216 | : MUnaryInstruction(classOpcode, def), |
217 | flags_(flags), |
218 | bytecodeOffset_(bytecodeOffset) { |
219 | setResultType(MIRType::Int64); |
220 | setGuard(); // neither removable nor movable because of possible |
221 | // side-effects. |
222 | } |
223 | |
224 | public: |
225 | INSTRUCTION_HEADER(WasmTruncateToInt64) |
226 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
227 | |
228 | bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; } |
229 | bool isSaturating() const { return flags_ & TRUNC_SATURATING; } |
230 | TruncFlags flags() const { return flags_; } |
231 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
232 | |
233 | bool congruentTo(const MDefinition* ins) const override { |
234 | return congruentIfOperandsEqual(ins) && |
235 | ins->toWasmTruncateToInt64()->flags() == flags_; |
236 | } |
237 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
238 | }; |
239 | |
240 | // Truncate a value to an int32, with wasm semantics: this will trap when the |
241 | // value is out of range. |
242 | class MWasmTruncateToInt32 : public MUnaryInstruction, |
243 | public NoTypePolicy::Data { |
244 | TruncFlags flags_; |
245 | wasm::BytecodeOffset bytecodeOffset_; |
246 | |
247 | explicit MWasmTruncateToInt32(MDefinition* def, TruncFlags flags, |
248 | wasm::BytecodeOffset bytecodeOffset) |
249 | : MUnaryInstruction(classOpcode, def), |
250 | flags_(flags), |
251 | bytecodeOffset_(bytecodeOffset) { |
252 | setResultType(MIRType::Int32); |
253 | setGuard(); // neither removable nor movable because of possible |
254 | // side-effects. |
255 | } |
256 | |
257 | public: |
258 | INSTRUCTION_HEADER(WasmTruncateToInt32) |
259 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
260 | |
261 | bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; } |
262 | bool isSaturating() const { return flags_ & TRUNC_SATURATING; } |
263 | TruncFlags flags() const { return flags_; } |
264 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
265 | |
266 | MDefinition* foldsTo(TempAllocator& alloc) override; |
267 | |
268 | bool congruentTo(const MDefinition* ins) const override { |
269 | return congruentIfOperandsEqual(ins) && |
270 | ins->toWasmTruncateToInt32()->flags() == flags_; |
271 | } |
272 | |
273 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
274 | }; |
275 | |
276 | // It is like MTruncateToInt32 but with instance dependency. |
277 | class MWasmBuiltinTruncateToInt32 : public MAryInstruction<2>, |
278 | public ToInt32Policy::Data { |
279 | wasm::BytecodeOffset bytecodeOffset_; |
280 | |
281 | MWasmBuiltinTruncateToInt32( |
282 | MDefinition* def, MDefinition* instance, |
283 | wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) |
284 | : MAryInstruction(classOpcode), bytecodeOffset_(bytecodeOffset) { |
285 | initOperand(0, def); |
286 | initOperand(1, instance); |
287 | setResultType(MIRType::Int32); |
288 | setMovable(); |
289 | |
290 | // Guard unless the conversion is known to be non-effectful & non-throwing. |
291 | if (MTruncateToInt32::mightHaveSideEffects(def)) { |
292 | setGuard(); |
293 | } |
294 | } |
295 | |
296 | public: |
297 | INSTRUCTION_HEADER(WasmBuiltinTruncateToInt32) |
298 | NAMED_OPERANDS((0, input), (1, instance))MDefinition* input() const { return getOperand(0); } MDefinition * instance() const { return getOperand(1); } |
299 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
300 | |
301 | bool congruentTo(const MDefinition* ins) const override { |
302 | return congruentIfOperandsEqual(ins); |
303 | } |
304 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
305 | |
306 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
307 | |
308 | ALLOW_CLONE(MWasmBuiltinTruncateToInt32)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBuiltinTruncateToInt32 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
309 | }; |
310 | |
311 | class MWasmBuiltinDivI64 : public MAryInstruction<3>, public ArithPolicy::Data { |
312 | bool canBeNegativeZero_; |
313 | bool canBeNegativeOverflow_; |
314 | bool canBeDivideByZero_; |
315 | bool canBeNegativeDividend_; |
316 | bool unsigned_; // If false, signedness will be derived from operands |
317 | bool trapOnError_; |
318 | wasm::BytecodeOffset bytecodeOffset_; |
319 | |
320 | MWasmBuiltinDivI64(MDefinition* left, MDefinition* right, |
321 | MDefinition* instance) |
322 | : MAryInstruction(classOpcode), |
323 | canBeNegativeZero_(true), |
324 | canBeNegativeOverflow_(true), |
325 | canBeDivideByZero_(true), |
326 | canBeNegativeDividend_(true), |
327 | unsigned_(false), |
328 | trapOnError_(false) { |
329 | initOperand(0, left); |
330 | initOperand(1, right); |
331 | initOperand(2, instance); |
332 | |
333 | setResultType(MIRType::Int64); |
334 | setMovable(); |
335 | } |
336 | |
337 | public: |
338 | INSTRUCTION_HEADER(WasmBuiltinDivI64) |
339 | |
340 | NAMED_OPERANDS((0, lhs), (1, rhs), (2, instance))MDefinition* lhs() const { return getOperand(0); } MDefinition * rhs() const { return getOperand(1); } MDefinition* instance () const { return getOperand(2); } |
341 | |
342 | static MWasmBuiltinDivI64* New( |
343 | TempAllocator& alloc, MDefinition* left, MDefinition* right, |
344 | MDefinition* instance, bool unsignd, bool trapOnError = false, |
345 | wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) { |
346 | auto* wasm64Div = new (alloc) MWasmBuiltinDivI64(left, right, instance); |
347 | wasm64Div->unsigned_ = unsignd; |
348 | wasm64Div->trapOnError_ = trapOnError; |
349 | wasm64Div->bytecodeOffset_ = bytecodeOffset; |
350 | if (trapOnError) { |
351 | wasm64Div->setGuard(); // not removable because of possible side-effects. |
352 | wasm64Div->setNotMovable(); |
353 | } |
354 | return wasm64Div; |
355 | } |
356 | |
357 | bool canBeNegativeZero() const { return canBeNegativeZero_; } |
358 | void setCanBeNegativeZero(bool negativeZero) { |
359 | canBeNegativeZero_ = negativeZero; |
360 | } |
361 | |
362 | bool canBeNegativeOverflow() const { return canBeNegativeOverflow_; } |
363 | |
364 | bool canBeDivideByZero() const { return canBeDivideByZero_; } |
365 | |
366 | bool canBeNegativeDividend() const { |
367 | // "Dividend" is an ambiguous concept for unsigned truncated |
368 | // division, because of the truncation procedure: |
369 | // ((x>>>0)/2)|0, for example, gets transformed in |
370 | // MWasmDiv::truncate into a node with lhs representing x (not |
371 | // x>>>0) and rhs representing the constant 2; in other words, |
372 | // the MIR node corresponds to "cast operands to unsigned and |
373 | // divide" operation. In this case, is the dividend x or is it |
374 | // x>>>0? In order to resolve such ambiguities, we disallow |
375 | // the usage of this method for unsigned division. |
376 | MOZ_ASSERT(!unsigned_)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!unsigned_)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!unsigned_))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!unsigned_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 376); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_" ")" ); do { *((volatile int*)__null) = 376; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
377 | return canBeNegativeDividend_; |
378 | } |
379 | |
380 | bool isUnsigned() const { return unsigned_; } |
381 | |
382 | bool trapOnError() const { return trapOnError_; } |
383 | wasm::BytecodeOffset bytecodeOffset() const { |
384 | MOZ_ASSERT(bytecodeOffset_.isValid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeOffset_.isValid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeOffset_.isValid()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeOffset_.isValid()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 384); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()" ")"); do { *((volatile int*)__null) = 384; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
385 | return bytecodeOffset_; |
386 | } |
387 | |
388 | ALLOW_CLONE(MWasmBuiltinDivI64)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBuiltinDivI64 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
389 | }; |
390 | |
391 | class MWasmBuiltinModD : public MAryInstruction<3>, public ArithPolicy::Data { |
392 | wasm::BytecodeOffset bytecodeOffset_; |
393 | |
394 | MWasmBuiltinModD(MDefinition* left, MDefinition* right, MDefinition* instance, |
395 | MIRType type) |
396 | : MAryInstruction(classOpcode) { |
397 | initOperand(0, left); |
398 | initOperand(1, right); |
399 | initOperand(2, instance); |
400 | |
401 | setResultType(type); |
402 | setMovable(); |
403 | } |
404 | |
405 | public: |
406 | INSTRUCTION_HEADER(WasmBuiltinModD) |
407 | NAMED_OPERANDS((0, lhs), (1, rhs), (2, instance))MDefinition* lhs() const { return getOperand(0); } MDefinition * rhs() const { return getOperand(1); } MDefinition* instance () const { return getOperand(2); } |
408 | |
409 | static MWasmBuiltinModD* New( |
410 | TempAllocator& alloc, MDefinition* left, MDefinition* right, |
411 | MDefinition* instance, MIRType type, |
412 | wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) { |
413 | auto* wasmBuiltinModD = |
414 | new (alloc) MWasmBuiltinModD(left, right, instance, type); |
415 | wasmBuiltinModD->bytecodeOffset_ = bytecodeOffset; |
416 | return wasmBuiltinModD; |
417 | } |
418 | |
419 | wasm::BytecodeOffset bytecodeOffset() const { |
420 | MOZ_ASSERT(bytecodeOffset_.isValid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeOffset_.isValid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeOffset_.isValid()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeOffset_.isValid()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 420); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()" ")"); do { *((volatile int*)__null) = 420; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
421 | return bytecodeOffset_; |
422 | } |
423 | |
424 | ALLOW_CLONE(MWasmBuiltinModD)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBuiltinModD (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
425 | }; |
426 | |
427 | class MWasmBuiltinModI64 : public MAryInstruction<3>, public ArithPolicy::Data { |
428 | bool unsigned_; // If false, signedness will be derived from operands |
429 | bool canBeNegativeDividend_; |
430 | bool canBeDivideByZero_; |
431 | bool trapOnError_; |
432 | wasm::BytecodeOffset bytecodeOffset_; |
433 | |
434 | MWasmBuiltinModI64(MDefinition* left, MDefinition* right, |
435 | MDefinition* instance) |
436 | : MAryInstruction(classOpcode), |
437 | unsigned_(false), |
438 | canBeNegativeDividend_(true), |
439 | canBeDivideByZero_(true), |
440 | trapOnError_(false) { |
441 | initOperand(0, left); |
442 | initOperand(1, right); |
443 | initOperand(2, instance); |
444 | |
445 | setResultType(MIRType::Int64); |
446 | setMovable(); |
447 | } |
448 | |
449 | public: |
450 | INSTRUCTION_HEADER(WasmBuiltinModI64) |
451 | |
452 | NAMED_OPERANDS((0, lhs), (1, rhs), (2, instance))MDefinition* lhs() const { return getOperand(0); } MDefinition * rhs() const { return getOperand(1); } MDefinition* instance () const { return getOperand(2); } |
453 | |
454 | static MWasmBuiltinModI64* New( |
455 | TempAllocator& alloc, MDefinition* left, MDefinition* right, |
456 | MDefinition* instance, bool unsignd, bool trapOnError = false, |
457 | wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) { |
458 | auto* mod = new (alloc) MWasmBuiltinModI64(left, right, instance); |
459 | mod->unsigned_ = unsignd; |
460 | mod->trapOnError_ = trapOnError; |
461 | mod->bytecodeOffset_ = bytecodeOffset; |
462 | if (trapOnError) { |
463 | mod->setGuard(); // not removable because of possible side-effects. |
464 | mod->setNotMovable(); |
465 | } |
466 | return mod; |
467 | } |
468 | |
469 | bool canBeNegativeDividend() const { |
470 | MOZ_ASSERT(!unsigned_)do { static_assert( mozilla::detail::AssertionConditionType< decltype(!unsigned_)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!unsigned_))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!unsigned_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_" ")" ); do { *((volatile int*)__null) = 470; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
471 | return canBeNegativeDividend_; |
472 | } |
473 | |
474 | bool canBeDivideByZero() const { return canBeDivideByZero_; } |
475 | |
476 | bool isUnsigned() const { return unsigned_; } |
477 | |
478 | bool trapOnError() const { return trapOnError_; } |
479 | wasm::BytecodeOffset bytecodeOffset() const { |
480 | MOZ_ASSERT(bytecodeOffset_.isValid())do { static_assert( mozilla::detail::AssertionConditionType< decltype(bytecodeOffset_.isValid())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(bytecodeOffset_.isValid()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("bytecodeOffset_.isValid()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()" ")"); do { *((volatile int*)__null) = 480; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
481 | return bytecodeOffset_; |
482 | } |
483 | |
484 | ALLOW_CLONE(MWasmBuiltinModI64)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBuiltinModI64 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
485 | }; |
486 | |
487 | // Check whether we need to fire the interrupt handler (in wasm code). |
488 | class MWasmInterruptCheck : public MUnaryInstruction, |
489 | public NoTypePolicy::Data { |
490 | wasm::BytecodeOffset bytecodeOffset_; |
491 | |
492 | MWasmInterruptCheck(MDefinition* instance, |
493 | wasm::BytecodeOffset bytecodeOffset) |
494 | : MUnaryInstruction(classOpcode, instance), |
495 | bytecodeOffset_(bytecodeOffset) { |
496 | setGuard(); |
497 | } |
498 | |
499 | public: |
500 | INSTRUCTION_HEADER(WasmInterruptCheck) |
501 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
502 | NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); } |
503 | |
504 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
505 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
506 | }; |
507 | |
508 | // Directly jumps to the indicated trap, leaving Wasm code and reporting a |
509 | // runtime error. |
510 | |
511 | class MWasmTrap : public MAryControlInstruction<0, 0>, |
512 | public NoTypePolicy::Data { |
513 | wasm::Trap trap_; |
514 | wasm::BytecodeOffset bytecodeOffset_; |
515 | |
516 | explicit MWasmTrap(wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset) |
517 | : MAryControlInstruction(classOpcode), |
518 | trap_(trap), |
519 | bytecodeOffset_(bytecodeOffset) {} |
520 | |
521 | public: |
522 | INSTRUCTION_HEADER(WasmTrap) |
523 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
524 | |
525 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
526 | |
527 | wasm::Trap trap() const { return trap_; } |
528 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
529 | }; |
530 | |
531 | // Flips the input's sign bit, independently of the rest of the number's |
532 | // payload. Note this is different from multiplying by minus-one, which has |
533 | // side-effects for e.g. NaNs. |
534 | class MWasmNeg : public MUnaryInstruction, public NoTypePolicy::Data { |
535 | MWasmNeg(MDefinition* op, MIRType type) : MUnaryInstruction(classOpcode, op) { |
536 | setResultType(type); |
537 | setMovable(); |
538 | } |
539 | |
540 | public: |
541 | INSTRUCTION_HEADER(WasmNeg) |
542 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
543 | }; |
544 | |
545 | // Machine-level bitwise AND/OR/XOR, avoiding all JS-level complexity embodied |
546 | // in MBinaryBitwiseInstruction. |
547 | class MWasmBinaryBitwise : public MBinaryInstruction, |
548 | public NoTypePolicy::Data { |
549 | public: |
550 | enum class SubOpcode { And, Or, Xor }; |
551 | |
552 | protected: |
553 | MWasmBinaryBitwise(MDefinition* left, MDefinition* right, MIRType type, |
554 | SubOpcode subOpcode) |
555 | : MBinaryInstruction(classOpcode, left, right), subOpcode_(subOpcode) { |
556 | MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == MIRType::Int32 || type == MIRType::Int64)> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(type == MIRType::Int32 || type == MIRType::Int64))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Int32 || type == MIRType::Int64" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 556); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32 || type == MIRType::Int64" ")"); do { *((volatile int*)__null) = 556; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
557 | setResultType(type); |
558 | setMovable(); |
559 | setCommutative(); |
560 | } |
561 | |
562 | public: |
563 | INSTRUCTION_HEADER(WasmBinaryBitwise) |
564 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
565 | |
566 | SubOpcode subOpcode() const { return subOpcode_; } |
567 | MDefinition* foldsTo(TempAllocator& alloc) override; |
568 | |
569 | bool congruentTo(const MDefinition* ins) const override { |
570 | return ins->isWasmBinaryBitwise() && |
571 | ins->toWasmBinaryBitwise()->subOpcode() == subOpcode() && |
572 | binaryCongruentTo(ins); |
573 | } |
574 | |
575 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
576 | |
577 | #ifdef JS_JITSPEW1 |
578 | void getExtras(ExtrasCollector* extras) const override { |
579 | const char* what = "!!unknown!!"; |
Value stored to 'what' during its initialization is never read | |
580 | switch (subOpcode()) { |
581 | case SubOpcode::And: |
582 | what = "And"; |
583 | break; |
584 | case SubOpcode::Or: |
585 | what = "Or"; |
586 | break; |
587 | case SubOpcode::Xor: |
588 | what = "Xor"; |
589 | break; |
590 | } |
591 | extras->add(what); |
592 | } |
593 | #endif |
594 | |
595 | private: |
596 | SubOpcode subOpcode_; |
597 | |
598 | ALLOW_CLONE(MWasmBinaryBitwise)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBinaryBitwise (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
599 | }; |
600 | |
601 | class MWasmLoadInstance : public MUnaryInstruction, public NoTypePolicy::Data { |
602 | uint32_t offset_; |
603 | AliasSet aliases_; |
604 | |
605 | explicit MWasmLoadInstance(MDefinition* instance, uint32_t offset, |
606 | MIRType type, AliasSet aliases) |
607 | : MUnaryInstruction(classOpcode, instance), |
608 | offset_(offset), |
609 | aliases_(aliases) { |
610 | // Different instance data have different alias classes and only those |
611 | // classes are allowed. |
612 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
613 | aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
614 | aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
615 | aliases_.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
616 | AliasSet::Load(AliasSet::WasmPendingException).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
617 | aliases_.flags() == AliasSet::None().flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta ).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException ).flags() || aliases_.flags() == AliasSet::None().flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 617); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Load(AliasSet::WasmHeapMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmTableMeta).flags() || aliases_.flags() == AliasSet::Load(AliasSet::WasmPendingException).flags() || aliases_.flags() == AliasSet::None().flags()" ")"); do { *((volatile int*)__null) = 617; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
618 | |
619 | // The only types supported at the moment. |
620 | MOZ_ASSERT(type == MIRType::Pointer || type == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
621 | type == MIRType::Int64 || type == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 621); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 621; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
622 | |
623 | setMovable(); |
624 | setResultType(type); |
625 | } |
626 | |
627 | public: |
628 | INSTRUCTION_HEADER(WasmLoadInstance) |
629 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
630 | NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); } |
631 | |
632 | uint32_t offset() const { return offset_; } |
633 | |
634 | bool congruentTo(const MDefinition* ins) const override { |
635 | return op() == ins->op() && |
636 | offset() == ins->toWasmLoadInstance()->offset() && |
637 | type() == ins->type(); |
638 | } |
639 | |
640 | HashNumber valueHash() const override { |
641 | return addU32ToHash(HashNumber(op()), offset()); |
642 | } |
643 | |
644 | AliasSet getAliasSet() const override { return aliases_; } |
645 | }; |
646 | |
647 | class MWasmStoreInstance : public MBinaryInstruction, |
648 | public NoTypePolicy::Data { |
649 | uint32_t offset_; |
650 | AliasSet aliases_; |
651 | |
652 | explicit MWasmStoreInstance(MDefinition* instance, MDefinition* value, |
653 | uint32_t offset, MIRType type, AliasSet aliases) |
654 | : MBinaryInstruction(classOpcode, instance, value), |
655 | offset_(offset), |
656 | aliases_(aliases) { |
657 | // Different instance data have different alias classes and only those |
658 | // classes are allowed. |
659 | MOZ_ASSERT(aliases_.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases_.flags() == AliasSet::Store (AliasSet::WasmPendingException).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()" ")"); do { *((volatile int*)__null) = 660; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
660 | AliasSet::Store(AliasSet::WasmPendingException).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases_.flags() == AliasSet::Store (AliasSet::WasmPendingException).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 660); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()" ")"); do { *((volatile int*)__null) = 660; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
661 | |
662 | // The only types supported at the moment. |
663 | MOZ_ASSERT(type == MIRType::Pointer || type == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 664; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
664 | type == MIRType::Int64 || type == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef)>:: isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 664); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 664; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
665 | } |
666 | |
667 | public: |
668 | INSTRUCTION_HEADER(WasmStoreInstance) |
669 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
670 | NAMED_OPERANDS((0, instance), (1, value))MDefinition* instance() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } |
671 | |
672 | uint32_t offset() const { return offset_; } |
673 | |
674 | AliasSet getAliasSet() const override { return aliases_; } |
675 | }; |
676 | |
677 | class MWasmHeapReg : public MNullaryInstruction { |
678 | AliasSet aliases_; |
679 | |
680 | explicit MWasmHeapReg(AliasSet aliases) |
681 | : MNullaryInstruction(classOpcode), aliases_(aliases) { |
682 | setMovable(); |
683 | setResultType(MIRType::Pointer); |
684 | } |
685 | |
686 | public: |
687 | INSTRUCTION_HEADER(WasmHeapReg) |
688 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
689 | |
690 | bool congruentTo(const MDefinition* ins) const override { |
691 | return ins->isWasmHeapReg(); |
692 | } |
693 | |
694 | AliasSet getAliasSet() const override { return aliases_; } |
695 | }; |
696 | |
697 | // For memory32, bounds check nodes are of type Int32 on 32-bit systems for both |
698 | // wasm and asm.js code, as well as on 64-bit systems for asm.js code and for |
699 | // wasm code that is known to have a bounds check limit that fits into 32 bits. |
700 | // They are of type Int64 only on 64-bit systems for wasm code with 4GB heaps. |
701 | // There is no way for nodes of both types to be present in the same function. |
702 | // Should this change, then BCE must be updated to take type into account. |
703 | // |
704 | // For memory64, bounds check nodes are always of type Int64. |
705 | |
706 | class MWasmBoundsCheck : public MBinaryInstruction, public NoTypePolicy::Data { |
707 | public: |
708 | enum Target { |
709 | // Linear memory at index zero, which is the only memory allowed so far. |
710 | Memory0, |
711 | // Everything else. Currently comprises tables, and arrays in the GC |
712 | // proposal. |
713 | Unknown |
714 | }; |
715 | |
716 | private: |
717 | wasm::BytecodeOffset bytecodeOffset_; |
718 | Target target_; |
719 | |
720 | explicit MWasmBoundsCheck(MDefinition* index, MDefinition* boundsCheckLimit, |
721 | wasm::BytecodeOffset bytecodeOffset, Target target) |
722 | : MBinaryInstruction(classOpcode, index, boundsCheckLimit), |
723 | bytecodeOffset_(bytecodeOffset), |
724 | target_(target) { |
725 | MOZ_ASSERT(index->type() == boundsCheckLimit->type())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index->type() == boundsCheckLimit->type())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(index->type() == boundsCheckLimit->type()))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("index->type() == boundsCheckLimit->type()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == boundsCheckLimit->type()" ")"); do { *((volatile int*)__null) = 725; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
726 | |
727 | // Bounds check is effectful: it throws for OOB. |
728 | setGuard(); |
729 | |
730 | if (JitOptions.spectreIndexMasking) { |
731 | setResultType(index->type()); |
732 | } |
733 | } |
734 | |
735 | public: |
736 | INSTRUCTION_HEADER(WasmBoundsCheck) |
737 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
738 | NAMED_OPERANDS((0, index), (1, boundsCheckLimit))MDefinition* index() const { return getOperand(0); } MDefinition * boundsCheckLimit() const { return getOperand(1); } |
739 | |
740 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
741 | |
742 | bool isMemory0() const { return target_ == MWasmBoundsCheck::Memory0; } |
743 | |
744 | bool isRedundant() const { return !isGuard(); } |
745 | |
746 | void setRedundant() { setNotGuard(); } |
747 | |
748 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
749 | }; |
750 | |
751 | class MWasmAddOffset : public MUnaryInstruction, public NoTypePolicy::Data { |
752 | uint64_t offset_; |
753 | wasm::BytecodeOffset bytecodeOffset_; |
754 | |
755 | MWasmAddOffset(MDefinition* base, uint64_t offset, |
756 | wasm::BytecodeOffset bytecodeOffset) |
757 | : MUnaryInstruction(classOpcode, base), |
758 | offset_(offset), |
759 | bytecodeOffset_(bytecodeOffset) { |
760 | setGuard(); |
761 | MOZ_ASSERT(base->type() == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::Int32 || base->type() == MIRType::Int64)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(base->type() == MIRType:: Int32 || base->type() == MIRType::Int64))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::Int32 || base->type() == MIRType::Int64" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Int32 || base->type() == MIRType::Int64" ")"); do { *((volatile int*)__null) = 762; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
762 | base->type() == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::Int32 || base->type() == MIRType::Int64)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(base->type() == MIRType:: Int32 || base->type() == MIRType::Int64))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::Int32 || base->type() == MIRType::Int64" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 762); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Int32 || base->type() == MIRType::Int64" ")"); do { *((volatile int*)__null) = 762; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
763 | setResultType(base->type()); |
764 | } |
765 | |
766 | public: |
767 | INSTRUCTION_HEADER(WasmAddOffset) |
768 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
769 | NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); } |
770 | |
771 | MDefinition* foldsTo(TempAllocator& alloc) override; |
772 | |
773 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
774 | |
775 | uint64_t offset() const { return offset_; } |
776 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
777 | }; |
778 | |
779 | class MWasmAlignmentCheck : public MUnaryInstruction, |
780 | public NoTypePolicy::Data { |
781 | uint32_t byteSize_; |
782 | wasm::BytecodeOffset bytecodeOffset_; |
783 | |
784 | explicit MWasmAlignmentCheck(MDefinition* index, uint32_t byteSize, |
785 | wasm::BytecodeOffset bytecodeOffset) |
786 | : MUnaryInstruction(classOpcode, index), |
787 | byteSize_(byteSize), |
788 | bytecodeOffset_(bytecodeOffset) { |
789 | MOZ_ASSERT(mozilla::IsPowerOfTwo(byteSize))do { static_assert( mozilla::detail::AssertionConditionType< decltype(mozilla::IsPowerOfTwo(byteSize))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(mozilla::IsPowerOfTwo(byteSize )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("mozilla::IsPowerOfTwo(byteSize)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 789); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::IsPowerOfTwo(byteSize)" ")"); do { *((volatile int*)__null) = 789; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
790 | // Alignment check is effectful: it throws for unaligned. |
791 | setGuard(); |
792 | } |
793 | |
794 | public: |
795 | INSTRUCTION_HEADER(WasmAlignmentCheck) |
796 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
797 | NAMED_OPERANDS((0, index))MDefinition* index() const { return getOperand(0); } |
798 | |
799 | bool congruentTo(const MDefinition* ins) const override; |
800 | |
801 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
802 | |
803 | uint32_t byteSize() const { return byteSize_; } |
804 | |
805 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
806 | }; |
807 | |
808 | class MWasmLoad |
809 | : public MVariadicInstruction, // memoryBase is nullptr on some platforms |
810 | public NoTypePolicy::Data { |
811 | wasm::MemoryAccessDesc access_; |
812 | |
813 | explicit MWasmLoad(const wasm::MemoryAccessDesc& access, MIRType resultType) |
814 | : MVariadicInstruction(classOpcode), access_(access) { |
815 | setGuard(); |
816 | setResultType(resultType); |
817 | } |
818 | |
819 | public: |
820 | INSTRUCTION_HEADER(WasmLoad) |
821 | NAMED_OPERANDS((0, base), (1, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition * memoryBase() const { return getOperand(1); }; |
822 | |
823 | static MWasmLoad* New(TempAllocator& alloc, MDefinition* memoryBase, |
824 | MDefinition* base, const wasm::MemoryAccessDesc& access, |
825 | MIRType resultType) { |
826 | MWasmLoad* load = new (alloc) MWasmLoad(access, resultType); |
827 | if (!load->init(alloc, 1 + !!memoryBase)) { |
828 | return nullptr; |
829 | } |
830 | |
831 | load->initOperand(0, base); |
832 | if (memoryBase) { |
833 | load->initOperand(1, memoryBase); |
834 | } |
835 | |
836 | return load; |
837 | } |
838 | |
839 | const wasm::MemoryAccessDesc& access() const { return access_; } |
840 | |
841 | AliasSet getAliasSet() const override { |
842 | // When a barrier is needed, make the instruction effectful by giving |
843 | // it a "store" effect. |
844 | if (access_.isAtomic()) { |
845 | return AliasSet::Store(AliasSet::WasmHeap); |
846 | } |
847 | return AliasSet::Load(AliasSet::WasmHeap); |
848 | } |
849 | |
850 | bool hasMemoryBase() const { return numOperands() > 1; } |
851 | |
852 | #ifdef JS_JITSPEW1 |
853 | void getExtras(ExtrasCollector* extras) const override { |
854 | char buf[64]; |
855 | SprintfLiteral(buf, "(offs=%lld)", (long long int)access().offset64()); |
856 | extras->add(buf); |
857 | } |
858 | #endif |
859 | }; |
860 | |
861 | class MWasmStore : public MVariadicInstruction, public NoTypePolicy::Data { |
862 | wasm::MemoryAccessDesc access_; |
863 | |
864 | explicit MWasmStore(const wasm::MemoryAccessDesc& access) |
865 | : MVariadicInstruction(classOpcode), access_(access) { |
866 | setGuard(); |
867 | } |
868 | |
869 | public: |
870 | INSTRUCTION_HEADER(WasmStore) |
871 | NAMED_OPERANDS((0, base), (1, value), (2, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } MDefinition* memoryBase () const { return getOperand(2); } |
872 | |
873 | static MWasmStore* New(TempAllocator& alloc, MDefinition* memoryBase, |
874 | MDefinition* base, |
875 | const wasm::MemoryAccessDesc& access, |
876 | MDefinition* value) { |
877 | MWasmStore* store = new (alloc) MWasmStore(access); |
878 | if (!store->init(alloc, 2 + !!memoryBase)) { |
879 | return nullptr; |
880 | } |
881 | |
882 | store->initOperand(0, base); |
883 | store->initOperand(1, value); |
884 | if (memoryBase) { |
885 | store->initOperand(2, memoryBase); |
886 | } |
887 | |
888 | return store; |
889 | } |
890 | |
891 | const wasm::MemoryAccessDesc& access() const { return access_; } |
892 | |
893 | AliasSet getAliasSet() const override { |
894 | return AliasSet::Store(AliasSet::WasmHeap); |
895 | } |
896 | |
897 | bool hasMemoryBase() const { return numOperands() > 2; } |
898 | |
899 | #ifdef JS_JITSPEW1 |
900 | void getExtras(ExtrasCollector* extras) const override { |
901 | char buf[64]; |
902 | SprintfLiteral(buf, "(offs=%lld)", (long long int)access().offset64()); |
903 | extras->add(buf); |
904 | } |
905 | #endif |
906 | }; |
907 | |
908 | class MAsmJSMemoryAccess { |
909 | Scalar::Type accessType_; |
910 | bool needsBoundsCheck_; |
911 | |
912 | public: |
913 | explicit MAsmJSMemoryAccess(Scalar::Type accessType) |
914 | : accessType_(accessType), needsBoundsCheck_(true) { |
915 | MOZ_ASSERT(accessType != Scalar::Uint8Clamped)do { static_assert( mozilla::detail::AssertionConditionType< decltype(accessType != Scalar::Uint8Clamped)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(accessType != Scalar::Uint8Clamped ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "accessType != Scalar::Uint8Clamped", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 915); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessType != Scalar::Uint8Clamped" ")"); do { *((volatile int*)__null) = 915; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
916 | } |
917 | |
918 | Scalar::Type accessType() const { return accessType_; } |
919 | unsigned byteSize() const { return TypedArrayElemSize(accessType()); } |
920 | bool needsBoundsCheck() const { return needsBoundsCheck_; } |
921 | |
922 | wasm::MemoryAccessDesc access() const { |
923 | return wasm::MemoryAccessDesc(0, accessType_, Scalar::byteSize(accessType_), |
924 | 0, wasm::BytecodeOffset(), false); |
925 | } |
926 | |
927 | void removeBoundsCheck() { needsBoundsCheck_ = false; } |
928 | }; |
929 | |
930 | class MAsmJSLoadHeap |
931 | : public MVariadicInstruction, // 1 plus optional memoryBase and |
932 | // boundsCheckLimit |
933 | public MAsmJSMemoryAccess, |
934 | public NoTypePolicy::Data { |
935 | uint32_t memoryBaseIndex_; |
936 | |
937 | explicit MAsmJSLoadHeap(uint32_t memoryBaseIndex, Scalar::Type accessType) |
938 | : MVariadicInstruction(classOpcode), |
939 | MAsmJSMemoryAccess(accessType), |
940 | memoryBaseIndex_(memoryBaseIndex) { |
941 | setResultType(ScalarTypeToMIRType(accessType)); |
942 | } |
943 | |
944 | public: |
945 | INSTRUCTION_HEADER(AsmJSLoadHeap) |
946 | NAMED_OPERANDS((0, base), (1, boundsCheckLimit))MDefinition* base() const { return getOperand(0); } MDefinition * boundsCheckLimit() const { return getOperand(1); } |
947 | |
948 | static MAsmJSLoadHeap* New(TempAllocator& alloc, MDefinition* memoryBase, |
949 | MDefinition* base, MDefinition* boundsCheckLimit, |
950 | Scalar::Type accessType) { |
951 | uint32_t nextIndex = 2; |
952 | uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U); |
953 | |
954 | MAsmJSLoadHeap* load = |
955 | new (alloc) MAsmJSLoadHeap(memoryBaseIndex, accessType); |
956 | if (!load->init(alloc, nextIndex)) { |
957 | return nullptr; |
958 | } |
959 | |
960 | load->initOperand(0, base); |
961 | load->initOperand(1, boundsCheckLimit); |
962 | if (memoryBase) { |
963 | load->initOperand(memoryBaseIndex, memoryBase); |
964 | } |
965 | |
966 | return load; |
967 | } |
968 | |
969 | bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); } |
970 | MDefinition* memoryBase() const { |
971 | MOZ_ASSERT(hasMemoryBase())do { static_assert( mozilla::detail::AssertionConditionType< decltype(hasMemoryBase())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(hasMemoryBase()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasMemoryBase()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()" ")"); do { *((volatile int*)__null) = 971; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
972 | return getOperand(memoryBaseIndex_); |
973 | } |
974 | |
975 | bool congruentTo(const MDefinition* ins) const override; |
976 | AliasSet getAliasSet() const override { |
977 | return AliasSet::Load(AliasSet::WasmHeap); |
978 | } |
979 | AliasType mightAlias(const MDefinition* def) const override; |
980 | }; |
981 | |
982 | class MAsmJSStoreHeap |
983 | : public MVariadicInstruction, // 2 plus optional memoryBase and |
984 | // boundsCheckLimit |
985 | public MAsmJSMemoryAccess, |
986 | public NoTypePolicy::Data { |
987 | uint32_t memoryBaseIndex_; |
988 | |
989 | explicit MAsmJSStoreHeap(uint32_t memoryBaseIndex, Scalar::Type accessType) |
990 | : MVariadicInstruction(classOpcode), |
991 | MAsmJSMemoryAccess(accessType), |
992 | memoryBaseIndex_(memoryBaseIndex) {} |
993 | |
994 | public: |
995 | INSTRUCTION_HEADER(AsmJSStoreHeap) |
996 | NAMED_OPERANDS((0, base), (1, value), (2, boundsCheckLimit))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } MDefinition* boundsCheckLimit () const { return getOperand(2); } |
997 | |
998 | static MAsmJSStoreHeap* New(TempAllocator& alloc, MDefinition* memoryBase, |
999 | MDefinition* base, MDefinition* boundsCheckLimit, |
1000 | Scalar::Type accessType, MDefinition* v) { |
1001 | uint32_t nextIndex = 3; |
1002 | uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U); |
1003 | |
1004 | MAsmJSStoreHeap* store = |
1005 | new (alloc) MAsmJSStoreHeap(memoryBaseIndex, accessType); |
1006 | if (!store->init(alloc, nextIndex)) { |
1007 | return nullptr; |
1008 | } |
1009 | |
1010 | store->initOperand(0, base); |
1011 | store->initOperand(1, v); |
1012 | store->initOperand(2, boundsCheckLimit); |
1013 | if (memoryBase) { |
1014 | store->initOperand(memoryBaseIndex, memoryBase); |
1015 | } |
1016 | |
1017 | return store; |
1018 | } |
1019 | |
1020 | bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); } |
1021 | MDefinition* memoryBase() const { |
1022 | MOZ_ASSERT(hasMemoryBase())do { static_assert( mozilla::detail::AssertionConditionType< decltype(hasMemoryBase())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(hasMemoryBase()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasMemoryBase()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()" ")"); do { *((volatile int*)__null) = 1022; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1023 | return getOperand(memoryBaseIndex_); |
1024 | } |
1025 | |
1026 | AliasSet getAliasSet() const override { |
1027 | return AliasSet::Store(AliasSet::WasmHeap); |
1028 | } |
1029 | }; |
1030 | |
1031 | class MWasmCompareExchangeHeap : public MVariadicInstruction, |
1032 | public NoTypePolicy::Data { |
1033 | wasm::MemoryAccessDesc access_; |
1034 | wasm::BytecodeOffset bytecodeOffset_; |
1035 | |
1036 | explicit MWasmCompareExchangeHeap(const wasm::MemoryAccessDesc& access, |
1037 | wasm::BytecodeOffset bytecodeOffset) |
1038 | : MVariadicInstruction(classOpcode), |
1039 | access_(access), |
1040 | bytecodeOffset_(bytecodeOffset) { |
1041 | setGuard(); // Not removable |
1042 | setResultType(ScalarTypeToMIRType(access.type())); |
1043 | } |
1044 | |
1045 | public: |
1046 | INSTRUCTION_HEADER(WasmCompareExchangeHeap) |
1047 | NAMED_OPERANDS((0, base), (1, oldValue), (2, newValue), (3, instance),MDefinition* base() const { return getOperand(0); } MDefinition * oldValue() const { return getOperand(1); } MDefinition* newValue () const { return getOperand(2); } MDefinition* instance() const { return getOperand(3); } MDefinition* memoryBase() const { return getOperand(4); } |
1048 | (4, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition * oldValue() const { return getOperand(1); } MDefinition* newValue () const { return getOperand(2); } MDefinition* instance() const { return getOperand(3); } MDefinition* memoryBase() const { return getOperand(4); } |
1049 | |
1050 | static MWasmCompareExchangeHeap* New(TempAllocator& alloc, |
1051 | wasm::BytecodeOffset bytecodeOffset, |
1052 | MDefinition* memoryBase, |
1053 | MDefinition* base, |
1054 | const wasm::MemoryAccessDesc& access, |
1055 | MDefinition* oldv, MDefinition* newv, |
1056 | MDefinition* instance) { |
1057 | MWasmCompareExchangeHeap* cas = |
1058 | new (alloc) MWasmCompareExchangeHeap(access, bytecodeOffset); |
1059 | if (!cas->init(alloc, 4 + !!memoryBase)) { |
1060 | return nullptr; |
1061 | } |
1062 | cas->initOperand(0, base); |
1063 | cas->initOperand(1, oldv); |
1064 | cas->initOperand(2, newv); |
1065 | cas->initOperand(3, instance); |
1066 | if (memoryBase) { |
1067 | cas->initOperand(4, memoryBase); |
1068 | } |
1069 | return cas; |
1070 | } |
1071 | |
1072 | const wasm::MemoryAccessDesc& access() const { return access_; } |
1073 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
1074 | |
1075 | AliasSet getAliasSet() const override { |
1076 | return AliasSet::Store(AliasSet::WasmHeap); |
1077 | } |
1078 | |
1079 | bool hasMemoryBase() const { return numOperands() > 4; } |
1080 | }; |
1081 | |
1082 | class MWasmAtomicExchangeHeap : public MVariadicInstruction, |
1083 | public NoTypePolicy::Data { |
1084 | wasm::MemoryAccessDesc access_; |
1085 | wasm::BytecodeOffset bytecodeOffset_; |
1086 | |
1087 | explicit MWasmAtomicExchangeHeap(const wasm::MemoryAccessDesc& access, |
1088 | wasm::BytecodeOffset bytecodeOffset) |
1089 | : MVariadicInstruction(classOpcode), |
1090 | access_(access), |
1091 | bytecodeOffset_(bytecodeOffset) { |
1092 | setGuard(); // Not removable |
1093 | setResultType(ScalarTypeToMIRType(access.type())); |
1094 | } |
1095 | |
1096 | public: |
1097 | INSTRUCTION_HEADER(WasmAtomicExchangeHeap) |
1098 | NAMED_OPERANDS((0, base), (1, value), (2, instance), (3, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } MDefinition* instance () const { return getOperand(2); } MDefinition* memoryBase() const { return getOperand(3); } |
1099 | |
1100 | static MWasmAtomicExchangeHeap* New(TempAllocator& alloc, |
1101 | wasm::BytecodeOffset bytecodeOffset, |
1102 | MDefinition* memoryBase, |
1103 | MDefinition* base, |
1104 | const wasm::MemoryAccessDesc& access, |
1105 | MDefinition* value, |
1106 | MDefinition* instance) { |
1107 | MWasmAtomicExchangeHeap* xchg = |
1108 | new (alloc) MWasmAtomicExchangeHeap(access, bytecodeOffset); |
1109 | if (!xchg->init(alloc, 3 + !!memoryBase)) { |
1110 | return nullptr; |
1111 | } |
1112 | |
1113 | xchg->initOperand(0, base); |
1114 | xchg->initOperand(1, value); |
1115 | xchg->initOperand(2, instance); |
1116 | if (memoryBase) { |
1117 | xchg->initOperand(3, memoryBase); |
1118 | } |
1119 | |
1120 | return xchg; |
1121 | } |
1122 | |
1123 | const wasm::MemoryAccessDesc& access() const { return access_; } |
1124 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
1125 | |
1126 | AliasSet getAliasSet() const override { |
1127 | return AliasSet::Store(AliasSet::WasmHeap); |
1128 | } |
1129 | |
1130 | bool hasMemoryBase() const { return numOperands() > 3; } |
1131 | }; |
1132 | |
1133 | class MWasmAtomicBinopHeap : public MVariadicInstruction, |
1134 | public NoTypePolicy::Data { |
1135 | AtomicOp op_; |
1136 | wasm::MemoryAccessDesc access_; |
1137 | wasm::BytecodeOffset bytecodeOffset_; |
1138 | |
1139 | explicit MWasmAtomicBinopHeap(AtomicOp op, |
1140 | const wasm::MemoryAccessDesc& access, |
1141 | wasm::BytecodeOffset bytecodeOffset) |
1142 | : MVariadicInstruction(classOpcode), |
1143 | op_(op), |
1144 | access_(access), |
1145 | bytecodeOffset_(bytecodeOffset) { |
1146 | setGuard(); // Not removable |
1147 | setResultType(ScalarTypeToMIRType(access.type())); |
1148 | } |
1149 | |
1150 | public: |
1151 | INSTRUCTION_HEADER(WasmAtomicBinopHeap) |
1152 | NAMED_OPERANDS((0, base), (1, value), (2, instance), (3, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } MDefinition* instance () const { return getOperand(2); } MDefinition* memoryBase() const { return getOperand(3); } |
1153 | |
1154 | static MWasmAtomicBinopHeap* New(TempAllocator& alloc, |
1155 | wasm::BytecodeOffset bytecodeOffset, |
1156 | AtomicOp op, MDefinition* memoryBase, |
1157 | MDefinition* base, |
1158 | const wasm::MemoryAccessDesc& access, |
1159 | MDefinition* v, MDefinition* instance) { |
1160 | MWasmAtomicBinopHeap* binop = |
1161 | new (alloc) MWasmAtomicBinopHeap(op, access, bytecodeOffset); |
1162 | if (!binop->init(alloc, 3 + !!memoryBase)) { |
1163 | return nullptr; |
1164 | } |
1165 | |
1166 | binop->initOperand(0, base); |
1167 | binop->initOperand(1, v); |
1168 | binop->initOperand(2, instance); |
1169 | if (memoryBase) { |
1170 | binop->initOperand(3, memoryBase); |
1171 | } |
1172 | |
1173 | return binop; |
1174 | } |
1175 | |
1176 | AtomicOp operation() const { return op_; } |
1177 | const wasm::MemoryAccessDesc& access() const { return access_; } |
1178 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
1179 | |
1180 | AliasSet getAliasSet() const override { |
1181 | return AliasSet::Store(AliasSet::WasmHeap); |
1182 | } |
1183 | |
1184 | bool hasMemoryBase() const { return numOperands() > 3; } |
1185 | }; |
1186 | |
1187 | class MWasmLoadInstanceDataField : public MUnaryInstruction, |
1188 | public NoTypePolicy::Data { |
1189 | MWasmLoadInstanceDataField(MIRType type, unsigned instanceDataOffset, |
1190 | bool isConstant, MDefinition* instance) |
1191 | : MUnaryInstruction(classOpcode, instance), |
1192 | instanceDataOffset_(instanceDataOffset), |
1193 | isConstant_(isConstant) { |
1194 | MOZ_ASSERT(IsNumberType(type) || type == MIRType::Simd128 ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(IsNumberType(type) || type == MIRType::Simd128 || type == MIRType ::Pointer || type == MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 1195; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1195 | type == MIRType::Pointer || type == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(IsNumberType(type) || type == MIRType::Simd128 || type == MIRType ::Pointer || type == MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1195); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 1195; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1196 | setResultType(type); |
1197 | setMovable(); |
1198 | } |
1199 | |
1200 | unsigned instanceDataOffset_; |
1201 | bool isConstant_; |
1202 | |
1203 | public: |
1204 | INSTRUCTION_HEADER(WasmLoadInstanceDataField) |
1205 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1206 | NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); } |
1207 | |
1208 | unsigned instanceDataOffset() const { return instanceDataOffset_; } |
1209 | |
1210 | HashNumber valueHash() const override; |
1211 | bool congruentTo(const MDefinition* ins) const override; |
1212 | MDefinition* foldsTo(TempAllocator& alloc) override; |
1213 | |
1214 | AliasSet getAliasSet() const override { |
1215 | return isConstant_ ? AliasSet::None() |
1216 | : AliasSet::Load(AliasSet::WasmInstanceData); |
1217 | } |
1218 | |
1219 | AliasType mightAlias(const MDefinition* def) const override; |
1220 | |
1221 | #ifdef JS_JITSPEW1 |
1222 | void getExtras(ExtrasCollector* extras) const override { |
1223 | char buf[96]; |
1224 | SprintfLiteral(buf, "(offs=%lld, isConst=%s)", |
1225 | (long long int)instanceDataOffset_, |
1226 | isConstant_ ? "true" : "false"); |
1227 | extras->add(buf); |
1228 | } |
1229 | #endif |
1230 | }; |
1231 | |
1232 | class MWasmLoadGlobalCell : public MUnaryInstruction, |
1233 | public NoTypePolicy::Data { |
1234 | MWasmLoadGlobalCell(MIRType type, MDefinition* cellPtr) |
1235 | : MUnaryInstruction(classOpcode, cellPtr) { |
1236 | setResultType(type); |
1237 | setMovable(); |
1238 | } |
1239 | |
1240 | public: |
1241 | INSTRUCTION_HEADER(WasmLoadGlobalCell) |
1242 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1243 | NAMED_OPERANDS((0, cellPtr))MDefinition* cellPtr() const { return getOperand(0); } |
1244 | |
1245 | // The default valueHash is good enough, because there are no non-operand |
1246 | // fields. |
1247 | bool congruentTo(const MDefinition* ins) const override; |
1248 | |
1249 | AliasSet getAliasSet() const override { |
1250 | return AliasSet::Load(AliasSet::WasmGlobalCell); |
1251 | } |
1252 | |
1253 | AliasType mightAlias(const MDefinition* def) const override; |
1254 | }; |
1255 | |
1256 | class MWasmLoadTableElement : public MBinaryInstruction, |
1257 | public NoTypePolicy::Data { |
1258 | MWasmLoadTableElement(MDefinition* elements, MDefinition* index) |
1259 | : MBinaryInstruction(classOpcode, elements, index) { |
1260 | setResultType(MIRType::WasmAnyRef); |
1261 | setMovable(); |
1262 | } |
1263 | |
1264 | public: |
1265 | INSTRUCTION_HEADER(WasmLoadTableElement) |
1266 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1267 | NAMED_OPERANDS((0, elements))MDefinition* elements() const { return getOperand(0); } |
1268 | NAMED_OPERANDS((1, index))MDefinition* index() const { return getOperand(1); } |
1269 | |
1270 | AliasSet getAliasSet() const override { |
1271 | return AliasSet::Load(AliasSet::WasmTableElement); |
1272 | } |
1273 | }; |
1274 | |
1275 | class MWasmStoreInstanceDataField : public MBinaryInstruction, |
1276 | public NoTypePolicy::Data { |
1277 | MWasmStoreInstanceDataField(unsigned instanceDataOffset, MDefinition* value, |
1278 | MDefinition* instance) |
1279 | : MBinaryInstruction(classOpcode, value, instance), |
1280 | instanceDataOffset_(instanceDataOffset) {} |
1281 | |
1282 | unsigned instanceDataOffset_; |
1283 | |
1284 | public: |
1285 | INSTRUCTION_HEADER(WasmStoreInstanceDataField) |
1286 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1287 | NAMED_OPERANDS((0, value), (1, instance))MDefinition* value() const { return getOperand(0); } MDefinition * instance() const { return getOperand(1); } |
1288 | |
1289 | unsigned instanceDataOffset() const { return instanceDataOffset_; } |
1290 | |
1291 | AliasSet getAliasSet() const override { |
1292 | return AliasSet::Store(AliasSet::WasmInstanceData); |
1293 | } |
1294 | }; |
1295 | |
1296 | class MWasmStoreGlobalCell : public MBinaryInstruction, |
1297 | public NoTypePolicy::Data { |
1298 | MWasmStoreGlobalCell(MDefinition* value, MDefinition* cellPtr) |
1299 | : MBinaryInstruction(classOpcode, value, cellPtr) {} |
1300 | |
1301 | public: |
1302 | INSTRUCTION_HEADER(WasmStoreGlobalCell) |
1303 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1304 | NAMED_OPERANDS((0, value), (1, cellPtr))MDefinition* value() const { return getOperand(0); } MDefinition * cellPtr() const { return getOperand(1); } |
1305 | |
1306 | AliasSet getAliasSet() const override { |
1307 | return AliasSet::Store(AliasSet::WasmGlobalCell); |
1308 | } |
1309 | }; |
1310 | |
1311 | class MWasmStoreStackResult : public MBinaryInstruction, |
1312 | public NoTypePolicy::Data { |
1313 | MWasmStoreStackResult(MDefinition* stackResultArea, uint32_t offset, |
1314 | MDefinition* value) |
1315 | : MBinaryInstruction(classOpcode, stackResultArea, value), |
1316 | offset_(offset) {} |
1317 | |
1318 | uint32_t offset_; |
1319 | |
1320 | public: |
1321 | INSTRUCTION_HEADER(WasmStoreStackResult) |
1322 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1323 | NAMED_OPERANDS((0, stackResultArea), (1, value))MDefinition* stackResultArea() const { return getOperand(0); } MDefinition* value() const { return getOperand(1); } |
1324 | |
1325 | uint32_t offset() const { return offset_; } |
1326 | |
1327 | AliasSet getAliasSet() const override { |
1328 | return AliasSet::Store(AliasSet::WasmStackResult); |
1329 | } |
1330 | }; |
1331 | |
1332 | // Represents a known-good derived pointer into an object or memory region (in |
1333 | // the most general sense) that will not move while the derived pointer is live. |
1334 | // The `offset` *must* be a valid offset into the object represented by `base`; |
1335 | // hence overflow in the address calculation will never be an issue. `offset` |
1336 | // must be representable as a 31-bit unsigned integer. |
1337 | // |
1338 | // DO NOT use this with a base value of any JS-heap-resident object type. |
1339 | // Such a value would need to be adjusted during GC, yet we have no mechanism |
1340 | // to do that. See bug 1810090. |
1341 | |
1342 | class MWasmDerivedPointer : public MUnaryInstruction, |
1343 | public NoTypePolicy::Data { |
1344 | MWasmDerivedPointer(MDefinition* base, size_t offset) |
1345 | : MUnaryInstruction(classOpcode, base), offset_(uint32_t(offset)) { |
1346 | MOZ_ASSERT(offset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(offset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(offset <= (2147483647)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("offset <= (2147483647)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1346); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)" ")"); do { *((volatile int*)__null) = 1346; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1347 | // Do not change this to allow `base` to be a GC-heap allocated type. |
1348 | MOZ_ASSERT(base->type() == MIRType::Pointer ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::Pointer || base->type () == TargetWordMIRType())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(base->type() == MIRType:: Pointer || base->type() == TargetWordMIRType()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()" ")"); do { *((volatile int*)__null) = 1349; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1349 | base->type() == TargetWordMIRType())do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::Pointer || base->type () == TargetWordMIRType())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(base->type() == MIRType:: Pointer || base->type() == TargetWordMIRType()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()" ")"); do { *((volatile int*)__null) = 1349; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1350 | setResultType(MIRType::Pointer); |
1351 | setMovable(); |
1352 | } |
1353 | |
1354 | uint32_t offset_; |
1355 | |
1356 | public: |
1357 | INSTRUCTION_HEADER(WasmDerivedPointer) |
1358 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1359 | NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); } |
1360 | |
1361 | uint32_t offset() const { return offset_; } |
1362 | |
1363 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1364 | |
1365 | bool congruentTo(const MDefinition* ins) const override { |
1366 | return congruentIfOperandsEqual(ins) && |
1367 | ins->toWasmDerivedPointer()->offset() == offset(); |
1368 | } |
1369 | |
1370 | #ifdef JS_JITSPEW1 |
1371 | void getExtras(ExtrasCollector* extras) const override { |
1372 | char buf[64]; |
1373 | SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_); |
1374 | extras->add(buf); |
1375 | } |
1376 | #endif |
1377 | |
1378 | ALLOW_CLONE(MWasmDerivedPointer)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmDerivedPointer (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
1379 | }; |
1380 | |
1381 | // As with MWasmDerivedPointer, DO NOT use this with a base value of any |
1382 | // JS-heap-resident object type. |
1383 | class MWasmDerivedIndexPointer : public MBinaryInstruction, |
1384 | public NoTypePolicy::Data { |
1385 | MWasmDerivedIndexPointer(MDefinition* base, MDefinition* index, Scale scale) |
1386 | : MBinaryInstruction(classOpcode, base, index), scale_(scale) { |
1387 | // Do not change this to allow `base` to be a GC-heap allocated type. |
1388 | MOZ_ASSERT(base->type() == MIRType::Pointer)do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::Pointer)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(base->type() == MIRType:: Pointer))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("base->type() == MIRType::Pointer", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer" ")"); do { *((volatile int*)__null) = 1388; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1389 | setResultType(MIRType::Pointer); |
1390 | setMovable(); |
1391 | } |
1392 | |
1393 | Scale scale_; |
1394 | |
1395 | public: |
1396 | INSTRUCTION_HEADER(WasmDerivedIndexPointer) |
1397 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1398 | NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); } |
1399 | NAMED_OPERANDS((1, index))MDefinition* index() const { return getOperand(1); } |
1400 | |
1401 | Scale scale() const { return scale_; } |
1402 | |
1403 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1404 | |
1405 | bool congruentTo(const MDefinition* ins) const override { |
1406 | return congruentIfOperandsEqual(ins) && |
1407 | ins->toWasmDerivedIndexPointer()->scale() == scale(); |
1408 | } |
1409 | |
1410 | ALLOW_CLONE(MWasmDerivedIndexPointer)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmDerivedIndexPointer (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
1411 | }; |
1412 | |
1413 | // Whether to perform a pre-write barrier for a wasm store reference. |
1414 | enum class WasmPreBarrierKind : uint8_t { None, Normal }; |
1415 | |
1416 | // Stores a reference to an address. This performs a pre-barrier on the address, |
1417 | // but not a post-barrier. A post-barrier must be performed separately, if it's |
1418 | // required. The accessed location is `valueBase + valueOffset`. The latter |
1419 | // must be be representable as a 31-bit unsigned integer. |
1420 | |
1421 | class MWasmStoreRef : public MAryInstruction<3>, public NoTypePolicy::Data { |
1422 | uint32_t offset_; |
1423 | AliasSet::Flag aliasSet_; |
1424 | WasmPreBarrierKind preBarrierKind_; |
1425 | |
1426 | MWasmStoreRef(MDefinition* instance, MDefinition* valueBase, |
1427 | size_t valueOffset, MDefinition* value, AliasSet::Flag aliasSet, |
1428 | WasmPreBarrierKind preBarrierKind) |
1429 | : MAryInstruction<3>(classOpcode), |
1430 | offset_(uint32_t(valueOffset)), |
1431 | aliasSet_(aliasSet), |
1432 | preBarrierKind_(preBarrierKind) { |
1433 | MOZ_ASSERT(valueOffset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(valueOffset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(valueOffset <= (2147483647 )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("valueOffset <= (2147483647)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1433); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueOffset <= (2147483647)" ")"); do { *((volatile int*)__null) = 1433; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1434 | MOZ_ASSERT(valueBase->type() == MIRType::Pointer ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(valueBase->type() == MIRType::Pointer || valueBase ->type() == MIRType::StackResults)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(valueBase->type() == MIRType ::Pointer || valueBase->type() == MIRType::StackResults))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults" ")"); do { *((volatile int*)__null) = 1435; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
1435 | valueBase->type() == MIRType::StackResults)do { static_assert( mozilla::detail::AssertionConditionType< decltype(valueBase->type() == MIRType::Pointer || valueBase ->type() == MIRType::StackResults)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(valueBase->type() == MIRType ::Pointer || valueBase->type() == MIRType::StackResults))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults" ")"); do { *((volatile int*)__null) = 1435; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1436 | MOZ_ASSERT(value->type() == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(value->type() == MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(value->type() == MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("value->type() == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 1436; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1437 | initOperand(0, instance); |
1438 | initOperand(1, valueBase); |
1439 | initOperand(2, value); |
1440 | } |
1441 | |
1442 | public: |
1443 | INSTRUCTION_HEADER(WasmStoreRef) |
1444 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1445 | NAMED_OPERANDS((0, instance), (1, valueBase), (2, value))MDefinition* instance() const { return getOperand(0); } MDefinition * valueBase() const { return getOperand(1); } MDefinition* value () const { return getOperand(2); } |
1446 | |
1447 | uint32_t offset() const { return offset_; } |
1448 | AliasSet getAliasSet() const override { return AliasSet::Store(aliasSet_); } |
1449 | WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; } |
1450 | |
1451 | #ifdef JS_JITSPEW1 |
1452 | void getExtras(ExtrasCollector* extras) const override { |
1453 | char buf[64]; |
1454 | SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_); |
1455 | extras->add(buf); |
1456 | } |
1457 | #endif |
1458 | }; |
1459 | |
1460 | // Given a value being written to another object, update the generational store |
1461 | // buffer if the value is in the nursery and object is in the tenured heap. |
1462 | class MWasmPostWriteBarrierImmediate : public MQuaternaryInstruction, |
1463 | public NoTypePolicy::Data { |
1464 | uint32_t valueOffset_; |
1465 | |
1466 | MWasmPostWriteBarrierImmediate(MDefinition* instance, MDefinition* object, |
1467 | MDefinition* valueBase, uint32_t valueOffset, |
1468 | MDefinition* value) |
1469 | : MQuaternaryInstruction(classOpcode, instance, object, valueBase, value), |
1470 | valueOffset_(valueOffset) { |
1471 | setGuard(); |
1472 | } |
1473 | |
1474 | public: |
1475 | INSTRUCTION_HEADER(WasmPostWriteBarrierImmediate) |
1476 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1477 | NAMED_OPERANDS((0, instance), (1, object), (2, valueBase), (3, value))MDefinition* instance() const { return getOperand(0); } MDefinition * object() const { return getOperand(1); } MDefinition* valueBase () const { return getOperand(2); } MDefinition* value() const { return getOperand(3); } |
1478 | |
1479 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1480 | uint32_t valueOffset() const { return valueOffset_; } |
1481 | |
1482 | ALLOW_CLONE(MWasmPostWriteBarrierImmediate)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmPostWriteBarrierImmediate (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
1483 | }; |
1484 | |
1485 | // Given a value being written to another object, update the generational store |
1486 | // buffer if the value is in the nursery and object is in the tenured heap. |
1487 | class MWasmPostWriteBarrierIndex : public MAryInstruction<5>, |
1488 | public NoTypePolicy::Data { |
1489 | uint32_t elemSize_; |
1490 | |
1491 | MWasmPostWriteBarrierIndex(MDefinition* instance, MDefinition* object, |
1492 | MDefinition* valueBase, MDefinition* index, |
1493 | uint32_t scale, MDefinition* value) |
1494 | : MAryInstruction<5>(classOpcode), elemSize_(scale) { |
1495 | initOperand(0, instance); |
1496 | initOperand(1, object); |
1497 | initOperand(2, valueBase); |
1498 | initOperand(3, index); |
1499 | initOperand(4, value); |
1500 | setGuard(); |
1501 | } |
1502 | |
1503 | public: |
1504 | INSTRUCTION_HEADER(WasmPostWriteBarrierIndex) |
1505 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1506 | NAMED_OPERANDS((0, instance), (1, object), (2, valueBase), (3, index),MDefinition* instance() const { return getOperand(0); } MDefinition * object() const { return getOperand(1); } MDefinition* valueBase () const { return getOperand(2); } MDefinition* index() const { return getOperand(3); } MDefinition* value() const { return getOperand(4); } |
1507 | (4, value))MDefinition* instance() const { return getOperand(0); } MDefinition * object() const { return getOperand(1); } MDefinition* valueBase () const { return getOperand(2); } MDefinition* index() const { return getOperand(3); } MDefinition* value() const { return getOperand(4); } |
1508 | |
1509 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1510 | uint32_t elemSize() const { return elemSize_; } |
1511 | |
1512 | ALLOW_CLONE(MWasmPostWriteBarrierIndex)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmPostWriteBarrierIndex (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
1513 | }; |
1514 | |
1515 | class MWasmParameter : public MNullaryInstruction { |
1516 | ABIArg abi_; |
1517 | |
1518 | MWasmParameter(ABIArg abi, MIRType mirType) |
1519 | : MNullaryInstruction(classOpcode), abi_(abi) { |
1520 | setResultType(mirType); |
1521 | } |
1522 | |
1523 | public: |
1524 | INSTRUCTION_HEADER(WasmParameter) |
1525 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1526 | |
1527 | ABIArg abi() const { return abi_; } |
1528 | }; |
1529 | |
1530 | class MWasmReturn : public MAryControlInstruction<2, 0>, |
1531 | public NoTypePolicy::Data { |
1532 | MWasmReturn(MDefinition* ins, MDefinition* instance) |
1533 | : MAryControlInstruction(classOpcode) { |
1534 | initOperand(0, ins); |
1535 | initOperand(1, instance); |
1536 | } |
1537 | |
1538 | public: |
1539 | INSTRUCTION_HEADER(WasmReturn) |
1540 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1541 | |
1542 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1543 | }; |
1544 | |
1545 | class MWasmReturnVoid : public MAryControlInstruction<1, 0>, |
1546 | public NoTypePolicy::Data { |
1547 | explicit MWasmReturnVoid(MDefinition* instance) |
1548 | : MAryControlInstruction(classOpcode) { |
1549 | initOperand(0, instance); |
1550 | } |
1551 | |
1552 | public: |
1553 | INSTRUCTION_HEADER(WasmReturnVoid) |
1554 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1555 | |
1556 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1557 | }; |
1558 | |
1559 | class MWasmStackArg : public MUnaryInstruction, public NoTypePolicy::Data { |
1560 | MWasmStackArg(uint32_t spOffset, MDefinition* ins) |
1561 | : MUnaryInstruction(classOpcode, ins), spOffset_(spOffset) {} |
1562 | |
1563 | uint32_t spOffset_; |
1564 | |
1565 | public: |
1566 | INSTRUCTION_HEADER(WasmStackArg) |
1567 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1568 | NAMED_OPERANDS((0, arg))MDefinition* arg() const { return getOperand(0); } |
1569 | |
1570 | uint32_t spOffset() const { return spOffset_; } |
1571 | void incrementOffset(uint32_t inc) { spOffset_ += inc; } |
1572 | }; |
1573 | |
1574 | template <typename Location> |
1575 | class MWasmResultBase : public MNullaryInstruction { |
1576 | Location loc_; |
1577 | |
1578 | protected: |
1579 | MWasmResultBase(Opcode op, MIRType type, Location loc) |
1580 | : MNullaryInstruction(op), loc_(loc) { |
1581 | setResultType(type); |
1582 | setCallResultCapture(); |
1583 | } |
1584 | |
1585 | public: |
1586 | Location loc() { return loc_; } |
1587 | }; |
1588 | |
1589 | class MWasmRegisterResult : public MWasmResultBase<Register> { |
1590 | MWasmRegisterResult(MIRType type, Register reg) |
1591 | : MWasmResultBase(classOpcode, type, reg) {} |
1592 | |
1593 | public: |
1594 | INSTRUCTION_HEADER(WasmRegisterResult) |
1595 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1596 | }; |
1597 | |
1598 | class MWasmFloatRegisterResult : public MWasmResultBase<FloatRegister> { |
1599 | MWasmFloatRegisterResult(MIRType type, FloatRegister reg) |
1600 | : MWasmResultBase(classOpcode, type, reg) {} |
1601 | |
1602 | public: |
1603 | INSTRUCTION_HEADER(WasmFloatRegisterResult) |
1604 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1605 | }; |
1606 | |
1607 | class MWasmRegister64Result : public MWasmResultBase<Register64> { |
1608 | explicit MWasmRegister64Result(Register64 reg) |
1609 | : MWasmResultBase(classOpcode, MIRType::Int64, reg) {} |
1610 | |
1611 | public: |
1612 | INSTRUCTION_HEADER(WasmRegister64Result) |
1613 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1614 | }; |
1615 | |
1616 | class MWasmStackResultArea : public MNullaryInstruction { |
1617 | public: |
1618 | class StackResult { |
1619 | // Offset in bytes from lowest address of stack result area. |
1620 | uint32_t offset_; |
1621 | MIRType type_; |
1622 | |
1623 | public: |
1624 | StackResult() : type_(MIRType::Undefined) {} |
1625 | StackResult(uint32_t offset, MIRType type) : offset_(offset), type_(type) {} |
1626 | |
1627 | bool initialized() const { return type_ != MIRType::Undefined; } |
1628 | uint32_t offset() const { |
1629 | MOZ_ASSERT(initialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(initialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("initialized()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initialized()" ")"); do { *((volatile int*)__null) = 1629; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1630 | return offset_; |
1631 | } |
1632 | MIRType type() const { |
1633 | MOZ_ASSERT(initialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(initialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(initialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("initialized()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initialized()" ")"); do { *((volatile int*)__null) = 1633; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1634 | return type_; |
1635 | } |
1636 | uint32_t endOffset() const { |
1637 | return offset() + wasm::MIRTypeToABIResultSize(type()); |
1638 | } |
1639 | }; |
1640 | |
1641 | private: |
1642 | FixedList<StackResult> results_; |
1643 | uint32_t base_; |
1644 | |
1645 | explicit MWasmStackResultArea() |
1646 | : MNullaryInstruction(classOpcode), base_(UINT32_MAX(4294967295U)) { |
1647 | setResultType(MIRType::StackResults); |
1648 | } |
1649 | |
1650 | void assertInitialized() const { |
1651 | MOZ_ASSERT(results_.length() != 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(results_.length() != 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(results_.length() != 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("results_.length() != 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1651); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_.length() != 0" ")"); do { *((volatile int*)__null) = 1651; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1652 | #ifdef DEBUG1 |
1653 | for (size_t i = 0; i < results_.length(); i++) { |
1654 | MOZ_ASSERT(results_[i].initialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(results_[i].initialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(results_[i].initialized()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("results_[i].initialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1654); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_[i].initialized()" ")"); do { *((volatile int*)__null) = 1654; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1655 | } |
1656 | #endif |
1657 | } |
1658 | |
1659 | bool baseInitialized() const { return base_ != UINT32_MAX(4294967295U); } |
1660 | |
1661 | public: |
1662 | INSTRUCTION_HEADER(WasmStackResultArea) |
1663 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1664 | |
1665 | [[nodiscard]] bool init(TempAllocator& alloc, size_t stackResultCount) { |
1666 | MOZ_ASSERT(results_.length() == 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(results_.length() == 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(results_.length() == 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("results_.length() == 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1666); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_.length() == 0" ")"); do { *((volatile int*)__null) = 1666; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1667 | MOZ_ASSERT(stackResultCount > 0)do { static_assert( mozilla::detail::AssertionConditionType< decltype(stackResultCount > 0)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(stackResultCount > 0))), 0 ))) { do { } while (false); MOZ_ReportAssertionFailure("stackResultCount > 0" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1667); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stackResultCount > 0" ")"); do { *((volatile int*)__null) = 1667; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1668 | if (!results_.init(alloc, stackResultCount)) { |
1669 | return false; |
1670 | } |
1671 | for (size_t n = 0; n < stackResultCount; n++) { |
1672 | results_[n] = StackResult(); |
1673 | } |
1674 | return true; |
1675 | } |
1676 | |
1677 | size_t resultCount() const { return results_.length(); } |
1678 | const StackResult& result(size_t n) const { |
1679 | MOZ_ASSERT(results_[n].initialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(results_[n].initialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(results_[n].initialized()))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("results_[n].initialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_[n].initialized()" ")"); do { *((volatile int*)__null) = 1679; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1680 | return results_[n]; |
1681 | } |
1682 | void initResult(size_t n, const StackResult& loc) { |
1683 | MOZ_ASSERT(!results_[n].initialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!results_[n].initialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!results_[n].initialized())) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!results_[n].initialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1683); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!results_[n].initialized()" ")"); do { *((volatile int*)__null) = 1683; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1684 | MOZ_ASSERT((n == 0) == (loc.offset() == 0))do { static_assert( mozilla::detail::AssertionConditionType< decltype((n == 0) == (loc.offset() == 0))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!((n == 0) == (loc.offset() == 0)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("(n == 0) == (loc.offset() == 0)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(n == 0) == (loc.offset() == 0)" ")"); do { *((volatile int*)__null) = 1684; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1685 | MOZ_ASSERT_IF(n > 0, loc.offset() >= result(n - 1).endOffset())do { if (n > 0) { do { static_assert( mozilla::detail::AssertionConditionType <decltype(loc.offset() >= result(n - 1).endOffset())> ::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(loc.offset() >= result(n - 1).endOffset()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("loc.offset() >= result(n - 1).endOffset()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1685); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.offset() >= result(n - 1).endOffset()" ")"); do { *((volatile int*)__null) = 1685; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
1686 | results_[n] = loc; |
1687 | } |
1688 | |
1689 | uint32_t byteSize() const { |
1690 | assertInitialized(); |
1691 | return result(resultCount() - 1).endOffset(); |
1692 | } |
1693 | |
1694 | // Stack index indicating base of stack area. |
1695 | uint32_t base() const { |
1696 | MOZ_ASSERT(baseInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(baseInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(baseInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("baseInitialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1696); AnnotateMozCrashReason("MOZ_ASSERT" "(" "baseInitialized()" ")"); do { *((volatile int*)__null) = 1696; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1697 | return base_; |
1698 | } |
1699 | void setBase(uint32_t base) { |
1700 | MOZ_ASSERT(!baseInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!baseInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!baseInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!baseInitialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1700); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!baseInitialized()" ")"); do { *((volatile int*)__null) = 1700; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1701 | base_ = base; |
1702 | MOZ_ASSERT(baseInitialized())do { static_assert( mozilla::detail::AssertionConditionType< decltype(baseInitialized())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(baseInitialized()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("baseInitialized()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1702); AnnotateMozCrashReason("MOZ_ASSERT" "(" "baseInitialized()" ")"); do { *((volatile int*)__null) = 1702; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1703 | } |
1704 | }; |
1705 | |
1706 | class MWasmStackResult : public MUnaryInstruction, public NoTypePolicy::Data { |
1707 | uint32_t resultIdx_; |
1708 | |
1709 | MWasmStackResult(MWasmStackResultArea* resultArea, size_t idx) |
1710 | : MUnaryInstruction(classOpcode, resultArea), resultIdx_(idx) { |
1711 | setResultType(result().type()); |
1712 | setCallResultCapture(); |
1713 | } |
1714 | |
1715 | public: |
1716 | INSTRUCTION_HEADER(WasmStackResult) |
1717 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1718 | NAMED_OPERANDS((0, resultArea))MDefinition* resultArea() const { return getOperand(0); } |
1719 | |
1720 | const MWasmStackResultArea::StackResult& result() const { |
1721 | return resultArea()->toWasmStackResultArea()->result(resultIdx_); |
1722 | } |
1723 | }; |
1724 | |
1725 | // Arguments for constructing a catchable wasm call inside of a try block. |
1726 | struct MWasmCallTryDesc { |
1727 | bool inTry; |
1728 | uint32_t relativeTryDepth; |
1729 | size_t tryNoteIndex; |
1730 | MBasicBlock* fallthroughBlock; |
1731 | MBasicBlock* prePadBlock; |
1732 | |
1733 | MWasmCallTryDesc() |
1734 | : inTry(false), |
1735 | relativeTryDepth(0), |
1736 | tryNoteIndex(0), |
1737 | fallthroughBlock(nullptr), |
1738 | prePadBlock(nullptr) {} |
1739 | }; |
1740 | |
1741 | // Mixin class for wasm calls that may or may not be catchable. |
1742 | class MWasmCallBase { |
1743 | public: |
1744 | struct Arg { |
1745 | AnyRegister reg; |
1746 | MDefinition* def; |
1747 | Arg(AnyRegister reg, MDefinition* def) : reg(reg), def(def) {} |
1748 | }; |
1749 | using Args = Vector<Arg, 8, SystemAllocPolicy>; |
1750 | |
1751 | protected: |
1752 | wasm::CallSiteDesc desc_; |
1753 | wasm::CalleeDesc callee_; |
1754 | wasm::FailureMode builtinMethodFailureMode_; |
1755 | FixedList<AnyRegister> argRegs_; |
1756 | uint32_t stackArgAreaSizeUnaligned_; |
1757 | ABIArg instanceArg_; |
1758 | bool inTry_; |
1759 | size_t tryNoteIndex_; |
1760 | |
1761 | MWasmCallBase(const wasm::CallSiteDesc& desc, const wasm::CalleeDesc& callee, |
1762 | uint32_t stackArgAreaSizeUnaligned, bool inTry, |
1763 | size_t tryNoteIndex) |
1764 | : desc_(desc), |
1765 | callee_(callee), |
1766 | builtinMethodFailureMode_(wasm::FailureMode::Infallible), |
1767 | stackArgAreaSizeUnaligned_(stackArgAreaSizeUnaligned), |
1768 | inTry_(inTry), |
1769 | tryNoteIndex_(tryNoteIndex) {} |
1770 | |
1771 | template <class MVariadicT> |
1772 | [[nodiscard]] bool initWithArgs(TempAllocator& alloc, MVariadicT* ins, |
1773 | const Args& args, |
1774 | MDefinition* tableIndexOrRef) { |
1775 | if (!argRegs_.init(alloc, args.length())) { |
1776 | return false; |
1777 | } |
1778 | for (size_t i = 0; i < argRegs_.length(); i++) { |
1779 | argRegs_[i] = args[i].reg; |
1780 | } |
1781 | |
1782 | if (!ins->init(alloc, argRegs_.length() + (tableIndexOrRef ? 1 : 0))) { |
1783 | return false; |
1784 | } |
1785 | // FixedList doesn't initialize its elements, so do an unchecked init. |
1786 | for (size_t i = 0; i < argRegs_.length(); i++) { |
1787 | ins->initOperand(i, args[i].def); |
1788 | } |
1789 | if (tableIndexOrRef) { |
1790 | ins->initOperand(argRegs_.length(), tableIndexOrRef); |
1791 | } |
1792 | return true; |
1793 | } |
1794 | |
1795 | public: |
1796 | static bool IsWasmCall(MDefinition* def) { |
1797 | return def->isWasmCallCatchable() || def->isWasmCallUncatchable() || |
1798 | def->isWasmReturnCall(); |
1799 | } |
1800 | |
1801 | size_t numArgs() const { return argRegs_.length(); } |
1802 | AnyRegister registerForArg(size_t index) const { |
1803 | MOZ_ASSERT(index < numArgs())do { static_assert( mozilla::detail::AssertionConditionType< decltype(index < numArgs())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(index < numArgs()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("index < numArgs()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1803); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < numArgs()" ")"); do { *((volatile int*)__null) = 1803; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1804 | return argRegs_[index]; |
1805 | } |
1806 | const wasm::CallSiteDesc& desc() const { return desc_; } |
1807 | const wasm::CalleeDesc& callee() const { return callee_; } |
1808 | wasm::FailureMode builtinMethodFailureMode() const { |
1809 | MOZ_ASSERT(callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod)do { static_assert( mozilla::detail::AssertionConditionType< decltype(callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod )>::isValid, "invalid assertion condition"); if ((__builtin_expect (!!(!(!!(callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1809); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod" ")"); do { *((volatile int*)__null) = 1809; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1810 | return builtinMethodFailureMode_; |
1811 | } |
1812 | uint32_t stackArgAreaSizeUnaligned() const { |
1813 | return stackArgAreaSizeUnaligned_; |
1814 | } |
1815 | |
1816 | const ABIArg& instanceArg() const { return instanceArg_; } |
1817 | |
1818 | bool inTry() const { return inTry_; } |
1819 | size_t tryNoteIndex() const { return tryNoteIndex_; } |
1820 | |
1821 | static AliasSet wasmCallAliasSet() { |
1822 | // This is ok because: |
1823 | // - numElements is immutable |
1824 | // - the GC will rewrite any array data pointers on move |
1825 | AliasSet exclude = AliasSet(AliasSet::WasmArrayNumElements) | |
1826 | AliasSet(AliasSet::WasmArrayDataPointer); |
1827 | return AliasSet::Store(AliasSet::Any) & ~exclude; |
1828 | } |
1829 | }; |
1830 | |
1831 | // A wasm call that is catchable. This instruction is a control instruction, |
1832 | // and terminates the block it is on. A normal return will proceed in a the |
1833 | // fallthrough block. An exceptional return will unwind into the landing pad |
1834 | // block for this call. The landing pad block must begin with an |
1835 | // MWasmCallLandingPrePad. |
1836 | class MWasmCallCatchable final : public MVariadicControlInstruction<2>, |
1837 | public MWasmCallBase, |
1838 | public NoTypePolicy::Data { |
1839 | MWasmCallCatchable(const wasm::CallSiteDesc& desc, |
1840 | const wasm::CalleeDesc& callee, |
1841 | uint32_t stackArgAreaSizeUnaligned, size_t tryNoteIndex) |
1842 | : MVariadicControlInstruction(classOpcode), |
1843 | MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, true, |
1844 | tryNoteIndex) {} |
1845 | |
1846 | public: |
1847 | INSTRUCTION_HEADER(WasmCallCatchable) |
1848 | |
1849 | static MWasmCallCatchable* New(TempAllocator& alloc, |
1850 | const wasm::CallSiteDesc& desc, |
1851 | const wasm::CalleeDesc& callee, |
1852 | const Args& args, |
1853 | uint32_t stackArgAreaSizeUnaligned, |
1854 | const MWasmCallTryDesc& tryDesc, |
1855 | MDefinition* tableIndexOrRef = nullptr); |
1856 | |
1857 | static MWasmCallCatchable* NewBuiltinInstanceMethodCall( |
1858 | TempAllocator& alloc, const wasm::CallSiteDesc& desc, |
1859 | const wasm::SymbolicAddress builtin, wasm::FailureMode failureMode, |
1860 | const ABIArg& instanceArg, const Args& args, |
1861 | uint32_t stackArgAreaSizeUnaligned, const MWasmCallTryDesc& tryDesc); |
1862 | |
1863 | bool possiblyCalls() const override { return true; } |
1864 | AliasSet getAliasSet() const override { return wasmCallAliasSet(); } |
1865 | |
1866 | static const size_t FallthroughBranchIndex = 0; |
1867 | static const size_t PrePadBranchIndex = 1; |
1868 | }; |
1869 | |
1870 | // A wasm call that is not catchable. This instruction is not a control |
1871 | // instruction, and therefore is not a block terminator. |
1872 | class MWasmCallUncatchable final : public MVariadicInstruction, |
1873 | public MWasmCallBase, |
1874 | public NoTypePolicy::Data { |
1875 | MWasmCallUncatchable(const wasm::CallSiteDesc& desc, |
1876 | const wasm::CalleeDesc& callee, |
1877 | uint32_t stackArgAreaSizeUnaligned) |
1878 | : MVariadicInstruction(classOpcode), |
1879 | MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, false, 0) {} |
1880 | |
1881 | public: |
1882 | INSTRUCTION_HEADER(WasmCallUncatchable) |
1883 | |
1884 | static MWasmCallUncatchable* New(TempAllocator& alloc, |
1885 | const wasm::CallSiteDesc& desc, |
1886 | const wasm::CalleeDesc& callee, |
1887 | const Args& args, |
1888 | uint32_t stackArgAreaSizeUnaligned, |
1889 | MDefinition* tableIndexOrRef = nullptr); |
1890 | |
1891 | static MWasmCallUncatchable* NewBuiltinInstanceMethodCall( |
1892 | TempAllocator& alloc, const wasm::CallSiteDesc& desc, |
1893 | const wasm::SymbolicAddress builtin, wasm::FailureMode failureMode, |
1894 | const ABIArg& instanceArg, const Args& args, |
1895 | uint32_t stackArgAreaSizeUnaligned); |
1896 | |
1897 | bool possiblyCalls() const override { return true; } |
1898 | AliasSet getAliasSet() const override { return wasmCallAliasSet(); } |
1899 | }; |
1900 | |
1901 | class MWasmReturnCall final : public MVariadicControlInstruction<0>, |
1902 | public MWasmCallBase, |
1903 | public NoTypePolicy::Data { |
1904 | MWasmReturnCall(const wasm::CallSiteDesc& desc, |
1905 | const wasm::CalleeDesc& callee, |
1906 | uint32_t stackArgAreaSizeUnaligned) |
1907 | : MVariadicControlInstruction(classOpcode), |
1908 | MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, false, 0) {} |
1909 | |
1910 | public: |
1911 | INSTRUCTION_HEADER(WasmReturnCall) |
1912 | |
1913 | static MWasmReturnCall* New(TempAllocator& alloc, |
1914 | const wasm::CallSiteDesc& desc, |
1915 | const wasm::CalleeDesc& callee, const Args& args, |
1916 | uint32_t stackArgAreaSizeUnaligned, |
1917 | MDefinition* tableIndexOrRef = nullptr); |
1918 | |
1919 | bool possiblyCalls() const override { return true; } |
1920 | }; |
1921 | |
1922 | // A marker instruction for a block which is the landing pad for a catchable |
1923 | // wasm call. This instruction does not emit any code, only filling in |
1924 | // metadata. This instruction must be the first instruction added to the |
1925 | // landing pad block. |
1926 | class MWasmCallLandingPrePad : public MNullaryInstruction { |
1927 | // The block of the call that may unwind to this landing pad. |
1928 | MBasicBlock* callBlock_; |
1929 | // The index of the try note to initialize a landing pad for. |
1930 | size_t tryNoteIndex_; |
1931 | |
1932 | explicit MWasmCallLandingPrePad(MBasicBlock* callBlock, size_t tryNoteIndex) |
1933 | : MNullaryInstruction(classOpcode), |
1934 | callBlock_(callBlock), |
1935 | tryNoteIndex_(tryNoteIndex) { |
1936 | setGuard(); |
1937 | } |
1938 | |
1939 | public: |
1940 | INSTRUCTION_HEADER(WasmCallLandingPrePad) |
1941 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1942 | |
1943 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1944 | |
1945 | size_t tryNoteIndex() { return tryNoteIndex_; } |
1946 | MBasicBlock* callBlock() { return callBlock_; } |
1947 | }; |
1948 | |
1949 | class MWasmSelect : public MTernaryInstruction, public NoTypePolicy::Data { |
1950 | MWasmSelect(MDefinition* trueExpr, MDefinition* falseExpr, |
1951 | MDefinition* condExpr) |
1952 | : MTernaryInstruction(classOpcode, trueExpr, falseExpr, condExpr) { |
1953 | MOZ_ASSERT(condExpr->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType< decltype(condExpr->type() == MIRType::Int32)>::isValid, "invalid assertion condition"); if ((__builtin_expect(!!(!(! !(condExpr->type() == MIRType::Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("condExpr->type() == MIRType::Int32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "condExpr->type() == MIRType::Int32" ")"); do { *((volatile int*)__null) = 1953; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1954 | MOZ_ASSERT(trueExpr->type() == falseExpr->type())do { static_assert( mozilla::detail::AssertionConditionType< decltype(trueExpr->type() == falseExpr->type())>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(trueExpr->type() == falseExpr->type()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("trueExpr->type() == falseExpr->type()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1954); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trueExpr->type() == falseExpr->type()" ")"); do { *((volatile int*)__null) = 1954; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1955 | setResultType(trueExpr->type()); |
1956 | setMovable(); |
1957 | } |
1958 | |
1959 | public: |
1960 | INSTRUCTION_HEADER(WasmSelect) |
1961 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1962 | NAMED_OPERANDS((0, trueExpr), (1, falseExpr), (2, condExpr))MDefinition* trueExpr() const { return getOperand(0); } MDefinition * falseExpr() const { return getOperand(1); } MDefinition* condExpr () const { return getOperand(2); } |
1963 | |
1964 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
1965 | |
1966 | bool congruentTo(const MDefinition* ins) const override { |
1967 | return congruentIfOperandsEqual(ins); |
1968 | } |
1969 | |
1970 | ALLOW_CLONE(MWasmSelect)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmSelect (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
1971 | }; |
1972 | |
1973 | class MWasmReinterpret : public MUnaryInstruction, public NoTypePolicy::Data { |
1974 | MWasmReinterpret(MDefinition* val, MIRType toType) |
1975 | : MUnaryInstruction(classOpcode, val) { |
1976 | switch (val->type()) { |
1977 | case MIRType::Int32: |
1978 | MOZ_ASSERT(toType == MIRType::Float32)do { static_assert( mozilla::detail::AssertionConditionType< decltype(toType == MIRType::Float32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(toType == MIRType::Float32)) ), 0))) { do { } while (false); MOZ_ReportAssertionFailure("toType == MIRType::Float32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1978); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Float32" ")"); do { *((volatile int*)__null) = 1978; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1979 | break; |
1980 | case MIRType::Float32: |
1981 | MOZ_ASSERT(toType == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType< decltype(toType == MIRType::Int32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(toType == MIRType::Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("toType == MIRType::Int32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1981); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Int32" ")"); do { *((volatile int*)__null) = 1981; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1982 | break; |
1983 | case MIRType::Double: |
1984 | MOZ_ASSERT(toType == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType< decltype(toType == MIRType::Int64)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(toType == MIRType::Int64))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("toType == MIRType::Int64" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Int64" ")"); do { *((volatile int*)__null) = 1984; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1985 | break; |
1986 | case MIRType::Int64: |
1987 | MOZ_ASSERT(toType == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType< decltype(toType == MIRType::Double)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(toType == MIRType::Double))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("toType == MIRType::Double" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Double" ")"); do { *((volatile int*)__null) = 1987; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
1988 | break; |
1989 | default: |
1990 | MOZ_CRASH("unexpected reinterpret conversion")do { do { } while (false); MOZ_ReportCrash("" "unexpected reinterpret conversion" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 1990); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected reinterpret conversion" ")"); do { *((volatile int*)__null) = 1990; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
1991 | } |
1992 | setMovable(); |
1993 | setResultType(toType); |
1994 | } |
1995 | |
1996 | public: |
1997 | INSTRUCTION_HEADER(WasmReinterpret) |
1998 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
1999 | |
2000 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2001 | bool congruentTo(const MDefinition* ins) const override { |
2002 | // No need to check type() here, because congruentIfOperandsEqual will |
2003 | // check it. |
2004 | return congruentIfOperandsEqual(ins); |
2005 | } |
2006 | |
2007 | ALLOW_CLONE(MWasmReinterpret)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmReinterpret (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2008 | }; |
2009 | |
2010 | // Wasm SIMD. |
2011 | // |
2012 | // See comment in WasmIonCompile.cpp for a justification for these nodes. |
2013 | |
2014 | // (v128, v128, v128) -> v128 effect-free operation. |
2015 | class MWasmTernarySimd128 : public MTernaryInstruction, |
2016 | public NoTypePolicy::Data { |
2017 | wasm::SimdOp simdOp_; |
2018 | |
2019 | MWasmTernarySimd128(MDefinition* v0, MDefinition* v1, MDefinition* v2, |
2020 | wasm::SimdOp simdOp) |
2021 | : MTernaryInstruction(classOpcode, v0, v1, v2), simdOp_(simdOp) { |
2022 | setMovable(); |
2023 | setResultType(MIRType::Simd128); |
2024 | } |
2025 | |
2026 | public: |
2027 | INSTRUCTION_HEADER(WasmTernarySimd128) |
2028 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2029 | NAMED_OPERANDS((0, v0), (1, v1), (2, v2))MDefinition* v0() const { return getOperand(0); } MDefinition * v1() const { return getOperand(1); } MDefinition* v2() const { return getOperand(2); } |
2030 | |
2031 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2032 | bool congruentTo(const MDefinition* ins) const override { |
2033 | return congruentIfOperandsEqual(ins) && |
2034 | simdOp() == ins->toWasmTernarySimd128()->simdOp(); |
2035 | } |
2036 | #ifdef ENABLE_WASM_SIMD1 |
2037 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2038 | |
2039 | // If the control mask of a bitselect allows the operation to be specialized |
2040 | // as a shuffle and it is profitable to specialize it on this platform, return |
2041 | // true and the appropriate shuffle mask. |
2042 | bool specializeBitselectConstantMaskAsShuffle(int8_t shuffle[16]); |
2043 | // Checks if more relaxed version of lane select can be used. It returns true |
2044 | // if a bit mask input expected to be all 0s or 1s for entire 8-bit lanes, |
2045 | // false otherwise. |
2046 | bool canRelaxBitselect(); |
2047 | #endif |
2048 | |
2049 | wasm::SimdOp simdOp() const { return simdOp_; } |
2050 | |
2051 | ALLOW_CLONE(MWasmTernarySimd128)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmTernarySimd128 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2052 | }; |
2053 | |
2054 | // (v128, v128) -> v128 effect-free operations. |
2055 | class MWasmBinarySimd128 : public MBinaryInstruction, |
2056 | public NoTypePolicy::Data { |
2057 | wasm::SimdOp simdOp_; |
2058 | |
2059 | MWasmBinarySimd128(MDefinition* lhs, MDefinition* rhs, bool commutative, |
2060 | wasm::SimdOp simdOp) |
2061 | : MBinaryInstruction(classOpcode, lhs, rhs), simdOp_(simdOp) { |
2062 | setMovable(); |
2063 | setResultType(MIRType::Simd128); |
2064 | if (commutative) { |
2065 | setCommutative(); |
2066 | } |
2067 | } |
2068 | |
2069 | public: |
2070 | INSTRUCTION_HEADER(WasmBinarySimd128) |
2071 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2072 | |
2073 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2074 | bool congruentTo(const MDefinition* ins) const override { |
2075 | return congruentIfOperandsEqual(ins) && |
2076 | ins->toWasmBinarySimd128()->simdOp() == simdOp_; |
2077 | } |
2078 | #ifdef ENABLE_WASM_SIMD1 |
2079 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2080 | |
2081 | // Checks if pmaddubsw operation is supported. |
2082 | bool canPmaddubsw(); |
2083 | #endif |
2084 | |
2085 | wasm::SimdOp simdOp() const { return simdOp_; } |
2086 | |
2087 | // Platform-dependent specialization. |
2088 | bool specializeForConstantRhs(); |
2089 | |
2090 | ALLOW_CLONE(MWasmBinarySimd128)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBinarySimd128 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2091 | }; |
2092 | |
2093 | // (v128, const) -> v128 effect-free operations. |
2094 | class MWasmBinarySimd128WithConstant : public MUnaryInstruction, |
2095 | public NoTypePolicy::Data { |
2096 | SimdConstant rhs_; |
2097 | wasm::SimdOp simdOp_; |
2098 | |
2099 | MWasmBinarySimd128WithConstant(MDefinition* lhs, const SimdConstant& rhs, |
2100 | wasm::SimdOp simdOp) |
2101 | : MUnaryInstruction(classOpcode, lhs), rhs_(rhs), simdOp_(simdOp) { |
2102 | setMovable(); |
2103 | setResultType(MIRType::Simd128); |
2104 | } |
2105 | |
2106 | public: |
2107 | INSTRUCTION_HEADER(WasmBinarySimd128WithConstant) |
2108 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2109 | |
2110 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2111 | bool congruentTo(const MDefinition* ins) const override { |
2112 | return congruentIfOperandsEqual(ins) && |
2113 | ins->toWasmBinarySimd128WithConstant()->simdOp() == simdOp_ && |
2114 | rhs_.bitwiseEqual(ins->toWasmBinarySimd128WithConstant()->rhs()); |
2115 | } |
2116 | |
2117 | wasm::SimdOp simdOp() const { return simdOp_; } |
2118 | MDefinition* lhs() const { return input(); } |
2119 | const SimdConstant& rhs() const { return rhs_; } |
2120 | |
2121 | ALLOW_CLONE(MWasmBinarySimd128WithConstant)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmBinarySimd128WithConstant (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2122 | }; |
2123 | |
2124 | // (v128, scalar, imm) -> v128 effect-free operations. |
2125 | class MWasmReplaceLaneSimd128 : public MBinaryInstruction, |
2126 | public NoTypePolicy::Data { |
2127 | uint32_t laneIndex_; |
2128 | wasm::SimdOp simdOp_; |
2129 | |
2130 | MWasmReplaceLaneSimd128(MDefinition* lhs, MDefinition* rhs, |
2131 | uint32_t laneIndex, wasm::SimdOp simdOp) |
2132 | : MBinaryInstruction(classOpcode, lhs, rhs), |
2133 | laneIndex_(laneIndex), |
2134 | simdOp_(simdOp) { |
2135 | setMovable(); |
2136 | setResultType(MIRType::Simd128); |
2137 | } |
2138 | |
2139 | public: |
2140 | INSTRUCTION_HEADER(WasmReplaceLaneSimd128) |
2141 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2142 | |
2143 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2144 | bool congruentTo(const MDefinition* ins) const override { |
2145 | return congruentIfOperandsEqual(ins) && |
2146 | ins->toWasmReplaceLaneSimd128()->simdOp() == simdOp_ && |
2147 | ins->toWasmReplaceLaneSimd128()->laneIndex() == laneIndex_; |
2148 | } |
2149 | |
2150 | uint32_t laneIndex() const { return laneIndex_; } |
2151 | wasm::SimdOp simdOp() const { return simdOp_; } |
2152 | |
2153 | ALLOW_CLONE(MWasmReplaceLaneSimd128)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmReplaceLaneSimd128 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2154 | }; |
2155 | |
2156 | // (scalar) -> v128 effect-free operations. |
2157 | class MWasmScalarToSimd128 : public MUnaryInstruction, |
2158 | public NoTypePolicy::Data { |
2159 | wasm::SimdOp simdOp_; |
2160 | |
2161 | MWasmScalarToSimd128(MDefinition* src, wasm::SimdOp simdOp) |
2162 | : MUnaryInstruction(classOpcode, src), simdOp_(simdOp) { |
2163 | setMovable(); |
2164 | setResultType(MIRType::Simd128); |
2165 | } |
2166 | |
2167 | public: |
2168 | INSTRUCTION_HEADER(WasmScalarToSimd128) |
2169 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2170 | |
2171 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2172 | bool congruentTo(const MDefinition* ins) const override { |
2173 | return congruentIfOperandsEqual(ins) && |
2174 | ins->toWasmScalarToSimd128()->simdOp() == simdOp_; |
2175 | } |
2176 | #ifdef ENABLE_WASM_SIMD1 |
2177 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2178 | #endif |
2179 | |
2180 | wasm::SimdOp simdOp() const { return simdOp_; } |
2181 | |
2182 | ALLOW_CLONE(MWasmScalarToSimd128)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmScalarToSimd128 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2183 | }; |
2184 | |
2185 | // (v128, imm) -> scalar effect-free operations. |
2186 | class MWasmReduceSimd128 : public MUnaryInstruction, public NoTypePolicy::Data { |
2187 | wasm::SimdOp simdOp_; |
2188 | uint32_t imm_; |
2189 | |
2190 | MWasmReduceSimd128(MDefinition* src, wasm::SimdOp simdOp, MIRType outType, |
2191 | uint32_t imm) |
2192 | : MUnaryInstruction(classOpcode, src), simdOp_(simdOp), imm_(imm) { |
2193 | setMovable(); |
2194 | setResultType(outType); |
2195 | } |
2196 | |
2197 | public: |
2198 | INSTRUCTION_HEADER(WasmReduceSimd128) |
2199 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2200 | |
2201 | AliasSet getAliasSet() const override { return AliasSet::None(); } |
2202 | bool congruentTo(const MDefinition* ins) const override { |
2203 | return congruentIfOperandsEqual(ins) && |
2204 | ins->toWasmReduceSimd128()->simdOp() == simdOp_ && |
2205 | ins->toWasmReduceSimd128()->imm() == imm_; |
2206 | } |
2207 | #ifdef ENABLE_WASM_SIMD1 |
2208 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2209 | #endif |
2210 | |
2211 | uint32_t imm() const { return imm_; } |
2212 | wasm::SimdOp simdOp() const { return simdOp_; } |
2213 | |
2214 | ALLOW_CLONE(MWasmReduceSimd128)bool canClone() const override { return true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) const override { MInstruction* res = new (alloc) MWasmReduceSimd128 (*this); for (size_t i = 0; i < numOperands(); i++) res-> replaceOperand(i, inputs[i]); return res; } |
2215 | }; |
2216 | |
2217 | class MWasmLoadLaneSimd128 |
2218 | : public MVariadicInstruction, // memoryBase is nullptr on some platforms |
2219 | public NoTypePolicy::Data { |
2220 | wasm::MemoryAccessDesc access_; |
2221 | uint32_t laneSize_; |
2222 | uint32_t laneIndex_; |
2223 | uint32_t memoryBaseIndex_; |
2224 | |
2225 | MWasmLoadLaneSimd128(const wasm::MemoryAccessDesc& access, uint32_t laneSize, |
2226 | uint32_t laneIndex, uint32_t memoryBaseIndex) |
2227 | : MVariadicInstruction(classOpcode), |
2228 | access_(access), |
2229 | laneSize_(laneSize), |
2230 | laneIndex_(laneIndex), |
2231 | memoryBaseIndex_(memoryBaseIndex) { |
2232 | MOZ_ASSERT(!access_.isAtomic())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!access_.isAtomic())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!access_.isAtomic()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!access_.isAtomic()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!access_.isAtomic()" ")"); do { *((volatile int*)__null) = 2232; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2233 | setGuard(); |
2234 | setResultType(MIRType::Simd128); |
2235 | } |
2236 | |
2237 | public: |
2238 | INSTRUCTION_HEADER(WasmLoadLaneSimd128) |
2239 | NAMED_OPERANDS((0, base), (1, value))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); }; |
2240 | |
2241 | static MWasmLoadLaneSimd128* New(TempAllocator& alloc, |
2242 | MDefinition* memoryBase, MDefinition* base, |
2243 | const wasm::MemoryAccessDesc& access, |
2244 | uint32_t laneSize, uint32_t laneIndex, |
2245 | MDefinition* value) { |
2246 | uint32_t nextIndex = 2; |
2247 | uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U); |
2248 | |
2249 | MWasmLoadLaneSimd128* load = new (alloc) |
2250 | MWasmLoadLaneSimd128(access, laneSize, laneIndex, memoryBaseIndex); |
2251 | if (!load->init(alloc, nextIndex)) { |
2252 | return nullptr; |
2253 | } |
2254 | |
2255 | load->initOperand(0, base); |
2256 | load->initOperand(1, value); |
2257 | if (memoryBase) { |
2258 | load->initOperand(memoryBaseIndex, memoryBase); |
2259 | } |
2260 | |
2261 | return load; |
2262 | } |
2263 | |
2264 | const wasm::MemoryAccessDesc& access() const { return access_; } |
2265 | uint32_t laneSize() const { return laneSize_; } |
2266 | uint32_t laneIndex() const { return laneIndex_; } |
2267 | bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); } |
2268 | MDefinition* memoryBase() const { |
2269 | MOZ_ASSERT(hasMemoryBase())do { static_assert( mozilla::detail::AssertionConditionType< decltype(hasMemoryBase())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(hasMemoryBase()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasMemoryBase()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2269); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()" ")"); do { *((volatile int*)__null) = 2269; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2270 | return getOperand(memoryBaseIndex_); |
2271 | } |
2272 | |
2273 | AliasSet getAliasSet() const override { |
2274 | return AliasSet::Load(AliasSet::WasmHeap); |
2275 | } |
2276 | }; |
2277 | |
2278 | class MWasmStoreLaneSimd128 : public MVariadicInstruction, |
2279 | public NoTypePolicy::Data { |
2280 | wasm::MemoryAccessDesc access_; |
2281 | uint32_t laneSize_; |
2282 | uint32_t laneIndex_; |
2283 | uint32_t memoryBaseIndex_; |
2284 | |
2285 | explicit MWasmStoreLaneSimd128(const wasm::MemoryAccessDesc& access, |
2286 | uint32_t laneSize, uint32_t laneIndex, |
2287 | uint32_t memoryBaseIndex) |
2288 | : MVariadicInstruction(classOpcode), |
2289 | access_(access), |
2290 | laneSize_(laneSize), |
2291 | laneIndex_(laneIndex), |
2292 | memoryBaseIndex_(memoryBaseIndex) { |
2293 | MOZ_ASSERT(!access_.isAtomic())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!access_.isAtomic())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!access_.isAtomic()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!access_.isAtomic()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2293); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!access_.isAtomic()" ")"); do { *((volatile int*)__null) = 2293; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2294 | setGuard(); |
2295 | setResultType(MIRType::Simd128); |
2296 | } |
2297 | |
2298 | public: |
2299 | INSTRUCTION_HEADER(WasmStoreLaneSimd128) |
2300 | NAMED_OPERANDS((0, base), (1, value))MDefinition* base() const { return getOperand(0); } MDefinition * value() const { return getOperand(1); } |
2301 | |
2302 | static MWasmStoreLaneSimd128* New(TempAllocator& alloc, |
2303 | MDefinition* memoryBase, MDefinition* base, |
2304 | const wasm::MemoryAccessDesc& access, |
2305 | uint32_t laneSize, uint32_t laneIndex, |
2306 | MDefinition* value) { |
2307 | uint32_t nextIndex = 2; |
2308 | uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U); |
2309 | |
2310 | MWasmStoreLaneSimd128* store = new (alloc) |
2311 | MWasmStoreLaneSimd128(access, laneSize, laneIndex, memoryBaseIndex); |
2312 | if (!store->init(alloc, nextIndex)) { |
2313 | return nullptr; |
2314 | } |
2315 | |
2316 | store->initOperand(0, base); |
2317 | store->initOperand(1, value); |
2318 | if (memoryBase) { |
2319 | store->initOperand(memoryBaseIndex, memoryBase); |
2320 | } |
2321 | |
2322 | return store; |
2323 | } |
2324 | |
2325 | const wasm::MemoryAccessDesc& access() const { return access_; } |
2326 | uint32_t laneSize() const { return laneSize_; } |
2327 | uint32_t laneIndex() const { return laneIndex_; } |
2328 | bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); } |
2329 | MDefinition* memoryBase() const { |
2330 | MOZ_ASSERT(hasMemoryBase())do { static_assert( mozilla::detail::AssertionConditionType< decltype(hasMemoryBase())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(hasMemoryBase()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasMemoryBase()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()" ")"); do { *((volatile int*)__null) = 2330; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2331 | return getOperand(memoryBaseIndex_); |
2332 | } |
2333 | |
2334 | AliasSet getAliasSet() const override { |
2335 | return AliasSet::Store(AliasSet::WasmHeap); |
2336 | } |
2337 | }; |
2338 | |
2339 | // End Wasm SIMD |
2340 | |
2341 | class MIonToWasmCall final : public MVariadicInstruction, |
2342 | public NoTypePolicy::Data { |
2343 | CompilerGCPointer<WasmInstanceObject*> instanceObj_; |
2344 | const wasm::FuncExport& funcExport_; |
2345 | |
2346 | MIonToWasmCall(WasmInstanceObject* instanceObj, MIRType resultType, |
2347 | const wasm::FuncExport& funcExport) |
2348 | : MVariadicInstruction(classOpcode), |
2349 | instanceObj_(instanceObj), |
2350 | funcExport_(funcExport) { |
2351 | setResultType(resultType); |
2352 | } |
2353 | |
2354 | public: |
2355 | INSTRUCTION_HEADER(IonToWasmCall); |
2356 | |
2357 | static MIonToWasmCall* New(TempAllocator& alloc, |
2358 | WasmInstanceObject* instanceObj, |
2359 | const wasm::FuncExport& funcExport); |
2360 | |
2361 | void initArg(size_t i, MDefinition* arg) { initOperand(i, arg); } |
2362 | |
2363 | WasmInstanceObject* instanceObject() const { return instanceObj_; } |
2364 | wasm::Instance* instance() const { return &instanceObj_->instance(); } |
2365 | const wasm::FuncExport& funcExport() const { return funcExport_; } |
2366 | bool possiblyCalls() const override { return true; } |
2367 | #ifdef DEBUG1 |
2368 | bool isConsistentFloat32Use(MUse* use) const override; |
2369 | #endif |
2370 | }; |
2371 | |
2372 | // For accesses to wasm object fields, we need to be able to describe 8- and |
2373 | // 16-bit accesses. But MIRType can't represent those. Hence these two |
2374 | // supplemental enums, used for reading and writing fields respectively. |
2375 | |
2376 | // Indicates how to widen an 8- or 16-bit value (when it is read from memory). |
2377 | enum class MWideningOp : uint8_t { None, FromU16, FromS16, FromU8, FromS8 }; |
2378 | |
2379 | #ifdef JS_JITSPEW1 |
2380 | static inline const char* StringFromMWideningOp(MWideningOp op) { |
2381 | switch (op) { |
2382 | case MWideningOp::None: |
2383 | return "None"; |
2384 | case MWideningOp::FromU16: |
2385 | return "FromU16"; |
2386 | case MWideningOp::FromS16: |
2387 | return "FromS16"; |
2388 | case MWideningOp::FromU8: |
2389 | return "FromU8"; |
2390 | case MWideningOp::FromS8: |
2391 | return "FromS8"; |
2392 | default: |
2393 | break; |
2394 | } |
2395 | MOZ_CRASH("Unknown MWideningOp")do { do { } while (false); MOZ_ReportCrash("" "Unknown MWideningOp" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2395); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown MWideningOp" ")"); do { *((volatile int*)__null) = 2395; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2396 | } |
2397 | #endif |
2398 | |
2399 | // Indicates how to narrow a 32-bit value (when it is written to memory). The |
2400 | // operation is a simple truncate. |
2401 | enum class MNarrowingOp : uint8_t { None, To16, To8 }; |
2402 | |
2403 | #ifdef JS_JITSPEW1 |
2404 | static inline const char* StringFromMNarrowingOp(MNarrowingOp op) { |
2405 | switch (op) { |
2406 | case MNarrowingOp::None: |
2407 | return "None"; |
2408 | case MNarrowingOp::To16: |
2409 | return "To16"; |
2410 | case MNarrowingOp::To8: |
2411 | return "To8"; |
2412 | default: |
2413 | break; |
2414 | } |
2415 | MOZ_CRASH("Unknown MNarrowingOp")do { do { } while (false); MOZ_ReportCrash("" "Unknown MNarrowingOp" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2415); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown MNarrowingOp" ")"); do { *((volatile int*)__null) = 2415; __attribute__((nomerge )) ::abort(); } while (false); } while (false); |
2416 | } |
2417 | #endif |
2418 | |
2419 | // Provide information about potential trap at the instruction machine code, |
2420 | // e.g. null pointer dereference. |
2421 | struct TrapSiteInfo { |
2422 | wasm::BytecodeOffset offset; |
2423 | explicit TrapSiteInfo(wasm::BytecodeOffset offset_) : offset(offset_) {} |
2424 | }; |
2425 | |
2426 | using MaybeTrapSiteInfo = mozilla::Maybe<TrapSiteInfo>; |
2427 | |
2428 | // Load an object field stored at a fixed offset from a base pointer. This |
2429 | // field may be any value type, including references. No barriers are |
2430 | // performed. The offset must be representable as a 31-bit unsigned integer. |
2431 | class MWasmLoadField : public MUnaryInstruction, public NoTypePolicy::Data { |
2432 | uint32_t offset_; |
2433 | MWideningOp wideningOp_; |
2434 | AliasSet aliases_; |
2435 | MaybeTrapSiteInfo maybeTrap_; |
2436 | |
2437 | MWasmLoadField(MDefinition* obj, uint32_t offset, MIRType type, |
2438 | MWideningOp wideningOp, AliasSet aliases, |
2439 | MaybeTrapSiteInfo maybeTrap = mozilla::Nothing()) |
2440 | : MUnaryInstruction(classOpcode, obj), |
2441 | offset_(uint32_t(offset)), |
2442 | wideningOp_(wideningOp), |
2443 | aliases_(aliases), |
2444 | maybeTrap_(maybeTrap) { |
2445 | MOZ_ASSERT(offset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(offset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(offset <= (2147483647)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("offset <= (2147483647)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)" ")"); do { *((volatile int*)__null) = 2445; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2446 | // "if you want to widen the value when it is loaded, the destination type |
2447 | // must be Int32". |
2448 | MOZ_ASSERT_IF(wideningOp != MWideningOp::None, type == MIRType::Int32)do { if (wideningOp != MWideningOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(type == MIRType::Int32)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(type == MIRType::Int32))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Int32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2448); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2448; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2449 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2450 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2451 | AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2452 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2453 | AliasSet::Load(AliasSet::WasmArrayNumElements).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2454 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2455 | AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2456 | aliases.flags() == AliasSet::Load(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayNumElements).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataPointer).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2456; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2457 | setResultType(type); |
2458 | if (maybeTrap_) { |
2459 | setGuard(); |
2460 | } |
2461 | } |
2462 | |
2463 | public: |
2464 | INSTRUCTION_HEADER(WasmLoadField) |
2465 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2466 | NAMED_OPERANDS((0, obj))MDefinition* obj() const { return getOperand(0); } |
2467 | |
2468 | uint32_t offset() const { return offset_; } |
2469 | MWideningOp wideningOp() const { return wideningOp_; } |
2470 | AliasSet getAliasSet() const override { return aliases_; } |
2471 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2472 | |
2473 | bool congruentTo(const MDefinition* ins) const override { |
2474 | // In the limited case where this insn is used to read |
2475 | // WasmStructObject::outlineData_ (the field itself, not what it points |
2476 | // at), we allow commoning up to happen. This is OK because |
2477 | // WasmStructObject::outlineData_ is readonly for the life of the |
2478 | // WasmStructObject. |
2479 | if (!ins->isWasmLoadField()) { |
2480 | return false; |
2481 | } |
2482 | const MWasmLoadField* other = ins->toWasmLoadField(); |
2483 | return ins->isWasmLoadField() && congruentIfOperandsEqual(ins) && |
2484 | offset() == other->offset() && wideningOp() == other->wideningOp() && |
2485 | getAliasSet().flags() == other->getAliasSet().flags(); |
2486 | } |
2487 | |
2488 | #ifdef JS_JITSPEW1 |
2489 | void getExtras(ExtrasCollector* extras) const override { |
2490 | char buf[96]; |
2491 | SprintfLiteral(buf, "(offs=%lld, wideningOp=%s)", (long long int)offset_, |
2492 | StringFromMWideningOp(wideningOp_)); |
2493 | extras->add(buf); |
2494 | } |
2495 | #endif |
2496 | }; |
2497 | |
2498 | // Loads a value from a location, denoted as a fixed offset from a base |
2499 | // pointer, which (it is assumed) is within a wasm object. This field may be |
2500 | // any value type, including references. No barriers are performed. |
2501 | // |
2502 | // This instruction takes a pointer to a second object `ka`, which it is |
2503 | // necessary to keep alive. It is expected that `ka` holds a reference to |
2504 | // `obj`, but this is not enforced and no code is generated to access `ka`. |
2505 | // This instruction extends the lifetime of `ka` so that it, and hence `obj`, |
2506 | // cannot be collected while `obj` is live. This is necessary if `obj` does |
2507 | // not point to a GC-managed object. `offset` must be representable as a |
2508 | // 31-bit unsigned integer. |
2509 | class MWasmLoadFieldKA : public MBinaryInstruction, public NoTypePolicy::Data { |
2510 | uint32_t offset_; |
2511 | MWideningOp wideningOp_; |
2512 | AliasSet aliases_; |
2513 | MaybeTrapSiteInfo maybeTrap_; |
2514 | |
2515 | MWasmLoadFieldKA(MDefinition* ka, MDefinition* obj, size_t offset, |
2516 | MIRType type, MWideningOp wideningOp, AliasSet aliases, |
2517 | MaybeTrapSiteInfo maybeTrap = mozilla::Nothing()) |
2518 | : MBinaryInstruction(classOpcode, ka, obj), |
2519 | offset_(uint32_t(offset)), |
2520 | wideningOp_(wideningOp), |
2521 | aliases_(aliases), |
2522 | maybeTrap_(maybeTrap) { |
2523 | MOZ_ASSERT(offset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(offset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(offset <= (2147483647)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("offset <= (2147483647)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2523); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)" ")"); do { *((volatile int*)__null) = 2523; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2524 | MOZ_ASSERT_IF(wideningOp != MWideningOp::None, type == MIRType::Int32)do { if (wideningOp != MWideningOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(type == MIRType::Int32)>::isValid, "invalid assertion condition") ; if ((__builtin_expect(!!(!(!!(type == MIRType::Int32))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Int32" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2524; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2525 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2526 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2527 | AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2528 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2529 | AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2530 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2531 | AliasSet::Load(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2532 | aliases.flags() == AliasSet::Load(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet ::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases .flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags () || aliases.flags() == AliasSet::Load(AliasSet::Any).flags( )))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2532); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2532; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2533 | setResultType(type); |
2534 | if (maybeTrap_) { |
2535 | setGuard(); |
2536 | } |
2537 | } |
2538 | |
2539 | public: |
2540 | INSTRUCTION_HEADER(WasmLoadFieldKA) |
2541 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2542 | NAMED_OPERANDS((0, ka), (1, obj))MDefinition* ka() const { return getOperand(0); } MDefinition * obj() const { return getOperand(1); } |
2543 | |
2544 | uint32_t offset() const { return offset_; } |
2545 | MWideningOp wideningOp() const { return wideningOp_; } |
2546 | AliasSet getAliasSet() const override { return aliases_; } |
2547 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2548 | |
2549 | #ifdef JS_JITSPEW1 |
2550 | void getExtras(ExtrasCollector* extras) const override { |
2551 | char buf[96]; |
2552 | SprintfLiteral(buf, "(offs=%lld, wideningOp=%s)", (long long int)offset_, |
2553 | StringFromMWideningOp(wideningOp_)); |
2554 | extras->add(buf); |
2555 | } |
2556 | #endif |
2557 | }; |
2558 | |
2559 | // Loads a value from base pointer, given an index and element size. This field |
2560 | // may be any value type, including references. No barriers are performed. |
2561 | // |
2562 | // The element size is implicitly defined by MIRType and MWideningOp. For |
2563 | // example, MIRType::Float32 indicates an element size of 32 bits, and |
2564 | // MIRType::Int32 and MWideningOp::FromU16 together indicate an element size of |
2565 | // 16 bits. |
2566 | // |
2567 | // This instruction takes a second object `ka` that must be kept alive, as |
2568 | // described for MWasmLoadFieldKA above. |
2569 | class MWasmLoadElementKA : public MTernaryInstruction, |
2570 | public NoTypePolicy::Data { |
2571 | MWideningOp wideningOp_; |
2572 | Scale scale_; |
2573 | AliasSet aliases_; |
2574 | MaybeTrapSiteInfo maybeTrap_; |
2575 | |
2576 | MWasmLoadElementKA(MDefinition* ka, MDefinition* base, MDefinition* index, |
2577 | MIRType type, MWideningOp wideningOp, Scale scale, |
2578 | AliasSet aliases, |
2579 | MaybeTrapSiteInfo maybeTrap = mozilla::Nothing()) |
2580 | : MTernaryInstruction(classOpcode, ka, base, index), |
2581 | wideningOp_(wideningOp), |
2582 | scale_(scale), |
2583 | aliases_(aliases), |
2584 | maybeTrap_(maybeTrap) { |
2585 | MOZ_ASSERT(base->type() == MIRType::WasmArrayData)do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::WasmArrayData)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(base->type() == MIRType::WasmArrayData))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2585; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2586 | MOZ_ASSERT(aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmArrayDataArea).flags() || aliases.flags() == AliasSet:: Load(AliasSet::Any).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2588; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2587 | AliasSet::Load(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmArrayDataArea).flags() || aliases.flags() == AliasSet:: Load(AliasSet::Any).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2588; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2588 | aliases.flags() == AliasSet::Load(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any) .flags())>::isValid, "invalid assertion condition"); if (( __builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Load(AliasSet ::WasmArrayDataArea).flags() || aliases.flags() == AliasSet:: Load(AliasSet::Any).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2588); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2588; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2589 | setResultType(type); |
2590 | if (maybeTrap_) { |
2591 | setGuard(); |
2592 | } |
2593 | } |
2594 | |
2595 | public: |
2596 | INSTRUCTION_HEADER(WasmLoadElementKA) |
2597 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2598 | NAMED_OPERANDS((0, ka), (1, base), (2, index))MDefinition* ka() const { return getOperand(0); } MDefinition * base() const { return getOperand(1); } MDefinition* index() const { return getOperand(2); } |
2599 | |
2600 | MWideningOp wideningOp() const { return wideningOp_; } |
2601 | Scale scale() const { return scale_; } |
2602 | AliasSet getAliasSet() const override { return aliases_; } |
2603 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2604 | |
2605 | #ifdef JS_JITSPEW1 |
2606 | void getExtras(ExtrasCollector* extras) const override { |
2607 | char buf[96]; |
2608 | SprintfLiteral(buf, "(wideningOp=%s, scale=%s)", |
2609 | StringFromMWideningOp(wideningOp_), StringFromScale(scale_)); |
2610 | extras->add(buf); |
2611 | } |
2612 | #endif |
2613 | }; |
2614 | |
2615 | // Stores a non-reference value to anlocation, denoted as a fixed offset from |
2616 | // a base pointer, which (it is assumed) is within a wasm object. This field |
2617 | // may be any value type, _excluding_ references. References _must_ use the |
2618 | // 'Ref' variant of this instruction. The offset must be representable as a |
2619 | // 31-bit unsigned integer. |
2620 | // |
2621 | // This instruction takes a second object `ka` that must be kept alive, as |
2622 | // described for MWasmLoadFieldKA above. |
2623 | class MWasmStoreFieldKA : public MTernaryInstruction, |
2624 | public NoTypePolicy::Data { |
2625 | uint32_t offset_; |
2626 | MNarrowingOp narrowingOp_; |
2627 | AliasSet aliases_; |
2628 | MaybeTrapSiteInfo maybeTrap_; |
2629 | |
2630 | MWasmStoreFieldKA(MDefinition* ka, MDefinition* obj, size_t offset, |
2631 | MDefinition* value, MNarrowingOp narrowingOp, |
2632 | AliasSet aliases, |
2633 | MaybeTrapSiteInfo maybeTrap = mozilla::Nothing()) |
2634 | : MTernaryInstruction(classOpcode, ka, obj, value), |
2635 | offset_(uint32_t(offset)), |
2636 | narrowingOp_(narrowingOp), |
2637 | aliases_(aliases), |
2638 | maybeTrap_(maybeTrap) { |
2639 | MOZ_ASSERT(offset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(offset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(offset <= (2147483647)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("offset <= (2147483647)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2639); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)" ")"); do { *((volatile int*)__null) = 2639; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2640 | MOZ_ASSERT(value->type() != MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(value->type() != MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(value->type() != MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("value->type() != MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2640); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 2640; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2641 | // "if you want to narrow the value when it is stored, the source type |
2642 | // must be Int32". |
2643 | MOZ_ASSERT_IF(narrowingOp != MNarrowingOp::None,do { if (narrowingOp != MNarrowingOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(value-> type() == MIRType::Int32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(value->type() == MIRType:: Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("value->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2644; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2644 | value->type() == MIRType::Int32)do { if (narrowingOp != MNarrowingOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(value-> type() == MIRType::Int32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(value->type() == MIRType:: Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("value->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2644); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2644; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2645 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2646 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2647 | AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2648 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2649 | AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2650 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2651 | AliasSet::Store(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2652 | aliases.flags() == AliasSet::Store(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2652); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2652; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2653 | if (maybeTrap_) { |
2654 | setGuard(); |
2655 | } |
2656 | } |
2657 | |
2658 | public: |
2659 | INSTRUCTION_HEADER(WasmStoreFieldKA) |
2660 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2661 | NAMED_OPERANDS((0, ka), (1, obj), (2, value))MDefinition* ka() const { return getOperand(0); } MDefinition * obj() const { return getOperand(1); } MDefinition* value() const { return getOperand(2); } |
2662 | |
2663 | uint32_t offset() const { return offset_; } |
2664 | MNarrowingOp narrowingOp() const { return narrowingOp_; } |
2665 | AliasSet getAliasSet() const override { return aliases_; } |
2666 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2667 | |
2668 | #ifdef JS_JITSPEW1 |
2669 | void getExtras(ExtrasCollector* extras) const override { |
2670 | char buf[96]; |
2671 | SprintfLiteral(buf, "(offs=%lld, narrowingOp=%s)", (long long int)offset_, |
2672 | StringFromMNarrowingOp(narrowingOp_)); |
2673 | extras->add(buf); |
2674 | } |
2675 | #endif |
2676 | }; |
2677 | |
2678 | // Stores a reference value to a location, denoted as a fixed offset from a |
2679 | // base pointer, which (it is assumed) is within a wasm object. This |
2680 | // instruction emits a pre-barrier. A post barrier _must_ be performed |
2681 | // separately. The offset must be representable as a 31-bit unsigned integer. |
2682 | // |
2683 | // This instruction takes a second object `ka` that must be kept alive, as |
2684 | // described for MWasmLoadFieldKA above. |
2685 | class MWasmStoreFieldRefKA : public MAryInstruction<4>, |
2686 | public NoTypePolicy::Data { |
2687 | uint32_t offset_; |
2688 | AliasSet aliases_; |
2689 | MaybeTrapSiteInfo maybeTrap_; |
2690 | WasmPreBarrierKind preBarrierKind_; |
2691 | |
2692 | MWasmStoreFieldRefKA(MDefinition* instance, MDefinition* ka, MDefinition* obj, |
2693 | size_t offset, MDefinition* value, AliasSet aliases, |
2694 | MaybeTrapSiteInfo maybeTrap, |
2695 | WasmPreBarrierKind preBarrierKind) |
2696 | : MAryInstruction<4>(classOpcode), |
2697 | offset_(uint32_t(offset)), |
2698 | aliases_(aliases), |
2699 | maybeTrap_(maybeTrap), |
2700 | preBarrierKind_(preBarrierKind) { |
2701 | MOZ_ASSERT(obj->type() == TargetWordMIRType() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(obj->type() == TargetWordMIRType() || obj->type () == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(obj->type() == TargetWordMIRType () || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2702 | obj->type() == MIRType::Pointer ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(obj->type() == TargetWordMIRType() || obj->type () == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(obj->type() == TargetWordMIRType () || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2703 | obj->type() == MIRType::WasmAnyRef ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(obj->type() == TargetWordMIRType() || obj->type () == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(obj->type() == TargetWordMIRType () || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2704 | obj->type() == MIRType::WasmArrayData)do { static_assert( mozilla::detail::AssertionConditionType< decltype(obj->type() == TargetWordMIRType() || obj->type () == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(obj->type() == TargetWordMIRType () || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData ))), 0))) { do { } while (false); MOZ_ReportAssertionFailure( "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2704; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2705 | MOZ_ASSERT(offset <= INT32_MAX)do { static_assert( mozilla::detail::AssertionConditionType< decltype(offset <= (2147483647))>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(offset <= (2147483647)))) , 0))) { do { } while (false); MOZ_ReportAssertionFailure("offset <= (2147483647)" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)" ")"); do { *((volatile int*)__null) = 2705; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2706 | MOZ_ASSERT(value->type() == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(value->type() == MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(value->type() == MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("value->type() == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2706); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 2706; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2707 | MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2708 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2709 | AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2710 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2711 | AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2712 | aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2713 | AliasSet::Store(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2714 | aliases.flags() == AliasSet::Store(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmStructInlineDataArea).flags() || aliases.flags( ) == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags () || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmStructInlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmStructOutlineDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2714; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2715 | initOperand(0, instance); |
2716 | initOperand(1, ka); |
2717 | initOperand(2, obj); |
2718 | initOperand(3, value); |
2719 | if (maybeTrap_) { |
2720 | setGuard(); |
2721 | } |
2722 | } |
2723 | |
2724 | public: |
2725 | INSTRUCTION_HEADER(WasmStoreFieldRefKA) |
2726 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2727 | NAMED_OPERANDS((0, instance), (1, ka), (2, obj), (3, value))MDefinition* instance() const { return getOperand(0); } MDefinition * ka() const { return getOperand(1); } MDefinition* obj() const { return getOperand(2); } MDefinition* value() const { return getOperand(3); } |
2728 | |
2729 | uint32_t offset() const { return offset_; } |
2730 | AliasSet getAliasSet() const override { return aliases_; } |
2731 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2732 | WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; } |
2733 | |
2734 | #ifdef JS_JITSPEW1 |
2735 | void getExtras(ExtrasCollector* extras) const override { |
2736 | char buf[64]; |
2737 | SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_); |
2738 | extras->add(buf); |
2739 | } |
2740 | #endif |
2741 | }; |
2742 | |
2743 | // Stores a non-reference value to a base pointer, given an index and element |
2744 | // size. This field may be any value type, excluding references. References MUST |
2745 | // use the 'Ref' variant of this instruction. |
2746 | // |
2747 | // The element size is implicitly defined by MIRType and MNarrowingOp. For |
2748 | // example, MIRType::Float32 indicates an element size of 32 bits, and |
2749 | // MIRType::Int32 and MNarrowingOp::To16 together indicate an element size of 16 |
2750 | // bits. |
2751 | // |
2752 | // This instruction takes a second object `ka` that must be kept alive, as |
2753 | // described for MWasmLoadFieldKA above. |
2754 | class MWasmStoreElementKA : public MQuaternaryInstruction, |
2755 | public NoTypePolicy::Data { |
2756 | MNarrowingOp narrowingOp_; |
2757 | Scale scale_; |
2758 | AliasSet aliases_; |
2759 | MaybeTrapSiteInfo maybeTrap_; |
2760 | |
2761 | MWasmStoreElementKA(MDefinition* ka, MDefinition* base, MDefinition* index, |
2762 | MDefinition* value, MNarrowingOp narrowingOp, Scale scale, |
2763 | AliasSet aliases, |
2764 | MaybeTrapSiteInfo maybeTrap = mozilla::Nothing()) |
2765 | : MQuaternaryInstruction(classOpcode, ka, base, index, value), |
2766 | narrowingOp_(narrowingOp), |
2767 | scale_(scale), |
2768 | aliases_(aliases), |
2769 | maybeTrap_(maybeTrap) { |
2770 | MOZ_ASSERT(base->type() == MIRType::WasmArrayData)do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::WasmArrayData)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(base->type() == MIRType::WasmArrayData))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2770; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2771 | MOZ_ASSERT(value->type() != MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(value->type() != MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(value->type() != MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("value->type() != MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2771); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 2771; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2772 | // "if you want to narrow the value when it is stored, the source type |
2773 | // must be Int32". |
2774 | MOZ_ASSERT_IF(narrowingOp != MNarrowingOp::None,do { if (narrowingOp != MNarrowingOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(value-> type() == MIRType::Int32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(value->type() == MIRType:: Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("value->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2775; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false) |
2775 | value->type() == MIRType::Int32)do { if (narrowingOp != MNarrowingOp::None) { do { static_assert ( mozilla::detail::AssertionConditionType<decltype(value-> type() == MIRType::Int32)>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(value->type() == MIRType:: Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure ("value->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2775); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32" ")"); do { *((volatile int*)__null) = 2775; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); } } while ( false); |
2776 | MOZ_ASSERT(aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2778; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2777 | AliasSet::Store(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2778; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2778 | aliases.flags() == AliasSet::Store(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2778); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2778; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2779 | if (maybeTrap_) { |
2780 | setGuard(); |
2781 | } |
2782 | } |
2783 | |
2784 | public: |
2785 | INSTRUCTION_HEADER(WasmStoreElementKA) |
2786 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2787 | NAMED_OPERANDS((0, ka), (1, base), (2, index), (3, value))MDefinition* ka() const { return getOperand(0); } MDefinition * base() const { return getOperand(1); } MDefinition* index() const { return getOperand(2); } MDefinition* value() const { return getOperand(3); } |
2788 | |
2789 | MNarrowingOp narrowingOp() const { return narrowingOp_; } |
2790 | Scale scale() const { return scale_; } |
2791 | AliasSet getAliasSet() const override { return aliases_; } |
2792 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2793 | |
2794 | #ifdef JS_JITSPEW1 |
2795 | void getExtras(ExtrasCollector* extras) const override { |
2796 | char buf[96]; |
2797 | SprintfLiteral(buf, "(narrowingOp=%s, scale=%s)", |
2798 | StringFromMNarrowingOp(narrowingOp_), |
2799 | StringFromScale(scale_)); |
2800 | extras->add(buf); |
2801 | } |
2802 | #endif |
2803 | }; |
2804 | |
2805 | // Stores a reference value to a base pointer, given an index and element size. |
2806 | // This instruction emits a pre-barrier. A post barrier MUST be performed |
2807 | // separately. |
2808 | // |
2809 | // The element size is implicitly defined by MIRType and MNarrowingOp, as |
2810 | // described for MWasmStoreElementKA above. |
2811 | // |
2812 | // This instruction takes a second object `ka` that must be kept alive, as |
2813 | // described for MWasmLoadFieldKA above. |
2814 | class MWasmStoreElementRefKA : public MAryInstruction<5>, |
2815 | public NoTypePolicy::Data { |
2816 | AliasSet aliases_; |
2817 | MaybeTrapSiteInfo maybeTrap_; |
2818 | WasmPreBarrierKind preBarrierKind_; |
2819 | |
2820 | MWasmStoreElementRefKA(MDefinition* instance, MDefinition* ka, |
2821 | MDefinition* base, MDefinition* index, |
2822 | MDefinition* value, AliasSet aliases, |
2823 | MaybeTrapSiteInfo maybeTrap, |
2824 | WasmPreBarrierKind preBarrierKind) |
2825 | : MAryInstruction<5>(classOpcode), |
2826 | aliases_(aliases), |
2827 | maybeTrap_(maybeTrap), |
2828 | preBarrierKind_(preBarrierKind) { |
2829 | MOZ_ASSERT(base->type() == MIRType::WasmArrayData)do { static_assert( mozilla::detail::AssertionConditionType< decltype(base->type() == MIRType::WasmArrayData)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(base->type() == MIRType::WasmArrayData))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("base->type() == MIRType::WasmArrayData" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2829); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData" ")"); do { *((volatile int*)__null) = 2829; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2830 | MOZ_ASSERT(value->type() == MIRType::WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType< decltype(value->type() == MIRType::WasmAnyRef)>::isValid , "invalid assertion condition"); if ((__builtin_expect(!!(!( !!(value->type() == MIRType::WasmAnyRef))), 0))) { do { } while (false); MOZ_ReportAssertionFailure("value->type() == MIRType::WasmAnyRef" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2830); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef" ")"); do { *((volatile int*)__null) = 2830; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2831 | MOZ_ASSERT(aliases.flags() ==do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2832 | AliasSet::Store(AliasSet::WasmArrayDataArea).flags() ||do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false) |
2833 | aliases.flags() == AliasSet::Store(AliasSet::Any).flags())do { static_assert( mozilla::detail::AssertionConditionType< decltype(aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea ).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any ).flags())>::isValid, "invalid assertion condition"); if ( (__builtin_expect(!!(!(!!(aliases.flags() == AliasSet::Store( AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet ::Store(AliasSet::Any).flags()))), 0))) { do { } while (false ); MOZ_ReportAssertionFailure("aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2833); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()" ")"); do { *((volatile int*)__null) = 2833; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2834 | initOperand(0, instance); |
2835 | initOperand(1, ka); |
2836 | initOperand(2, base); |
2837 | initOperand(3, index); |
2838 | initOperand(4, value); |
2839 | if (maybeTrap_) { |
2840 | setGuard(); |
2841 | } |
2842 | } |
2843 | |
2844 | public: |
2845 | INSTRUCTION_HEADER(WasmStoreElementRefKA) |
2846 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2847 | NAMED_OPERANDS((0, instance), (1, ka), (2, base), (3, index), (4, value))MDefinition* instance() const { return getOperand(0); } MDefinition * ka() const { return getOperand(1); } MDefinition* base() const { return getOperand(2); } MDefinition* index() const { return getOperand(3); } MDefinition* value() const { return getOperand (4); } |
2848 | |
2849 | AliasSet getAliasSet() const override { return aliases_; } |
2850 | MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; } |
2851 | WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; } |
2852 | }; |
2853 | |
2854 | class MWasmRefIsSubtypeOfAbstract : public MUnaryInstruction, |
2855 | public NoTypePolicy::Data { |
2856 | wasm::RefType sourceType_; |
2857 | wasm::RefType destType_; |
2858 | |
2859 | MWasmRefIsSubtypeOfAbstract(MDefinition* ref, wasm::RefType sourceType, |
2860 | wasm::RefType destType) |
2861 | : MUnaryInstruction(classOpcode, ref), |
2862 | sourceType_(sourceType), |
2863 | destType_(destType) { |
2864 | MOZ_ASSERT(!destType.isTypeRef())do { static_assert( mozilla::detail::AssertionConditionType< decltype(!destType.isTypeRef())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(!destType.isTypeRef()))), 0) )) { do { } while (false); MOZ_ReportAssertionFailure("!destType.isTypeRef()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2864); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!destType.isTypeRef()" ")"); do { *((volatile int*)__null) = 2864; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2865 | setResultType(MIRType::Int32); |
2866 | setMovable(); |
2867 | } |
2868 | |
2869 | public: |
2870 | INSTRUCTION_HEADER(WasmRefIsSubtypeOfAbstract) |
2871 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2872 | NAMED_OPERANDS((0, ref))MDefinition* ref() const { return getOperand(0); } |
2873 | |
2874 | wasm::RefType sourceType() const { return sourceType_; }; |
2875 | wasm::RefType destType() const { return destType_; }; |
2876 | |
2877 | bool congruentTo(const MDefinition* ins) const override { |
2878 | return congruentIfOperandsEqual(ins) && |
2879 | sourceType() == ins->toWasmRefIsSubtypeOfAbstract()->sourceType() && |
2880 | destType() == ins->toWasmRefIsSubtypeOfAbstract()->destType(); |
2881 | } |
2882 | |
2883 | HashNumber valueHash() const override { |
2884 | HashNumber hn = MUnaryInstruction::valueHash(); |
2885 | hn = addU64ToHash(hn, sourceType().packed().bits()); |
2886 | hn = addU64ToHash(hn, destType().packed().bits()); |
2887 | return hn; |
2888 | } |
2889 | |
2890 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2891 | }; |
2892 | |
2893 | // Tests if the wasm ref `ref` is a subtype of `superSTV`. |
2894 | // The actual super type definition must be known at compile time, so that the |
2895 | // subtyping depth of super type depth can be used. |
2896 | class MWasmRefIsSubtypeOfConcrete : public MBinaryInstruction, |
2897 | public NoTypePolicy::Data { |
2898 | wasm::RefType sourceType_; |
2899 | wasm::RefType destType_; |
2900 | |
2901 | MWasmRefIsSubtypeOfConcrete(MDefinition* ref, MDefinition* superSTV, |
2902 | wasm::RefType sourceType, wasm::RefType destType) |
2903 | : MBinaryInstruction(classOpcode, ref, superSTV), |
2904 | sourceType_(sourceType), |
2905 | destType_(destType) { |
2906 | MOZ_ASSERT(destType.isTypeRef())do { static_assert( mozilla::detail::AssertionConditionType< decltype(destType.isTypeRef())>::isValid, "invalid assertion condition" ); if ((__builtin_expect(!!(!(!!(destType.isTypeRef()))), 0)) ) { do { } while (false); MOZ_ReportAssertionFailure("destType.isTypeRef()" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR-wasm.h" , 2906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "destType.isTypeRef()" ")"); do { *((volatile int*)__null) = 2906; __attribute__((nomerge )) ::abort(); } while (false); } } while (false); |
2907 | setResultType(MIRType::Int32); |
2908 | setMovable(); |
2909 | } |
2910 | |
2911 | public: |
2912 | INSTRUCTION_HEADER(WasmRefIsSubtypeOfConcrete) |
2913 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2914 | NAMED_OPERANDS((0, ref), (1, superSTV))MDefinition* ref() const { return getOperand(0); } MDefinition * superSTV() const { return getOperand(1); } |
2915 | |
2916 | wasm::RefType sourceType() const { return sourceType_; }; |
2917 | wasm::RefType destType() const { return destType_; }; |
2918 | |
2919 | bool congruentTo(const MDefinition* ins) const override { |
2920 | return congruentIfOperandsEqual(ins) && |
2921 | sourceType() == ins->toWasmRefIsSubtypeOfConcrete()->sourceType() && |
2922 | destType() == ins->toWasmRefIsSubtypeOfConcrete()->destType(); |
2923 | } |
2924 | |
2925 | HashNumber valueHash() const override { |
2926 | HashNumber hn = MBinaryInstruction::valueHash(); |
2927 | hn = addU64ToHash(hn, sourceType().packed().bits()); |
2928 | hn = addU64ToHash(hn, destType().packed().bits()); |
2929 | return hn; |
2930 | } |
2931 | |
2932 | MDefinition* foldsTo(TempAllocator& alloc) override; |
2933 | }; |
2934 | |
2935 | class MWasmNewStructObject : public MBinaryInstruction, |
2936 | public NoTypePolicy::Data { |
2937 | private: |
2938 | bool isOutline_; |
2939 | bool zeroFields_; |
2940 | gc::AllocKind allocKind_; |
2941 | |
2942 | MWasmNewStructObject(MDefinition* instance, MDefinition* typeDefData, |
2943 | bool isOutline, bool zeroFields, gc::AllocKind allocKind) |
2944 | : MBinaryInstruction(classOpcode, instance, typeDefData), |
2945 | isOutline_(isOutline), |
2946 | zeroFields_(zeroFields), |
2947 | allocKind_(allocKind) { |
2948 | setResultType(MIRType::WasmAnyRef); |
2949 | } |
2950 | |
2951 | public: |
2952 | INSTRUCTION_HEADER(WasmNewStructObject) |
2953 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2954 | NAMED_OPERANDS((0, instance), (1, typeDefData))MDefinition* instance() const { return getOperand(0); } MDefinition * typeDefData() const { return getOperand(1); } |
2955 | |
2956 | AliasSet getAliasSet() const override { |
2957 | if (js::SupportDifferentialTesting()) { |
2958 | // Consider allocations effectful for differential testing. |
2959 | return MDefinition::getAliasSet(); |
2960 | } |
2961 | return AliasSet::None(); |
2962 | } |
2963 | bool isOutline() const { return isOutline_; } |
2964 | bool zeroFields() const { return zeroFields_; } |
2965 | gc::AllocKind allocKind() const { return allocKind_; } |
2966 | }; |
2967 | |
2968 | class MWasmNewArrayObject : public MTernaryInstruction, |
2969 | public NoTypePolicy::Data { |
2970 | private: |
2971 | uint32_t elemSize_; |
2972 | bool zeroFields_; |
2973 | wasm::BytecodeOffset bytecodeOffset_; |
2974 | |
2975 | MWasmNewArrayObject(MDefinition* instance, MDefinition* numElements, |
2976 | MDefinition* typeDefData, uint32_t elemSize, |
2977 | bool zeroFields, wasm::BytecodeOffset bytecodeOffset) |
2978 | : MTernaryInstruction(classOpcode, instance, numElements, typeDefData), |
2979 | elemSize_(elemSize), |
2980 | zeroFields_(zeroFields), |
2981 | bytecodeOffset_(bytecodeOffset) { |
2982 | setResultType(MIRType::WasmAnyRef); |
2983 | } |
2984 | |
2985 | public: |
2986 | INSTRUCTION_HEADER(WasmNewArrayObject) |
2987 | TRIVIAL_NEW_WRAPPERStemplate <typename... Args> static MThisOpcode* New(TempAllocator & alloc, Args&&... args) { return new (alloc) MThisOpcode (std::forward<Args>(args)...); } template <typename... Args> static MThisOpcode* New(TempAllocator::Fallible alloc , Args&&... args) { return new (alloc) MThisOpcode(std ::forward<Args>(args)...); } |
2988 | NAMED_OPERANDS((0, instance), (1, numElements), (2, typeDefData))MDefinition* instance() const { return getOperand(0); } MDefinition * numElements() const { return getOperand(1); } MDefinition* typeDefData () const { return getOperand(2); } |
2989 | |
2990 | AliasSet getAliasSet() const override { |
2991 | if (js::SupportDifferentialTesting()) { |
2992 | // Consider allocations effectful for differential testing. |
2993 | return MDefinition::getAliasSet(); |
2994 | } |
2995 | return AliasSet::None(); |
2996 | } |
2997 | uint32_t elemSize() const { return elemSize_; } |
2998 | bool zeroFields() const { return zeroFields_; } |
2999 | wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; } |
3000 | }; |
3001 | |
3002 | #undef INSTRUCTION_HEADER |
3003 | |
3004 | #ifdef ENABLE_WASM_SIMD1 |
3005 | MWasmShuffleSimd128* BuildWasmShuffleSimd128(TempAllocator& alloc, |
3006 | const int8_t* control, |
3007 | MDefinition* lhs, |
3008 | MDefinition* rhs); |
3009 | #endif // ENABLE_WASM_SIMD |
3010 | |
3011 | } // namespace jit |
3012 | } // namespace js |
3013 | |
3014 | #endif /* jit_MIR_wasm_h */ |