Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h
Warning:line 9474, column 17
Value stored to 'what' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_cpp_js_src_jit0.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/jit -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/jit -resource-dir /usr/lib/llvm-18/lib/clang/18 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/js-confdefs.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D WASM_SUPPORTS_HUGE_MEMORY -D JS_CACHEIR_SPEW -D JS_STRUCTURED_SPEW -D JS_HAS_CTYPES -D FFI_BUILDING -D EXPORT_JS_API -D MOZ_HAS_MOZGLUE -I /var/lib/jenkins/workspace/firefox-scan-build/js/src/jit -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src/jit -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/js/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/x86_64-linux-gnu/c++/13 -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../include/c++/13/backward -internal-isystem /usr/lib/llvm-18/lib/clang/18/include -internal-isystem /usr/local/include -internal-isystem /usr/bin/../lib/gcc/x86_64-linux-gnu/13/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-05-16-034744-15991-1 -x c++ Unified_cpp_js_src_jit0.cpp
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_h
13#define jit_MIR_h
14
15#include "mozilla/Array.h"
16#include "mozilla/HashFunctions.h"
17#ifdef JS_JITSPEW1
18# include "mozilla/Attributes.h" // MOZ_STACK_CLASS
19#endif
20#include "mozilla/MacroForEach.h"
21#ifdef JS_JITSPEW1
22# include "mozilla/Sprintf.h"
23# include "mozilla/Vector.h"
24#endif
25
26#include <algorithm>
27#include <initializer_list>
28
29#include "NamespaceImports.h"
30
31#include "jit/AtomicOp.h"
32#include "jit/FixedList.h"
33#include "jit/InlineList.h"
34#include "jit/JitAllocPolicy.h"
35#include "jit/MacroAssembler.h"
36#include "jit/MIROpsGenerated.h"
37#include "jit/ShuffleAnalysis.h"
38#include "jit/TypeData.h"
39#include "jit/TypePolicy.h"
40#include "js/experimental/JitInfo.h" // JSJit{Getter,Setter}Op, JSJitInfo
41#include "js/HeapAPI.h"
42#include "js/ScalarType.h" // js::Scalar::Type
43#include "js/Value.h"
44#include "js/Vector.h"
45#include "util/DifferentialTesting.h"
46#include "vm/BigIntType.h"
47#include "vm/EnvironmentObject.h"
48#include "vm/FunctionFlags.h" // js::FunctionFlags
49#include "vm/JSContext.h"
50#include "vm/RegExpObject.h"
51#include "vm/TypedArrayObject.h"
52#include "wasm/WasmJS.h" // for WasmInstanceObject
53
54namespace JS {
55struct ExpandoAndGeneration;
56}
57
58namespace js {
59
60namespace wasm {
61class FuncExport;
62extern uint32_t MIRTypeToABIResultSize(jit::MIRType);
63} // namespace wasm
64
65class JS_PUBLIC_API GenericPrinter;
66class NativeIteratorListHead;
67class StringObject;
68
69enum class UnaryMathFunction : uint8_t;
70
71bool CurrentThreadIsIonCompiling();
72
73namespace jit {
74
75class CallInfo;
76
77#ifdef JS_JITSPEW1
78// Helper for debug printing. Avoids creating a MIR.h <--> MIRGraph.h cycle.
79// Implementation of this needs to see inside `MBasicBlock`; that is possible
80// in MIR.cpp since it also includes MIRGraph.h, whereas this file does not.
81class MBasicBlock;
82uint32_t GetMBasicBlockId(const MBasicBlock* block);
83
84// Helper class for debug printing. This class allows `::getExtras` methods
85// to add strings to be printed, on a per-MIR-node basis. The strings are
86// copied into storage owned by this class when `::add` is called, so the
87// `::getExtras` methods do not need to be concerned about storage management.
88class MOZ_STACK_CLASS ExtrasCollector {
89 mozilla::Vector<UniqueChars, 4> strings_;
90
91 public:
92 // Add `str` to the collection. A copy, owned by this object, is made. In
93 // case of OOM the call has no effect.
94 void add(const char* str) {
95 UniqueChars dup = DuplicateString(str);
96 if (dup) {
97 (void)strings_.append(std::move(dup));
98 }
99 }
100 size_t count() const { return strings_.length(); }
101 UniqueChars get(size_t ix) { return std::move(strings_[ix]); }
102};
103#endif
104
105// Forward declarations of MIR types.
106#define FORWARD_DECLARE(op) class M##op;
107MIR_OPCODE_LIST(FORWARD_DECLARE)FORWARD_DECLARE(Start)FORWARD_DECLARE(OsrEntry)FORWARD_DECLARE
(Nop)FORWARD_DECLARE(LimitedTruncate)FORWARD_DECLARE(Constant
)FORWARD_DECLARE(WasmNullConstant)FORWARD_DECLARE(WasmFloatConstant
)FORWARD_DECLARE(Parameter)FORWARD_DECLARE(Callee)FORWARD_DECLARE
(IsConstructing)FORWARD_DECLARE(TableSwitch)FORWARD_DECLARE(Goto
)FORWARD_DECLARE(Test)FORWARD_DECLARE(Return)FORWARD_DECLARE(
Throw)FORWARD_DECLARE(ThrowWithStack)FORWARD_DECLARE(NewArray
)FORWARD_DECLARE(NewArrayDynamicLength)FORWARD_DECLARE(NewTypedArray
)FORWARD_DECLARE(NewTypedArrayDynamicLength)FORWARD_DECLARE(NewTypedArrayFromArray
)FORWARD_DECLARE(NewTypedArrayFromArrayBuffer)FORWARD_DECLARE
(NewObject)FORWARD_DECLARE(NewPlainObject)FORWARD_DECLARE(NewArrayObject
)FORWARD_DECLARE(NewIterator)FORWARD_DECLARE(ObjectState)FORWARD_DECLARE
(ArrayState)FORWARD_DECLARE(BindFunction)FORWARD_DECLARE(NewBoundFunction
)FORWARD_DECLARE(BoundFunctionNumArgs)FORWARD_DECLARE(GuardBoundFunctionIsConstructor
)FORWARD_DECLARE(MutateProto)FORWARD_DECLARE(InitPropGetterSetter
)FORWARD_DECLARE(InitElemGetterSetter)FORWARD_DECLARE(Call)FORWARD_DECLARE
(CallClassHook)FORWARD_DECLARE(ApplyArgs)FORWARD_DECLARE(ApplyArgsObj
)FORWARD_DECLARE(ApplyArray)FORWARD_DECLARE(ConstructArgs)FORWARD_DECLARE
(ConstructArray)FORWARD_DECLARE(Bail)FORWARD_DECLARE(Unreachable
)FORWARD_DECLARE(EncodeSnapshot)FORWARD_DECLARE(AssertRecoveredOnBailout
)FORWARD_DECLARE(AssertFloat32)FORWARD_DECLARE(Compare)FORWARD_DECLARE
(SameValueDouble)FORWARD_DECLARE(SameValue)FORWARD_DECLARE(Box
)FORWARD_DECLARE(Unbox)FORWARD_DECLARE(AssertRange)FORWARD_DECLARE
(AssertClass)FORWARD_DECLARE(AssertShape)FORWARD_DECLARE(CreateThis
)FORWARD_DECLARE(CreateArgumentsObject)FORWARD_DECLARE(CreateInlinedArgumentsObject
)FORWARD_DECLARE(GetInlinedArgument)FORWARD_DECLARE(GetInlinedArgumentHole
)FORWARD_DECLARE(GetArgumentsObjectArg)FORWARD_DECLARE(SetArgumentsObjectArg
)FORWARD_DECLARE(LoadArgumentsObjectArg)FORWARD_DECLARE(LoadArgumentsObjectArgHole
)FORWARD_DECLARE(InArgumentsObjectArg)FORWARD_DECLARE(ArgumentsObjectLength
)FORWARD_DECLARE(ArrayFromArgumentsObject)FORWARD_DECLARE(GuardArgumentsObjectFlags
)FORWARD_DECLARE(LoadScriptedProxyHandler)FORWARD_DECLARE(CheckScriptedProxyGetResult
)FORWARD_DECLARE(IdToStringOrSymbol)FORWARD_DECLARE(ReturnFromCtor
)FORWARD_DECLARE(ToDouble)FORWARD_DECLARE(ToFloat32)FORWARD_DECLARE
(WasmUnsignedToDouble)FORWARD_DECLARE(WasmUnsignedToFloat32)FORWARD_DECLARE
(WrapInt64ToInt32)FORWARD_DECLARE(ExtendInt32ToInt64)FORWARD_DECLARE
(WasmBuiltinTruncateToInt64)FORWARD_DECLARE(WasmTruncateToInt64
)FORWARD_DECLARE(WasmTruncateToInt32)FORWARD_DECLARE(WasmAnyRefFromJSValue
)FORWARD_DECLARE(WasmAnyRefFromJSObject)FORWARD_DECLARE(WasmAnyRefFromJSString
)FORWARD_DECLARE(WasmNewI31Ref)FORWARD_DECLARE(WasmI31RefGet)
FORWARD_DECLARE(Int32ToIntPtr)FORWARD_DECLARE(NonNegativeIntPtrToInt32
)FORWARD_DECLARE(IntPtrToDouble)FORWARD_DECLARE(AdjustDataViewLength
)FORWARD_DECLARE(Int64ToFloatingPoint)FORWARD_DECLARE(BuiltinInt64ToFloatingPoint
)FORWARD_DECLARE(ToNumberInt32)FORWARD_DECLARE(BooleanToInt32
)FORWARD_DECLARE(TruncateToInt32)FORWARD_DECLARE(WasmBuiltinTruncateToInt32
)FORWARD_DECLARE(ToBigInt)FORWARD_DECLARE(ToInt64)FORWARD_DECLARE
(TruncateBigIntToInt64)FORWARD_DECLARE(Int64ToBigInt)FORWARD_DECLARE
(ToString)FORWARD_DECLARE(BitNot)FORWARD_DECLARE(TypeOf)FORWARD_DECLARE
(TypeOfName)FORWARD_DECLARE(TypeOfIs)FORWARD_DECLARE(ToAsyncIter
)FORWARD_DECLARE(ToPropertyKeyCache)FORWARD_DECLARE(BitAnd)FORWARD_DECLARE
(BitOr)FORWARD_DECLARE(BitXor)FORWARD_DECLARE(Lsh)FORWARD_DECLARE
(Rsh)FORWARD_DECLARE(Ursh)FORWARD_DECLARE(SignExtendInt32)FORWARD_DECLARE
(SignExtendInt64)FORWARD_DECLARE(MinMax)FORWARD_DECLARE(MinMaxArray
)FORWARD_DECLARE(Abs)FORWARD_DECLARE(Clz)FORWARD_DECLARE(Ctz)
FORWARD_DECLARE(Popcnt)FORWARD_DECLARE(Sqrt)FORWARD_DECLARE(CopySign
)FORWARD_DECLARE(Atan2)FORWARD_DECLARE(Hypot)FORWARD_DECLARE(
Pow)FORWARD_DECLARE(PowHalf)FORWARD_DECLARE(Random)FORWARD_DECLARE
(Sign)FORWARD_DECLARE(MathFunction)FORWARD_DECLARE(Add)FORWARD_DECLARE
(Sub)FORWARD_DECLARE(Mul)FORWARD_DECLARE(Div)FORWARD_DECLARE(
WasmBuiltinDivI64)FORWARD_DECLARE(Mod)FORWARD_DECLARE(WasmBuiltinModD
)FORWARD_DECLARE(WasmBuiltinModI64)FORWARD_DECLARE(BigIntAdd)
FORWARD_DECLARE(BigIntSub)FORWARD_DECLARE(BigIntMul)FORWARD_DECLARE
(BigIntDiv)FORWARD_DECLARE(BigIntMod)FORWARD_DECLARE(BigIntPow
)FORWARD_DECLARE(BigIntBitAnd)FORWARD_DECLARE(BigIntBitOr)FORWARD_DECLARE
(BigIntBitXor)FORWARD_DECLARE(BigIntLsh)FORWARD_DECLARE(BigIntRsh
)FORWARD_DECLARE(BigIntIncrement)FORWARD_DECLARE(BigIntDecrement
)FORWARD_DECLARE(BigIntNegate)FORWARD_DECLARE(BigIntBitNot)FORWARD_DECLARE
(Int32ToStringWithBase)FORWARD_DECLARE(NumberParseInt)FORWARD_DECLARE
(DoubleParseInt)FORWARD_DECLARE(Concat)FORWARD_DECLARE(LinearizeString
)FORWARD_DECLARE(LinearizeForCharAccess)FORWARD_DECLARE(LinearizeForCodePointAccess
)FORWARD_DECLARE(ToRelativeStringIndex)FORWARD_DECLARE(CharCodeAt
)FORWARD_DECLARE(CharCodeAtOrNegative)FORWARD_DECLARE(CodePointAt
)FORWARD_DECLARE(CodePointAtOrNegative)FORWARD_DECLARE(NegativeToNaN
)FORWARD_DECLARE(NegativeToUndefined)FORWARD_DECLARE(FromCharCode
)FORWARD_DECLARE(FromCharCodeEmptyIfNegative)FORWARD_DECLARE(
FromCharCodeUndefinedIfNegative)FORWARD_DECLARE(FromCodePoint
)FORWARD_DECLARE(StringIncludes)FORWARD_DECLARE(StringIndexOf
)FORWARD_DECLARE(StringLastIndexOf)FORWARD_DECLARE(StringStartsWith
)FORWARD_DECLARE(StringEndsWith)FORWARD_DECLARE(StringConvertCase
)FORWARD_DECLARE(CharCodeConvertCase)FORWARD_DECLARE(StringTrimStartIndex
)FORWARD_DECLARE(StringTrimEndIndex)FORWARD_DECLARE(StringSplit
)FORWARD_DECLARE(BoxNonStrictThis)FORWARD_DECLARE(ImplicitThis
)FORWARD_DECLARE(Phi)FORWARD_DECLARE(Beta)FORWARD_DECLARE(NaNToZero
)FORWARD_DECLARE(OsrValue)FORWARD_DECLARE(OsrEnvironmentChain
)FORWARD_DECLARE(OsrArgumentsObject)FORWARD_DECLARE(OsrReturnValue
)FORWARD_DECLARE(BinaryCache)FORWARD_DECLARE(UnaryCache)FORWARD_DECLARE
(CheckOverRecursed)FORWARD_DECLARE(InterruptCheck)FORWARD_DECLARE
(WasmInterruptCheck)FORWARD_DECLARE(WasmTrap)FORWARD_DECLARE(
WasmTrapIfNull)FORWARD_DECLARE(LexicalCheck)FORWARD_DECLARE(ThrowRuntimeLexicalError
)FORWARD_DECLARE(ThrowMsg)FORWARD_DECLARE(GlobalDeclInstantiation
)FORWARD_DECLARE(RegExp)FORWARD_DECLARE(RegExpMatcher)FORWARD_DECLARE
(RegExpSearcher)FORWARD_DECLARE(RegExpSearcherLastLimit)FORWARD_DECLARE
(RegExpExecMatch)FORWARD_DECLARE(RegExpExecTest)FORWARD_DECLARE
(RegExpHasCaptureGroups)FORWARD_DECLARE(RegExpPrototypeOptimizable
)FORWARD_DECLARE(RegExpInstanceOptimizable)FORWARD_DECLARE(GetFirstDollarIndex
)FORWARD_DECLARE(StringReplace)FORWARD_DECLARE(Substr)FORWARD_DECLARE
(ModuleMetadata)FORWARD_DECLARE(DynamicImport)FORWARD_DECLARE
(Lambda)FORWARD_DECLARE(FunctionWithProto)FORWARD_DECLARE(SetFunName
)FORWARD_DECLARE(Slots)FORWARD_DECLARE(Elements)FORWARD_DECLARE
(InitializedLength)FORWARD_DECLARE(SetInitializedLength)FORWARD_DECLARE
(ArrayLength)FORWARD_DECLARE(SetArrayLength)FORWARD_DECLARE(FunctionLength
)FORWARD_DECLARE(FunctionName)FORWARD_DECLARE(GetNextEntryForIterator
)FORWARD_DECLARE(ArrayBufferByteLength)FORWARD_DECLARE(ArrayBufferViewLength
)FORWARD_DECLARE(ArrayBufferViewByteOffset)FORWARD_DECLARE(ArrayBufferViewElements
)FORWARD_DECLARE(ResizableTypedArrayByteOffsetMaybeOutOfBounds
)FORWARD_DECLARE(ResizableTypedArrayLength)FORWARD_DECLARE(ResizableDataViewByteLength
)FORWARD_DECLARE(GrowableSharedArrayBufferByteLength)FORWARD_DECLARE
(TypedArrayElementSize)FORWARD_DECLARE(GuardHasAttachedArrayBuffer
)FORWARD_DECLARE(GuardResizableArrayBufferViewInBounds)FORWARD_DECLARE
(GuardResizableArrayBufferViewInBoundsOrDetached)FORWARD_DECLARE
(GuardNumberToIntPtrIndex)FORWARD_DECLARE(KeepAliveObject)FORWARD_DECLARE
(DebugEnterGCUnsafeRegion)FORWARD_DECLARE(DebugLeaveGCUnsafeRegion
)FORWARD_DECLARE(Not)FORWARD_DECLARE(BoundsCheck)FORWARD_DECLARE
(BoundsCheckLower)FORWARD_DECLARE(SpectreMaskIndex)FORWARD_DECLARE
(LoadElement)FORWARD_DECLARE(LoadElementAndUnbox)FORWARD_DECLARE
(LoadElementHole)FORWARD_DECLARE(StoreElement)FORWARD_DECLARE
(StoreHoleValueElement)FORWARD_DECLARE(StoreElementHole)FORWARD_DECLARE
(ArrayPopShift)FORWARD_DECLARE(ArrayPush)FORWARD_DECLARE(ArraySlice
)FORWARD_DECLARE(ArgumentsSlice)FORWARD_DECLARE(FrameArgumentsSlice
)FORWARD_DECLARE(InlineArgumentsSlice)FORWARD_DECLARE(NormalizeSliceTerm
)FORWARD_DECLARE(ArrayJoin)FORWARD_DECLARE(ObjectKeys)FORWARD_DECLARE
(ObjectKeysLength)FORWARD_DECLARE(LoadUnboxedScalar)FORWARD_DECLARE
(LoadDataViewElement)FORWARD_DECLARE(LoadTypedArrayElementHole
)FORWARD_DECLARE(StoreUnboxedScalar)FORWARD_DECLARE(StoreDataViewElement
)FORWARD_DECLARE(StoreTypedArrayElementHole)FORWARD_DECLARE(EffectiveAddress
)FORWARD_DECLARE(ClampToUint8)FORWARD_DECLARE(LoadFixedSlot)FORWARD_DECLARE
(LoadFixedSlotAndUnbox)FORWARD_DECLARE(LoadDynamicSlotAndUnbox
)FORWARD_DECLARE(StoreFixedSlot)FORWARD_DECLARE(GetPropertyCache
)FORWARD_DECLARE(HomeObjectSuperBase)FORWARD_DECLARE(GetPropSuperCache
)FORWARD_DECLARE(BindNameCache)FORWARD_DECLARE(CallBindVar)FORWARD_DECLARE
(GuardShape)FORWARD_DECLARE(GuardFuse)FORWARD_DECLARE(GuardMultipleShapes
)FORWARD_DECLARE(GuardProto)FORWARD_DECLARE(GuardNullProto)FORWARD_DECLARE
(GuardIsNativeObject)FORWARD_DECLARE(GuardGlobalGeneration)FORWARD_DECLARE
(GuardIsProxy)FORWARD_DECLARE(GuardIsNotDOMProxy)FORWARD_DECLARE
(GuardIsNotProxy)FORWARD_DECLARE(ProxyGet)FORWARD_DECLARE(ProxyGetByValue
)FORWARD_DECLARE(ProxyHasProp)FORWARD_DECLARE(ProxySet)FORWARD_DECLARE
(ProxySetByValue)FORWARD_DECLARE(CallSetArrayLength)FORWARD_DECLARE
(MegamorphicLoadSlot)FORWARD_DECLARE(MegamorphicLoadSlotByValue
)FORWARD_DECLARE(MegamorphicStoreSlot)FORWARD_DECLARE(MegamorphicHasProp
)FORWARD_DECLARE(SmallObjectVariableKeyHasProp)FORWARD_DECLARE
(GuardIsNotArrayBufferMaybeShared)FORWARD_DECLARE(GuardIsTypedArray
)FORWARD_DECLARE(GuardIsFixedLengthTypedArray)FORWARD_DECLARE
(GuardIsResizableTypedArray)FORWARD_DECLARE(GuardHasProxyHandler
)FORWARD_DECLARE(NurseryObject)FORWARD_DECLARE(GuardValue)FORWARD_DECLARE
(GuardNullOrUndefined)FORWARD_DECLARE(GuardIsNotObject)FORWARD_DECLARE
(GuardFunctionFlags)FORWARD_DECLARE(GuardFunctionIsNonBuiltinCtor
)FORWARD_DECLARE(GuardFunctionKind)FORWARD_DECLARE(GuardFunctionScript
)FORWARD_DECLARE(GuardObjectIdentity)FORWARD_DECLARE(GuardSpecificFunction
)FORWARD_DECLARE(GuardSpecificAtom)FORWARD_DECLARE(GuardSpecificSymbol
)FORWARD_DECLARE(GuardSpecificInt32)FORWARD_DECLARE(GuardStringToIndex
)FORWARD_DECLARE(GuardStringToInt32)FORWARD_DECLARE(GuardStringToDouble
)FORWARD_DECLARE(GuardNoDenseElements)FORWARD_DECLARE(GuardTagNotEqual
)FORWARD_DECLARE(LoadDynamicSlot)FORWARD_DECLARE(FunctionEnvironment
)FORWARD_DECLARE(NewLexicalEnvironmentObject)FORWARD_DECLARE(
NewClassBodyEnvironmentObject)FORWARD_DECLARE(NewVarEnvironmentObject
)FORWARD_DECLARE(HomeObject)FORWARD_DECLARE(AddAndStoreSlot)FORWARD_DECLARE
(AllocateAndStoreSlot)FORWARD_DECLARE(AddSlotAndCallAddPropHook
)FORWARD_DECLARE(StoreDynamicSlot)FORWARD_DECLARE(GetNameCache
)FORWARD_DECLARE(CallGetIntrinsicValue)FORWARD_DECLARE(DeleteProperty
)FORWARD_DECLARE(DeleteElement)FORWARD_DECLARE(SetPropertyCache
)FORWARD_DECLARE(MegamorphicSetElement)FORWARD_DECLARE(SetDOMProperty
)FORWARD_DECLARE(GetDOMProperty)FORWARD_DECLARE(GetDOMMember)
FORWARD_DECLARE(ObjectToIterator)FORWARD_DECLARE(ValueToIterator
)FORWARD_DECLARE(IteratorHasIndices)FORWARD_DECLARE(LoadSlotByIteratorIndex
)FORWARD_DECLARE(StoreSlotByIteratorIndex)FORWARD_DECLARE(LoadDOMExpandoValue
)FORWARD_DECLARE(LoadDOMExpandoValueGuardGeneration)FORWARD_DECLARE
(LoadDOMExpandoValueIgnoreGeneration)FORWARD_DECLARE(GuardDOMExpandoMissingOrGuardShape
)FORWARD_DECLARE(StringLength)FORWARD_DECLARE(Floor)FORWARD_DECLARE
(Ceil)FORWARD_DECLARE(Round)FORWARD_DECLARE(Trunc)FORWARD_DECLARE
(NearbyInt)FORWARD_DECLARE(GetIteratorCache)FORWARD_DECLARE(OptimizeSpreadCallCache
)FORWARD_DECLARE(IteratorMore)FORWARD_DECLARE(IsNoIter)FORWARD_DECLARE
(IteratorEnd)FORWARD_DECLARE(CloseIterCache)FORWARD_DECLARE(OptimizeGetIteratorCache
)FORWARD_DECLARE(InCache)FORWARD_DECLARE(InArray)FORWARD_DECLARE
(GuardElementNotHole)FORWARD_DECLARE(NewPrivateName)FORWARD_DECLARE
(CheckPrivateFieldCache)FORWARD_DECLARE(HasOwnCache)FORWARD_DECLARE
(InstanceOf)FORWARD_DECLARE(InstanceOfCache)FORWARD_DECLARE(ArgumentsLength
)FORWARD_DECLARE(GetFrameArgument)FORWARD_DECLARE(GetFrameArgumentHole
)FORWARD_DECLARE(NewTarget)FORWARD_DECLARE(Rest)FORWARD_DECLARE
(PostWriteBarrier)FORWARD_DECLARE(PostWriteElementBarrier)FORWARD_DECLARE
(AssertCanElidePostWriteBarrier)FORWARD_DECLARE(NewNamedLambdaObject
)FORWARD_DECLARE(NewCallObject)FORWARD_DECLARE(NewStringObject
)FORWARD_DECLARE(IsCallable)FORWARD_DECLARE(IsConstructor)FORWARD_DECLARE
(IsCrossRealmArrayConstructor)FORWARD_DECLARE(IsObject)FORWARD_DECLARE
(IsNullOrUndefined)FORWARD_DECLARE(HasClass)FORWARD_DECLARE(GuardToClass
)FORWARD_DECLARE(GuardToEitherClass)FORWARD_DECLARE(GuardToFunction
)FORWARD_DECLARE(IsArray)FORWARD_DECLARE(IsTypedArray)FORWARD_DECLARE
(ObjectClassToString)FORWARD_DECLARE(CheckReturn)FORWARD_DECLARE
(CheckThis)FORWARD_DECLARE(AsyncResolve)FORWARD_DECLARE(AsyncReject
)FORWARD_DECLARE(GeneratorReturn)FORWARD_DECLARE(AsyncAwait)FORWARD_DECLARE
(CheckThisReinit)FORWARD_DECLARE(Generator)FORWARD_DECLARE(CanSkipAwait
)FORWARD_DECLARE(MaybeExtractAwaitValue)FORWARD_DECLARE(IncrementWarmUpCounter
)FORWARD_DECLARE(AtomicIsLockFree)FORWARD_DECLARE(CompareExchangeTypedArrayElement
)FORWARD_DECLARE(AtomicExchangeTypedArrayElement)FORWARD_DECLARE
(AtomicTypedArrayElementBinop)FORWARD_DECLARE(Debugger)FORWARD_DECLARE
(CheckIsObj)FORWARD_DECLARE(CheckObjCoercible)FORWARD_DECLARE
(CheckClassHeritage)FORWARD_DECLARE(DebugCheckSelfHosted)FORWARD_DECLARE
(IsPackedArray)FORWARD_DECLARE(GuardArrayIsPacked)FORWARD_DECLARE
(GetPrototypeOf)FORWARD_DECLARE(ObjectWithProto)FORWARD_DECLARE
(ObjectStaticProto)FORWARD_DECLARE(ConstantProto)FORWARD_DECLARE
(BuiltinObject)FORWARD_DECLARE(SuperFunction)FORWARD_DECLARE(
InitHomeObject)FORWARD_DECLARE(IsTypedArrayConstructor)FORWARD_DECLARE
(LoadValueTag)FORWARD_DECLARE(LoadWrapperTarget)FORWARD_DECLARE
(GuardHasGetterSetter)FORWARD_DECLARE(GuardIsExtensible)FORWARD_DECLARE
(GuardInt32IsNonNegative)FORWARD_DECLARE(GuardInt32Range)FORWARD_DECLARE
(GuardIndexIsNotDenseElement)FORWARD_DECLARE(GuardIndexIsValidUpdateOrAdd
)FORWARD_DECLARE(CallAddOrUpdateSparseElement)FORWARD_DECLARE
(CallGetSparseElement)FORWARD_DECLARE(CallNativeGetElement)FORWARD_DECLARE
(CallNativeGetElementSuper)FORWARD_DECLARE(CallObjectHasSparseElement
)FORWARD_DECLARE(BigIntAsIntN)FORWARD_DECLARE(BigIntAsUintN)FORWARD_DECLARE
(GuardNonGCThing)FORWARD_DECLARE(ToHashableNonGCThing)FORWARD_DECLARE
(ToHashableString)FORWARD_DECLARE(ToHashableValue)FORWARD_DECLARE
(HashNonGCThing)FORWARD_DECLARE(HashString)FORWARD_DECLARE(HashSymbol
)FORWARD_DECLARE(HashBigInt)FORWARD_DECLARE(HashObject)FORWARD_DECLARE
(HashValue)FORWARD_DECLARE(SetObjectHasNonBigInt)FORWARD_DECLARE
(SetObjectHasBigInt)FORWARD_DECLARE(SetObjectHasValue)FORWARD_DECLARE
(SetObjectHasValueVMCall)FORWARD_DECLARE(SetObjectSize)FORWARD_DECLARE
(MapObjectHasNonBigInt)FORWARD_DECLARE(MapObjectHasBigInt)FORWARD_DECLARE
(MapObjectHasValue)FORWARD_DECLARE(MapObjectHasValueVMCall)FORWARD_DECLARE
(MapObjectGetNonBigInt)FORWARD_DECLARE(MapObjectGetBigInt)FORWARD_DECLARE
(MapObjectGetValue)FORWARD_DECLARE(MapObjectGetValueVMCall)FORWARD_DECLARE
(MapObjectSize)FORWARD_DECLARE(PostIntPtrConversion)FORWARD_DECLARE
(WasmNeg)FORWARD_DECLARE(WasmBinaryBitwise)FORWARD_DECLARE(WasmLoadInstance
)FORWARD_DECLARE(WasmStoreInstance)FORWARD_DECLARE(WasmHeapReg
)FORWARD_DECLARE(WasmBoundsCheck)FORWARD_DECLARE(WasmBoundsCheckRange32
)FORWARD_DECLARE(WasmExtendU32Index)FORWARD_DECLARE(WasmWrapU32Index
)FORWARD_DECLARE(WasmAddOffset)FORWARD_DECLARE(WasmAlignmentCheck
)FORWARD_DECLARE(WasmLoad)FORWARD_DECLARE(WasmStore)FORWARD_DECLARE
(AsmJSLoadHeap)FORWARD_DECLARE(AsmJSStoreHeap)FORWARD_DECLARE
(WasmFence)FORWARD_DECLARE(WasmCompareExchangeHeap)FORWARD_DECLARE
(WasmAtomicExchangeHeap)FORWARD_DECLARE(WasmAtomicBinopHeap)FORWARD_DECLARE
(WasmLoadInstanceDataField)FORWARD_DECLARE(WasmLoadGlobalCell
)FORWARD_DECLARE(WasmLoadTableElement)FORWARD_DECLARE(WasmStoreInstanceDataField
)FORWARD_DECLARE(WasmStoreGlobalCell)FORWARD_DECLARE(WasmStoreStackResult
)FORWARD_DECLARE(WasmDerivedPointer)FORWARD_DECLARE(WasmDerivedIndexPointer
)FORWARD_DECLARE(WasmStoreRef)FORWARD_DECLARE(WasmPostWriteBarrierImmediate
)FORWARD_DECLARE(WasmPostWriteBarrierIndex)FORWARD_DECLARE(WasmParameter
)FORWARD_DECLARE(WasmReturn)FORWARD_DECLARE(WasmReturnVoid)FORWARD_DECLARE
(WasmStackArg)FORWARD_DECLARE(WasmRegisterResult)FORWARD_DECLARE
(WasmFloatRegisterResult)FORWARD_DECLARE(WasmRegister64Result
)FORWARD_DECLARE(WasmStackResultArea)FORWARD_DECLARE(WasmStackResult
)FORWARD_DECLARE(WasmCallCatchable)FORWARD_DECLARE(WasmCallUncatchable
)FORWARD_DECLARE(WasmCallLandingPrePad)FORWARD_DECLARE(WasmReturnCall
)FORWARD_DECLARE(WasmSelect)FORWARD_DECLARE(WasmReinterpret)FORWARD_DECLARE
(Rotate)FORWARD_DECLARE(WasmStackSwitchToMain)FORWARD_DECLARE
(WasmStackSwitchToSuspendable)FORWARD_DECLARE(WasmStackContinueOnSuspendable
)FORWARD_DECLARE(WasmBinarySimd128)FORWARD_DECLARE(WasmBinarySimd128WithConstant
)FORWARD_DECLARE(WasmShiftSimd128)FORWARD_DECLARE(WasmShuffleSimd128
)FORWARD_DECLARE(WasmReplaceLaneSimd128)FORWARD_DECLARE(WasmUnarySimd128
)FORWARD_DECLARE(WasmTernarySimd128)FORWARD_DECLARE(WasmScalarToSimd128
)FORWARD_DECLARE(WasmReduceSimd128)FORWARD_DECLARE(WasmLoadLaneSimd128
)FORWARD_DECLARE(WasmStoreLaneSimd128)FORWARD_DECLARE(UnreachableResult
)FORWARD_DECLARE(IonToWasmCall)FORWARD_DECLARE(WasmLoadField)
FORWARD_DECLARE(WasmLoadFieldKA)FORWARD_DECLARE(WasmLoadElementKA
)FORWARD_DECLARE(WasmStoreFieldKA)FORWARD_DECLARE(WasmStoreFieldRefKA
)FORWARD_DECLARE(WasmStoreElementKA)FORWARD_DECLARE(WasmStoreElementRefKA
)FORWARD_DECLARE(WasmRefIsSubtypeOfConcrete)FORWARD_DECLARE(WasmRefIsSubtypeOfAbstract
)FORWARD_DECLARE(WasmNewStructObject)FORWARD_DECLARE(WasmNewArrayObject
)
108#undef FORWARD_DECLARE
109
110// MDefinition visitor which ignores non-overloaded visit functions.
111class MDefinitionVisitorDefaultNoop {
112 public:
113#define VISIT_INS(op) \
114 void visit##op(M##op*) {}
115 MIR_OPCODE_LIST(VISIT_INS)VISIT_INS(Start)VISIT_INS(OsrEntry)VISIT_INS(Nop)VISIT_INS(LimitedTruncate
)VISIT_INS(Constant)VISIT_INS(WasmNullConstant)VISIT_INS(WasmFloatConstant
)VISIT_INS(Parameter)VISIT_INS(Callee)VISIT_INS(IsConstructing
)VISIT_INS(TableSwitch)VISIT_INS(Goto)VISIT_INS(Test)VISIT_INS
(Return)VISIT_INS(Throw)VISIT_INS(ThrowWithStack)VISIT_INS(NewArray
)VISIT_INS(NewArrayDynamicLength)VISIT_INS(NewTypedArray)VISIT_INS
(NewTypedArrayDynamicLength)VISIT_INS(NewTypedArrayFromArray)
VISIT_INS(NewTypedArrayFromArrayBuffer)VISIT_INS(NewObject)VISIT_INS
(NewPlainObject)VISIT_INS(NewArrayObject)VISIT_INS(NewIterator
)VISIT_INS(ObjectState)VISIT_INS(ArrayState)VISIT_INS(BindFunction
)VISIT_INS(NewBoundFunction)VISIT_INS(BoundFunctionNumArgs)VISIT_INS
(GuardBoundFunctionIsConstructor)VISIT_INS(MutateProto)VISIT_INS
(InitPropGetterSetter)VISIT_INS(InitElemGetterSetter)VISIT_INS
(Call)VISIT_INS(CallClassHook)VISIT_INS(ApplyArgs)VISIT_INS(ApplyArgsObj
)VISIT_INS(ApplyArray)VISIT_INS(ConstructArgs)VISIT_INS(ConstructArray
)VISIT_INS(Bail)VISIT_INS(Unreachable)VISIT_INS(EncodeSnapshot
)VISIT_INS(AssertRecoveredOnBailout)VISIT_INS(AssertFloat32)VISIT_INS
(Compare)VISIT_INS(SameValueDouble)VISIT_INS(SameValue)VISIT_INS
(Box)VISIT_INS(Unbox)VISIT_INS(AssertRange)VISIT_INS(AssertClass
)VISIT_INS(AssertShape)VISIT_INS(CreateThis)VISIT_INS(CreateArgumentsObject
)VISIT_INS(CreateInlinedArgumentsObject)VISIT_INS(GetInlinedArgument
)VISIT_INS(GetInlinedArgumentHole)VISIT_INS(GetArgumentsObjectArg
)VISIT_INS(SetArgumentsObjectArg)VISIT_INS(LoadArgumentsObjectArg
)VISIT_INS(LoadArgumentsObjectArgHole)VISIT_INS(InArgumentsObjectArg
)VISIT_INS(ArgumentsObjectLength)VISIT_INS(ArrayFromArgumentsObject
)VISIT_INS(GuardArgumentsObjectFlags)VISIT_INS(LoadScriptedProxyHandler
)VISIT_INS(CheckScriptedProxyGetResult)VISIT_INS(IdToStringOrSymbol
)VISIT_INS(ReturnFromCtor)VISIT_INS(ToDouble)VISIT_INS(ToFloat32
)VISIT_INS(WasmUnsignedToDouble)VISIT_INS(WasmUnsignedToFloat32
)VISIT_INS(WrapInt64ToInt32)VISIT_INS(ExtendInt32ToInt64)VISIT_INS
(WasmBuiltinTruncateToInt64)VISIT_INS(WasmTruncateToInt64)VISIT_INS
(WasmTruncateToInt32)VISIT_INS(WasmAnyRefFromJSValue)VISIT_INS
(WasmAnyRefFromJSObject)VISIT_INS(WasmAnyRefFromJSString)VISIT_INS
(WasmNewI31Ref)VISIT_INS(WasmI31RefGet)VISIT_INS(Int32ToIntPtr
)VISIT_INS(NonNegativeIntPtrToInt32)VISIT_INS(IntPtrToDouble)
VISIT_INS(AdjustDataViewLength)VISIT_INS(Int64ToFloatingPoint
)VISIT_INS(BuiltinInt64ToFloatingPoint)VISIT_INS(ToNumberInt32
)VISIT_INS(BooleanToInt32)VISIT_INS(TruncateToInt32)VISIT_INS
(WasmBuiltinTruncateToInt32)VISIT_INS(ToBigInt)VISIT_INS(ToInt64
)VISIT_INS(TruncateBigIntToInt64)VISIT_INS(Int64ToBigInt)VISIT_INS
(ToString)VISIT_INS(BitNot)VISIT_INS(TypeOf)VISIT_INS(TypeOfName
)VISIT_INS(TypeOfIs)VISIT_INS(ToAsyncIter)VISIT_INS(ToPropertyKeyCache
)VISIT_INS(BitAnd)VISIT_INS(BitOr)VISIT_INS(BitXor)VISIT_INS(
Lsh)VISIT_INS(Rsh)VISIT_INS(Ursh)VISIT_INS(SignExtendInt32)VISIT_INS
(SignExtendInt64)VISIT_INS(MinMax)VISIT_INS(MinMaxArray)VISIT_INS
(Abs)VISIT_INS(Clz)VISIT_INS(Ctz)VISIT_INS(Popcnt)VISIT_INS(Sqrt
)VISIT_INS(CopySign)VISIT_INS(Atan2)VISIT_INS(Hypot)VISIT_INS
(Pow)VISIT_INS(PowHalf)VISIT_INS(Random)VISIT_INS(Sign)VISIT_INS
(MathFunction)VISIT_INS(Add)VISIT_INS(Sub)VISIT_INS(Mul)VISIT_INS
(Div)VISIT_INS(WasmBuiltinDivI64)VISIT_INS(Mod)VISIT_INS(WasmBuiltinModD
)VISIT_INS(WasmBuiltinModI64)VISIT_INS(BigIntAdd)VISIT_INS(BigIntSub
)VISIT_INS(BigIntMul)VISIT_INS(BigIntDiv)VISIT_INS(BigIntMod)
VISIT_INS(BigIntPow)VISIT_INS(BigIntBitAnd)VISIT_INS(BigIntBitOr
)VISIT_INS(BigIntBitXor)VISIT_INS(BigIntLsh)VISIT_INS(BigIntRsh
)VISIT_INS(BigIntIncrement)VISIT_INS(BigIntDecrement)VISIT_INS
(BigIntNegate)VISIT_INS(BigIntBitNot)VISIT_INS(Int32ToStringWithBase
)VISIT_INS(NumberParseInt)VISIT_INS(DoubleParseInt)VISIT_INS(
Concat)VISIT_INS(LinearizeString)VISIT_INS(LinearizeForCharAccess
)VISIT_INS(LinearizeForCodePointAccess)VISIT_INS(ToRelativeStringIndex
)VISIT_INS(CharCodeAt)VISIT_INS(CharCodeAtOrNegative)VISIT_INS
(CodePointAt)VISIT_INS(CodePointAtOrNegative)VISIT_INS(NegativeToNaN
)VISIT_INS(NegativeToUndefined)VISIT_INS(FromCharCode)VISIT_INS
(FromCharCodeEmptyIfNegative)VISIT_INS(FromCharCodeUndefinedIfNegative
)VISIT_INS(FromCodePoint)VISIT_INS(StringIncludes)VISIT_INS(StringIndexOf
)VISIT_INS(StringLastIndexOf)VISIT_INS(StringStartsWith)VISIT_INS
(StringEndsWith)VISIT_INS(StringConvertCase)VISIT_INS(CharCodeConvertCase
)VISIT_INS(StringTrimStartIndex)VISIT_INS(StringTrimEndIndex)
VISIT_INS(StringSplit)VISIT_INS(BoxNonStrictThis)VISIT_INS(ImplicitThis
)VISIT_INS(Phi)VISIT_INS(Beta)VISIT_INS(NaNToZero)VISIT_INS(OsrValue
)VISIT_INS(OsrEnvironmentChain)VISIT_INS(OsrArgumentsObject)VISIT_INS
(OsrReturnValue)VISIT_INS(BinaryCache)VISIT_INS(UnaryCache)VISIT_INS
(CheckOverRecursed)VISIT_INS(InterruptCheck)VISIT_INS(WasmInterruptCheck
)VISIT_INS(WasmTrap)VISIT_INS(WasmTrapIfNull)VISIT_INS(LexicalCheck
)VISIT_INS(ThrowRuntimeLexicalError)VISIT_INS(ThrowMsg)VISIT_INS
(GlobalDeclInstantiation)VISIT_INS(RegExp)VISIT_INS(RegExpMatcher
)VISIT_INS(RegExpSearcher)VISIT_INS(RegExpSearcherLastLimit)VISIT_INS
(RegExpExecMatch)VISIT_INS(RegExpExecTest)VISIT_INS(RegExpHasCaptureGroups
)VISIT_INS(RegExpPrototypeOptimizable)VISIT_INS(RegExpInstanceOptimizable
)VISIT_INS(GetFirstDollarIndex)VISIT_INS(StringReplace)VISIT_INS
(Substr)VISIT_INS(ModuleMetadata)VISIT_INS(DynamicImport)VISIT_INS
(Lambda)VISIT_INS(FunctionWithProto)VISIT_INS(SetFunName)VISIT_INS
(Slots)VISIT_INS(Elements)VISIT_INS(InitializedLength)VISIT_INS
(SetInitializedLength)VISIT_INS(ArrayLength)VISIT_INS(SetArrayLength
)VISIT_INS(FunctionLength)VISIT_INS(FunctionName)VISIT_INS(GetNextEntryForIterator
)VISIT_INS(ArrayBufferByteLength)VISIT_INS(ArrayBufferViewLength
)VISIT_INS(ArrayBufferViewByteOffset)VISIT_INS(ArrayBufferViewElements
)VISIT_INS(ResizableTypedArrayByteOffsetMaybeOutOfBounds)VISIT_INS
(ResizableTypedArrayLength)VISIT_INS(ResizableDataViewByteLength
)VISIT_INS(GrowableSharedArrayBufferByteLength)VISIT_INS(TypedArrayElementSize
)VISIT_INS(GuardHasAttachedArrayBuffer)VISIT_INS(GuardResizableArrayBufferViewInBounds
)VISIT_INS(GuardResizableArrayBufferViewInBoundsOrDetached)VISIT_INS
(GuardNumberToIntPtrIndex)VISIT_INS(KeepAliveObject)VISIT_INS
(DebugEnterGCUnsafeRegion)VISIT_INS(DebugLeaveGCUnsafeRegion)
VISIT_INS(Not)VISIT_INS(BoundsCheck)VISIT_INS(BoundsCheckLower
)VISIT_INS(SpectreMaskIndex)VISIT_INS(LoadElement)VISIT_INS(LoadElementAndUnbox
)VISIT_INS(LoadElementHole)VISIT_INS(StoreElement)VISIT_INS(StoreHoleValueElement
)VISIT_INS(StoreElementHole)VISIT_INS(ArrayPopShift)VISIT_INS
(ArrayPush)VISIT_INS(ArraySlice)VISIT_INS(ArgumentsSlice)VISIT_INS
(FrameArgumentsSlice)VISIT_INS(InlineArgumentsSlice)VISIT_INS
(NormalizeSliceTerm)VISIT_INS(ArrayJoin)VISIT_INS(ObjectKeys)
VISIT_INS(ObjectKeysLength)VISIT_INS(LoadUnboxedScalar)VISIT_INS
(LoadDataViewElement)VISIT_INS(LoadTypedArrayElementHole)VISIT_INS
(StoreUnboxedScalar)VISIT_INS(StoreDataViewElement)VISIT_INS(
StoreTypedArrayElementHole)VISIT_INS(EffectiveAddress)VISIT_INS
(ClampToUint8)VISIT_INS(LoadFixedSlot)VISIT_INS(LoadFixedSlotAndUnbox
)VISIT_INS(LoadDynamicSlotAndUnbox)VISIT_INS(StoreFixedSlot)VISIT_INS
(GetPropertyCache)VISIT_INS(HomeObjectSuperBase)VISIT_INS(GetPropSuperCache
)VISIT_INS(BindNameCache)VISIT_INS(CallBindVar)VISIT_INS(GuardShape
)VISIT_INS(GuardFuse)VISIT_INS(GuardMultipleShapes)VISIT_INS(
GuardProto)VISIT_INS(GuardNullProto)VISIT_INS(GuardIsNativeObject
)VISIT_INS(GuardGlobalGeneration)VISIT_INS(GuardIsProxy)VISIT_INS
(GuardIsNotDOMProxy)VISIT_INS(GuardIsNotProxy)VISIT_INS(ProxyGet
)VISIT_INS(ProxyGetByValue)VISIT_INS(ProxyHasProp)VISIT_INS(ProxySet
)VISIT_INS(ProxySetByValue)VISIT_INS(CallSetArrayLength)VISIT_INS
(MegamorphicLoadSlot)VISIT_INS(MegamorphicLoadSlotByValue)VISIT_INS
(MegamorphicStoreSlot)VISIT_INS(MegamorphicHasProp)VISIT_INS(
SmallObjectVariableKeyHasProp)VISIT_INS(GuardIsNotArrayBufferMaybeShared
)VISIT_INS(GuardIsTypedArray)VISIT_INS(GuardIsFixedLengthTypedArray
)VISIT_INS(GuardIsResizableTypedArray)VISIT_INS(GuardHasProxyHandler
)VISIT_INS(NurseryObject)VISIT_INS(GuardValue)VISIT_INS(GuardNullOrUndefined
)VISIT_INS(GuardIsNotObject)VISIT_INS(GuardFunctionFlags)VISIT_INS
(GuardFunctionIsNonBuiltinCtor)VISIT_INS(GuardFunctionKind)VISIT_INS
(GuardFunctionScript)VISIT_INS(GuardObjectIdentity)VISIT_INS(
GuardSpecificFunction)VISIT_INS(GuardSpecificAtom)VISIT_INS(GuardSpecificSymbol
)VISIT_INS(GuardSpecificInt32)VISIT_INS(GuardStringToIndex)VISIT_INS
(GuardStringToInt32)VISIT_INS(GuardStringToDouble)VISIT_INS(GuardNoDenseElements
)VISIT_INS(GuardTagNotEqual)VISIT_INS(LoadDynamicSlot)VISIT_INS
(FunctionEnvironment)VISIT_INS(NewLexicalEnvironmentObject)VISIT_INS
(NewClassBodyEnvironmentObject)VISIT_INS(NewVarEnvironmentObject
)VISIT_INS(HomeObject)VISIT_INS(AddAndStoreSlot)VISIT_INS(AllocateAndStoreSlot
)VISIT_INS(AddSlotAndCallAddPropHook)VISIT_INS(StoreDynamicSlot
)VISIT_INS(GetNameCache)VISIT_INS(CallGetIntrinsicValue)VISIT_INS
(DeleteProperty)VISIT_INS(DeleteElement)VISIT_INS(SetPropertyCache
)VISIT_INS(MegamorphicSetElement)VISIT_INS(SetDOMProperty)VISIT_INS
(GetDOMProperty)VISIT_INS(GetDOMMember)VISIT_INS(ObjectToIterator
)VISIT_INS(ValueToIterator)VISIT_INS(IteratorHasIndices)VISIT_INS
(LoadSlotByIteratorIndex)VISIT_INS(StoreSlotByIteratorIndex)VISIT_INS
(LoadDOMExpandoValue)VISIT_INS(LoadDOMExpandoValueGuardGeneration
)VISIT_INS(LoadDOMExpandoValueIgnoreGeneration)VISIT_INS(GuardDOMExpandoMissingOrGuardShape
)VISIT_INS(StringLength)VISIT_INS(Floor)VISIT_INS(Ceil)VISIT_INS
(Round)VISIT_INS(Trunc)VISIT_INS(NearbyInt)VISIT_INS(GetIteratorCache
)VISIT_INS(OptimizeSpreadCallCache)VISIT_INS(IteratorMore)VISIT_INS
(IsNoIter)VISIT_INS(IteratorEnd)VISIT_INS(CloseIterCache)VISIT_INS
(OptimizeGetIteratorCache)VISIT_INS(InCache)VISIT_INS(InArray
)VISIT_INS(GuardElementNotHole)VISIT_INS(NewPrivateName)VISIT_INS
(CheckPrivateFieldCache)VISIT_INS(HasOwnCache)VISIT_INS(InstanceOf
)VISIT_INS(InstanceOfCache)VISIT_INS(ArgumentsLength)VISIT_INS
(GetFrameArgument)VISIT_INS(GetFrameArgumentHole)VISIT_INS(NewTarget
)VISIT_INS(Rest)VISIT_INS(PostWriteBarrier)VISIT_INS(PostWriteElementBarrier
)VISIT_INS(AssertCanElidePostWriteBarrier)VISIT_INS(NewNamedLambdaObject
)VISIT_INS(NewCallObject)VISIT_INS(NewStringObject)VISIT_INS(
IsCallable)VISIT_INS(IsConstructor)VISIT_INS(IsCrossRealmArrayConstructor
)VISIT_INS(IsObject)VISIT_INS(IsNullOrUndefined)VISIT_INS(HasClass
)VISIT_INS(GuardToClass)VISIT_INS(GuardToEitherClass)VISIT_INS
(GuardToFunction)VISIT_INS(IsArray)VISIT_INS(IsTypedArray)VISIT_INS
(ObjectClassToString)VISIT_INS(CheckReturn)VISIT_INS(CheckThis
)VISIT_INS(AsyncResolve)VISIT_INS(AsyncReject)VISIT_INS(GeneratorReturn
)VISIT_INS(AsyncAwait)VISIT_INS(CheckThisReinit)VISIT_INS(Generator
)VISIT_INS(CanSkipAwait)VISIT_INS(MaybeExtractAwaitValue)VISIT_INS
(IncrementWarmUpCounter)VISIT_INS(AtomicIsLockFree)VISIT_INS(
CompareExchangeTypedArrayElement)VISIT_INS(AtomicExchangeTypedArrayElement
)VISIT_INS(AtomicTypedArrayElementBinop)VISIT_INS(Debugger)VISIT_INS
(CheckIsObj)VISIT_INS(CheckObjCoercible)VISIT_INS(CheckClassHeritage
)VISIT_INS(DebugCheckSelfHosted)VISIT_INS(IsPackedArray)VISIT_INS
(GuardArrayIsPacked)VISIT_INS(GetPrototypeOf)VISIT_INS(ObjectWithProto
)VISIT_INS(ObjectStaticProto)VISIT_INS(ConstantProto)VISIT_INS
(BuiltinObject)VISIT_INS(SuperFunction)VISIT_INS(InitHomeObject
)VISIT_INS(IsTypedArrayConstructor)VISIT_INS(LoadValueTag)VISIT_INS
(LoadWrapperTarget)VISIT_INS(GuardHasGetterSetter)VISIT_INS(GuardIsExtensible
)VISIT_INS(GuardInt32IsNonNegative)VISIT_INS(GuardInt32Range)
VISIT_INS(GuardIndexIsNotDenseElement)VISIT_INS(GuardIndexIsValidUpdateOrAdd
)VISIT_INS(CallAddOrUpdateSparseElement)VISIT_INS(CallGetSparseElement
)VISIT_INS(CallNativeGetElement)VISIT_INS(CallNativeGetElementSuper
)VISIT_INS(CallObjectHasSparseElement)VISIT_INS(BigIntAsIntN)
VISIT_INS(BigIntAsUintN)VISIT_INS(GuardNonGCThing)VISIT_INS(ToHashableNonGCThing
)VISIT_INS(ToHashableString)VISIT_INS(ToHashableValue)VISIT_INS
(HashNonGCThing)VISIT_INS(HashString)VISIT_INS(HashSymbol)VISIT_INS
(HashBigInt)VISIT_INS(HashObject)VISIT_INS(HashValue)VISIT_INS
(SetObjectHasNonBigInt)VISIT_INS(SetObjectHasBigInt)VISIT_INS
(SetObjectHasValue)VISIT_INS(SetObjectHasValueVMCall)VISIT_INS
(SetObjectSize)VISIT_INS(MapObjectHasNonBigInt)VISIT_INS(MapObjectHasBigInt
)VISIT_INS(MapObjectHasValue)VISIT_INS(MapObjectHasValueVMCall
)VISIT_INS(MapObjectGetNonBigInt)VISIT_INS(MapObjectGetBigInt
)VISIT_INS(MapObjectGetValue)VISIT_INS(MapObjectGetValueVMCall
)VISIT_INS(MapObjectSize)VISIT_INS(PostIntPtrConversion)VISIT_INS
(WasmNeg)VISIT_INS(WasmBinaryBitwise)VISIT_INS(WasmLoadInstance
)VISIT_INS(WasmStoreInstance)VISIT_INS(WasmHeapReg)VISIT_INS(
WasmBoundsCheck)VISIT_INS(WasmBoundsCheckRange32)VISIT_INS(WasmExtendU32Index
)VISIT_INS(WasmWrapU32Index)VISIT_INS(WasmAddOffset)VISIT_INS
(WasmAlignmentCheck)VISIT_INS(WasmLoad)VISIT_INS(WasmStore)VISIT_INS
(AsmJSLoadHeap)VISIT_INS(AsmJSStoreHeap)VISIT_INS(WasmFence)VISIT_INS
(WasmCompareExchangeHeap)VISIT_INS(WasmAtomicExchangeHeap)VISIT_INS
(WasmAtomicBinopHeap)VISIT_INS(WasmLoadInstanceDataField)VISIT_INS
(WasmLoadGlobalCell)VISIT_INS(WasmLoadTableElement)VISIT_INS(
WasmStoreInstanceDataField)VISIT_INS(WasmStoreGlobalCell)VISIT_INS
(WasmStoreStackResult)VISIT_INS(WasmDerivedPointer)VISIT_INS(
WasmDerivedIndexPointer)VISIT_INS(WasmStoreRef)VISIT_INS(WasmPostWriteBarrierImmediate
)VISIT_INS(WasmPostWriteBarrierIndex)VISIT_INS(WasmParameter)
VISIT_INS(WasmReturn)VISIT_INS(WasmReturnVoid)VISIT_INS(WasmStackArg
)VISIT_INS(WasmRegisterResult)VISIT_INS(WasmFloatRegisterResult
)VISIT_INS(WasmRegister64Result)VISIT_INS(WasmStackResultArea
)VISIT_INS(WasmStackResult)VISIT_INS(WasmCallCatchable)VISIT_INS
(WasmCallUncatchable)VISIT_INS(WasmCallLandingPrePad)VISIT_INS
(WasmReturnCall)VISIT_INS(WasmSelect)VISIT_INS(WasmReinterpret
)VISIT_INS(Rotate)VISIT_INS(WasmStackSwitchToMain)VISIT_INS(WasmStackSwitchToSuspendable
)VISIT_INS(WasmStackContinueOnSuspendable)VISIT_INS(WasmBinarySimd128
)VISIT_INS(WasmBinarySimd128WithConstant)VISIT_INS(WasmShiftSimd128
)VISIT_INS(WasmShuffleSimd128)VISIT_INS(WasmReplaceLaneSimd128
)VISIT_INS(WasmUnarySimd128)VISIT_INS(WasmTernarySimd128)VISIT_INS
(WasmScalarToSimd128)VISIT_INS(WasmReduceSimd128)VISIT_INS(WasmLoadLaneSimd128
)VISIT_INS(WasmStoreLaneSimd128)VISIT_INS(UnreachableResult)VISIT_INS
(IonToWasmCall)VISIT_INS(WasmLoadField)VISIT_INS(WasmLoadFieldKA
)VISIT_INS(WasmLoadElementKA)VISIT_INS(WasmStoreFieldKA)VISIT_INS
(WasmStoreFieldRefKA)VISIT_INS(WasmStoreElementKA)VISIT_INS(WasmStoreElementRefKA
)VISIT_INS(WasmRefIsSubtypeOfConcrete)VISIT_INS(WasmRefIsSubtypeOfAbstract
)VISIT_INS(WasmNewStructObject)VISIT_INS(WasmNewArrayObject)
116#undef VISIT_INS
117};
118
119class BytecodeSite;
120class CompactBufferWriter;
121class Range;
122
123#define MIR_FLAG_LIST(_)_(InWorklist) _(EmittedAtUses) _(Commutative) _(Movable) _(Lowered
) _(Guard) _(GuardRangeBailouts) _(ImplicitlyUsed) _(Unused) _
(RecoveredOnBailout) _(IncompleteObject) _(CallResultCapture)
_(Discarded)
\
124 _(InWorklist) \
125 _(EmittedAtUses) \
126 _(Commutative) \
127 _(Movable) /* Allow passes like LICM to move this instruction */ \
128 _(Lowered) /* (Debug only) has a virtual register */ \
129 _(Guard) /* Not removable if uses == 0 */ \
130 \
131 /* Flag an instruction to be considered as a Guard if the instructions \
132 * bails out on some inputs. \
133 * \
134 * Some optimizations can replace an instruction, and leave its operands \
135 * unused. When the type information of the operand got used as a \
136 * predicate of the transformation, then we have to flag the operands as \
137 * GuardRangeBailouts. \
138 * \
139 * This flag prevents further optimization of instructions, which \
140 * might remove the run-time checks (bailout conditions) used as a \
141 * predicate of the previous transformation. \
142 */ \
143 _(GuardRangeBailouts) \
144 \
145 /* Some instructions have uses that aren't directly represented in the \
146 * graph, and need to be handled specially. As an example, this is used to \
147 * keep the flagged instruction in resume points, not substituting with an \
148 * UndefinedValue. This can be used by call inlining when a function \
149 * argument is not used by the inlined instructions. It is also used \
150 * to annotate instructions which were used in removed branches. \
151 */ \
152 _(ImplicitlyUsed) \
153 \
154 /* The instruction has been marked dead for lazy removal from resume \
155 * points. \
156 */ \
157 _(Unused) \
158 \
159 /* Marks if the current instruction should go to the bailout paths instead \
160 * of producing code as part of the control flow. This flag can only be set \
161 * on instructions which are only used by ResumePoint or by other flagged \
162 * instructions. \
163 */ \
164 _(RecoveredOnBailout) \
165 \
166 /* Some instructions might represent an object, but the memory of these \
167 * objects might be incomplete if we have not recovered all the stores which \
168 * were supposed to happen before. This flag is used to annotate \
169 * instructions which might return a pointer to a memory area which is not \
170 * yet fully initialized. This flag is used to ensure that stores are \
171 * executed before returning the value. \
172 */ \
173 _(IncompleteObject) \
174 \
175 /* For WebAssembly, there are functions with multiple results. Instead of \
176 * having the results defined by one call instruction, they are instead \
177 * captured in subsequent result capture instructions, because modelling \
178 * multi-value results in Ion is too complicated. However since they \
179 * capture ambient live registers, it would be an error to move an unrelated \
180 * instruction between the call and the result capture. This flag is used \
181 * to prevent code motion from moving instructions in invalid ways. \
182 */ \
183 _(CallResultCapture) \
184 \
185 /* The current instruction got discarded from the MIR Graph. This is useful \
186 * when we want to iterate over resume points and instructions, while \
187 * handling instructions which are discarded without reporting to the \
188 * iterator. \
189 */ \
190 _(Discarded)
191
192class MDefinition;
193class MInstruction;
194class MBasicBlock;
195class MNode;
196class MUse;
197class MPhi;
198class MIRGraph;
199class MResumePoint;
200class MControlInstruction;
201
202// Represents a use of a node.
203class MUse : public TempObject, public InlineListNode<MUse> {
204 // Grant access to setProducerUnchecked.
205 friend class MDefinition;
206 friend class MPhi;
207
208 MDefinition* producer_; // MDefinition that is being used.
209 MNode* consumer_; // The node that is using this operand.
210
211 // Low-level unchecked edit method for replaceAllUsesWith and
212 // MPhi::removeOperand. This doesn't update use lists!
213 // replaceAllUsesWith and MPhi::removeOperand do that manually.
214 void setProducerUnchecked(MDefinition* producer) {
215 MOZ_ASSERT(consumer_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("consumer_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 215); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer_" ")"
); do { *((volatile int*)__null) = 215; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
216 MOZ_ASSERT(producer_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(producer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(producer_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("producer_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 216); AnnotateMozCrashReason("MOZ_ASSERT" "(" "producer_" ")"
); do { *((volatile int*)__null) = 216; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
217 MOZ_ASSERT(producer)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(producer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(producer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("producer", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 217); AnnotateMozCrashReason("MOZ_ASSERT" "(" "producer" ")"
); do { *((volatile int*)__null) = 217; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
218 producer_ = producer;
219 }
220
221 public:
222 // Default constructor for use in vectors.
223 MUse() : producer_(nullptr), consumer_(nullptr) {}
224
225 // Move constructor for use in vectors. When an MUse is moved, it stays
226 // in its containing use list.
227 MUse(MUse&& other)
228 : InlineListNode<MUse>(std::move(other)),
229 producer_(other.producer_),
230 consumer_(other.consumer_) {}
231
232 // Construct an MUse initialized with |producer| and |consumer|.
233 MUse(MDefinition* producer, MNode* consumer) {
234 initUnchecked(producer, consumer);
235 }
236
237 // Set this use, which was previously clear.
238 inline void init(MDefinition* producer, MNode* consumer);
239 // Like init, but works even when the use contains uninitialized data.
240 inline void initUnchecked(MDefinition* producer, MNode* consumer);
241 // Like initUnchecked, but set the producer to nullptr.
242 inline void initUncheckedWithoutProducer(MNode* consumer);
243 // Set this use, which was not previously clear.
244 inline void replaceProducer(MDefinition* producer);
245 // Clear this use.
246 inline void releaseProducer();
247
248 MDefinition* producer() const {
249 MOZ_ASSERT(producer_ != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(producer_ != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(producer_ != nullptr))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("producer_ != nullptr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 249); AnnotateMozCrashReason("MOZ_ASSERT" "(" "producer_ != nullptr"
")"); do { *((volatile int*)__null) = 249; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
250 return producer_;
251 }
252 bool hasProducer() const { return producer_ != nullptr; }
253 MNode* consumer() const {
254 MOZ_ASSERT(consumer_ != nullptr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer_ != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer_ != nullptr))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("consumer_ != nullptr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 254); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer_ != nullptr"
")"); do { *((volatile int*)__null) = 254; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
255 return consumer_;
256 }
257
258#ifdef DEBUG1
259 // Return the operand index of this MUse in its consumer. This is DEBUG-only
260 // as normal code should instead call indexOf on the cast consumer directly,
261 // to allow it to be devirtualized and inlined.
262 size_t index() const;
263#endif
264};
265
266using MUseIterator = InlineList<MUse>::iterator;
267
268// A node is an entry in the MIR graph. It has two kinds:
269// MInstruction: an instruction which appears in the IR stream.
270// MResumePoint: a list of instructions that correspond to the state of the
271// interpreter/Baseline stack.
272//
273// Nodes can hold references to MDefinitions. Each MDefinition has a list of
274// nodes holding such a reference (its use chain).
275class MNode : public TempObject {
276 protected:
277 enum class Kind { Definition = 0, ResumePoint };
278
279 private:
280 static const uintptr_t KindMask = 0x1;
281 uintptr_t blockAndKind_;
282
283 Kind kind() const { return Kind(blockAndKind_ & KindMask); }
284
285 protected:
286 explicit MNode(const MNode& other) : blockAndKind_(other.blockAndKind_) {}
287
288 MNode(MBasicBlock* block, Kind kind) { setBlockAndKind(block, kind); }
289
290 void setBlockAndKind(MBasicBlock* block, Kind kind) {
291 blockAndKind_ = uintptr_t(block) | uintptr_t(kind);
292 MOZ_ASSERT(this->block() == block)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this->block() == block)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this->block() == block)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("this->block() == block"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this->block() == block"
")"); do { *((volatile int*)__null) = 292; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
293 }
294
295 MBasicBlock* definitionBlock() const {
296 MOZ_ASSERT(isDefinition())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isDefinition())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isDefinition()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isDefinition()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 296); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isDefinition()"
")"); do { *((volatile int*)__null) = 296; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
297 static_assert(unsigned(Kind::Definition) == 0,
298 "Code below relies on low bit being 0");
299 return reinterpret_cast<MBasicBlock*>(blockAndKind_);
300 }
301 MBasicBlock* resumePointBlock() const {
302 MOZ_ASSERT(isResumePoint())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isResumePoint())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isResumePoint()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isResumePoint()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 302); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isResumePoint()"
")"); do { *((volatile int*)__null) = 302; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
303 static_assert(unsigned(Kind::ResumePoint) == 1,
304 "Code below relies on low bit being 1");
305 // Use a subtraction: if the caller does block()->foo, the compiler
306 // will be able to fold it with the load.
307 return reinterpret_cast<MBasicBlock*>(blockAndKind_ - 1);
308 }
309
310 public:
311 // Returns the definition at a given operand.
312 virtual MDefinition* getOperand(size_t index) const = 0;
313 virtual size_t numOperands() const = 0;
314 virtual size_t indexOf(const MUse* u) const = 0;
315
316 bool isDefinition() const { return kind() == Kind::Definition; }
317 bool isResumePoint() const { return kind() == Kind::ResumePoint; }
318 MBasicBlock* block() const {
319 return reinterpret_cast<MBasicBlock*>(blockAndKind_ & ~KindMask);
320 }
321 MBasicBlock* caller() const;
322
323 // Sets an already set operand, updating use information. If you're looking
324 // for setOperand, this is probably what you want.
325 virtual void replaceOperand(size_t index, MDefinition* operand) = 0;
326
327 // Resets the operand to an uninitialized state, breaking the link
328 // with the previous operand's producer.
329 void releaseOperand(size_t index) { getUseFor(index)->releaseProducer(); }
330 bool hasOperand(size_t index) const {
331 return getUseFor(index)->hasProducer();
332 }
333
334 inline MDefinition* toDefinition();
335 inline MResumePoint* toResumePoint();
336
337 [[nodiscard]] virtual bool writeRecoverData(
338 CompactBufferWriter& writer) const;
339
340#ifdef JS_JITSPEW1
341 virtual void dump(GenericPrinter& out) const = 0;
342 virtual void dump() const = 0;
343#endif
344
345 protected:
346 // Need visibility on getUseFor to avoid O(n^2) complexity.
347 friend void AssertBasicGraphCoherency(MIRGraph& graph, bool force);
348
349 // Gets the MUse corresponding to given operand.
350 virtual MUse* getUseFor(size_t index) = 0;
351 virtual const MUse* getUseFor(size_t index) const = 0;
352};
353
354class AliasSet {
355 private:
356 uint32_t flags_;
357
358 public:
359 enum Flag {
360 None_ = 0,
361 ObjectFields = 1 << 0, // shape, class, slots, length etc.
362 Element = 1 << 1, // A Value member of obj->elements or
363 // a typed object.
364 UnboxedElement = 1 << 2, // An unboxed scalar or reference member of
365 // typed object.
366 DynamicSlot = 1 << 3, // A Value member of obj->slots.
367 FixedSlot = 1 << 4, // A Value member of obj->fixedSlots().
368 DOMProperty = 1 << 5, // A DOM property
369 WasmInstanceData = 1 << 6, // An asm.js/wasm private global var
370 WasmHeap = 1 << 7, // An asm.js/wasm heap load
371 WasmHeapMeta = 1 << 8, // The asm.js/wasm heap base pointer and
372 // bounds check limit, in Instance.
373 ArrayBufferViewLengthOrOffset =
374 1 << 9, // An array buffer view's length or byteOffset
375 WasmGlobalCell = 1 << 10, // A wasm global cell
376 WasmTableElement = 1 << 11, // An element of a wasm table
377 WasmTableMeta = 1 << 12, // A wasm table elements pointer and
378 // length field, in instance data.
379 WasmStackResult = 1 << 13, // A stack result from the current function
380
381 // JSContext's exception state. This is used on instructions like MThrow
382 // or MNewArrayDynamicLength that throw exceptions (other than OOM) but have
383 // no other side effect, to ensure that they get their own up-to-date resume
384 // point. (This resume point will be used when constructing the Baseline
385 // frame during exception bailouts.)
386 ExceptionState = 1 << 14,
387
388 // Used for instructions that load the privateSlot of DOM proxies and
389 // the ExpandoAndGeneration.
390 DOMProxyExpando = 1 << 15,
391
392 // Hash table of a Map or Set object.
393 MapOrSetHashTable = 1 << 16,
394
395 // Internal state of the random number generator
396 RNG = 1 << 17,
397
398 // The pendingException slot on the wasm instance object.
399 WasmPendingException = 1 << 18,
400
401 // The fuzzilliHash slot
402 FuzzilliHash = 1 << 19,
403
404 // The WasmStructObject::inlineData_[..] storage area
405 WasmStructInlineDataArea = 1 << 20,
406
407 // The WasmStructObject::outlineData_ pointer only
408 WasmStructOutlineDataPointer = 1 << 21,
409
410 // The malloc'd block that WasmStructObject::outlineData_ points at
411 WasmStructOutlineDataArea = 1 << 22,
412
413 // The WasmArrayObject::numElements_ field
414 WasmArrayNumElements = 1 << 23,
415
416 // The WasmArrayObject::data_ pointer only
417 WasmArrayDataPointer = 1 << 24,
418
419 // The malloc'd block that WasmArrayObject::data_ points at
420 WasmArrayDataArea = 1 << 25,
421
422 // The generation counter associated with the global object
423 GlobalGenerationCounter = 1 << 26,
424
425 // The SharedArrayRawBuffer::length field.
426 SharedArrayRawBufferLength = 1 << 27,
427
428 Last = SharedArrayRawBufferLength,
429
430 Any = Last | (Last - 1),
431 NumCategories = 28,
432
433 // Indicates load or store.
434 Store_ = 1 << 31
435 };
436
437 static_assert((1 << NumCategories) - 1 == Any,
438 "NumCategories must include all flags present in Any");
439
440 explicit AliasSet(uint32_t flags) : flags_(flags) {}
441
442 public:
443 inline bool isNone() const { return flags_ == None_; }
444 uint32_t flags() const { return flags_ & Any; }
445 inline bool isStore() const { return !!(flags_ & Store_); }
446 inline bool isLoad() const { return !isStore() && !isNone(); }
447 inline AliasSet operator|(const AliasSet& other) const {
448 return AliasSet(flags_ | other.flags_);
449 }
450 inline AliasSet operator&(const AliasSet& other) const {
451 return AliasSet(flags_ & other.flags_);
452 }
453 inline AliasSet operator~() const { return AliasSet(~flags_); }
454 static AliasSet None() { return AliasSet(None_); }
455 static AliasSet Load(uint32_t flags) {
456 MOZ_ASSERT(flags && !(flags & Store_))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(flags && !(flags & Store_))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(flags && !(flags & Store_)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("flags && !(flags & Store_)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 456); AnnotateMozCrashReason("MOZ_ASSERT" "(" "flags && !(flags & Store_)"
")"); do { *((volatile int*)__null) = 456; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
457 return AliasSet(flags);
458 }
459 static AliasSet Store(uint32_t flags) {
460 MOZ_ASSERT(flags && !(flags & Store_))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(flags && !(flags & Store_))>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(flags && !(flags & Store_)))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("flags && !(flags & Store_)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 460); AnnotateMozCrashReason("MOZ_ASSERT" "(" "flags && !(flags & Store_)"
")"); do { *((volatile int*)__null) = 460; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
461 return AliasSet(flags | Store_);
462 }
463};
464
465typedef Vector<MDefinition*, 6, JitAllocPolicy> MDefinitionVector;
466typedef Vector<MInstruction*, 6, JitAllocPolicy> MInstructionVector;
467
468// When a floating-point value is used by nodes which would prefer to
469// receive integer inputs, we may be able to help by computing our result
470// into an integer directly.
471//
472// A value can be truncated in 4 differents ways:
473// 1. Ignore Infinities (x / 0 --> 0).
474// 2. Ignore overflow (INT_MIN / -1 == (INT_MAX + 1) --> INT_MIN)
475// 3. Ignore negative zeros. (-0 --> 0)
476// 4. Ignore remainder. (3 / 4 --> 0)
477//
478// Indirect truncation is used to represent that we are interested in the
479// truncated result, but only if it can safely flow into operations which
480// are computed modulo 2^32, such as (2) and (3). Infinities are not safe,
481// as they would have absorbed other math operations. Remainders are not
482// safe, as fractions can be scaled up by multiplication.
483//
484// Division is a particularly interesting node here because it covers all 4
485// cases even when its own operands are integers.
486//
487// Note that these enum values are ordered from least value-modifying to
488// most value-modifying, and code relies on this ordering.
489enum class TruncateKind {
490 // No correction.
491 NoTruncate = 0,
492 // An integer is desired, but we can't skip bailout checks.
493 TruncateAfterBailouts = 1,
494 // The value will be truncated after some arithmetic (see above).
495 IndirectTruncate = 2,
496 // Direct and infallible truncation to int32.
497 Truncate = 3
498};
499
500// An MDefinition is an SSA name.
501class MDefinition : public MNode {
502 friend class MBasicBlock;
503
504 public:
505 enum class Opcode : uint16_t {
506#define DEFINE_OPCODES(op) op,
507 MIR_OPCODE_LIST(DEFINE_OPCODES)DEFINE_OPCODES(Start)DEFINE_OPCODES(OsrEntry)DEFINE_OPCODES(Nop
)DEFINE_OPCODES(LimitedTruncate)DEFINE_OPCODES(Constant)DEFINE_OPCODES
(WasmNullConstant)DEFINE_OPCODES(WasmFloatConstant)DEFINE_OPCODES
(Parameter)DEFINE_OPCODES(Callee)DEFINE_OPCODES(IsConstructing
)DEFINE_OPCODES(TableSwitch)DEFINE_OPCODES(Goto)DEFINE_OPCODES
(Test)DEFINE_OPCODES(Return)DEFINE_OPCODES(Throw)DEFINE_OPCODES
(ThrowWithStack)DEFINE_OPCODES(NewArray)DEFINE_OPCODES(NewArrayDynamicLength
)DEFINE_OPCODES(NewTypedArray)DEFINE_OPCODES(NewTypedArrayDynamicLength
)DEFINE_OPCODES(NewTypedArrayFromArray)DEFINE_OPCODES(NewTypedArrayFromArrayBuffer
)DEFINE_OPCODES(NewObject)DEFINE_OPCODES(NewPlainObject)DEFINE_OPCODES
(NewArrayObject)DEFINE_OPCODES(NewIterator)DEFINE_OPCODES(ObjectState
)DEFINE_OPCODES(ArrayState)DEFINE_OPCODES(BindFunction)DEFINE_OPCODES
(NewBoundFunction)DEFINE_OPCODES(BoundFunctionNumArgs)DEFINE_OPCODES
(GuardBoundFunctionIsConstructor)DEFINE_OPCODES(MutateProto)DEFINE_OPCODES
(InitPropGetterSetter)DEFINE_OPCODES(InitElemGetterSetter)DEFINE_OPCODES
(Call)DEFINE_OPCODES(CallClassHook)DEFINE_OPCODES(ApplyArgs)DEFINE_OPCODES
(ApplyArgsObj)DEFINE_OPCODES(ApplyArray)DEFINE_OPCODES(ConstructArgs
)DEFINE_OPCODES(ConstructArray)DEFINE_OPCODES(Bail)DEFINE_OPCODES
(Unreachable)DEFINE_OPCODES(EncodeSnapshot)DEFINE_OPCODES(AssertRecoveredOnBailout
)DEFINE_OPCODES(AssertFloat32)DEFINE_OPCODES(Compare)DEFINE_OPCODES
(SameValueDouble)DEFINE_OPCODES(SameValue)DEFINE_OPCODES(Box)
DEFINE_OPCODES(Unbox)DEFINE_OPCODES(AssertRange)DEFINE_OPCODES
(AssertClass)DEFINE_OPCODES(AssertShape)DEFINE_OPCODES(CreateThis
)DEFINE_OPCODES(CreateArgumentsObject)DEFINE_OPCODES(CreateInlinedArgumentsObject
)DEFINE_OPCODES(GetInlinedArgument)DEFINE_OPCODES(GetInlinedArgumentHole
)DEFINE_OPCODES(GetArgumentsObjectArg)DEFINE_OPCODES(SetArgumentsObjectArg
)DEFINE_OPCODES(LoadArgumentsObjectArg)DEFINE_OPCODES(LoadArgumentsObjectArgHole
)DEFINE_OPCODES(InArgumentsObjectArg)DEFINE_OPCODES(ArgumentsObjectLength
)DEFINE_OPCODES(ArrayFromArgumentsObject)DEFINE_OPCODES(GuardArgumentsObjectFlags
)DEFINE_OPCODES(LoadScriptedProxyHandler)DEFINE_OPCODES(CheckScriptedProxyGetResult
)DEFINE_OPCODES(IdToStringOrSymbol)DEFINE_OPCODES(ReturnFromCtor
)DEFINE_OPCODES(ToDouble)DEFINE_OPCODES(ToFloat32)DEFINE_OPCODES
(WasmUnsignedToDouble)DEFINE_OPCODES(WasmUnsignedToFloat32)DEFINE_OPCODES
(WrapInt64ToInt32)DEFINE_OPCODES(ExtendInt32ToInt64)DEFINE_OPCODES
(WasmBuiltinTruncateToInt64)DEFINE_OPCODES(WasmTruncateToInt64
)DEFINE_OPCODES(WasmTruncateToInt32)DEFINE_OPCODES(WasmAnyRefFromJSValue
)DEFINE_OPCODES(WasmAnyRefFromJSObject)DEFINE_OPCODES(WasmAnyRefFromJSString
)DEFINE_OPCODES(WasmNewI31Ref)DEFINE_OPCODES(WasmI31RefGet)DEFINE_OPCODES
(Int32ToIntPtr)DEFINE_OPCODES(NonNegativeIntPtrToInt32)DEFINE_OPCODES
(IntPtrToDouble)DEFINE_OPCODES(AdjustDataViewLength)DEFINE_OPCODES
(Int64ToFloatingPoint)DEFINE_OPCODES(BuiltinInt64ToFloatingPoint
)DEFINE_OPCODES(ToNumberInt32)DEFINE_OPCODES(BooleanToInt32)DEFINE_OPCODES
(TruncateToInt32)DEFINE_OPCODES(WasmBuiltinTruncateToInt32)DEFINE_OPCODES
(ToBigInt)DEFINE_OPCODES(ToInt64)DEFINE_OPCODES(TruncateBigIntToInt64
)DEFINE_OPCODES(Int64ToBigInt)DEFINE_OPCODES(ToString)DEFINE_OPCODES
(BitNot)DEFINE_OPCODES(TypeOf)DEFINE_OPCODES(TypeOfName)DEFINE_OPCODES
(TypeOfIs)DEFINE_OPCODES(ToAsyncIter)DEFINE_OPCODES(ToPropertyKeyCache
)DEFINE_OPCODES(BitAnd)DEFINE_OPCODES(BitOr)DEFINE_OPCODES(BitXor
)DEFINE_OPCODES(Lsh)DEFINE_OPCODES(Rsh)DEFINE_OPCODES(Ursh)DEFINE_OPCODES
(SignExtendInt32)DEFINE_OPCODES(SignExtendInt64)DEFINE_OPCODES
(MinMax)DEFINE_OPCODES(MinMaxArray)DEFINE_OPCODES(Abs)DEFINE_OPCODES
(Clz)DEFINE_OPCODES(Ctz)DEFINE_OPCODES(Popcnt)DEFINE_OPCODES(
Sqrt)DEFINE_OPCODES(CopySign)DEFINE_OPCODES(Atan2)DEFINE_OPCODES
(Hypot)DEFINE_OPCODES(Pow)DEFINE_OPCODES(PowHalf)DEFINE_OPCODES
(Random)DEFINE_OPCODES(Sign)DEFINE_OPCODES(MathFunction)DEFINE_OPCODES
(Add)DEFINE_OPCODES(Sub)DEFINE_OPCODES(Mul)DEFINE_OPCODES(Div
)DEFINE_OPCODES(WasmBuiltinDivI64)DEFINE_OPCODES(Mod)DEFINE_OPCODES
(WasmBuiltinModD)DEFINE_OPCODES(WasmBuiltinModI64)DEFINE_OPCODES
(BigIntAdd)DEFINE_OPCODES(BigIntSub)DEFINE_OPCODES(BigIntMul)
DEFINE_OPCODES(BigIntDiv)DEFINE_OPCODES(BigIntMod)DEFINE_OPCODES
(BigIntPow)DEFINE_OPCODES(BigIntBitAnd)DEFINE_OPCODES(BigIntBitOr
)DEFINE_OPCODES(BigIntBitXor)DEFINE_OPCODES(BigIntLsh)DEFINE_OPCODES
(BigIntRsh)DEFINE_OPCODES(BigIntIncrement)DEFINE_OPCODES(BigIntDecrement
)DEFINE_OPCODES(BigIntNegate)DEFINE_OPCODES(BigIntBitNot)DEFINE_OPCODES
(Int32ToStringWithBase)DEFINE_OPCODES(NumberParseInt)DEFINE_OPCODES
(DoubleParseInt)DEFINE_OPCODES(Concat)DEFINE_OPCODES(LinearizeString
)DEFINE_OPCODES(LinearizeForCharAccess)DEFINE_OPCODES(LinearizeForCodePointAccess
)DEFINE_OPCODES(ToRelativeStringIndex)DEFINE_OPCODES(CharCodeAt
)DEFINE_OPCODES(CharCodeAtOrNegative)DEFINE_OPCODES(CodePointAt
)DEFINE_OPCODES(CodePointAtOrNegative)DEFINE_OPCODES(NegativeToNaN
)DEFINE_OPCODES(NegativeToUndefined)DEFINE_OPCODES(FromCharCode
)DEFINE_OPCODES(FromCharCodeEmptyIfNegative)DEFINE_OPCODES(FromCharCodeUndefinedIfNegative
)DEFINE_OPCODES(FromCodePoint)DEFINE_OPCODES(StringIncludes)DEFINE_OPCODES
(StringIndexOf)DEFINE_OPCODES(StringLastIndexOf)DEFINE_OPCODES
(StringStartsWith)DEFINE_OPCODES(StringEndsWith)DEFINE_OPCODES
(StringConvertCase)DEFINE_OPCODES(CharCodeConvertCase)DEFINE_OPCODES
(StringTrimStartIndex)DEFINE_OPCODES(StringTrimEndIndex)DEFINE_OPCODES
(StringSplit)DEFINE_OPCODES(BoxNonStrictThis)DEFINE_OPCODES(ImplicitThis
)DEFINE_OPCODES(Phi)DEFINE_OPCODES(Beta)DEFINE_OPCODES(NaNToZero
)DEFINE_OPCODES(OsrValue)DEFINE_OPCODES(OsrEnvironmentChain)DEFINE_OPCODES
(OsrArgumentsObject)DEFINE_OPCODES(OsrReturnValue)DEFINE_OPCODES
(BinaryCache)DEFINE_OPCODES(UnaryCache)DEFINE_OPCODES(CheckOverRecursed
)DEFINE_OPCODES(InterruptCheck)DEFINE_OPCODES(WasmInterruptCheck
)DEFINE_OPCODES(WasmTrap)DEFINE_OPCODES(WasmTrapIfNull)DEFINE_OPCODES
(LexicalCheck)DEFINE_OPCODES(ThrowRuntimeLexicalError)DEFINE_OPCODES
(ThrowMsg)DEFINE_OPCODES(GlobalDeclInstantiation)DEFINE_OPCODES
(RegExp)DEFINE_OPCODES(RegExpMatcher)DEFINE_OPCODES(RegExpSearcher
)DEFINE_OPCODES(RegExpSearcherLastLimit)DEFINE_OPCODES(RegExpExecMatch
)DEFINE_OPCODES(RegExpExecTest)DEFINE_OPCODES(RegExpHasCaptureGroups
)DEFINE_OPCODES(RegExpPrototypeOptimizable)DEFINE_OPCODES(RegExpInstanceOptimizable
)DEFINE_OPCODES(GetFirstDollarIndex)DEFINE_OPCODES(StringReplace
)DEFINE_OPCODES(Substr)DEFINE_OPCODES(ModuleMetadata)DEFINE_OPCODES
(DynamicImport)DEFINE_OPCODES(Lambda)DEFINE_OPCODES(FunctionWithProto
)DEFINE_OPCODES(SetFunName)DEFINE_OPCODES(Slots)DEFINE_OPCODES
(Elements)DEFINE_OPCODES(InitializedLength)DEFINE_OPCODES(SetInitializedLength
)DEFINE_OPCODES(ArrayLength)DEFINE_OPCODES(SetArrayLength)DEFINE_OPCODES
(FunctionLength)DEFINE_OPCODES(FunctionName)DEFINE_OPCODES(GetNextEntryForIterator
)DEFINE_OPCODES(ArrayBufferByteLength)DEFINE_OPCODES(ArrayBufferViewLength
)DEFINE_OPCODES(ArrayBufferViewByteOffset)DEFINE_OPCODES(ArrayBufferViewElements
)DEFINE_OPCODES(ResizableTypedArrayByteOffsetMaybeOutOfBounds
)DEFINE_OPCODES(ResizableTypedArrayLength)DEFINE_OPCODES(ResizableDataViewByteLength
)DEFINE_OPCODES(GrowableSharedArrayBufferByteLength)DEFINE_OPCODES
(TypedArrayElementSize)DEFINE_OPCODES(GuardHasAttachedArrayBuffer
)DEFINE_OPCODES(GuardResizableArrayBufferViewInBounds)DEFINE_OPCODES
(GuardResizableArrayBufferViewInBoundsOrDetached)DEFINE_OPCODES
(GuardNumberToIntPtrIndex)DEFINE_OPCODES(KeepAliveObject)DEFINE_OPCODES
(DebugEnterGCUnsafeRegion)DEFINE_OPCODES(DebugLeaveGCUnsafeRegion
)DEFINE_OPCODES(Not)DEFINE_OPCODES(BoundsCheck)DEFINE_OPCODES
(BoundsCheckLower)DEFINE_OPCODES(SpectreMaskIndex)DEFINE_OPCODES
(LoadElement)DEFINE_OPCODES(LoadElementAndUnbox)DEFINE_OPCODES
(LoadElementHole)DEFINE_OPCODES(StoreElement)DEFINE_OPCODES(StoreHoleValueElement
)DEFINE_OPCODES(StoreElementHole)DEFINE_OPCODES(ArrayPopShift
)DEFINE_OPCODES(ArrayPush)DEFINE_OPCODES(ArraySlice)DEFINE_OPCODES
(ArgumentsSlice)DEFINE_OPCODES(FrameArgumentsSlice)DEFINE_OPCODES
(InlineArgumentsSlice)DEFINE_OPCODES(NormalizeSliceTerm)DEFINE_OPCODES
(ArrayJoin)DEFINE_OPCODES(ObjectKeys)DEFINE_OPCODES(ObjectKeysLength
)DEFINE_OPCODES(LoadUnboxedScalar)DEFINE_OPCODES(LoadDataViewElement
)DEFINE_OPCODES(LoadTypedArrayElementHole)DEFINE_OPCODES(StoreUnboxedScalar
)DEFINE_OPCODES(StoreDataViewElement)DEFINE_OPCODES(StoreTypedArrayElementHole
)DEFINE_OPCODES(EffectiveAddress)DEFINE_OPCODES(ClampToUint8)
DEFINE_OPCODES(LoadFixedSlot)DEFINE_OPCODES(LoadFixedSlotAndUnbox
)DEFINE_OPCODES(LoadDynamicSlotAndUnbox)DEFINE_OPCODES(StoreFixedSlot
)DEFINE_OPCODES(GetPropertyCache)DEFINE_OPCODES(HomeObjectSuperBase
)DEFINE_OPCODES(GetPropSuperCache)DEFINE_OPCODES(BindNameCache
)DEFINE_OPCODES(CallBindVar)DEFINE_OPCODES(GuardShape)DEFINE_OPCODES
(GuardFuse)DEFINE_OPCODES(GuardMultipleShapes)DEFINE_OPCODES(
GuardProto)DEFINE_OPCODES(GuardNullProto)DEFINE_OPCODES(GuardIsNativeObject
)DEFINE_OPCODES(GuardGlobalGeneration)DEFINE_OPCODES(GuardIsProxy
)DEFINE_OPCODES(GuardIsNotDOMProxy)DEFINE_OPCODES(GuardIsNotProxy
)DEFINE_OPCODES(ProxyGet)DEFINE_OPCODES(ProxyGetByValue)DEFINE_OPCODES
(ProxyHasProp)DEFINE_OPCODES(ProxySet)DEFINE_OPCODES(ProxySetByValue
)DEFINE_OPCODES(CallSetArrayLength)DEFINE_OPCODES(MegamorphicLoadSlot
)DEFINE_OPCODES(MegamorphicLoadSlotByValue)DEFINE_OPCODES(MegamorphicStoreSlot
)DEFINE_OPCODES(MegamorphicHasProp)DEFINE_OPCODES(SmallObjectVariableKeyHasProp
)DEFINE_OPCODES(GuardIsNotArrayBufferMaybeShared)DEFINE_OPCODES
(GuardIsTypedArray)DEFINE_OPCODES(GuardIsFixedLengthTypedArray
)DEFINE_OPCODES(GuardIsResizableTypedArray)DEFINE_OPCODES(GuardHasProxyHandler
)DEFINE_OPCODES(NurseryObject)DEFINE_OPCODES(GuardValue)DEFINE_OPCODES
(GuardNullOrUndefined)DEFINE_OPCODES(GuardIsNotObject)DEFINE_OPCODES
(GuardFunctionFlags)DEFINE_OPCODES(GuardFunctionIsNonBuiltinCtor
)DEFINE_OPCODES(GuardFunctionKind)DEFINE_OPCODES(GuardFunctionScript
)DEFINE_OPCODES(GuardObjectIdentity)DEFINE_OPCODES(GuardSpecificFunction
)DEFINE_OPCODES(GuardSpecificAtom)DEFINE_OPCODES(GuardSpecificSymbol
)DEFINE_OPCODES(GuardSpecificInt32)DEFINE_OPCODES(GuardStringToIndex
)DEFINE_OPCODES(GuardStringToInt32)DEFINE_OPCODES(GuardStringToDouble
)DEFINE_OPCODES(GuardNoDenseElements)DEFINE_OPCODES(GuardTagNotEqual
)DEFINE_OPCODES(LoadDynamicSlot)DEFINE_OPCODES(FunctionEnvironment
)DEFINE_OPCODES(NewLexicalEnvironmentObject)DEFINE_OPCODES(NewClassBodyEnvironmentObject
)DEFINE_OPCODES(NewVarEnvironmentObject)DEFINE_OPCODES(HomeObject
)DEFINE_OPCODES(AddAndStoreSlot)DEFINE_OPCODES(AllocateAndStoreSlot
)DEFINE_OPCODES(AddSlotAndCallAddPropHook)DEFINE_OPCODES(StoreDynamicSlot
)DEFINE_OPCODES(GetNameCache)DEFINE_OPCODES(CallGetIntrinsicValue
)DEFINE_OPCODES(DeleteProperty)DEFINE_OPCODES(DeleteElement)DEFINE_OPCODES
(SetPropertyCache)DEFINE_OPCODES(MegamorphicSetElement)DEFINE_OPCODES
(SetDOMProperty)DEFINE_OPCODES(GetDOMProperty)DEFINE_OPCODES(
GetDOMMember)DEFINE_OPCODES(ObjectToIterator)DEFINE_OPCODES(ValueToIterator
)DEFINE_OPCODES(IteratorHasIndices)DEFINE_OPCODES(LoadSlotByIteratorIndex
)DEFINE_OPCODES(StoreSlotByIteratorIndex)DEFINE_OPCODES(LoadDOMExpandoValue
)DEFINE_OPCODES(LoadDOMExpandoValueGuardGeneration)DEFINE_OPCODES
(LoadDOMExpandoValueIgnoreGeneration)DEFINE_OPCODES(GuardDOMExpandoMissingOrGuardShape
)DEFINE_OPCODES(StringLength)DEFINE_OPCODES(Floor)DEFINE_OPCODES
(Ceil)DEFINE_OPCODES(Round)DEFINE_OPCODES(Trunc)DEFINE_OPCODES
(NearbyInt)DEFINE_OPCODES(GetIteratorCache)DEFINE_OPCODES(OptimizeSpreadCallCache
)DEFINE_OPCODES(IteratorMore)DEFINE_OPCODES(IsNoIter)DEFINE_OPCODES
(IteratorEnd)DEFINE_OPCODES(CloseIterCache)DEFINE_OPCODES(OptimizeGetIteratorCache
)DEFINE_OPCODES(InCache)DEFINE_OPCODES(InArray)DEFINE_OPCODES
(GuardElementNotHole)DEFINE_OPCODES(NewPrivateName)DEFINE_OPCODES
(CheckPrivateFieldCache)DEFINE_OPCODES(HasOwnCache)DEFINE_OPCODES
(InstanceOf)DEFINE_OPCODES(InstanceOfCache)DEFINE_OPCODES(ArgumentsLength
)DEFINE_OPCODES(GetFrameArgument)DEFINE_OPCODES(GetFrameArgumentHole
)DEFINE_OPCODES(NewTarget)DEFINE_OPCODES(Rest)DEFINE_OPCODES(
PostWriteBarrier)DEFINE_OPCODES(PostWriteElementBarrier)DEFINE_OPCODES
(AssertCanElidePostWriteBarrier)DEFINE_OPCODES(NewNamedLambdaObject
)DEFINE_OPCODES(NewCallObject)DEFINE_OPCODES(NewStringObject)
DEFINE_OPCODES(IsCallable)DEFINE_OPCODES(IsConstructor)DEFINE_OPCODES
(IsCrossRealmArrayConstructor)DEFINE_OPCODES(IsObject)DEFINE_OPCODES
(IsNullOrUndefined)DEFINE_OPCODES(HasClass)DEFINE_OPCODES(GuardToClass
)DEFINE_OPCODES(GuardToEitherClass)DEFINE_OPCODES(GuardToFunction
)DEFINE_OPCODES(IsArray)DEFINE_OPCODES(IsTypedArray)DEFINE_OPCODES
(ObjectClassToString)DEFINE_OPCODES(CheckReturn)DEFINE_OPCODES
(CheckThis)DEFINE_OPCODES(AsyncResolve)DEFINE_OPCODES(AsyncReject
)DEFINE_OPCODES(GeneratorReturn)DEFINE_OPCODES(AsyncAwait)DEFINE_OPCODES
(CheckThisReinit)DEFINE_OPCODES(Generator)DEFINE_OPCODES(CanSkipAwait
)DEFINE_OPCODES(MaybeExtractAwaitValue)DEFINE_OPCODES(IncrementWarmUpCounter
)DEFINE_OPCODES(AtomicIsLockFree)DEFINE_OPCODES(CompareExchangeTypedArrayElement
)DEFINE_OPCODES(AtomicExchangeTypedArrayElement)DEFINE_OPCODES
(AtomicTypedArrayElementBinop)DEFINE_OPCODES(Debugger)DEFINE_OPCODES
(CheckIsObj)DEFINE_OPCODES(CheckObjCoercible)DEFINE_OPCODES(CheckClassHeritage
)DEFINE_OPCODES(DebugCheckSelfHosted)DEFINE_OPCODES(IsPackedArray
)DEFINE_OPCODES(GuardArrayIsPacked)DEFINE_OPCODES(GetPrototypeOf
)DEFINE_OPCODES(ObjectWithProto)DEFINE_OPCODES(ObjectStaticProto
)DEFINE_OPCODES(ConstantProto)DEFINE_OPCODES(BuiltinObject)DEFINE_OPCODES
(SuperFunction)DEFINE_OPCODES(InitHomeObject)DEFINE_OPCODES(IsTypedArrayConstructor
)DEFINE_OPCODES(LoadValueTag)DEFINE_OPCODES(LoadWrapperTarget
)DEFINE_OPCODES(GuardHasGetterSetter)DEFINE_OPCODES(GuardIsExtensible
)DEFINE_OPCODES(GuardInt32IsNonNegative)DEFINE_OPCODES(GuardInt32Range
)DEFINE_OPCODES(GuardIndexIsNotDenseElement)DEFINE_OPCODES(GuardIndexIsValidUpdateOrAdd
)DEFINE_OPCODES(CallAddOrUpdateSparseElement)DEFINE_OPCODES(CallGetSparseElement
)DEFINE_OPCODES(CallNativeGetElement)DEFINE_OPCODES(CallNativeGetElementSuper
)DEFINE_OPCODES(CallObjectHasSparseElement)DEFINE_OPCODES(BigIntAsIntN
)DEFINE_OPCODES(BigIntAsUintN)DEFINE_OPCODES(GuardNonGCThing)
DEFINE_OPCODES(ToHashableNonGCThing)DEFINE_OPCODES(ToHashableString
)DEFINE_OPCODES(ToHashableValue)DEFINE_OPCODES(HashNonGCThing
)DEFINE_OPCODES(HashString)DEFINE_OPCODES(HashSymbol)DEFINE_OPCODES
(HashBigInt)DEFINE_OPCODES(HashObject)DEFINE_OPCODES(HashValue
)DEFINE_OPCODES(SetObjectHasNonBigInt)DEFINE_OPCODES(SetObjectHasBigInt
)DEFINE_OPCODES(SetObjectHasValue)DEFINE_OPCODES(SetObjectHasValueVMCall
)DEFINE_OPCODES(SetObjectSize)DEFINE_OPCODES(MapObjectHasNonBigInt
)DEFINE_OPCODES(MapObjectHasBigInt)DEFINE_OPCODES(MapObjectHasValue
)DEFINE_OPCODES(MapObjectHasValueVMCall)DEFINE_OPCODES(MapObjectGetNonBigInt
)DEFINE_OPCODES(MapObjectGetBigInt)DEFINE_OPCODES(MapObjectGetValue
)DEFINE_OPCODES(MapObjectGetValueVMCall)DEFINE_OPCODES(MapObjectSize
)DEFINE_OPCODES(PostIntPtrConversion)DEFINE_OPCODES(WasmNeg)DEFINE_OPCODES
(WasmBinaryBitwise)DEFINE_OPCODES(WasmLoadInstance)DEFINE_OPCODES
(WasmStoreInstance)DEFINE_OPCODES(WasmHeapReg)DEFINE_OPCODES(
WasmBoundsCheck)DEFINE_OPCODES(WasmBoundsCheckRange32)DEFINE_OPCODES
(WasmExtendU32Index)DEFINE_OPCODES(WasmWrapU32Index)DEFINE_OPCODES
(WasmAddOffset)DEFINE_OPCODES(WasmAlignmentCheck)DEFINE_OPCODES
(WasmLoad)DEFINE_OPCODES(WasmStore)DEFINE_OPCODES(AsmJSLoadHeap
)DEFINE_OPCODES(AsmJSStoreHeap)DEFINE_OPCODES(WasmFence)DEFINE_OPCODES
(WasmCompareExchangeHeap)DEFINE_OPCODES(WasmAtomicExchangeHeap
)DEFINE_OPCODES(WasmAtomicBinopHeap)DEFINE_OPCODES(WasmLoadInstanceDataField
)DEFINE_OPCODES(WasmLoadGlobalCell)DEFINE_OPCODES(WasmLoadTableElement
)DEFINE_OPCODES(WasmStoreInstanceDataField)DEFINE_OPCODES(WasmStoreGlobalCell
)DEFINE_OPCODES(WasmStoreStackResult)DEFINE_OPCODES(WasmDerivedPointer
)DEFINE_OPCODES(WasmDerivedIndexPointer)DEFINE_OPCODES(WasmStoreRef
)DEFINE_OPCODES(WasmPostWriteBarrierImmediate)DEFINE_OPCODES(
WasmPostWriteBarrierIndex)DEFINE_OPCODES(WasmParameter)DEFINE_OPCODES
(WasmReturn)DEFINE_OPCODES(WasmReturnVoid)DEFINE_OPCODES(WasmStackArg
)DEFINE_OPCODES(WasmRegisterResult)DEFINE_OPCODES(WasmFloatRegisterResult
)DEFINE_OPCODES(WasmRegister64Result)DEFINE_OPCODES(WasmStackResultArea
)DEFINE_OPCODES(WasmStackResult)DEFINE_OPCODES(WasmCallCatchable
)DEFINE_OPCODES(WasmCallUncatchable)DEFINE_OPCODES(WasmCallLandingPrePad
)DEFINE_OPCODES(WasmReturnCall)DEFINE_OPCODES(WasmSelect)DEFINE_OPCODES
(WasmReinterpret)DEFINE_OPCODES(Rotate)DEFINE_OPCODES(WasmStackSwitchToMain
)DEFINE_OPCODES(WasmStackSwitchToSuspendable)DEFINE_OPCODES(WasmStackContinueOnSuspendable
)DEFINE_OPCODES(WasmBinarySimd128)DEFINE_OPCODES(WasmBinarySimd128WithConstant
)DEFINE_OPCODES(WasmShiftSimd128)DEFINE_OPCODES(WasmShuffleSimd128
)DEFINE_OPCODES(WasmReplaceLaneSimd128)DEFINE_OPCODES(WasmUnarySimd128
)DEFINE_OPCODES(WasmTernarySimd128)DEFINE_OPCODES(WasmScalarToSimd128
)DEFINE_OPCODES(WasmReduceSimd128)DEFINE_OPCODES(WasmLoadLaneSimd128
)DEFINE_OPCODES(WasmStoreLaneSimd128)DEFINE_OPCODES(UnreachableResult
)DEFINE_OPCODES(IonToWasmCall)DEFINE_OPCODES(WasmLoadField)DEFINE_OPCODES
(WasmLoadFieldKA)DEFINE_OPCODES(WasmLoadElementKA)DEFINE_OPCODES
(WasmStoreFieldKA)DEFINE_OPCODES(WasmStoreFieldRefKA)DEFINE_OPCODES
(WasmStoreElementKA)DEFINE_OPCODES(WasmStoreElementRefKA)DEFINE_OPCODES
(WasmRefIsSubtypeOfConcrete)DEFINE_OPCODES(WasmRefIsSubtypeOfAbstract
)DEFINE_OPCODES(WasmNewStructObject)DEFINE_OPCODES(WasmNewArrayObject
)
508#undef DEFINE_OPCODES
509 };
510
511 private:
512 InlineList<MUse> uses_; // Use chain.
513 uint32_t id_; // Instruction ID, which after block re-ordering
514 // is sorted within a basic block.
515 Opcode op_; // Opcode.
516 uint16_t flags_; // Bit flags.
517 Range* range_; // Any computed range for this def.
518 union {
519 MDefinition*
520 loadDependency_; // Implicit dependency (store, call, etc.) of this
521 // instruction. Used by alias analysis, GVN and LICM.
522 uint32_t virtualRegister_; // Used by lowering to map definitions to
523 // virtual registers.
524 };
525
526 // Track bailouts by storing the current pc in MIR instruction. Also used
527 // for profiling and keeping track of what the last known pc was.
528 const BytecodeSite* trackedSite_;
529
530 // If we generate a bailout path for this instruction, this is the
531 // bailout kind that will be encoded in the snapshot. When we bail out,
532 // FinishBailoutToBaseline may take action based on the bailout kind to
533 // prevent bailout loops. (For example, if an instruction bails out after
534 // being hoisted by LICM, we will disable LICM when recompiling the script.)
535 BailoutKind bailoutKind_;
536
537 MIRType resultType_; // Representation of result type.
538
539 private:
540 enum Flag {
541 None = 0,
542#define DEFINE_FLAG(flag) flag,
543 MIR_FLAG_LIST(DEFINE_FLAG)DEFINE_FLAG(InWorklist) DEFINE_FLAG(EmittedAtUses) DEFINE_FLAG
(Commutative) DEFINE_FLAG(Movable) DEFINE_FLAG(Lowered) DEFINE_FLAG
(Guard) DEFINE_FLAG(GuardRangeBailouts) DEFINE_FLAG(ImplicitlyUsed
) DEFINE_FLAG(Unused) DEFINE_FLAG(RecoveredOnBailout) DEFINE_FLAG
(IncompleteObject) DEFINE_FLAG(CallResultCapture) DEFINE_FLAG
(Discarded)
544#undef DEFINE_FLAG
545 Total
546 };
547
548 bool hasFlags(uint32_t flags) const { return (flags_ & flags) == flags; }
549 void removeFlags(uint32_t flags) { flags_ &= ~flags; }
550 void setFlags(uint32_t flags) { flags_ |= flags; }
551
552 // Calling isDefinition or isResumePoint on MDefinition is unnecessary.
553 bool isDefinition() const = delete;
554 bool isResumePoint() const = delete;
555
556 protected:
557 void setInstructionBlock(MBasicBlock* block, const BytecodeSite* site) {
558 MOZ_ASSERT(isInstruction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isInstruction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isInstruction()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isInstruction()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isInstruction()"
")"); do { *((volatile int*)__null) = 558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
559 setBlockAndKind(block, Kind::Definition);
560 setTrackedSite(site);
561 }
562
563 void setPhiBlock(MBasicBlock* block) {
564 MOZ_ASSERT(isPhi())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isPhi())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isPhi()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("isPhi()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isPhi()" ")"
); do { *((volatile int*)__null) = 564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
565 setBlockAndKind(block, Kind::Definition);
566 }
567
568 static HashNumber addU32ToHash(HashNumber hash, uint32_t data) {
569 return data + (hash << 6) + (hash << 16) - hash;
570 }
571
572 static HashNumber addU64ToHash(HashNumber hash, uint64_t data) {
573 hash = addU32ToHash(hash, uint32_t(data));
574 hash = addU32ToHash(hash, uint32_t(data >> 32));
575 return hash;
576 }
577
578 public:
579 explicit MDefinition(Opcode op)
580 : MNode(nullptr, Kind::Definition),
581 id_(0),
582 op_(op),
583 flags_(0),
584 range_(nullptr),
585 loadDependency_(nullptr),
586 trackedSite_(nullptr),
587 bailoutKind_(BailoutKind::Unknown),
588 resultType_(MIRType::None) {}
589
590 // Copying a definition leaves the list of uses empty.
591 explicit MDefinition(const MDefinition& other)
592 : MNode(other),
593 id_(0),
594 op_(other.op_),
595 flags_(other.flags_),
596 range_(other.range_),
597 loadDependency_(other.loadDependency_),
598 trackedSite_(other.trackedSite_),
599 bailoutKind_(other.bailoutKind_),
600 resultType_(other.resultType_) {}
601
602 Opcode op() const { return op_; }
603
604#ifdef JS_JITSPEW1
605 const char* opName() const;
606 void printName(GenericPrinter& out) const;
607 static void PrintOpcodeName(GenericPrinter& out, Opcode op);
608 virtual void printOpcode(GenericPrinter& out) const;
609 void dump(GenericPrinter& out) const override;
610 void dump() const override;
611 void dumpLocation(GenericPrinter& out) const;
612 void dumpLocation() const;
613 // Dump any other stuff the node wants to have printed in `extras`. The
614 // added strings are copied, with the `ExtrasCollector` taking ownership of
615 // the copies.
616 virtual void getExtras(ExtrasCollector* extras) {}
617#endif
618
619 // Also for LICM. Test whether this definition is likely to be a call, which
620 // would clobber all or many of the floating-point registers, such that
621 // hoisting floating-point constants out of containing loops isn't likely to
622 // be worthwhile.
623 virtual bool possiblyCalls() const { return false; }
624
625 MBasicBlock* block() const { return definitionBlock(); }
626
627 private:
628 void setTrackedSite(const BytecodeSite* site) {
629 MOZ_ASSERT(site)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(site)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(site))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("site", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 629); AnnotateMozCrashReason("MOZ_ASSERT" "(" "site" ")"); do
{ *((volatile int*)__null) = 629; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
630 trackedSite_ = site;
631 }
632
633 public:
634 const BytecodeSite* trackedSite() const {
635 MOZ_ASSERT(trackedSite_,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(trackedSite_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(trackedSite_))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("trackedSite_" " ("
"missing tracked bytecode site; node not assigned to a block?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trackedSite_"
") (" "missing tracked bytecode site; node not assigned to a block?"
")"); do { *((volatile int*)__null) = 636; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
636 "missing tracked bytecode site; node not assigned to a block?")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(trackedSite_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(trackedSite_))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("trackedSite_" " ("
"missing tracked bytecode site; node not assigned to a block?"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 636); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trackedSite_"
") (" "missing tracked bytecode site; node not assigned to a block?"
")"); do { *((volatile int*)__null) = 636; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
637 return trackedSite_;
638 }
639
640 BailoutKind bailoutKind() const { return bailoutKind_; }
641 void setBailoutKind(BailoutKind kind) { bailoutKind_ = kind; }
642
643 // Return the range of this value, *before* any bailout checks. Contrast
644 // this with the type() method, and the Range constructor which takes an
645 // MDefinition*, which describe the value *after* any bailout checks.
646 //
647 // Warning: Range analysis is removing the bit-operations such as '| 0' at
648 // the end of the transformations. Using this function to analyse any
649 // operands after the truncate phase of the range analysis will lead to
650 // errors. Instead, one should define the collectRangeInfoPreTrunc() to set
651 // the right set of flags which are dependent on the range of the inputs.
652 Range* range() const {
653 MOZ_ASSERT(type() != MIRType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() != MIRType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() != MIRType::None))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("type() != MIRType::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 653); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() != MIRType::None"
")"); do { *((volatile int*)__null) = 653; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
654 return range_;
655 }
656 void setRange(Range* range) {
657 MOZ_ASSERT(type() != MIRType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() != MIRType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() != MIRType::None))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("type() != MIRType::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() != MIRType::None"
")"); do { *((volatile int*)__null) = 657; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
658 range_ = range;
659 }
660
661 virtual HashNumber valueHash() const;
662 virtual bool congruentTo(const MDefinition* ins) const { return false; }
663 const MDefinition* skipObjectGuards() const;
664
665 // Note that, for a call `congruentIfOperandsEqual(ins)` inside some class
666 // MFoo, if `true` is returned then we are ensured that `ins` is also an
667 // MFoo, so it is safe to do `ins->toMFoo()` without first checking whether
668 // `ins->isMFoo()`.
669 bool congruentIfOperandsEqual(const MDefinition* ins) const;
670
671 virtual MDefinition* foldsTo(TempAllocator& alloc);
672 virtual void analyzeEdgeCasesForward();
673 virtual void analyzeEdgeCasesBackward();
674
675 // |canTruncate| reports if this instruction supports truncation. If
676 // |canTruncate| function returns true, then the |truncate| function is
677 // called on the same instruction to mutate the instruction, such as updating
678 // the return type, the range and the specialization of the instruction.
679 virtual bool canTruncate() const;
680 virtual void truncate(TruncateKind kind);
681
682 // Determine what kind of truncate this node prefers for the operand at the
683 // given index.
684 virtual TruncateKind operandTruncateKind(size_t index) const;
685
686 // Compute an absolute or symbolic range for the value of this node.
687 virtual void computeRange(TempAllocator& alloc) {}
688
689 // Collect information from the pre-truncated ranges.
690 virtual void collectRangeInfoPreTrunc() {}
691
692 uint32_t id() const {
693 MOZ_ASSERT(block())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(block())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(block()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("block()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 693); AnnotateMozCrashReason("MOZ_ASSERT" "(" "block()" ")"
); do { *((volatile int*)__null) = 693; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
694 return id_;
695 }
696 void setId(uint32_t id) { id_ = id; }
697
698#define FLAG_ACCESSOR(flag) \
699 bool is##flag() const { \
700 static_assert(Flag::Total <= sizeof(flags_) * 8, \
701 "Flags should fit in flags_ field"); \
702 return hasFlags(1 << flag); \
703 } \
704 void set##flag() { \
705 MOZ_ASSERT(!hasFlags(1 << flag))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!hasFlags(1 << flag))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!hasFlags(1 << flag)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!hasFlags(1 << flag)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 705); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!hasFlags(1 << flag)"
")"); do { *((volatile int*)__null) = 705; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; \
706 setFlags(1 << flag); \
707 } \
708 void setNot##flag() { \
709 MOZ_ASSERT(hasFlags(1 << flag))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(hasFlags(1 << flag))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(hasFlags(1 << flag))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("hasFlags(1 << flag)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 709); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasFlags(1 << flag)"
")"); do { *((volatile int*)__null) = 709; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
; \
710 removeFlags(1 << flag); \
711 } \
712 void set##flag##Unchecked() { setFlags(1 << flag); } \
713 void setNot##flag##Unchecked() { removeFlags(1 << flag); }
714
715 MIR_FLAG_LIST(FLAG_ACCESSOR)FLAG_ACCESSOR(InWorklist) FLAG_ACCESSOR(EmittedAtUses) FLAG_ACCESSOR
(Commutative) FLAG_ACCESSOR(Movable) FLAG_ACCESSOR(Lowered) FLAG_ACCESSOR
(Guard) FLAG_ACCESSOR(GuardRangeBailouts) FLAG_ACCESSOR(ImplicitlyUsed
) FLAG_ACCESSOR(Unused) FLAG_ACCESSOR(RecoveredOnBailout) FLAG_ACCESSOR
(IncompleteObject) FLAG_ACCESSOR(CallResultCapture) FLAG_ACCESSOR
(Discarded)
716#undef FLAG_ACCESSOR
717
718 // Return the type of this value. This may be speculative, and enforced
719 // dynamically with the use of bailout checks. If all the bailout checks
720 // pass, the value will have this type.
721 //
722 // Unless this is an MUrsh that has bailouts disabled, which, as a special
723 // case, may return a value in (INT32_MAX,UINT32_MAX] even when its type()
724 // is MIRType::Int32.
725 MIRType type() const { return resultType_; }
726
727 bool mightBeType(MIRType type) const {
728 MOZ_ASSERT(type != MIRType::Value)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type != MIRType::Value)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type != MIRType::Value))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("type != MIRType::Value"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 728); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type != MIRType::Value"
")"); do { *((volatile int*)__null) = 728; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
729
730 if (type == this->type()) {
731 return true;
732 }
733
734 if (this->type() == MIRType::Value) {
735 return true;
736 }
737
738 return false;
739 }
740
741 bool mightBeMagicType() const;
742
743 // Return true if the result-set types are a subset of the given types.
744 bool definitelyType(std::initializer_list<MIRType> types) const;
745
746 // Float32 specialization operations (see big comment in IonAnalysis before
747 // the Float32 specialization algorithm).
748 virtual bool isFloat32Commutative() const { return false; }
749 virtual bool canProduceFloat32() const { return false; }
750 virtual bool canConsumeFloat32(MUse* use) const { return false; }
751 virtual void trySpecializeFloat32(TempAllocator& alloc) {}
752#ifdef DEBUG1
753 // Used during the pass that checks that Float32 flow into valid MDefinitions
754 virtual bool isConsistentFloat32Use(MUse* use) const {
755 return type() == MIRType::Float32 || canConsumeFloat32(use);
756 }
757#endif
758
759 // Returns the beginning of this definition's use chain.
760 MUseIterator usesBegin() const { return uses_.begin(); }
761
762 // Returns the end of this definition's use chain.
763 MUseIterator usesEnd() const { return uses_.end(); }
764
765 bool canEmitAtUses() const { return !isEmittedAtUses(); }
766
767 // Removes a use at the given position
768 void removeUse(MUse* use) { uses_.remove(use); }
769
770#if defined(DEBUG1) || defined(JS_JITSPEW1)
771 // Number of uses of this instruction. This function is only available
772 // in DEBUG mode since it requires traversing the list. Most users should
773 // use hasUses() or hasOneUse() instead.
774 size_t useCount() const;
775
776 // Number of uses of this instruction (only counting MDefinitions, ignoring
777 // MResumePoints). This function is only available in DEBUG mode since it
778 // requires traversing the list. Most users should use hasUses() or
779 // hasOneUse() instead.
780 size_t defUseCount() const;
781#endif
782
783 // Test whether this MDefinition has exactly one use.
784 bool hasOneUse() const;
785
786 // Test whether this MDefinition has exactly one use.
787 // (only counting MDefinitions, ignoring MResumePoints)
788 bool hasOneDefUse() const;
789
790 // Test whether this MDefinition has exactly one live use. (only counting
791 // MDefinitions which are not recovered on bailout and ignoring MResumePoints)
792 bool hasOneLiveDefUse() const;
793
794 // Test whether this MDefinition has at least one use.
795 // (only counting MDefinitions, ignoring MResumePoints)
796 bool hasDefUses() const;
797
798 // Test whether this MDefinition has at least one non-recovered use.
799 // (only counting MDefinitions, ignoring MResumePoints)
800 bool hasLiveDefUses() const;
801
802 bool hasUses() const { return !uses_.empty(); }
803
804 // If this MDefinition has a single use (ignoring MResumePoints), returns that
805 // use's definition. Else returns nullptr.
806 MDefinition* maybeSingleDefUse() const;
807
808 // Returns the most recently added use (ignoring MResumePoints) for this
809 // MDefinition. Returns nullptr if there are no uses. Note that this relies on
810 // addUse adding new uses to the front of the list, and should only be called
811 // during MIR building (before optimization passes make changes to the uses).
812 MDefinition* maybeMostRecentlyAddedDefUse() const;
813
814 void addUse(MUse* use) {
815 MOZ_ASSERT(use->producer() == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(use->producer() == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(use->producer() == this))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("use->producer() == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 815); AnnotateMozCrashReason("MOZ_ASSERT" "(" "use->producer() == this"
")"); do { *((volatile int*)__null) = 815; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
816 uses_.pushFront(use);
817 }
818 void addUseUnchecked(MUse* use) {
819 MOZ_ASSERT(use->producer() == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(use->producer() == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(use->producer() == this))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("use->producer() == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 819); AnnotateMozCrashReason("MOZ_ASSERT" "(" "use->producer() == this"
")"); do { *((volatile int*)__null) = 819; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
820 uses_.pushFrontUnchecked(use);
821 }
822 void replaceUse(MUse* old, MUse* now) {
823 MOZ_ASSERT(now->producer() == this)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(now->producer() == this)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(now->producer() == this))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("now->producer() == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 823); AnnotateMozCrashReason("MOZ_ASSERT" "(" "now->producer() == this"
")"); do { *((volatile int*)__null) = 823; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
824 uses_.replace(old, now);
825 }
826
827 // Replace the current instruction by a dominating instruction |dom| in all
828 // uses of the current instruction.
829 void replaceAllUsesWith(MDefinition* dom);
830
831 // Like replaceAllUsesWith, but doesn't set ImplicitlyUsed on |this|'s
832 // operands.
833 void justReplaceAllUsesWith(MDefinition* dom);
834
835 // Replace the current instruction by an optimized-out constant in all uses
836 // of the current instruction. Note, that optimized-out constant should not
837 // be observed, and thus they should not flow in any computation.
838 [[nodiscard]] bool optimizeOutAllUses(TempAllocator& alloc);
839
840 // Replace the current instruction by a dominating instruction |dom| in all
841 // instruction, but keep the current instruction for resume point and
842 // instruction which are recovered on bailouts.
843 void replaceAllLiveUsesWith(MDefinition* dom);
844
845 void setVirtualRegister(uint32_t vreg) {
846 virtualRegister_ = vreg;
847 setLoweredUnchecked();
848 }
849 uint32_t virtualRegister() const {
850 MOZ_ASSERT(isLowered())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isLowered())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isLowered()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("isLowered()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 850); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isLowered()"
")"); do { *((volatile int*)__null) = 850; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
851 return virtualRegister_;
852 }
853
854 public:
855 // Opcode testing and casts.
856 template <typename MIRType>
857 bool is() const {
858 return op() == MIRType::classOpcode;
859 }
860 template <typename MIRType>
861 MIRType* to() {
862 MOZ_ASSERT(this->is<MIRType>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this->is<MIRType>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this->is<MIRType>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"this->is<MIRType>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this->is<MIRType>()"
")"); do { *((volatile int*)__null) = 862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
863 return static_cast<MIRType*>(this);
864 }
865 template <typename MIRType>
866 const MIRType* to() const {
867 MOZ_ASSERT(this->is<MIRType>())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(this->is<MIRType>())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(this->is<MIRType>()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"this->is<MIRType>()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 867); AnnotateMozCrashReason("MOZ_ASSERT" "(" "this->is<MIRType>()"
")"); do { *((volatile int*)__null) = 867; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
868 return static_cast<const MIRType*>(this);
869 }
870#define OPCODE_CASTS(opcode) \
871 bool is##opcode() const { return this->is<M##opcode>(); } \
872 M##opcode* to##opcode() { return this->to<M##opcode>(); } \
873 const M##opcode* to##opcode() const { return this->to<M##opcode>(); }
874 MIR_OPCODE_LIST(OPCODE_CASTS)OPCODE_CASTS(Start)OPCODE_CASTS(OsrEntry)OPCODE_CASTS(Nop)OPCODE_CASTS
(LimitedTruncate)OPCODE_CASTS(Constant)OPCODE_CASTS(WasmNullConstant
)OPCODE_CASTS(WasmFloatConstant)OPCODE_CASTS(Parameter)OPCODE_CASTS
(Callee)OPCODE_CASTS(IsConstructing)OPCODE_CASTS(TableSwitch)
OPCODE_CASTS(Goto)OPCODE_CASTS(Test)OPCODE_CASTS(Return)OPCODE_CASTS
(Throw)OPCODE_CASTS(ThrowWithStack)OPCODE_CASTS(NewArray)OPCODE_CASTS
(NewArrayDynamicLength)OPCODE_CASTS(NewTypedArray)OPCODE_CASTS
(NewTypedArrayDynamicLength)OPCODE_CASTS(NewTypedArrayFromArray
)OPCODE_CASTS(NewTypedArrayFromArrayBuffer)OPCODE_CASTS(NewObject
)OPCODE_CASTS(NewPlainObject)OPCODE_CASTS(NewArrayObject)OPCODE_CASTS
(NewIterator)OPCODE_CASTS(ObjectState)OPCODE_CASTS(ArrayState
)OPCODE_CASTS(BindFunction)OPCODE_CASTS(NewBoundFunction)OPCODE_CASTS
(BoundFunctionNumArgs)OPCODE_CASTS(GuardBoundFunctionIsConstructor
)OPCODE_CASTS(MutateProto)OPCODE_CASTS(InitPropGetterSetter)OPCODE_CASTS
(InitElemGetterSetter)OPCODE_CASTS(Call)OPCODE_CASTS(CallClassHook
)OPCODE_CASTS(ApplyArgs)OPCODE_CASTS(ApplyArgsObj)OPCODE_CASTS
(ApplyArray)OPCODE_CASTS(ConstructArgs)OPCODE_CASTS(ConstructArray
)OPCODE_CASTS(Bail)OPCODE_CASTS(Unreachable)OPCODE_CASTS(EncodeSnapshot
)OPCODE_CASTS(AssertRecoveredOnBailout)OPCODE_CASTS(AssertFloat32
)OPCODE_CASTS(Compare)OPCODE_CASTS(SameValueDouble)OPCODE_CASTS
(SameValue)OPCODE_CASTS(Box)OPCODE_CASTS(Unbox)OPCODE_CASTS(AssertRange
)OPCODE_CASTS(AssertClass)OPCODE_CASTS(AssertShape)OPCODE_CASTS
(CreateThis)OPCODE_CASTS(CreateArgumentsObject)OPCODE_CASTS(CreateInlinedArgumentsObject
)OPCODE_CASTS(GetInlinedArgument)OPCODE_CASTS(GetInlinedArgumentHole
)OPCODE_CASTS(GetArgumentsObjectArg)OPCODE_CASTS(SetArgumentsObjectArg
)OPCODE_CASTS(LoadArgumentsObjectArg)OPCODE_CASTS(LoadArgumentsObjectArgHole
)OPCODE_CASTS(InArgumentsObjectArg)OPCODE_CASTS(ArgumentsObjectLength
)OPCODE_CASTS(ArrayFromArgumentsObject)OPCODE_CASTS(GuardArgumentsObjectFlags
)OPCODE_CASTS(LoadScriptedProxyHandler)OPCODE_CASTS(CheckScriptedProxyGetResult
)OPCODE_CASTS(IdToStringOrSymbol)OPCODE_CASTS(ReturnFromCtor)
OPCODE_CASTS(ToDouble)OPCODE_CASTS(ToFloat32)OPCODE_CASTS(WasmUnsignedToDouble
)OPCODE_CASTS(WasmUnsignedToFloat32)OPCODE_CASTS(WrapInt64ToInt32
)OPCODE_CASTS(ExtendInt32ToInt64)OPCODE_CASTS(WasmBuiltinTruncateToInt64
)OPCODE_CASTS(WasmTruncateToInt64)OPCODE_CASTS(WasmTruncateToInt32
)OPCODE_CASTS(WasmAnyRefFromJSValue)OPCODE_CASTS(WasmAnyRefFromJSObject
)OPCODE_CASTS(WasmAnyRefFromJSString)OPCODE_CASTS(WasmNewI31Ref
)OPCODE_CASTS(WasmI31RefGet)OPCODE_CASTS(Int32ToIntPtr)OPCODE_CASTS
(NonNegativeIntPtrToInt32)OPCODE_CASTS(IntPtrToDouble)OPCODE_CASTS
(AdjustDataViewLength)OPCODE_CASTS(Int64ToFloatingPoint)OPCODE_CASTS
(BuiltinInt64ToFloatingPoint)OPCODE_CASTS(ToNumberInt32)OPCODE_CASTS
(BooleanToInt32)OPCODE_CASTS(TruncateToInt32)OPCODE_CASTS(WasmBuiltinTruncateToInt32
)OPCODE_CASTS(ToBigInt)OPCODE_CASTS(ToInt64)OPCODE_CASTS(TruncateBigIntToInt64
)OPCODE_CASTS(Int64ToBigInt)OPCODE_CASTS(ToString)OPCODE_CASTS
(BitNot)OPCODE_CASTS(TypeOf)OPCODE_CASTS(TypeOfName)OPCODE_CASTS
(TypeOfIs)OPCODE_CASTS(ToAsyncIter)OPCODE_CASTS(ToPropertyKeyCache
)OPCODE_CASTS(BitAnd)OPCODE_CASTS(BitOr)OPCODE_CASTS(BitXor)OPCODE_CASTS
(Lsh)OPCODE_CASTS(Rsh)OPCODE_CASTS(Ursh)OPCODE_CASTS(SignExtendInt32
)OPCODE_CASTS(SignExtendInt64)OPCODE_CASTS(MinMax)OPCODE_CASTS
(MinMaxArray)OPCODE_CASTS(Abs)OPCODE_CASTS(Clz)OPCODE_CASTS(Ctz
)OPCODE_CASTS(Popcnt)OPCODE_CASTS(Sqrt)OPCODE_CASTS(CopySign)
OPCODE_CASTS(Atan2)OPCODE_CASTS(Hypot)OPCODE_CASTS(Pow)OPCODE_CASTS
(PowHalf)OPCODE_CASTS(Random)OPCODE_CASTS(Sign)OPCODE_CASTS(MathFunction
)OPCODE_CASTS(Add)OPCODE_CASTS(Sub)OPCODE_CASTS(Mul)OPCODE_CASTS
(Div)OPCODE_CASTS(WasmBuiltinDivI64)OPCODE_CASTS(Mod)OPCODE_CASTS
(WasmBuiltinModD)OPCODE_CASTS(WasmBuiltinModI64)OPCODE_CASTS(
BigIntAdd)OPCODE_CASTS(BigIntSub)OPCODE_CASTS(BigIntMul)OPCODE_CASTS
(BigIntDiv)OPCODE_CASTS(BigIntMod)OPCODE_CASTS(BigIntPow)OPCODE_CASTS
(BigIntBitAnd)OPCODE_CASTS(BigIntBitOr)OPCODE_CASTS(BigIntBitXor
)OPCODE_CASTS(BigIntLsh)OPCODE_CASTS(BigIntRsh)OPCODE_CASTS(BigIntIncrement
)OPCODE_CASTS(BigIntDecrement)OPCODE_CASTS(BigIntNegate)OPCODE_CASTS
(BigIntBitNot)OPCODE_CASTS(Int32ToStringWithBase)OPCODE_CASTS
(NumberParseInt)OPCODE_CASTS(DoubleParseInt)OPCODE_CASTS(Concat
)OPCODE_CASTS(LinearizeString)OPCODE_CASTS(LinearizeForCharAccess
)OPCODE_CASTS(LinearizeForCodePointAccess)OPCODE_CASTS(ToRelativeStringIndex
)OPCODE_CASTS(CharCodeAt)OPCODE_CASTS(CharCodeAtOrNegative)OPCODE_CASTS
(CodePointAt)OPCODE_CASTS(CodePointAtOrNegative)OPCODE_CASTS(
NegativeToNaN)OPCODE_CASTS(NegativeToUndefined)OPCODE_CASTS(FromCharCode
)OPCODE_CASTS(FromCharCodeEmptyIfNegative)OPCODE_CASTS(FromCharCodeUndefinedIfNegative
)OPCODE_CASTS(FromCodePoint)OPCODE_CASTS(StringIncludes)OPCODE_CASTS
(StringIndexOf)OPCODE_CASTS(StringLastIndexOf)OPCODE_CASTS(StringStartsWith
)OPCODE_CASTS(StringEndsWith)OPCODE_CASTS(StringConvertCase)OPCODE_CASTS
(CharCodeConvertCase)OPCODE_CASTS(StringTrimStartIndex)OPCODE_CASTS
(StringTrimEndIndex)OPCODE_CASTS(StringSplit)OPCODE_CASTS(BoxNonStrictThis
)OPCODE_CASTS(ImplicitThis)OPCODE_CASTS(Phi)OPCODE_CASTS(Beta
)OPCODE_CASTS(NaNToZero)OPCODE_CASTS(OsrValue)OPCODE_CASTS(OsrEnvironmentChain
)OPCODE_CASTS(OsrArgumentsObject)OPCODE_CASTS(OsrReturnValue)
OPCODE_CASTS(BinaryCache)OPCODE_CASTS(UnaryCache)OPCODE_CASTS
(CheckOverRecursed)OPCODE_CASTS(InterruptCheck)OPCODE_CASTS(WasmInterruptCheck
)OPCODE_CASTS(WasmTrap)OPCODE_CASTS(WasmTrapIfNull)OPCODE_CASTS
(LexicalCheck)OPCODE_CASTS(ThrowRuntimeLexicalError)OPCODE_CASTS
(ThrowMsg)OPCODE_CASTS(GlobalDeclInstantiation)OPCODE_CASTS(RegExp
)OPCODE_CASTS(RegExpMatcher)OPCODE_CASTS(RegExpSearcher)OPCODE_CASTS
(RegExpSearcherLastLimit)OPCODE_CASTS(RegExpExecMatch)OPCODE_CASTS
(RegExpExecTest)OPCODE_CASTS(RegExpHasCaptureGroups)OPCODE_CASTS
(RegExpPrototypeOptimizable)OPCODE_CASTS(RegExpInstanceOptimizable
)OPCODE_CASTS(GetFirstDollarIndex)OPCODE_CASTS(StringReplace)
OPCODE_CASTS(Substr)OPCODE_CASTS(ModuleMetadata)OPCODE_CASTS(
DynamicImport)OPCODE_CASTS(Lambda)OPCODE_CASTS(FunctionWithProto
)OPCODE_CASTS(SetFunName)OPCODE_CASTS(Slots)OPCODE_CASTS(Elements
)OPCODE_CASTS(InitializedLength)OPCODE_CASTS(SetInitializedLength
)OPCODE_CASTS(ArrayLength)OPCODE_CASTS(SetArrayLength)OPCODE_CASTS
(FunctionLength)OPCODE_CASTS(FunctionName)OPCODE_CASTS(GetNextEntryForIterator
)OPCODE_CASTS(ArrayBufferByteLength)OPCODE_CASTS(ArrayBufferViewLength
)OPCODE_CASTS(ArrayBufferViewByteOffset)OPCODE_CASTS(ArrayBufferViewElements
)OPCODE_CASTS(ResizableTypedArrayByteOffsetMaybeOutOfBounds)OPCODE_CASTS
(ResizableTypedArrayLength)OPCODE_CASTS(ResizableDataViewByteLength
)OPCODE_CASTS(GrowableSharedArrayBufferByteLength)OPCODE_CASTS
(TypedArrayElementSize)OPCODE_CASTS(GuardHasAttachedArrayBuffer
)OPCODE_CASTS(GuardResizableArrayBufferViewInBounds)OPCODE_CASTS
(GuardResizableArrayBufferViewInBoundsOrDetached)OPCODE_CASTS
(GuardNumberToIntPtrIndex)OPCODE_CASTS(KeepAliveObject)OPCODE_CASTS
(DebugEnterGCUnsafeRegion)OPCODE_CASTS(DebugLeaveGCUnsafeRegion
)OPCODE_CASTS(Not)OPCODE_CASTS(BoundsCheck)OPCODE_CASTS(BoundsCheckLower
)OPCODE_CASTS(SpectreMaskIndex)OPCODE_CASTS(LoadElement)OPCODE_CASTS
(LoadElementAndUnbox)OPCODE_CASTS(LoadElementHole)OPCODE_CASTS
(StoreElement)OPCODE_CASTS(StoreHoleValueElement)OPCODE_CASTS
(StoreElementHole)OPCODE_CASTS(ArrayPopShift)OPCODE_CASTS(ArrayPush
)OPCODE_CASTS(ArraySlice)OPCODE_CASTS(ArgumentsSlice)OPCODE_CASTS
(FrameArgumentsSlice)OPCODE_CASTS(InlineArgumentsSlice)OPCODE_CASTS
(NormalizeSliceTerm)OPCODE_CASTS(ArrayJoin)OPCODE_CASTS(ObjectKeys
)OPCODE_CASTS(ObjectKeysLength)OPCODE_CASTS(LoadUnboxedScalar
)OPCODE_CASTS(LoadDataViewElement)OPCODE_CASTS(LoadTypedArrayElementHole
)OPCODE_CASTS(StoreUnboxedScalar)OPCODE_CASTS(StoreDataViewElement
)OPCODE_CASTS(StoreTypedArrayElementHole)OPCODE_CASTS(EffectiveAddress
)OPCODE_CASTS(ClampToUint8)OPCODE_CASTS(LoadFixedSlot)OPCODE_CASTS
(LoadFixedSlotAndUnbox)OPCODE_CASTS(LoadDynamicSlotAndUnbox)OPCODE_CASTS
(StoreFixedSlot)OPCODE_CASTS(GetPropertyCache)OPCODE_CASTS(HomeObjectSuperBase
)OPCODE_CASTS(GetPropSuperCache)OPCODE_CASTS(BindNameCache)OPCODE_CASTS
(CallBindVar)OPCODE_CASTS(GuardShape)OPCODE_CASTS(GuardFuse)OPCODE_CASTS
(GuardMultipleShapes)OPCODE_CASTS(GuardProto)OPCODE_CASTS(GuardNullProto
)OPCODE_CASTS(GuardIsNativeObject)OPCODE_CASTS(GuardGlobalGeneration
)OPCODE_CASTS(GuardIsProxy)OPCODE_CASTS(GuardIsNotDOMProxy)OPCODE_CASTS
(GuardIsNotProxy)OPCODE_CASTS(ProxyGet)OPCODE_CASTS(ProxyGetByValue
)OPCODE_CASTS(ProxyHasProp)OPCODE_CASTS(ProxySet)OPCODE_CASTS
(ProxySetByValue)OPCODE_CASTS(CallSetArrayLength)OPCODE_CASTS
(MegamorphicLoadSlot)OPCODE_CASTS(MegamorphicLoadSlotByValue)
OPCODE_CASTS(MegamorphicStoreSlot)OPCODE_CASTS(MegamorphicHasProp
)OPCODE_CASTS(SmallObjectVariableKeyHasProp)OPCODE_CASTS(GuardIsNotArrayBufferMaybeShared
)OPCODE_CASTS(GuardIsTypedArray)OPCODE_CASTS(GuardIsFixedLengthTypedArray
)OPCODE_CASTS(GuardIsResizableTypedArray)OPCODE_CASTS(GuardHasProxyHandler
)OPCODE_CASTS(NurseryObject)OPCODE_CASTS(GuardValue)OPCODE_CASTS
(GuardNullOrUndefined)OPCODE_CASTS(GuardIsNotObject)OPCODE_CASTS
(GuardFunctionFlags)OPCODE_CASTS(GuardFunctionIsNonBuiltinCtor
)OPCODE_CASTS(GuardFunctionKind)OPCODE_CASTS(GuardFunctionScript
)OPCODE_CASTS(GuardObjectIdentity)OPCODE_CASTS(GuardSpecificFunction
)OPCODE_CASTS(GuardSpecificAtom)OPCODE_CASTS(GuardSpecificSymbol
)OPCODE_CASTS(GuardSpecificInt32)OPCODE_CASTS(GuardStringToIndex
)OPCODE_CASTS(GuardStringToInt32)OPCODE_CASTS(GuardStringToDouble
)OPCODE_CASTS(GuardNoDenseElements)OPCODE_CASTS(GuardTagNotEqual
)OPCODE_CASTS(LoadDynamicSlot)OPCODE_CASTS(FunctionEnvironment
)OPCODE_CASTS(NewLexicalEnvironmentObject)OPCODE_CASTS(NewClassBodyEnvironmentObject
)OPCODE_CASTS(NewVarEnvironmentObject)OPCODE_CASTS(HomeObject
)OPCODE_CASTS(AddAndStoreSlot)OPCODE_CASTS(AllocateAndStoreSlot
)OPCODE_CASTS(AddSlotAndCallAddPropHook)OPCODE_CASTS(StoreDynamicSlot
)OPCODE_CASTS(GetNameCache)OPCODE_CASTS(CallGetIntrinsicValue
)OPCODE_CASTS(DeleteProperty)OPCODE_CASTS(DeleteElement)OPCODE_CASTS
(SetPropertyCache)OPCODE_CASTS(MegamorphicSetElement)OPCODE_CASTS
(SetDOMProperty)OPCODE_CASTS(GetDOMProperty)OPCODE_CASTS(GetDOMMember
)OPCODE_CASTS(ObjectToIterator)OPCODE_CASTS(ValueToIterator)OPCODE_CASTS
(IteratorHasIndices)OPCODE_CASTS(LoadSlotByIteratorIndex)OPCODE_CASTS
(StoreSlotByIteratorIndex)OPCODE_CASTS(LoadDOMExpandoValue)OPCODE_CASTS
(LoadDOMExpandoValueGuardGeneration)OPCODE_CASTS(LoadDOMExpandoValueIgnoreGeneration
)OPCODE_CASTS(GuardDOMExpandoMissingOrGuardShape)OPCODE_CASTS
(StringLength)OPCODE_CASTS(Floor)OPCODE_CASTS(Ceil)OPCODE_CASTS
(Round)OPCODE_CASTS(Trunc)OPCODE_CASTS(NearbyInt)OPCODE_CASTS
(GetIteratorCache)OPCODE_CASTS(OptimizeSpreadCallCache)OPCODE_CASTS
(IteratorMore)OPCODE_CASTS(IsNoIter)OPCODE_CASTS(IteratorEnd)
OPCODE_CASTS(CloseIterCache)OPCODE_CASTS(OptimizeGetIteratorCache
)OPCODE_CASTS(InCache)OPCODE_CASTS(InArray)OPCODE_CASTS(GuardElementNotHole
)OPCODE_CASTS(NewPrivateName)OPCODE_CASTS(CheckPrivateFieldCache
)OPCODE_CASTS(HasOwnCache)OPCODE_CASTS(InstanceOf)OPCODE_CASTS
(InstanceOfCache)OPCODE_CASTS(ArgumentsLength)OPCODE_CASTS(GetFrameArgument
)OPCODE_CASTS(GetFrameArgumentHole)OPCODE_CASTS(NewTarget)OPCODE_CASTS
(Rest)OPCODE_CASTS(PostWriteBarrier)OPCODE_CASTS(PostWriteElementBarrier
)OPCODE_CASTS(AssertCanElidePostWriteBarrier)OPCODE_CASTS(NewNamedLambdaObject
)OPCODE_CASTS(NewCallObject)OPCODE_CASTS(NewStringObject)OPCODE_CASTS
(IsCallable)OPCODE_CASTS(IsConstructor)OPCODE_CASTS(IsCrossRealmArrayConstructor
)OPCODE_CASTS(IsObject)OPCODE_CASTS(IsNullOrUndefined)OPCODE_CASTS
(HasClass)OPCODE_CASTS(GuardToClass)OPCODE_CASTS(GuardToEitherClass
)OPCODE_CASTS(GuardToFunction)OPCODE_CASTS(IsArray)OPCODE_CASTS
(IsTypedArray)OPCODE_CASTS(ObjectClassToString)OPCODE_CASTS(CheckReturn
)OPCODE_CASTS(CheckThis)OPCODE_CASTS(AsyncResolve)OPCODE_CASTS
(AsyncReject)OPCODE_CASTS(GeneratorReturn)OPCODE_CASTS(AsyncAwait
)OPCODE_CASTS(CheckThisReinit)OPCODE_CASTS(Generator)OPCODE_CASTS
(CanSkipAwait)OPCODE_CASTS(MaybeExtractAwaitValue)OPCODE_CASTS
(IncrementWarmUpCounter)OPCODE_CASTS(AtomicIsLockFree)OPCODE_CASTS
(CompareExchangeTypedArrayElement)OPCODE_CASTS(AtomicExchangeTypedArrayElement
)OPCODE_CASTS(AtomicTypedArrayElementBinop)OPCODE_CASTS(Debugger
)OPCODE_CASTS(CheckIsObj)OPCODE_CASTS(CheckObjCoercible)OPCODE_CASTS
(CheckClassHeritage)OPCODE_CASTS(DebugCheckSelfHosted)OPCODE_CASTS
(IsPackedArray)OPCODE_CASTS(GuardArrayIsPacked)OPCODE_CASTS(GetPrototypeOf
)OPCODE_CASTS(ObjectWithProto)OPCODE_CASTS(ObjectStaticProto)
OPCODE_CASTS(ConstantProto)OPCODE_CASTS(BuiltinObject)OPCODE_CASTS
(SuperFunction)OPCODE_CASTS(InitHomeObject)OPCODE_CASTS(IsTypedArrayConstructor
)OPCODE_CASTS(LoadValueTag)OPCODE_CASTS(LoadWrapperTarget)OPCODE_CASTS
(GuardHasGetterSetter)OPCODE_CASTS(GuardIsExtensible)OPCODE_CASTS
(GuardInt32IsNonNegative)OPCODE_CASTS(GuardInt32Range)OPCODE_CASTS
(GuardIndexIsNotDenseElement)OPCODE_CASTS(GuardIndexIsValidUpdateOrAdd
)OPCODE_CASTS(CallAddOrUpdateSparseElement)OPCODE_CASTS(CallGetSparseElement
)OPCODE_CASTS(CallNativeGetElement)OPCODE_CASTS(CallNativeGetElementSuper
)OPCODE_CASTS(CallObjectHasSparseElement)OPCODE_CASTS(BigIntAsIntN
)OPCODE_CASTS(BigIntAsUintN)OPCODE_CASTS(GuardNonGCThing)OPCODE_CASTS
(ToHashableNonGCThing)OPCODE_CASTS(ToHashableString)OPCODE_CASTS
(ToHashableValue)OPCODE_CASTS(HashNonGCThing)OPCODE_CASTS(HashString
)OPCODE_CASTS(HashSymbol)OPCODE_CASTS(HashBigInt)OPCODE_CASTS
(HashObject)OPCODE_CASTS(HashValue)OPCODE_CASTS(SetObjectHasNonBigInt
)OPCODE_CASTS(SetObjectHasBigInt)OPCODE_CASTS(SetObjectHasValue
)OPCODE_CASTS(SetObjectHasValueVMCall)OPCODE_CASTS(SetObjectSize
)OPCODE_CASTS(MapObjectHasNonBigInt)OPCODE_CASTS(MapObjectHasBigInt
)OPCODE_CASTS(MapObjectHasValue)OPCODE_CASTS(MapObjectHasValueVMCall
)OPCODE_CASTS(MapObjectGetNonBigInt)OPCODE_CASTS(MapObjectGetBigInt
)OPCODE_CASTS(MapObjectGetValue)OPCODE_CASTS(MapObjectGetValueVMCall
)OPCODE_CASTS(MapObjectSize)OPCODE_CASTS(PostIntPtrConversion
)OPCODE_CASTS(WasmNeg)OPCODE_CASTS(WasmBinaryBitwise)OPCODE_CASTS
(WasmLoadInstance)OPCODE_CASTS(WasmStoreInstance)OPCODE_CASTS
(WasmHeapReg)OPCODE_CASTS(WasmBoundsCheck)OPCODE_CASTS(WasmBoundsCheckRange32
)OPCODE_CASTS(WasmExtendU32Index)OPCODE_CASTS(WasmWrapU32Index
)OPCODE_CASTS(WasmAddOffset)OPCODE_CASTS(WasmAlignmentCheck)OPCODE_CASTS
(WasmLoad)OPCODE_CASTS(WasmStore)OPCODE_CASTS(AsmJSLoadHeap)OPCODE_CASTS
(AsmJSStoreHeap)OPCODE_CASTS(WasmFence)OPCODE_CASTS(WasmCompareExchangeHeap
)OPCODE_CASTS(WasmAtomicExchangeHeap)OPCODE_CASTS(WasmAtomicBinopHeap
)OPCODE_CASTS(WasmLoadInstanceDataField)OPCODE_CASTS(WasmLoadGlobalCell
)OPCODE_CASTS(WasmLoadTableElement)OPCODE_CASTS(WasmStoreInstanceDataField
)OPCODE_CASTS(WasmStoreGlobalCell)OPCODE_CASTS(WasmStoreStackResult
)OPCODE_CASTS(WasmDerivedPointer)OPCODE_CASTS(WasmDerivedIndexPointer
)OPCODE_CASTS(WasmStoreRef)OPCODE_CASTS(WasmPostWriteBarrierImmediate
)OPCODE_CASTS(WasmPostWriteBarrierIndex)OPCODE_CASTS(WasmParameter
)OPCODE_CASTS(WasmReturn)OPCODE_CASTS(WasmReturnVoid)OPCODE_CASTS
(WasmStackArg)OPCODE_CASTS(WasmRegisterResult)OPCODE_CASTS(WasmFloatRegisterResult
)OPCODE_CASTS(WasmRegister64Result)OPCODE_CASTS(WasmStackResultArea
)OPCODE_CASTS(WasmStackResult)OPCODE_CASTS(WasmCallCatchable)
OPCODE_CASTS(WasmCallUncatchable)OPCODE_CASTS(WasmCallLandingPrePad
)OPCODE_CASTS(WasmReturnCall)OPCODE_CASTS(WasmSelect)OPCODE_CASTS
(WasmReinterpret)OPCODE_CASTS(Rotate)OPCODE_CASTS(WasmStackSwitchToMain
)OPCODE_CASTS(WasmStackSwitchToSuspendable)OPCODE_CASTS(WasmStackContinueOnSuspendable
)OPCODE_CASTS(WasmBinarySimd128)OPCODE_CASTS(WasmBinarySimd128WithConstant
)OPCODE_CASTS(WasmShiftSimd128)OPCODE_CASTS(WasmShuffleSimd128
)OPCODE_CASTS(WasmReplaceLaneSimd128)OPCODE_CASTS(WasmUnarySimd128
)OPCODE_CASTS(WasmTernarySimd128)OPCODE_CASTS(WasmScalarToSimd128
)OPCODE_CASTS(WasmReduceSimd128)OPCODE_CASTS(WasmLoadLaneSimd128
)OPCODE_CASTS(WasmStoreLaneSimd128)OPCODE_CASTS(UnreachableResult
)OPCODE_CASTS(IonToWasmCall)OPCODE_CASTS(WasmLoadField)OPCODE_CASTS
(WasmLoadFieldKA)OPCODE_CASTS(WasmLoadElementKA)OPCODE_CASTS(
WasmStoreFieldKA)OPCODE_CASTS(WasmStoreFieldRefKA)OPCODE_CASTS
(WasmStoreElementKA)OPCODE_CASTS(WasmStoreElementRefKA)OPCODE_CASTS
(WasmRefIsSubtypeOfConcrete)OPCODE_CASTS(WasmRefIsSubtypeOfAbstract
)OPCODE_CASTS(WasmNewStructObject)OPCODE_CASTS(WasmNewArrayObject
)
875#undef OPCODE_CASTS
876
877 inline MConstant* maybeConstantValue();
878
879 inline MInstruction* toInstruction();
880 inline const MInstruction* toInstruction() const;
881 bool isInstruction() const { return !isPhi(); }
882
883 virtual bool isControlInstruction() const { return false; }
884 inline MControlInstruction* toControlInstruction();
885
886 void setResultType(MIRType type) { resultType_ = type; }
887 virtual AliasSet getAliasSet() const {
888 // Instructions are effectful by default.
889 return AliasSet::Store(AliasSet::Any);
890 }
891
892#ifdef DEBUG1
893 bool hasDefaultAliasSet() const {
894 AliasSet set = getAliasSet();
895 return set.isStore() && set.flags() == AliasSet::Flag::Any;
896 }
897#endif
898
899 MDefinition* dependency() const {
900 if (getAliasSet().isStore()) {
901 return nullptr;
902 }
903 return loadDependency_;
904 }
905 void setDependency(MDefinition* dependency) {
906 MOZ_ASSERT(!getAliasSet().isStore())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!getAliasSet().isStore())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!getAliasSet().isStore()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("!getAliasSet().isStore()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 906); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!getAliasSet().isStore()"
")"); do { *((volatile int*)__null) = 906; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
907 loadDependency_ = dependency;
908 }
909 bool isEffectful() const { return getAliasSet().isStore(); }
910
911#ifdef DEBUG1
912 bool needsResumePoint() const {
913 // Return whether this instruction should have its own resume point.
914 return isEffectful();
915 }
916#endif
917
918 enum class AliasType : uint32_t { NoAlias = 0, MayAlias = 1, MustAlias = 2 };
919 virtual AliasType mightAlias(const MDefinition* store) const {
920 // Return whether this load may depend on the specified store, given
921 // that the alias sets intersect. This may be refined to exclude
922 // possible aliasing in cases where alias set flags are too imprecise.
923 if (!(getAliasSet().flags() & store->getAliasSet().flags())) {
924 return AliasType::NoAlias;
925 }
926 MOZ_ASSERT(!isEffectful() && store->isEffectful())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isEffectful() && store->isEffectful())>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!isEffectful() && store->isEffectful())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!isEffectful() && store->isEffectful()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 926); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isEffectful() && store->isEffectful()"
")"); do { *((volatile int*)__null) = 926; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
927 return AliasType::MayAlias;
928 }
929
930 virtual bool canRecoverOnBailout() const { return false; }
931};
932
933// An MUseDefIterator walks over uses in a definition, skipping any use that is
934// not a definition. Items from the use list must not be deleted during
935// iteration.
936class MUseDefIterator {
937 const MDefinition* def_;
938 MUseIterator current_;
939
940 MUseIterator search(MUseIterator start) {
941 MUseIterator i(start);
942 for (; i != def_->usesEnd(); i++) {
943 if (i->consumer()->isDefinition()) {
944 return i;
945 }
946 }
947 return def_->usesEnd();
948 }
949
950 public:
951 explicit MUseDefIterator(const MDefinition* def)
952 : def_(def), current_(search(def->usesBegin())) {}
953
954 explicit operator bool() const { return current_ != def_->usesEnd(); }
955 MUseDefIterator operator++() {
956 MOZ_ASSERT(current_ != def_->usesEnd())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(current_ != def_->usesEnd())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(current_ != def_->usesEnd
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("current_ != def_->usesEnd()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 956); AnnotateMozCrashReason("MOZ_ASSERT" "(" "current_ != def_->usesEnd()"
")"); do { *((volatile int*)__null) = 956; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
957 ++current_;
958 current_ = search(current_);
959 return *this;
960 }
961 MUseDefIterator operator++(int) {
962 MUseDefIterator old(*this);
963 operator++();
964 return old;
965 }
966 MUse* use() const { return *current_; }
967 MDefinition* def() const { return current_->consumer()->toDefinition(); }
968};
969
970// Helper class to check that GC pointers embedded in MIR instructions are not
971// in the nursery. Off-thread compilation and nursery GCs can happen in
972// parallel. Nursery pointers are handled with MNurseryObject and the
973// nurseryObjects lists in WarpSnapshot and IonScript.
974//
975// These GC things are rooted through the WarpSnapshot. Compacting GCs cancel
976// off-thread compilations.
977template <typename T>
978class CompilerGCPointer {
979 js::gc::Cell* ptr_;
980
981 public:
982 explicit CompilerGCPointer(T ptr) : ptr_(ptr) {
983 MOZ_ASSERT_IF(ptr, !IsInsideNursery(ptr))do { if (ptr) { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(!IsInsideNursery(ptr))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsInsideNursery(ptr)))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("!IsInsideNursery(ptr)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 983); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsInsideNursery(ptr)"
")"); do { *((volatile int*)__null) = 983; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
984 MOZ_ASSERT_IF(!CurrentThreadIsIonCompiling(), TlsContext.get()->suppressGC)do { if (!CurrentThreadIsIonCompiling()) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(TlsContext
.get()->suppressGC)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(TlsContext.get()->suppressGC
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"TlsContext.get()->suppressGC", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 984); AnnotateMozCrashReason("MOZ_ASSERT" "(" "TlsContext.get()->suppressGC"
")"); do { *((volatile int*)__null) = 984; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
985 }
986
987 operator T() const { return static_cast<T>(ptr_); }
988 T operator->() const { return static_cast<T>(ptr_); }
989
990 private:
991 CompilerGCPointer() = delete;
992 CompilerGCPointer(const CompilerGCPointer<T>&) = delete;
993 CompilerGCPointer<T>& operator=(const CompilerGCPointer<T>&) = delete;
994};
995
996using CompilerObject = CompilerGCPointer<JSObject*>;
997using CompilerNativeObject = CompilerGCPointer<NativeObject*>;
998using CompilerFunction = CompilerGCPointer<JSFunction*>;
999using CompilerBaseScript = CompilerGCPointer<BaseScript*>;
1000using CompilerPropertyName = CompilerGCPointer<PropertyName*>;
1001using CompilerShape = CompilerGCPointer<Shape*>;
1002using CompilerGetterSetter = CompilerGCPointer<GetterSetter*>;
1003
1004// An instruction is an SSA name that is inserted into a basic block's IR
1005// stream.
1006class MInstruction : public MDefinition, public InlineListNode<MInstruction> {
1007 MResumePoint* resumePoint_;
1008
1009 protected:
1010 // All MInstructions are using the "MFoo::New(alloc)" notation instead of
1011 // the TempObject new operator. This code redefines the new operator as
1012 // protected, and delegates to the TempObject new operator. Thus, the
1013 // following code prevents calls to "new(alloc) MFoo" outside the MFoo
1014 // members.
1015 inline void* operator new(size_t nbytes,
1016 TempAllocator::Fallible view) noexcept(true) {
1017 return TempObject::operator new(nbytes, view);
1018 }
1019 inline void* operator new(size_t nbytes, TempAllocator& alloc) {
1020 return TempObject::operator new(nbytes, alloc);
1021 }
1022 template <class T>
1023 inline void* operator new(size_t nbytes, T* pos) {
1024 return TempObject::operator new(nbytes, pos);
1025 }
1026
1027 public:
1028 explicit MInstruction(Opcode op) : MDefinition(op), resumePoint_(nullptr) {}
1029
1030 // Copying an instruction leaves the resume point as empty.
1031 explicit MInstruction(const MInstruction& other)
1032 : MDefinition(other), resumePoint_(nullptr) {}
1033
1034 // Convenient function used for replacing a load by the value of the store
1035 // if the types are match, and boxing the value if they do not match.
1036 MDefinition* foldsToStore(TempAllocator& alloc);
1037
1038 void setResumePoint(MResumePoint* resumePoint);
1039 void stealResumePoint(MInstruction* other);
1040
1041 void moveResumePointAsEntry();
1042 void clearResumePoint();
1043 MResumePoint* resumePoint() const { return resumePoint_; }
1044
1045 // For instructions which can be cloned with new inputs, with all other
1046 // information being the same. clone() implementations do not need to worry
1047 // about cloning generic MInstruction/MDefinition state like flags and
1048 // resume points.
1049 virtual bool canClone() const { return false; }
1050 virtual MInstruction* clone(TempAllocator& alloc,
1051 const MDefinitionVector& inputs) const {
1052 MOZ_CRASH()do { do { } while (false); MOZ_ReportCrash("" , "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1052); AnnotateMozCrashReason("MOZ_CRASH(" ")"); do { *((volatile
int*)__null) = 1052; __attribute__((nomerge)) ::abort(); } while
(false); } while (false)
;
1053 }
1054
1055 // Instructions needing to hook into type analysis should return a
1056 // TypePolicy.
1057 virtual const TypePolicy* typePolicy() = 0;
1058 virtual MIRType typePolicySpecialization() = 0;
1059};
1060
1061// Note: GenerateOpcodeFiles.py generates MOpcodesGenerated.h based on the
1062// INSTRUCTION_HEADER* macros.
1063#define INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(opcode)static const Opcode classOpcode = Opcode::opcode; using MThisOpcode
= Mopcode;
\
1064 static const Opcode classOpcode = Opcode::opcode; \
1065 using MThisOpcode = M##opcode;
1066
1067#define INSTRUCTION_HEADER(opcode) \
1068 INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(opcode)static const Opcode classOpcode = Opcode::opcode; using MThisOpcode
= Mopcode;
\
1069 virtual const TypePolicy* typePolicy() override; \
1070 virtual MIRType typePolicySpecialization() override;
1071
1072#define ALLOW_CLONE(typename)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) typename
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
\
1073 bool canClone() const override { return true; } \
1074 MInstruction* clone(TempAllocator& alloc, const MDefinitionVector& inputs) \
1075 const override { \
1076 MInstruction* res = new (alloc) typename(*this); \
1077 for (size_t i = 0; i < numOperands(); i++) \
1078 res->replaceOperand(i, inputs[i]); \
1079 return res; \
1080 }
1081
1082// Adds MFoo::New functions which are mirroring the arguments of the
1083// constructors. Opcodes which are using this macro can be called with a
1084// TempAllocator, or the fallible version of the TempAllocator.
1085#define 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)...); }
\
1086 template <typename... Args> \
1087 static MThisOpcode* New(TempAllocator& alloc, Args&&... args) { \
1088 return new (alloc) MThisOpcode(std::forward<Args>(args)...); \
1089 } \
1090 template <typename... Args> \
1091 static MThisOpcode* New(TempAllocator::Fallible alloc, Args&&... args) { \
1092 return new (alloc) MThisOpcode(std::forward<Args>(args)...); \
1093 }
1094
1095// These macros are used as a syntactic sugar for writting getOperand
1096// accessors. They are meant to be used in the body of MIR Instructions as
1097// follows:
1098//
1099// public:
1100// INSTRUCTION_HEADER(Foo)
1101// NAMED_OPERANDS((0, lhs), (1, rhs))
1102//
1103// The above example defines 2 accessors, one named "lhs" accessing the first
1104// operand, and a one named "rhs" accessing the second operand.
1105#define NAMED_OPERAND_ACCESSOR(Index, Name)MDefinition* Name() const { return getOperand(Index); } \
1106 MDefinition* Name() const { return getOperand(Index); }
1107#define NAMED_OPERAND_ACCESSOR_APPLY(Args)NAMED_OPERAND_ACCESSOR Args NAMED_OPERAND_ACCESSOR Args
1108#define NAMED_OPERANDS(...)NAMED_OPERAND_ACCESSOR ... \
1109 MOZ_FOR_EACH(NAMED_OPERAND_ACCESSOR_APPLY, (), (__VA_ARGS__))NAMED_OPERAND_ACCESSOR __VA_ARGS__
1110
1111template <size_t Arity>
1112class MAryInstruction : public MInstruction {
1113 mozilla::Array<MUse, Arity> operands_;
1114
1115 protected:
1116 MUse* getUseFor(size_t index) final { return &operands_[index]; }
1117 const MUse* getUseFor(size_t index) const final { return &operands_[index]; }
1118 void initOperand(size_t index, MDefinition* operand) {
1119 operands_[index].init(operand, this);
1120 }
1121
1122 public:
1123 MDefinition* getOperand(size_t index) const final {
1124 return operands_[index].producer();
1125 }
1126 size_t numOperands() const final { return Arity; }
1127#ifdef DEBUG1
1128 static const size_t staticNumOperands = Arity;
1129#endif
1130 size_t indexOf(const MUse* u) const final {
1131 MOZ_ASSERT(u >= &operands_[0])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u >= &operands_[0])>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u >= &operands_[0])))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("u >= &operands_[0]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u >= &operands_[0]"
")"); do { *((volatile int*)__null) = 1131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1132 MOZ_ASSERT(u <= &operands_[numOperands() - 1])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u <= &operands_[numOperands() - 1])>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(u <= &operands_[numOperands() - 1]))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("u <= &operands_[numOperands() - 1]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1132); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u <= &operands_[numOperands() - 1]"
")"); do { *((volatile int*)__null) = 1132; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1133 return u - &operands_[0];
1134 }
1135 void replaceOperand(size_t index, MDefinition* operand) final {
1136 operands_[index].replaceProducer(operand);
1137 }
1138
1139 explicit MAryInstruction(Opcode op) : MInstruction(op) {}
1140
1141 explicit MAryInstruction(const MAryInstruction<Arity>& other)
1142 : MInstruction(other) {
1143 for (int i = 0; i < (int)Arity;
1144 i++) { // N.B. use |int| to avoid warnings when Arity == 0
1145 operands_[i].init(other.operands_[i].producer(), this);
1146 }
1147 }
1148};
1149
1150class MNullaryInstruction : public MAryInstruction<0>,
1151 public NoTypePolicy::Data {
1152 protected:
1153 explicit MNullaryInstruction(Opcode op) : MAryInstruction(op) {}
1154
1155 HashNumber valueHash() const override;
1156};
1157
1158class MUnaryInstruction : public MAryInstruction<1> {
1159 protected:
1160 MUnaryInstruction(Opcode op, MDefinition* ins) : MAryInstruction(op) {
1161 initOperand(0, ins);
1162 }
1163
1164 HashNumber valueHash() const override;
1165
1166 public:
1167 NAMED_OPERANDS((0, input))MDefinition* input() const { return getOperand(0); }
1168};
1169
1170class MBinaryInstruction : public MAryInstruction<2> {
1171 protected:
1172 MBinaryInstruction(Opcode op, MDefinition* left, MDefinition* right)
1173 : MAryInstruction(op) {
1174 initOperand(0, left);
1175 initOperand(1, right);
1176 }
1177
1178 public:
1179 NAMED_OPERANDS((0, lhs), (1, rhs))MDefinition* lhs() const { return getOperand(0); } MDefinition
* rhs() const { return getOperand(1); }
1180
1181 protected:
1182 HashNumber valueHash() const override;
1183
1184 bool binaryCongruentTo(const MDefinition* ins) const {
1185 if (op() != ins->op()) {
1186 return false;
1187 }
1188
1189 if (type() != ins->type()) {
1190 return false;
1191 }
1192
1193 if (isEffectful() || ins->isEffectful()) {
1194 return false;
1195 }
1196
1197 const MDefinition* left = getOperand(0);
1198 const MDefinition* right = getOperand(1);
1199 if (isCommutative() && left->id() > right->id()) {
1200 std::swap(left, right);
1201 }
1202
1203 const MBinaryInstruction* bi = static_cast<const MBinaryInstruction*>(ins);
1204 const MDefinition* insLeft = bi->getOperand(0);
1205 const MDefinition* insRight = bi->getOperand(1);
1206 if (bi->isCommutative() && insLeft->id() > insRight->id()) {
1207 std::swap(insLeft, insRight);
1208 }
1209
1210 return left == insLeft && right == insRight;
1211 }
1212
1213 public:
1214 // Return if the operands to this instruction are both unsigned.
1215 static bool unsignedOperands(MDefinition* left, MDefinition* right);
1216 bool unsignedOperands();
1217
1218 // Replace any wrapping operands with the underlying int32 operands
1219 // in case of unsigned operands.
1220 void replaceWithUnsignedOperands();
1221};
1222
1223class MTernaryInstruction : public MAryInstruction<3> {
1224 protected:
1225 MTernaryInstruction(Opcode op, MDefinition* first, MDefinition* second,
1226 MDefinition* third)
1227 : MAryInstruction(op) {
1228 initOperand(0, first);
1229 initOperand(1, second);
1230 initOperand(2, third);
1231 }
1232
1233 HashNumber valueHash() const override;
1234};
1235
1236class MQuaternaryInstruction : public MAryInstruction<4> {
1237 protected:
1238 MQuaternaryInstruction(Opcode op, MDefinition* first, MDefinition* second,
1239 MDefinition* third, MDefinition* fourth)
1240 : MAryInstruction(op) {
1241 initOperand(0, first);
1242 initOperand(1, second);
1243 initOperand(2, third);
1244 initOperand(3, fourth);
1245 }
1246
1247 HashNumber valueHash() const override;
1248};
1249
1250template <class T>
1251class MVariadicT : public T {
1252 FixedList<MUse> operands_;
1253
1254 protected:
1255 explicit MVariadicT(typename T::Opcode op) : T(op) {}
1256 [[nodiscard]] bool init(TempAllocator& alloc, size_t length) {
1257 return operands_.init(alloc, length);
1258 }
1259 void initOperand(size_t index, MDefinition* operand) {
1260 // FixedList doesn't initialize its elements, so do an unchecked init.
1261 operands_[index].initUnchecked(operand, this);
1262 }
1263 MUse* getUseFor(size_t index) final { return &operands_[index]; }
1264 const MUse* getUseFor(size_t index) const final { return &operands_[index]; }
1265
1266 // The MWasmCallBase mixin performs initialization for it's subclasses.
1267 friend class MWasmCallBase;
1268
1269 public:
1270 // Will assert if called before initialization.
1271 MDefinition* getOperand(size_t index) const final {
1272 return operands_[index].producer();
1273 }
1274 size_t numOperands() const final { return operands_.length(); }
1275 size_t indexOf(const MUse* u) const final {
1276 MOZ_ASSERT(u >= &operands_[0])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u >= &operands_[0])>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u >= &operands_[0])))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("u >= &operands_[0]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u >= &operands_[0]"
")"); do { *((volatile int*)__null) = 1276; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1277 MOZ_ASSERT(u <= &operands_[numOperands() - 1])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u <= &operands_[numOperands() - 1])>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(u <= &operands_[numOperands() - 1]))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("u <= &operands_[numOperands() - 1]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u <= &operands_[numOperands() - 1]"
")"); do { *((volatile int*)__null) = 1277; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1278 return u - &operands_[0];
1279 }
1280 void replaceOperand(size_t index, MDefinition* operand) final {
1281 operands_[index].replaceProducer(operand);
1282 }
1283};
1284
1285// An instruction with a variable number of operands. Note that the
1286// MFoo::New constructor for variadic instructions fallibly
1287// initializes the operands_ array and must be checked for OOM.
1288using MVariadicInstruction = MVariadicT<MInstruction>;
1289
1290// All barriered operations:
1291// - MCompareExchangeTypedArrayElement
1292// - MExchangeTypedArrayElement
1293// - MAtomicTypedArrayElementBinop
1294// - MGrowableSharedArrayBufferByteLength
1295//
1296// And operations which are optionally barriered:
1297// - MLoadUnboxedScalar
1298// - MStoreUnboxedScalar
1299// - MResizableTypedArrayLength
1300// - MResizableDataViewByteLength
1301//
1302// Must have the following attributes:
1303//
1304// - Not movable
1305// - Not removable
1306// - Not congruent with any other instruction
1307// - Effectful (they alias every TypedArray store)
1308//
1309// The intended effect of those constraints is to prevent all loads and stores
1310// preceding the barriered operation from being moved to after the barriered
1311// operation, and vice versa, and to prevent the barriered operation from being
1312// removed or hoisted.
1313
1314enum class MemoryBarrierRequirement : bool {
1315 NotRequired,
1316 Required,
1317};
1318
1319MIR_OPCODE_CLASS_GENERATEDclass MStart : public MNullaryInstruction { explicit MStart()
: MNullaryInstruction(classOpcode) { } public: INSTRUCTION_HEADER
(Start) template <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)...); }};class MOsrEntry
: public MNullaryInstruction { explicit MOsrEntry() : MNullaryInstruction
(classOpcode) { setResultType(MIRType::Pointer); } public: INSTRUCTION_HEADER
(OsrEntry) template <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)...); }};class MNop
: public MNullaryInstruction { explicit MNop() : MNullaryInstruction
(classOpcode) { } public: INSTRUCTION_HEADER(Nop) template <
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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool canClone() const override
{ return true; } MInstruction* clone(TempAllocator& alloc
, const MDefinitionVector& inputs) const override { MInstruction
* res = new (alloc) MNop(*this); for (size_t i = 0; i < numOperands
(); i++) res->replaceOperand(i, inputs[i]); return res; }}
;class MCallee : public MNullaryInstruction { explicit MCallee
() : MNullaryInstruction(classOpcode) { setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(Callee) template
<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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MIsConstructing : public MNullaryInstruction {
explicit MIsConstructing() : MNullaryInstruction(classOpcode
) { setMovable(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(IsConstructing) template <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)...); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MThrow : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MThrow(MDefinition* value) : MUnaryInstruction
(classOpcode, value) { } public: INSTRUCTION_HEADER(Throw) template
<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)...); } MDefinition* value() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool possiblyCalls() const override { return true; }};class
MThrowWithStack : public MBinaryInstruction, public MixPolicy
<BoxPolicy<0>, BoxPolicy<1>>::Data { explicit
MThrowWithStack(MDefinition* value, MDefinition* stack) : MBinaryInstruction
(classOpcode, value, stack) { } public: INSTRUCTION_HEADER(ThrowWithStack
) template <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)...); } MDefinition* value() const
{ return getOperand(0); } MDefinition* stack() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
possiblyCalls() const override { return true; }};class MNewArrayDynamicLength
: public MUnaryInstruction, public UnboxedInt32Policy<0>
::Data { CompilerGCPointer<JSObject*> templateObject_; gc
::Heap initialHeap_; explicit MNewArrayDynamicLength(MDefinition
* length, JSObject* templateObject, gc::Heap initialHeap) : MUnaryInstruction
(classOpcode, length), templateObject_(templateObject), initialHeap_
(initialHeap) { setGuard(); setResultType(MIRType::Object); }
public: JSObject* templateObject() const { return templateObject_
; } gc::Heap initialHeap() const { return initialHeap_; } INSTRUCTION_HEADER
(NewArrayDynamicLength) template <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
)...); } MDefinition* length() const { return getOperand(0); }
AliasSet getAliasSet() const override;};class MNewTypedArrayDynamicLength
: public MUnaryInstruction, public UnboxedInt32Policy<0>
::Data { CompilerGCPointer<JSObject*> templateObject_; gc
::Heap initialHeap_; explicit MNewTypedArrayDynamicLength(MDefinition
* length, JSObject* templateObject, gc::Heap initialHeap) : MUnaryInstruction
(classOpcode, length), templateObject_(templateObject), initialHeap_
(initialHeap) { setGuard(); setResultType(MIRType::Object); }
public: JSObject* templateObject() const { return templateObject_
; } gc::Heap initialHeap() const { return initialHeap_; } INSTRUCTION_HEADER
(NewTypedArrayDynamicLength) template <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
)...); } MDefinition* length() const { return getOperand(0); }
AliasSet getAliasSet() const override;};class MNewTypedArrayFromArray
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ CompilerGCPointer<JSObject*> templateObject_; gc::Heap
initialHeap_; explicit MNewTypedArrayFromArray(MDefinition* array
, JSObject* templateObject, gc::Heap initialHeap) : MUnaryInstruction
(classOpcode, array), templateObject_(templateObject), initialHeap_
(initialHeap) { setGuard(); setResultType(MIRType::Object); }
public: JSObject* templateObject() const { return templateObject_
; } gc::Heap initialHeap() const { return initialHeap_; } INSTRUCTION_HEADER
(NewTypedArrayFromArray) template <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
)...); } MDefinition* array() const { return getOperand(0); }
bool possiblyCalls() const override { return true; }};class MNewTypedArrayFromArrayBuffer
: public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>, BoxPolicy<2>>::Data {
CompilerGCPointer<JSObject*> templateObject_; gc::Heap
initialHeap_; explicit MNewTypedArrayFromArrayBuffer(MDefinition
* arrayBuffer, MDefinition* byteOffset, MDefinition* length, JSObject
* templateObject, gc::Heap initialHeap) : MTernaryInstruction
(classOpcode, arrayBuffer, byteOffset, length), templateObject_
(templateObject), initialHeap_(initialHeap) { setGuard(); setResultType
(MIRType::Object); } public: JSObject* templateObject() const
{ return templateObject_; } gc::Heap initialHeap() const { return
initialHeap_; } INSTRUCTION_HEADER(NewTypedArrayFromArrayBuffer
) template <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)...); } MDefinition* arrayBuffer()
const { return getOperand(0); } MDefinition* byteOffset() const
{ return getOperand(1); } MDefinition* length() const { return
getOperand(2); } bool possiblyCalls() const override { return
true; }};class MNewBoundFunction : public MNullaryInstruction
{ CompilerGCPointer<JSObject*> templateObj_; explicit MNewBoundFunction
(JSObject* templateObj) : MNullaryInstruction(classOpcode), templateObj_
(templateObj) { setResultType(MIRType::Object); } public: JSObject
* templateObj() const { return templateObj_; } INSTRUCTION_HEADER
(NewBoundFunction) template <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)...); } AliasSet getAliasSet
() const override { return AliasSet::None(); }};class MBoundFunctionNumArgs
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MBoundFunctionNumArgs(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setMovable(); setResultType(MIRType::
Int32); } public: INSTRUCTION_HEADER(BoundFunctionNumArgs) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardBoundFunctionIsConstructor : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardBoundFunctionIsConstructor
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardBoundFunctionIsConstructor
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMutateProto : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>>::Data { explicit
MMutateProto(MDefinition* object, MDefinition* value) : MBinaryInstruction
(classOpcode, object, value) { setResultType(MIRType::None); }
public: INSTRUCTION_HEADER(MutateProto) template <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)...); } MDefinition* object() const { return
getOperand(0); } MDefinition* value() const { return getOperand
(1); } bool possiblyCalls() const override { return true; }};
class MInitPropGetterSetter : public MBinaryInstruction, public
MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>>
::Data { CompilerGCPointer<PropertyName*> name_; explicit
MInitPropGetterSetter(MDefinition* object, MDefinition* value
, PropertyName* name) : MBinaryInstruction(classOpcode, object
, value), name_(name) { } public: PropertyName* name() const {
return name_; } INSTRUCTION_HEADER(InitPropGetterSetter) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* value() const { return
getOperand(1); }};class MInitElemGetterSetter : public MTernaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>
, ObjectPolicy<2>>::Data { explicit MInitElemGetterSetter
(MDefinition* object, MDefinition* id, MDefinition* value) : MTernaryInstruction
(classOpcode, object, id, value) { } public: INSTRUCTION_HEADER
(InitElemGetterSetter) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* id() const { return getOperand(1); } MDefinition
* value() const { return getOperand(2); }};class MEncodeSnapshot
: public MNullaryInstruction { explicit MEncodeSnapshot() : MNullaryInstruction
(classOpcode) { setGuard(); } public: INSTRUCTION_HEADER(EncodeSnapshot
) template <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)...); }};class MSameValueDouble : public
MBinaryInstruction, public MixPolicy<DoublePolicy<0>
, DoublePolicy<1>>::Data { explicit MSameValueDouble
(MDefinition* left, MDefinition* right) : MBinaryInstruction(
classOpcode, left, right) { setMovable(); setResultType(MIRType
::Boolean); } public: INSTRUCTION_HEADER(SameValueDouble) template
<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)...); } MDefinition* left() const {
return getOperand(0); } MDefinition* right() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); } bool canClone() const
override { return true; } MInstruction* clone(TempAllocator&
alloc, const MDefinitionVector& inputs) const override {
MInstruction* res = new (alloc) MSameValueDouble(*this); for
(size_t i = 0; i < numOperands(); i++) res->replaceOperand
(i, inputs[i]); return res; }};class MSameValue : public MBinaryInstruction
, public MixPolicy<BoxPolicy<0>, BoxPolicy<1>>
::Data { explicit MSameValue(MDefinition* left, MDefinition* right
) : MBinaryInstruction(classOpcode, left, right) { setMovable
(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(SameValue) template <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)...); } MDefinition
* left() const { return getOperand(0); } MDefinition* right()
const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSameValue
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MCreateThis
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, ObjectPolicy<1>>::Data { explicit MCreateThis
(MDefinition* callee, MDefinition* newTarget) : MBinaryInstruction
(classOpcode, callee, newTarget) { setResultType(MIRType::Value
); } public: INSTRUCTION_HEADER(CreateThis) template <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)...); } MDefinition* callee() const { return
getOperand(0); } MDefinition* newTarget() const { return getOperand
(1); } AliasSet getAliasSet() const override; bool possiblyCalls
() const override { return true; }};class MGetArgumentsObjectArg
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ size_t argno_; explicit MGetArgumentsObjectArg(MDefinition
* argsObject, size_t argno) : MUnaryInstruction(classOpcode, argsObject
), argno_(argno) { setResultType(MIRType::Value); } public: size_t
argno() const { return argno_; } INSTRUCTION_HEADER(GetArgumentsObjectArg
) template <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)...); } MDefinition* argsObject() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override;};class
MSetArgumentsObjectArg : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>>::Data { size_t
argno_; explicit MSetArgumentsObjectArg(MDefinition* argsObject
, MDefinition* value, size_t argno) : MBinaryInstruction(classOpcode
, argsObject, value), argno_(argno) { } public: size_t argno(
) const { return argno_; } INSTRUCTION_HEADER(SetArgumentsObjectArg
) template <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)...); } MDefinition* argsObject() const
{ return getOperand(0); } MDefinition* value() const { return
getOperand(1); } AliasSet getAliasSet() const override;};class
MLoadArgumentsObjectArg : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, UnboxedInt32Policy<1>>::Data
{ explicit MLoadArgumentsObjectArg(MDefinition* argsObject, MDefinition
* index) : MBinaryInstruction(classOpcode, argsObject, index)
{ setGuard(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(LoadArgumentsObjectArg) template <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
)...); } MDefinition* argsObject() const { return getOperand(
0); } MDefinition* index() const { return getOperand(1); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MLoadArgumentsObjectArgHole : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MLoadArgumentsObjectArgHole(MDefinition
* argsObject, MDefinition* index) : MBinaryInstruction(classOpcode
, argsObject, index) { setGuard(); setResultType(MIRType::Value
); } public: INSTRUCTION_HEADER(LoadArgumentsObjectArgHole) template
<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)...); } MDefinition* argsObject() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MInArgumentsObjectArg : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MInArgumentsObjectArg(MDefinition
* argsObject, MDefinition* index) : MBinaryInstruction(classOpcode
, argsObject, index) { setGuard(); setResultType(MIRType::Boolean
); } public: INSTRUCTION_HEADER(InArgumentsObjectArg) template
<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)...); } MDefinition* argsObject() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MArgumentsObjectLength : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MArgumentsObjectLength
(MDefinition* argsObject) : MUnaryInstruction(classOpcode, argsObject
) { setGuard(); setMovable(); setResultType(MIRType::Int32); }
public: INSTRUCTION_HEADER(ArgumentsObjectLength) template <
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)...); } MDefinition* argsObject() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MArrayFromArgumentsObject
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ CompilerGCPointer<Shape*> shape_; explicit MArrayFromArgumentsObject
(MDefinition* argsObject, Shape* shape) : MUnaryInstruction(classOpcode
, argsObject), shape_(shape) { setResultType(MIRType::Object)
; } public: Shape* shape() const { return shape_; } INSTRUCTION_HEADER
(ArrayFromArgumentsObject) template <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
)...); } MDefinition* argsObject() const { return getOperand(
0); } bool possiblyCalls() const override { return true; }};class
MGuardArgumentsObjectFlags : public MUnaryInstruction, public
ObjectPolicy<0>::Data { uint32_t flags_; explicit MGuardArgumentsObjectFlags
(MDefinition* argsObject, uint32_t flags) : MUnaryInstruction
(classOpcode, argsObject), flags_(flags) { setGuard(); setMovable
(); setResultType(MIRType::Object); } public: uint32_t flags(
) const { return flags_; } INSTRUCTION_HEADER(GuardArgumentsObjectFlags
) template <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)...); } MDefinition* argsObject() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override;};class
MLoadScriptedProxyHandler : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MLoadScriptedProxyHandler
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(LoadScriptedProxyHandler) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MCheckScriptedProxyGetResult
: public MTernaryInstruction, public MixPolicy<BoxPolicy<
0>, BoxPolicy<1>, BoxPolicy<2>>::Data { explicit
MCheckScriptedProxyGetResult(MDefinition* target, MDefinition
* id, MDefinition* value) : MTernaryInstruction(classOpcode, target
, id, value) { setGuard(); } public: INSTRUCTION_HEADER(CheckScriptedProxyGetResult
) template <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)...); } MDefinition* target() const
{ return getOperand(0); } MDefinition* id() const { return getOperand
(1); } MDefinition* value() const { return getOperand(2); } AliasSet
getAliasSet() const override;};class MIdToStringOrSymbol : public
MUnaryInstruction, public BoxPolicy<0>::Data { explicit
MIdToStringOrSymbol(MDefinition* idVal) : MUnaryInstruction(
classOpcode, idVal) { setResultType(MIRType::Value); } public
: INSTRUCTION_HEADER(IdToStringOrSymbol) template <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)...); } MDefinition* idVal() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } MDefinition* foldsTo(TempAllocator& alloc
) override; bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MReturnFromCtor
: public MBinaryInstruction, public MixPolicy<BoxPolicy<
0>, ObjectPolicy<1>>::Data { explicit MReturnFromCtor
(MDefinition* value, MDefinition* object) : MBinaryInstruction
(classOpcode, value, object) { setResultType(MIRType::Object)
; } public: INSTRUCTION_HEADER(ReturnFromCtor) template <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)...); } MDefinition* value() const { return
getOperand(0); } MDefinition* object() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MWasmUnsignedToDouble
: public MUnaryInstruction, public NoTypePolicy::Data { explicit
MWasmUnsignedToDouble(MDefinition* def) : MUnaryInstruction(
classOpcode, def) { setMovable(); setResultType(MIRType::Double
); } public: INSTRUCTION_HEADER(WasmUnsignedToDouble) template
<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)...); } MDefinition* def() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MWasmAnyRefFromJSValue : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MWasmAnyRefFromJSValue(MDefinition
* def) : MUnaryInstruction(classOpcode, def) { setResultType(
MIRType::WasmAnyRef); } public: INSTRUCTION_HEADER(WasmAnyRefFromJSValue
) template <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)...); } MDefinition* def() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MWasmAnyRefFromJSObject : public MUnaryInstruction,
public NoTypePolicy::Data { explicit MWasmAnyRefFromJSObject
(MDefinition* def) : MUnaryInstruction(classOpcode, def) { setResultType
(MIRType::WasmAnyRef); } public: INSTRUCTION_HEADER(WasmAnyRefFromJSObject
) template <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)...); } MDefinition* def() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MWasmAnyRefFromJSString : public MUnaryInstruction,
public NoTypePolicy::Data { explicit MWasmAnyRefFromJSString
(MDefinition* def) : MUnaryInstruction(classOpcode, def) { setResultType
(MIRType::WasmAnyRef); } public: INSTRUCTION_HEADER(WasmAnyRefFromJSString
) template <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)...); } MDefinition* def() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MWasmNewI31Ref : public MUnaryInstruction, public NoTypePolicy
::Data { explicit MWasmNewI31Ref(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::WasmAnyRef
); } public: INSTRUCTION_HEADER(WasmNewI31Ref) template <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)...); } MDefinition* input() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MWasmI31RefGet : public MUnaryInstruction, public NoTypePolicy
::Data { wasm::FieldWideningOp wideningOp_; explicit MWasmI31RefGet
(MDefinition* input, wasm::FieldWideningOp wideningOp) : MUnaryInstruction
(classOpcode, input), wideningOp_(wideningOp) { setMovable();
setResultType(MIRType::Int32); } public: wasm::FieldWideningOp
wideningOp() const { return wideningOp_; } INSTRUCTION_HEADER
(WasmI31RefGet) template <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)...); } MDefinition
* input() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MBooleanToInt32 : public MUnaryInstruction, public
BooleanPolicy<0>::Data { explicit MBooleanToInt32(MDefinition
* input) : MUnaryInstruction(classOpcode, input) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(BooleanToInt32) template <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)...); } MDefinition
* input() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } MDefinition* foldsTo
(TempAllocator& alloc) override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} void computeRange(TempAllocator& alloc) override;};class
MTypeOfName : public MUnaryInstruction, public UnboxedInt32Policy
<0>::Data { explicit MTypeOfName(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::String
); } public: INSTRUCTION_HEADER(TypeOfName) template <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)...); } MDefinition* input() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } MDefinition* foldsTo(TempAllocator& alloc
) override; bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); } [[nodiscard]] bool
writeRecoverData( CompactBufferWriter& writer) const override
; bool canRecoverOnBailout() const override { return true; }}
;class MToAsyncIter : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>>::Data { explicit
MToAsyncIter(MDefinition* iterator, MDefinition* nextMethod)
: MBinaryInstruction(classOpcode, iterator, nextMethod) { setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(ToAsyncIter) template
<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)...); } MDefinition* iterator() const
{ return getOperand(0); } MDefinition* nextMethod() const { return
getOperand(1); }};class MToPropertyKeyCache : public MUnaryInstruction
, public BoxPolicy<0>::Data { explicit MToPropertyKeyCache
(MDefinition* input) : MUnaryInstruction(classOpcode, input) {
setResultType(MIRType::Value); } public: INSTRUCTION_HEADER(
ToPropertyKeyCache) template <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)...); } MDefinition
* input() const { return getOperand(0); }};class MAtan2 : public
MBinaryInstruction, public MixPolicy<DoublePolicy<0>
, DoublePolicy<1>>::Data { explicit MAtan2(MDefinition
* y, MDefinition* x) : MBinaryInstruction(classOpcode, y, x) {
setMovable(); setResultType(MIRType::Double); } public: INSTRUCTION_HEADER
(Atan2) template <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)...); } MDefinition
* y() const { return getOperand(0); } MDefinition* x() const {
return getOperand(1); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} bool possiblyCalls() const override { return true; } [[nodiscard
]] bool writeRecoverData( CompactBufferWriter& writer) const
override; bool canRecoverOnBailout() const override { return
true; } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MAtan2
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MRandom : public
MNullaryInstruction { explicit MRandom() : MNullaryInstruction
(classOpcode) { setResultType(MIRType::Double); } public: INSTRUCTION_HEADER
(Random) template <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)...); } AliasSet getAliasSet
() const override; bool possiblyCalls() const override { return
true; } void computeRange(TempAllocator& alloc) override
; [[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
; bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MRandom
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MInt32ToStringWithBase
: public MBinaryInstruction, public MixPolicy<UnboxedInt32Policy
<0>, UnboxedInt32Policy<1>>::Data { bool lowerCase_
; explicit MInt32ToStringWithBase(MDefinition* input, MDefinition
* base, bool lowerCase) : MBinaryInstruction(classOpcode, input
, base), lowerCase_(lowerCase) { setMovable(); setResultType(
MIRType::String); } public: bool lowerCase() const { return lowerCase_
; } INSTRUCTION_HEADER(Int32ToStringWithBase) template <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)...); } MDefinition* input() const { return
getOperand(0); } MDefinition* base() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool congruentTo(const MDefinition* ins) const override
;};class MNumberParseInt : public MBinaryInstruction, public MixPolicy
<StringPolicy<0>, UnboxedInt32Policy<1>>::Data
{ explicit MNumberParseInt(MDefinition* string, MDefinition*
radix) : MBinaryInstruction(classOpcode, string, radix) { setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(NumberParseInt) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* radix
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MDoubleParseInt : public MUnaryInstruction, public DoublePolicy
<0>::Data { explicit MDoubleParseInt(MDefinition* number
) : MUnaryInstruction(classOpcode, number) { setMovable(); setResultType
(MIRType::Int32); } public: INSTRUCTION_HEADER(DoubleParseInt
) template <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)...); } MDefinition* number() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MLinearizeString : public MUnaryInstruction, public
StringPolicy<0>::Data { explicit MLinearizeString(MDefinition
* string) : MUnaryInstruction(classOpcode, string) { setMovable
(); setResultType(MIRType::String); } public: INSTRUCTION_HEADER
(LinearizeString) template <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)...); } MDefinition
* string() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MLinearizeForCharAccess : public MBinaryInstruction
, public MixPolicy<StringPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MLinearizeForCharAccess(MDefinition
* string, MDefinition* index) : MBinaryInstruction(classOpcode
, string, index) { setMovable(); setResultType(MIRType::String
); } public: INSTRUCTION_HEADER(LinearizeForCharAccess) template
<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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MLinearizeForCodePointAccess : public MBinaryInstruction, public
MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>>
::Data { explicit MLinearizeForCodePointAccess(MDefinition* string
, MDefinition* index) : MBinaryInstruction(classOpcode, string
, index) { setMovable(); setResultType(MIRType::String); } public
: INSTRUCTION_HEADER(LinearizeForCodePointAccess) template <
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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MToRelativeStringIndex : public MBinaryInstruction, public MixPolicy
<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>>
::Data { explicit MToRelativeStringIndex(MDefinition* index, MDefinition
* length) : MBinaryInstruction(classOpcode, index, length) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(ToRelativeStringIndex) template <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
)...); } MDefinition* index() const { return getOperand(0); }
MDefinition* length() const { return getOperand(1); } AliasSet
getAliasSet() const override { return AliasSet::None(); } MDefinition
* foldsTo(TempAllocator& alloc) override; bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MCharCodeAt : public MBinaryInstruction, public
MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>>
::Data { explicit MCharCodeAt(MDefinition* string, MDefinition
* index) : MBinaryInstruction(classOpcode, string, index) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(CharCodeAt) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* index
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); } void
computeRange(TempAllocator& alloc) override; [[nodiscard
]] bool writeRecoverData( CompactBufferWriter& writer) const
override; bool canRecoverOnBailout() const override { return
true; } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MCharCodeAt
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MCharCodeAtOrNegative
: public MBinaryInstruction, public MixPolicy<StringPolicy
<0>, UnboxedInt32Policy<1>>::Data { explicit MCharCodeAtOrNegative
(MDefinition* string, MDefinition* index) : MBinaryInstruction
(classOpcode, string, index) { setMovable(); setResultType(MIRType
::Int32); } public: INSTRUCTION_HEADER(CharCodeAtOrNegative) template
<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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MCodePointAt : public MBinaryInstruction, public MixPolicy<
StringPolicy<0>, UnboxedInt32Policy<1>>::Data {
explicit MCodePointAt(MDefinition* string, MDefinition* index
) : MBinaryInstruction(classOpcode, string, index) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(CodePointAt) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* index
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); } void
computeRange(TempAllocator& alloc) override; bool canClone
() const override { return true; } MInstruction* clone(TempAllocator
& alloc, const MDefinitionVector& inputs) const override
{ MInstruction* res = new (alloc) MCodePointAt(*this); for (
size_t i = 0; i < numOperands(); i++) res->replaceOperand
(i, inputs[i]); return res; }};class MCodePointAtOrNegative :
public MBinaryInstruction, public MixPolicy<StringPolicy<
0>, UnboxedInt32Policy<1>>::Data { explicit MCodePointAtOrNegative
(MDefinition* string, MDefinition* index) : MBinaryInstruction
(classOpcode, string, index) { setMovable(); setResultType(MIRType
::Int32); } public: INSTRUCTION_HEADER(CodePointAtOrNegative)
template <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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MNegativeToNaN : public MUnaryInstruction, public UnboxedInt32Policy
<0>::Data { explicit MNegativeToNaN(MDefinition* input)
: MUnaryInstruction(classOpcode, input) { setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(NegativeToNaN)
template <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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MNegativeToUndefined : public MUnaryInstruction, public
UnboxedInt32Policy<0>::Data { explicit MNegativeToUndefined
(MDefinition* input) : MUnaryInstruction(classOpcode, input) {
setMovable(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(NegativeToUndefined) template <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
)...); } MDefinition* input() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MFromCharCode
: public MUnaryInstruction, public UnboxedInt32Policy<0>
::Data { explicit MFromCharCode(MDefinition* code) : MUnaryInstruction
(classOpcode, code) { setMovable(); setResultType(MIRType::String
); } public: INSTRUCTION_HEADER(FromCharCode) template <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)...); } MDefinition* code() const { return getOperand
(0); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); } [[nodiscard]] bool
writeRecoverData( CompactBufferWriter& writer) const override
; bool canRecoverOnBailout() const override { return true; } bool
canClone() const override { return true; } MInstruction* clone
(TempAllocator& alloc, const MDefinitionVector& inputs
) const override { MInstruction* res = new (alloc) MFromCharCode
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MFromCharCodeEmptyIfNegative
: public MUnaryInstruction, public UnboxedInt32Policy<0>
::Data { explicit MFromCharCodeEmptyIfNegative(MDefinition* code
) : MUnaryInstruction(classOpcode, code) { setMovable(); setResultType
(MIRType::String); } public: INSTRUCTION_HEADER(FromCharCodeEmptyIfNegative
) template <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)...); } MDefinition* code() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} [[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
{ return true; } bool canClone() const override { return true
; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector
& inputs) const override { MInstruction* res = new (alloc
) MFromCharCodeEmptyIfNegative(*this); for (size_t i = 0; i <
numOperands(); i++) res->replaceOperand(i, inputs[i]); return
res; }};class MFromCharCodeUndefinedIfNegative : public MUnaryInstruction
, public UnboxedInt32Policy<0>::Data { explicit MFromCharCodeUndefinedIfNegative
(MDefinition* code) : MUnaryInstruction(classOpcode, code) { setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(FromCharCodeUndefinedIfNegative) template <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
)...); } MDefinition* code() const { return getOperand(0); } AliasSet
getAliasSet() const override { return AliasSet::None(); } bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MFromCodePoint : public MUnaryInstruction, public
UnboxedInt32Policy<0>::Data { explicit MFromCodePoint(
MDefinition* codePoint) : MUnaryInstruction(classOpcode, codePoint
) { setGuard(); setMovable(); setResultType(MIRType::String);
} public: INSTRUCTION_HEADER(FromCodePoint) template <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)...); } MDefinition* codePoint() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); } bool
canClone() const override { return true; } MInstruction* clone
(TempAllocator& alloc, const MDefinitionVector& inputs
) const override { MInstruction* res = new (alloc) MFromCodePoint
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MStringIncludes
: public MBinaryInstruction, public MixPolicy<StringPolicy
<0>, StringPolicy<1>>::Data { explicit MStringIncludes
(MDefinition* string, MDefinition* searchString) : MBinaryInstruction
(classOpcode, string, searchString) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(StringIncludes
) template <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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* searchString() const {
return getOperand(1); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} bool possiblyCalls() const override { return true; }};class
MStringIndexOf : public MBinaryInstruction, public MixPolicy
<StringPolicy<0>, StringPolicy<1>>::Data { explicit
MStringIndexOf(MDefinition* string, MDefinition* searchString
) : MBinaryInstruction(classOpcode, string, searchString) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(StringIndexOf) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* searchString
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MStringLastIndexOf : public MBinaryInstruction, public
MixPolicy<StringPolicy<0>, StringPolicy<1>>
::Data { explicit MStringLastIndexOf(MDefinition* string, MDefinition
* searchString) : MBinaryInstruction(classOpcode, string, searchString
) { setMovable(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(StringLastIndexOf) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* searchString
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MStringStartsWith : public MBinaryInstruction, public
MixPolicy<StringPolicy<0>, StringPolicy<1>>
::Data { explicit MStringStartsWith(MDefinition* string, MDefinition
* searchString) : MBinaryInstruction(classOpcode, string, searchString
) { setMovable(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(StringStartsWith) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* searchString
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MStringEndsWith : public MBinaryInstruction, public MixPolicy
<StringPolicy<0>, StringPolicy<1>>::Data { explicit
MStringEndsWith(MDefinition* string, MDefinition* searchString
) : MBinaryInstruction(classOpcode, string, searchString) { setMovable
(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(StringEndsWith) template <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)...); } MDefinition
* string() const { return getOperand(0); } MDefinition* searchString
() const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MStringTrimStartIndex : public MUnaryInstruction, public
StringPolicy<0>::Data { explicit MStringTrimStartIndex
(MDefinition* string) : MUnaryInstruction(classOpcode, string
) { setMovable(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(StringTrimStartIndex) template <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
)...); } MDefinition* string() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MStringTrimEndIndex
: public MBinaryInstruction, public MixPolicy<StringPolicy
<0>, UnboxedInt32Policy<1>>::Data { explicit MStringTrimEndIndex
(MDefinition* string, MDefinition* start) : MBinaryInstruction
(classOpcode, string, start) { setMovable(); setResultType(MIRType
::Int32); } public: INSTRUCTION_HEADER(StringTrimEndIndex) template
<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)...); } MDefinition* string() const
{ return getOperand(0); } MDefinition* start() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MStringSplit : public MBinaryInstruction, public MixPolicy<
StringPolicy<0>, StringPolicy<1>>::Data { explicit
MStringSplit(MDefinition* string, MDefinition* separator) : MBinaryInstruction
(classOpcode, string, separator) { setResultType(MIRType::Object
); } public: INSTRUCTION_HEADER(StringSplit) template <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)...); } MDefinition* string() const { return
getOperand(0); } MDefinition* separator() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool possiblyCalls() const override { return true
; } [[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
{ return true; }};class MBoxNonStrictThis : public MUnaryInstruction
, public BoxPolicy<0>::Data { CompilerGCPointer<JSObject
*> globalThis_; explicit MBoxNonStrictThis(MDefinition* def
, JSObject* globalThis) : MUnaryInstruction(classOpcode, def)
, globalThis_(globalThis) { setResultType(MIRType::Object); }
public: JSObject* globalThis() const { return globalThis_; }
INSTRUCTION_HEADER(BoxNonStrictThis) template <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)...); } MDefinition* def() const { return getOperand
(0); } AliasSet getAliasSet() const override { return AliasSet
::None(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool possiblyCalls() const override { return true; }};class
MImplicitThis : public MUnaryInstruction, public ObjectPolicy
<0>::Data { CompilerGCPointer<PropertyName*> name_
; explicit MImplicitThis(MDefinition* envChain, PropertyName*
name) : MUnaryInstruction(classOpcode, envChain), name_(name
) { setResultType(MIRType::Value); } public: PropertyName* name
() const { return name_; } INSTRUCTION_HEADER(ImplicitThis) template
<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)...); } MDefinition* envChain() const
{ return getOperand(0); } bool possiblyCalls() const override
{ return true; }};class MUnaryCache : public MUnaryInstruction
, public BoxPolicy<0>::Data { explicit MUnaryCache(MDefinition
* input) : MUnaryInstruction(classOpcode, input) { setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(UnaryCache) template
<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)...); } MDefinition* input() const
{ return getOperand(0); }};class MCheckOverRecursed : public
MNullaryInstruction { explicit MCheckOverRecursed() : MNullaryInstruction
(classOpcode) { setGuard(); } public: INSTRUCTION_HEADER(CheckOverRecursed
) template <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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MInterruptCheck
: public MNullaryInstruction { explicit MInterruptCheck() : MNullaryInstruction
(classOpcode) { setGuard(); } public: INSTRUCTION_HEADER(InterruptCheck
) template <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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MWasmTrapIfNull
: public MUnaryInstruction, public NoTypePolicy::Data { wasm
::Trap trap_; wasm::BytecodeOffset bytecodeOffset_; explicit MWasmTrapIfNull
(MDefinition* ref, wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset
) : MUnaryInstruction(classOpcode, ref), trap_(trap), bytecodeOffset_
(bytecodeOffset) { setGuard(); setResultType(MIRType::None); }
public: wasm::Trap trap() const { return trap_; } wasm::BytecodeOffset
bytecodeOffset() const { return bytecodeOffset_; } INSTRUCTION_HEADER
(WasmTrapIfNull) template <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)...); } MDefinition
* ref() const { return getOperand(0); }};class MThrowRuntimeLexicalError
: public MNullaryInstruction { unsigned errorNumber_; explicit
MThrowRuntimeLexicalError(unsigned errorNumber) : MNullaryInstruction
(classOpcode), errorNumber_(errorNumber) { setGuard(); setResultType
(MIRType::None); } public: unsigned errorNumber() const { return
errorNumber_; } INSTRUCTION_HEADER(ThrowRuntimeLexicalError)
template <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)...); } AliasSet getAliasSet() const
override;};class MGlobalDeclInstantiation : public MNullaryInstruction
{ explicit MGlobalDeclInstantiation() : MNullaryInstruction(
classOpcode) { setGuard(); } public: INSTRUCTION_HEADER(GlobalDeclInstantiation
) template <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)...); }};class MRegExp : public MNullaryInstruction
{ CompilerGCPointer<RegExpObject*> source_; bool hasShared_
; explicit MRegExp(RegExpObject* source, bool hasShared) : MNullaryInstruction
(classOpcode), source_(source), hasShared_(hasShared) { setResultType
(MIRType::Object); } public: RegExpObject* source() const { return
source_; } bool hasShared() const { return hasShared_; } INSTRUCTION_HEADER
(RegExp) template <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)...); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool possiblyCalls
() const override { return true; }};class MRegExpMatcher : public
MTernaryInstruction, public MixPolicy<ObjectPolicy<0>
, StringPolicy<1>, UnboxedInt32Policy<2>>::Data
{ explicit MRegExpMatcher(MDefinition* regexp, MDefinition* string
, MDefinition* lastIndex) : MTernaryInstruction(classOpcode, regexp
, string, lastIndex) { setResultType(MIRType::Value); } public
: INSTRUCTION_HEADER(RegExpMatcher) template <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
)...); } MDefinition* regexp() const { return getOperand(0); }
MDefinition* string() const { return getOperand(1); } MDefinition
* lastIndex() const { return getOperand(2); } bool possiblyCalls
() const override { return true; } [[nodiscard]] bool writeRecoverData
( CompactBufferWriter& writer) const override; bool canRecoverOnBailout
() const override { return true; }};class MRegExpSearcher : public
MTernaryInstruction, public MixPolicy<ObjectPolicy<0>
, StringPolicy<1>, UnboxedInt32Policy<2>>::Data
{ explicit MRegExpSearcher(MDefinition* regexp, MDefinition*
string, MDefinition* lastIndex) : MTernaryInstruction(classOpcode
, regexp, string, lastIndex) { setResultType(MIRType::Int32);
} public: INSTRUCTION_HEADER(RegExpSearcher) template <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)...); } MDefinition* regexp() const { return
getOperand(0); } MDefinition* string() const { return getOperand
(1); } MDefinition* lastIndex() const { return getOperand(2);
} bool possiblyCalls() const override { return true; }};class
MRegExpSearcherLastLimit : public MNullaryInstruction { explicit
MRegExpSearcherLastLimit() : MNullaryInstruction(classOpcode
) { setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(RegExpSearcherLastLimit) template <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
)...); }};class MRegExpExecMatch : public MBinaryInstruction,
public MixPolicy<ObjectPolicy<0>, StringPolicy<1
>>::Data { explicit MRegExpExecMatch(MDefinition* regexp
, MDefinition* string) : MBinaryInstruction(classOpcode, regexp
, string) { setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(RegExpExecMatch) template <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)...); } MDefinition
* regexp() const { return getOperand(0); } MDefinition* string
() const { return getOperand(1); } bool possiblyCalls() const
override { return true; }};class MRegExpExecTest : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, StringPolicy<
1>>::Data { explicit MRegExpExecTest(MDefinition* regexp
, MDefinition* string) : MBinaryInstruction(classOpcode, regexp
, string) { setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(RegExpExecTest) template <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)...); } MDefinition
* regexp() const { return getOperand(0); } MDefinition* string
() const { return getOperand(1); } bool possiblyCalls() const
override { return true; }};class MRegExpHasCaptureGroups : public
MBinaryInstruction, public MixPolicy<ObjectPolicy<0>
, StringPolicy<1>>::Data { explicit MRegExpHasCaptureGroups
(MDefinition* regexp, MDefinition* input) : MBinaryInstruction
(classOpcode, regexp, input) { setResultType(MIRType::Boolean
); } public: INSTRUCTION_HEADER(RegExpHasCaptureGroups) template
<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)...); } MDefinition* regexp() const
{ return getOperand(0); } MDefinition* input() const { return
getOperand(1); } bool possiblyCalls() const override { return
true; }};class MRegExpPrototypeOptimizable : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MRegExpPrototypeOptimizable
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(RegExpPrototypeOptimizable) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); }};class MRegExpInstanceOptimizable : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, ObjectPolicy<
1>>::Data { explicit MRegExpInstanceOptimizable(MDefinition
* object, MDefinition* proto) : MBinaryInstruction(classOpcode
, object, proto) { setResultType(MIRType::Boolean); } public:
INSTRUCTION_HEADER(RegExpInstanceOptimizable) template <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)...); } MDefinition* object() const { return
getOperand(0); } MDefinition* proto() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); }};class MSubstr : public MTernaryInstruction, public
MixPolicy<StringPolicy<0>, UnboxedInt32Policy<1>
, UnboxedInt32Policy<2>>::Data { explicit MSubstr(MDefinition
* string, MDefinition* begin, MDefinition* length) : MTernaryInstruction
(classOpcode, string, begin, length) { setResultType(MIRType::
String); } public: INSTRUCTION_HEADER(Substr) template <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)...); } MDefinition* string() const { return
getOperand(0); } MDefinition* begin() const { return getOperand
(1); } MDefinition* length() const { return getOperand(2); } AliasSet
getAliasSet() const override { return AliasSet::None(); } MDefinition
* foldsTo(TempAllocator& alloc) override; bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } [[nodiscard]] bool writeRecoverData( CompactBufferWriter
& writer) const override; bool canRecoverOnBailout() const
override { return true; }};class MModuleMetadata : public MNullaryInstruction
{ CompilerGCPointer<JSObject*> module_; explicit MModuleMetadata
(JSObject* module) : MNullaryInstruction(classOpcode), module_
(module) { setResultType(MIRType::Object); } public: JSObject
* module() const { return module_; } INSTRUCTION_HEADER(ModuleMetadata
) template <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)...); }};class MDynamicImport : public
MBinaryInstruction, public MixPolicy<BoxPolicy<0>, BoxPolicy
<1>>::Data { explicit MDynamicImport(MDefinition* specifier
, MDefinition* options) : MBinaryInstruction(classOpcode, specifier
, options) { setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(DynamicImport) template <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)...); } MDefinition
* specifier() const { return getOperand(0); } MDefinition* options
() const { return getOperand(1); }};class MSetFunName : public
MBinaryInstruction, public MixPolicy<ObjectPolicy<0>
, BoxPolicy<1>>::Data { uint8_t prefixKind_; explicit
MSetFunName(MDefinition* fun, MDefinition* name, uint8_t prefixKind
) : MBinaryInstruction(classOpcode, fun, name), prefixKind_(prefixKind
) { setResultType(MIRType::None); } public: uint8_t prefixKind
() const { return prefixKind_; } INSTRUCTION_HEADER(SetFunName
) template <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)...); } MDefinition* fun() const {
return getOperand(0); } MDefinition* name() const { return getOperand
(1); } bool possiblyCalls() const override { return true; }};
class MSlots : public MUnaryInstruction, public ObjectPolicy<
0>::Data { explicit MSlots(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setMovable(); setResultType(MIRType::
Slots); } public: INSTRUCTION_HEADER(Slots) template <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)...); } MDefinition* object() const { return
getOperand(0); } AliasSet getAliasSet() const override; AliasType
mightAlias(const MDefinition* store) const override; bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSlots
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MElements :
public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MElements(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setMovable(); setResultType(MIRType::
Elements); } public: INSTRUCTION_HEADER(Elements) template <
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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); } bool canClone() const override
{ return true; } MInstruction* clone(TempAllocator& alloc
, const MDefinitionVector& inputs) const override { MInstruction
* res = new (alloc) MElements(*this); for (size_t i = 0; i <
numOperands(); i++) res->replaceOperand(i, inputs[i]); return
res; }};class MInitializedLength : public MUnaryInstruction,
public NoTypePolicy::Data { explicit MInitializedLength(MDefinition
* elements) : MUnaryInstruction(classOpcode, elements) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(InitializedLength) template <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)...); } MDefinition
* elements() const { return getOperand(0); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); } void computeRange
(TempAllocator& alloc) override; bool canClone() const override
{ return true; } MInstruction* clone(TempAllocator& alloc
, const MDefinitionVector& inputs) const override { MInstruction
* res = new (alloc) MInitializedLength(*this); for (size_t i =
0; i < numOperands(); i++) res->replaceOperand(i, inputs
[i]); return res; }};class MSetInitializedLength : public MBinaryInstruction
, public NoTypePolicy::Data { explicit MSetInitializedLength(
MDefinition* elements, MDefinition* index) : MBinaryInstruction
(classOpcode, elements, index) { } public: INSTRUCTION_HEADER
(SetInitializedLength) template <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
)...); } MDefinition* elements() const { return getOperand(0)
; } MDefinition* index() const { return getOperand(1); } AliasSet
getAliasSet() const override; bool canClone() const override
{ return true; } MInstruction* clone(TempAllocator& alloc
, const MDefinitionVector& inputs) const override { MInstruction
* res = new (alloc) MSetInitializedLength(*this); for (size_t
i = 0; i < numOperands(); i++) res->replaceOperand(i, inputs
[i]); return res; }};class MArrayLength : public MUnaryInstruction
, public NoTypePolicy::Data { explicit MArrayLength(MDefinition
* elements) : MUnaryInstruction(classOpcode, elements) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(ArrayLength) template <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)...); } MDefinition
* elements() const { return getOperand(0); } AliasSet getAliasSet
() const override; MDefinition* foldsTo(TempAllocator& alloc
) override; bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); } void computeRange(
TempAllocator& alloc) override; bool canClone() const override
{ return true; } MInstruction* clone(TempAllocator& alloc
, const MDefinitionVector& inputs) const override { MInstruction
* res = new (alloc) MArrayLength(*this); for (size_t i = 0; i
< numOperands(); i++) res->replaceOperand(i, inputs[i]
); return res; }};class MSetArrayLength : public MBinaryInstruction
, public NoTypePolicy::Data { explicit MSetArrayLength(MDefinition
* elements, MDefinition* index) : MBinaryInstruction(classOpcode
, elements, index) { } public: INSTRUCTION_HEADER(SetArrayLength
) template <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)...); } MDefinition* elements() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override;};class
MFunctionLength : public MUnaryInstruction, public ObjectPolicy
<0>::Data { explicit MFunctionLength(MDefinition* function
) : MUnaryInstruction(classOpcode, function) { setGuard(); setResultType
(MIRType::Int32); } public: INSTRUCTION_HEADER(FunctionLength
) template <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)...); } MDefinition* function() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MFunctionName : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MFunctionName(MDefinition* function) : MUnaryInstruction(classOpcode
, function) { setGuard(); setResultType(MIRType::String); } public
: INSTRUCTION_HEADER(FunctionName) template <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
)...); } MDefinition* function() const { return getOperand(0)
; } AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MArrayBufferByteLength : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MArrayBufferByteLength
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::IntPtr); } public: INSTRUCTION_HEADER
(ArrayBufferByteLength) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MArrayBufferViewLength : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MArrayBufferViewLength
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::IntPtr); } public: INSTRUCTION_HEADER
(ArrayBufferViewLength) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } void computeRange(TempAllocator& alloc) override
;};class MArrayBufferViewByteOffset : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MArrayBufferViewByteOffset
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::IntPtr); } public: INSTRUCTION_HEADER
(ArrayBufferViewByteOffset) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } void computeRange(TempAllocator& alloc) override
;};class MArrayBufferViewElements : public MUnaryInstruction,
public ObjectPolicy<0>::Data { explicit MArrayBufferViewElements
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::Elements); } public:
INSTRUCTION_HEADER(ArrayBufferViewElements) template <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)...); } MDefinition* object() const { return
getOperand(0); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MArrayBufferViewElements
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MResizableTypedArrayByteOffsetMaybeOutOfBounds
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MResizableTypedArrayByteOffsetMaybeOutOfBounds(MDefinition
* object) : MUnaryInstruction(classOpcode, object) { setMovable
(); setResultType(MIRType::IntPtr); } public: INSTRUCTION_HEADER
(ResizableTypedArrayByteOffsetMaybeOutOfBounds) template <
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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); } void computeRange(TempAllocator
& alloc) override;};class MResizableTypedArrayLength : public
MUnaryInstruction, public ObjectPolicy<0>::Data { MemoryBarrierRequirement
requiresMemoryBarrier_; explicit MResizableTypedArrayLength(
MDefinition* object, MemoryBarrierRequirement requiresMemoryBarrier
) : MUnaryInstruction(classOpcode, object), requiresMemoryBarrier_
(requiresMemoryBarrier) { setGuard(); setResultType(MIRType::
IntPtr); } public: MemoryBarrierRequirement requiresMemoryBarrier
() const { return requiresMemoryBarrier_; } INSTRUCTION_HEADER
(ResizableTypedArrayLength) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override; void computeRange(TempAllocator
& alloc) override;};class MResizableDataViewByteLength : public
MUnaryInstruction, public ObjectPolicy<0>::Data { MemoryBarrierRequirement
requiresMemoryBarrier_; explicit MResizableDataViewByteLength
(MDefinition* object, MemoryBarrierRequirement requiresMemoryBarrier
) : MUnaryInstruction(classOpcode, object), requiresMemoryBarrier_
(requiresMemoryBarrier) { setGuard(); setResultType(MIRType::
IntPtr); } public: MemoryBarrierRequirement requiresMemoryBarrier
() const { return requiresMemoryBarrier_; } INSTRUCTION_HEADER
(ResizableDataViewByteLength) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override; void computeRange(TempAllocator
& alloc) override;};class MGrowableSharedArrayBufferByteLength
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGrowableSharedArrayBufferByteLength(MDefinition*
object) : MUnaryInstruction(classOpcode, object) { setGuard(
); setResultType(MIRType::IntPtr); } public: INSTRUCTION_HEADER
(GrowableSharedArrayBufferByteLength) template <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)...); } MDefinition* object() const { return getOperand
(0); } AliasSet getAliasSet() const override;};class MTypedArrayElementSize
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MTypedArrayElementSize(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setMovable(); setResultType(MIRType::
Int32); } public: INSTRUCTION_HEADER(TypedArrayElementSize) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} void computeRange(TempAllocator& alloc) override;};class
MGuardHasAttachedArrayBuffer : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MGuardHasAttachedArrayBuffer
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardHasAttachedArrayBuffer) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MGuardResizableArrayBufferViewInBounds
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGuardResizableArrayBufferViewInBounds(MDefinition
* object) : MUnaryInstruction(classOpcode, object) { setGuard
(); setMovable(); setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(GuardResizableArrayBufferViewInBounds) template <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)...); } MDefinition* object() const { return
getOperand(0); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGuardResizableArrayBufferViewInBoundsOrDetached
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGuardResizableArrayBufferViewInBoundsOrDetached(
MDefinition* object) : MUnaryInstruction(classOpcode, object)
{ setGuard(); setMovable(); setResultType(MIRType::Object); }
public: INSTRUCTION_HEADER(GuardResizableArrayBufferViewInBoundsOrDetached
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MKeepAliveObject : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MKeepAliveObject(MDefinition* object) : MUnaryInstruction(classOpcode
, object) { setGuard(); setResultType(MIRType::None); } public
: INSTRUCTION_HEADER(KeepAliveObject) template <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)...); } MDefinition* object() const { return getOperand
(0); }};class MDebugEnterGCUnsafeRegion : public MNullaryInstruction
{ explicit MDebugEnterGCUnsafeRegion() : MNullaryInstruction
(classOpcode) { setGuard(); setResultType(MIRType::None); } public
: INSTRUCTION_HEADER(DebugEnterGCUnsafeRegion) template <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)...); } AliasSet getAliasSet() const override
{ return AliasSet::None(); }};class MDebugLeaveGCUnsafeRegion
: public MNullaryInstruction { explicit MDebugLeaveGCUnsafeRegion
() : MNullaryInstruction(classOpcode) { setGuard(); setResultType
(MIRType::None); } public: INSTRUCTION_HEADER(DebugLeaveGCUnsafeRegion
) template <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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MArrayPush : public
MBinaryInstruction, public MixPolicy<ObjectPolicy<0>
, BoxPolicy<1>>::Data { explicit MArrayPush(MDefinition
* object, MDefinition* value) : MBinaryInstruction(classOpcode
, object, value) { setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(ArrayPush) template <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)...); } MDefinition
* object() const { return getOperand(0); } MDefinition* value
() const { return getOperand(1); } AliasSet getAliasSet() const
override; void computeRange(TempAllocator& alloc) override
; bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MArrayPush
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MArraySlice
: public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy<
2>>::Data { CompilerGCPointer<JSObject*> templateObj_
; gc::Heap initialHeap_; explicit MArraySlice(MDefinition* object
, MDefinition* begin, MDefinition* end, JSObject* templateObj
, gc::Heap initialHeap) : MTernaryInstruction(classOpcode, object
, begin, end), templateObj_(templateObj), initialHeap_(initialHeap
) { setResultType(MIRType::Object); } public: JSObject* templateObj
() const { return templateObj_; } gc::Heap initialHeap() const
{ return initialHeap_; } INSTRUCTION_HEADER(ArraySlice) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* begin() const { return
getOperand(1); } MDefinition* end() const { return getOperand
(2); } bool possiblyCalls() const override { return true; }};
class MArgumentsSlice : public MTernaryInstruction, public MixPolicy
<ObjectPolicy<0>, UnboxedInt32Policy<1>, UnboxedInt32Policy
<2>>::Data { CompilerGCPointer<JSObject*> templateObj_
; gc::Heap initialHeap_; explicit MArgumentsSlice(MDefinition
* object, MDefinition* begin, MDefinition* end, JSObject* templateObj
, gc::Heap initialHeap) : MTernaryInstruction(classOpcode, object
, begin, end), templateObj_(templateObj), initialHeap_(initialHeap
) { setResultType(MIRType::Object); } public: JSObject* templateObj
() const { return templateObj_; } gc::Heap initialHeap() const
{ return initialHeap_; } INSTRUCTION_HEADER(ArgumentsSlice) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* begin() const { return
getOperand(1); } MDefinition* end() const { return getOperand
(2); } bool possiblyCalls() const override { return true; }};
class MFrameArgumentsSlice : public MBinaryInstruction, public
MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy
<1>>::Data { CompilerGCPointer<JSObject*> templateObj_
; gc::Heap initialHeap_; explicit MFrameArgumentsSlice(MDefinition
* begin, MDefinition* count, JSObject* templateObj, gc::Heap initialHeap
) : MBinaryInstruction(classOpcode, begin, count), templateObj_
(templateObj), initialHeap_(initialHeap) { setResultType(MIRType
::Object); } public: JSObject* templateObj() const { return templateObj_
; } gc::Heap initialHeap() const { return initialHeap_; } INSTRUCTION_HEADER
(FrameArgumentsSlice) template <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
)...); } MDefinition* begin() const { return getOperand(0); }
MDefinition* count() const { return getOperand(1); } AliasSet
getAliasSet() const override { return AliasSet::None(); } bool
possiblyCalls() const override { return true; }};class MNormalizeSliceTerm
: public MBinaryInstruction, public MixPolicy<UnboxedInt32Policy
<0>, UnboxedInt32Policy<1>>::Data { explicit MNormalizeSliceTerm
(MDefinition* value, MDefinition* length) : MBinaryInstruction
(classOpcode, value, length) { setMovable(); setResultType(MIRType
::Int32); } public: INSTRUCTION_HEADER(NormalizeSliceTerm) template
<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)...); } MDefinition* value() const
{ return getOperand(0); } MDefinition* length() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } MDefinition* foldsTo(TempAllocator& alloc
) override; bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MArrayJoin :
public MBinaryInstruction, public MixPolicy<ObjectPolicy<
0>, StringPolicy<1>>::Data { explicit MArrayJoin(
MDefinition* array, MDefinition* sep) : MBinaryInstruction(classOpcode
, array, sep) { setResultType(MIRType::String); } public: INSTRUCTION_HEADER
(ArrayJoin) template <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)...); } MDefinition
* array() const { return getOperand(0); } MDefinition* sep() const
{ return getOperand(1); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool possiblyCalls() const override { return
true; }};class MObjectKeys : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MObjectKeys(MDefinition
* object) : MUnaryInstruction(classOpcode, object) { setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(ObjectKeys) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } [[nodiscard]] bool writeRecoverData
( CompactBufferWriter& writer) const override; bool canRecoverOnBailout
() const override;};class MObjectKeysLength : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MObjectKeysLength
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(ObjectKeysLength) template <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)...); } MDefinition
* object() const { return getOperand(0); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); } bool canClone
() const override { return true; } MInstruction* clone(TempAllocator
& alloc, const MDefinitionVector& inputs) const override
{ MInstruction* res = new (alloc) MObjectKeysLength(*this); for
(size_t i = 0; i < numOperands(); i++) res->replaceOperand
(i, inputs[i]); return res; }};class MHomeObjectSuperBase : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MHomeObjectSuperBase(MDefinition* homeObject) : MUnaryInstruction
(classOpcode, homeObject) { setMovable(); setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(HomeObjectSuperBase) template
<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)...); } MDefinition* homeObject() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MBindNameCache : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MBindNameCache(MDefinition* envChain) : MUnaryInstruction(classOpcode
, envChain) { setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(BindNameCache) template <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)...); } MDefinition
* envChain() const { return getOperand(0); }};class MCallBindVar
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MCallBindVar(MDefinition* environmentChain) : MUnaryInstruction
(classOpcode, environmentChain) { setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(CallBindVar) template
<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)...); } MDefinition* environmentChain
() const { return getOperand(0); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override;};class MGuardShape : public
MUnaryInstruction, public ObjectPolicy<0>::Data { CompilerGCPointer
<Shape*> shape_; explicit MGuardShape(MDefinition* object
, Shape* shape) : MUnaryInstruction(classOpcode, object), shape_
(shape) { setGuard(); setMovable(); setResultType(MIRType::Object
); } public: Shape* shape() const { return shape_; } INSTRUCTION_HEADER
(GuardShape) template <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)...); } MDefinition
* object() const { return getOperand(0); } AliasSet getAliasSet
() const override; AliasType mightAlias(const MDefinition* store
) const override; bool congruentTo(const MDefinition* ins) const
override;};class MGuardFuse : public MNullaryInstruction { RealmFuses
::FuseIndex fuseIndex_; explicit MGuardFuse(RealmFuses::FuseIndex
fuseIndex) : MNullaryInstruction(classOpcode), fuseIndex_(fuseIndex
) { setGuard(); setMovable(); setResultType(MIRType::None); }
public: RealmFuses::FuseIndex fuseIndex() const { return fuseIndex_
; } INSTRUCTION_HEADER(GuardFuse) template <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
)...); } AliasSet getAliasSet() const override; bool congruentTo
(const MDefinition* ins) const override;};class MGuardMultipleShapes
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, ObjectPolicy<1>>::Data { explicit MGuardMultipleShapes
(MDefinition* object, MDefinition* shapeList) : MBinaryInstruction
(classOpcode, object, shapeList) { setGuard(); setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(GuardMultipleShapes
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* shapeList() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGuardIsNativeObject : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardIsNativeObject
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardIsNativeObject) template <
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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardGlobalGeneration : public MNullaryInstruction
{ uint32_t expected_; const void* generationAddr_; explicit MGuardGlobalGeneration
(uint32_t expected, const void* generationAddr) : MNullaryInstruction
(classOpcode), expected_(expected), generationAddr_(generationAddr
) { setGuard(); setMovable(); setResultType(MIRType::None); }
public: uint32_t expected() const { return expected_; } const
void* generationAddr() const { return generationAddr_; } INSTRUCTION_HEADER
(GuardGlobalGeneration) template <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
)...); } AliasSet getAliasSet() const override; bool congruentTo
(const MDefinition* ins) const override;};class MGuardIsProxy
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGuardIsProxy(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setGuard(); setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(GuardIsProxy)
template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardIsNotDOMProxy : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MGuardIsNotDOMProxy(MDefinition
* proxy) : MUnaryInstruction(classOpcode, proxy) { setGuard()
; setMovable(); setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(GuardIsNotDOMProxy) template <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
)...); } MDefinition* proxy() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MGuardIsNotProxy
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGuardIsNotProxy(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setGuard(); setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(GuardIsNotProxy
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MProxyGet : public MUnaryInstruction, public ObjectPolicy<
0>::Data { jsid id_; explicit MProxyGet(MDefinition* proxy
, jsid id) : MUnaryInstruction(classOpcode, proxy), id_(id) {
setResultType(MIRType::Value); } public: jsid id() const { return
id_; } INSTRUCTION_HEADER(ProxyGet) template <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)...); } MDefinition* proxy() const { return getOperand
(0); } bool possiblyCalls() const override { return true; }};
class MProxyGetByValue : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>>::Data { explicit
MProxyGetByValue(MDefinition* proxy, MDefinition* idVal) : MBinaryInstruction
(classOpcode, proxy, idVal) { setResultType(MIRType::Value); }
public: INSTRUCTION_HEADER(ProxyGetByValue) template <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)...); } MDefinition* proxy() const { return
getOperand(0); } MDefinition* idVal() const { return getOperand
(1); } bool possiblyCalls() const override { return true; }};
class MProxyHasProp : public MBinaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>>::Data { bool
hasOwn_; explicit MProxyHasProp(MDefinition* proxy, MDefinition
* idVal, bool hasOwn) : MBinaryInstruction(classOpcode, proxy
, idVal), hasOwn_(hasOwn) { setResultType(MIRType::Boolean); }
public: bool hasOwn() const { return hasOwn_; } INSTRUCTION_HEADER
(ProxyHasProp) template <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)...); } MDefinition
* proxy() const { return getOperand(0); } MDefinition* idVal(
) const { return getOperand(1); } bool possiblyCalls() const override
{ return true; }};class MProxySet : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { jsid id_; bool strict_; explicit MProxySet(MDefinition
* proxy, MDefinition* rhs, jsid id, bool strict) : MBinaryInstruction
(classOpcode, proxy, rhs), id_(id), strict_(strict) { } public
: jsid id() const { return id_; } bool strict() const { return
strict_; } INSTRUCTION_HEADER(ProxySet) template <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)...); } MDefinition* proxy() const { return
getOperand(0); } MDefinition* rhs() const { return getOperand
(1); } bool possiblyCalls() const override { return true; }};
class MProxySetByValue : public MTernaryInstruction, public MixPolicy
<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy<2
>>::Data { bool strict_; explicit MProxySetByValue(MDefinition
* proxy, MDefinition* idVal, MDefinition* rhs, bool strict) :
MTernaryInstruction(classOpcode, proxy, idVal, rhs), strict_
(strict) { } public: bool strict() const { return strict_; } INSTRUCTION_HEADER
(ProxySetByValue) template <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)...); } MDefinition
* proxy() const { return getOperand(0); } MDefinition* idVal(
) const { return getOperand(1); } MDefinition* rhs() const { return
getOperand(2); } bool possiblyCalls() const override { return
true; }};class MCallSetArrayLength : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { bool strict_; explicit MCallSetArrayLength(MDefinition
* obj, MDefinition* rhs, bool strict) : MBinaryInstruction(classOpcode
, obj, rhs), strict_(strict) { } public: bool strict() const {
return strict_; } INSTRUCTION_HEADER(CallSetArrayLength) template
<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)...); } MDefinition* obj() const {
return getOperand(0); } MDefinition* rhs() const { return getOperand
(1); } bool possiblyCalls() const override { return true; }};
class MMegamorphicLoadSlot : public MUnaryInstruction, public
ObjectPolicy<0>::Data { PropertyKey name_; explicit MMegamorphicLoadSlot
(MDefinition* object, PropertyKey name) : MUnaryInstruction(classOpcode
, object), name_(name) { setGuard(); setResultType(MIRType::Value
); } public: PropertyKey name() const { return name_; } INSTRUCTION_HEADER
(MegamorphicLoadSlot) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override; bool congruentTo(const
MDefinition* ins) const override; bool possiblyCalls() const
override { return true; }};class MMegamorphicLoadSlotByValue
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>>::Data { explicit MMegamorphicLoadSlotByValue
(MDefinition* object, MDefinition* idVal) : MBinaryInstruction
(classOpcode, object, idVal) { setGuard(); setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(MegamorphicLoadSlotByValue
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* idVal() const { return
getOperand(1); } AliasSet getAliasSet() const override; MDefinition
* foldsTo(TempAllocator& alloc) override; bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MMegamorphicStoreSlot : public MBinaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>::
Data { PropertyKey name_; bool strict_; explicit MMegamorphicStoreSlot
(MDefinition* object, MDefinition* rhs, PropertyKey name, bool
strict) : MBinaryInstruction(classOpcode, object, rhs), name_
(name), strict_(strict) { } public: PropertyKey name() const {
return name_; } bool strict() const { return strict_; } INSTRUCTION_HEADER
(MegamorphicStoreSlot) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* rhs() const { return getOperand(1); } bool possiblyCalls
() const override { return true; }};class MMegamorphicHasProp
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>>::Data { bool hasOwn_; explicit
MMegamorphicHasProp(MDefinition* object, MDefinition* idVal,
bool hasOwn) : MBinaryInstruction(classOpcode, object, idVal
), hasOwn_(hasOwn) { setGuard(); setResultType(MIRType::Boolean
); } public: bool hasOwn() const { return hasOwn_; } INSTRUCTION_HEADER
(MegamorphicHasProp) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* idVal() const { return getOperand(1); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override; bool possiblyCalls() const override { return
true; }};class MSmallObjectVariableKeyHasProp : public MUnaryInstruction
, public StringPolicy<0>::Data { CompilerGCPointer<Shape
*> shape_; explicit MSmallObjectVariableKeyHasProp(MDefinition
* idStr, Shape* shape) : MUnaryInstruction(classOpcode, idStr
), shape_(shape) { setResultType(MIRType::Boolean); } public:
Shape* shape() const { return shape_; } INSTRUCTION_HEADER(SmallObjectVariableKeyHasProp
) template <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)...); } MDefinition* idStr() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override;};class
MGuardIsNotArrayBufferMaybeShared : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardIsNotArrayBufferMaybeShared
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardIsNotArrayBufferMaybeShared
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MGuardIsTypedArray : public MUnaryInstruction, public ObjectPolicy
<0>::Data { explicit MGuardIsTypedArray(MDefinition* object
) : MUnaryInstruction(classOpcode, object) { setGuard(); setMovable
(); setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(GuardIsTypedArray) template <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)...); } MDefinition
* object() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGuardIsFixedLengthTypedArray : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardIsFixedLengthTypedArray
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardIsFixedLengthTypedArray) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardIsResizableTypedArray : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardIsResizableTypedArray
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardIsResizableTypedArray) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardHasProxyHandler : public MUnaryInstruction, public
ObjectPolicy<0>::Data { const void* handler_; explicit
MGuardHasProxyHandler(MDefinition* object, const void* handler
) : MUnaryInstruction(classOpcode, object), handler_(handler)
{ setGuard(); setMovable(); setResultType(MIRType::Object); }
public: const void* handler() const { return handler_; } INSTRUCTION_HEADER
(GuardHasProxyHandler) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MNurseryObject
: public MNullaryInstruction { uint32_t nurseryIndex_; explicit
MNurseryObject(uint32_t nurseryIndex) : MNullaryInstruction(
classOpcode), nurseryIndex_(nurseryIndex) { setMovable(); setResultType
(MIRType::Object); } public: uint32_t nurseryIndex() const { return
nurseryIndex_; } INSTRUCTION_HEADER(NurseryObject) template <
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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override;};class MGuardNullOrUndefined
: public MUnaryInstruction, public BoxPolicy<0>::Data {
explicit MGuardNullOrUndefined(MDefinition* value) : MUnaryInstruction
(classOpcode, value) { setGuard(); setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(GuardNullOrUndefined
) template <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)...); } MDefinition* value() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MGuardIsNotObject : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MGuardIsNotObject(MDefinition* value
) : MUnaryInstruction(classOpcode, value) { setGuard(); setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(GuardIsNotObject) template <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)...); } MDefinition
* value() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } MDefinition* foldsTo
(TempAllocator& alloc) override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MGuardFunctionIsNonBuiltinCtor : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardFunctionIsNonBuiltinCtor
(MDefinition* function) : MUnaryInstruction(classOpcode, function
) { setGuard(); setMovable(); setResultType(MIRType::Object);
} public: INSTRUCTION_HEADER(GuardFunctionIsNonBuiltinCtor) template
<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)...); } MDefinition* function() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MGuardFunctionKind :
public MUnaryInstruction, public ObjectPolicy<0>::Data
{ FunctionFlags::FunctionKind expected_; bool bailOnEquality_
; explicit MGuardFunctionKind(MDefinition* function, FunctionFlags
::FunctionKind expected, bool bailOnEquality) : MUnaryInstruction
(classOpcode, function), expected_(expected), bailOnEquality_
(bailOnEquality) { setGuard(); setMovable(); setResultType(MIRType
::Object); } public: FunctionFlags::FunctionKind expected() const
{ return expected_; } bool bailOnEquality() const { return bailOnEquality_
; } INSTRUCTION_HEADER(GuardFunctionKind) template <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)...); } MDefinition* function() const { return
getOperand(0); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override;};class MGuardFunctionScript
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ CompilerGCPointer<BaseScript*> expected_; uint16_t nargs_
; FunctionFlags flags_; explicit MGuardFunctionScript(MDefinition
* function, BaseScript* expected, uint16_t nargs, FunctionFlags
flags) : MUnaryInstruction(classOpcode, function), expected_
(expected), nargs_(nargs), flags_(flags) { setGuard(); setMovable
(); setResultType(MIRType::Object); } public: BaseScript* expected
() const { return expected_; } uint16_t nargs() const { return
nargs_; } FunctionFlags flags() const { return flags_; } INSTRUCTION_HEADER
(GuardFunctionScript) template <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
)...); } MDefinition* function() const { return getOperand(0)
; } AliasSet getAliasSet() const override; MDefinition* foldsTo
(TempAllocator& alloc) override; bool congruentTo(const MDefinition
* ins) const override;};class MGuardSpecificAtom : public MUnaryInstruction
, public StringPolicy<0>::Data { CompilerGCPointer<JSAtom
*> atom_; explicit MGuardSpecificAtom(MDefinition* str, JSAtom
* atom) : MUnaryInstruction(classOpcode, str), atom_(atom) { setGuard
(); setMovable(); setResultType(MIRType::String); } public: JSAtom
* atom() const { return atom_; } INSTRUCTION_HEADER(GuardSpecificAtom
) template <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)...); } MDefinition* str() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override;};class MGuardSpecificInt32 : public MUnaryInstruction
, public UnboxedInt32Policy<0>::Data { int32_t expected_
; explicit MGuardSpecificInt32(MDefinition* num, int32_t expected
) : MUnaryInstruction(classOpcode, num), expected_(expected) {
setGuard(); setMovable(); setResultType(MIRType::Int32); } public
: int32_t expected() const { return expected_; } INSTRUCTION_HEADER
(GuardSpecificInt32) template <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
)...); } MDefinition* num() const { return getOperand(0); } AliasSet
getAliasSet() const override { return AliasSet::None(); } MDefinition
* foldsTo(TempAllocator& alloc) override;};class MGuardStringToIndex
: public MUnaryInstruction, public StringPolicy<0>::Data
{ explicit MGuardStringToIndex(MDefinition* string) : MUnaryInstruction
(classOpcode, string) { setGuard(); setMovable(); setResultType
(MIRType::Int32); } public: INSTRUCTION_HEADER(GuardStringToIndex
) template <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)...); } MDefinition* string() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MGuardStringToInt32 : public MUnaryInstruction, public StringPolicy
<0>::Data { explicit MGuardStringToInt32(MDefinition* string
) : MUnaryInstruction(classOpcode, string) { setGuard(); setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(GuardStringToInt32) template <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
)...); } MDefinition* string() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MGuardStringToDouble
: public MUnaryInstruction, public StringPolicy<0>::Data
{ explicit MGuardStringToDouble(MDefinition* string) : MUnaryInstruction
(classOpcode, string) { setGuard(); setMovable(); setResultType
(MIRType::Double); } public: INSTRUCTION_HEADER(GuardStringToDouble
) template <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)...); } MDefinition* string() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MGuardNoDenseElements : public MUnaryInstruction, public ObjectPolicy
<0>::Data { explicit MGuardNoDenseElements(MDefinition*
object) : MUnaryInstruction(classOpcode, object) { setGuard(
); setMovable(); setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(GuardNoDenseElements) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override;};class MFunctionEnvironment
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MFunctionEnvironment(MDefinition* function) : MUnaryInstruction
(classOpcode, function) { setMovable(); setResultType(MIRType
::Object); } public: INSTRUCTION_HEADER(FunctionEnvironment) template
<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)...); } MDefinition* function() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override;};class MNewLexicalEnvironmentObject : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MNewLexicalEnvironmentObject(MDefinition* templateObj) : MUnaryInstruction
(classOpcode, templateObj) { setResultType(MIRType::Object); }
public: INSTRUCTION_HEADER(NewLexicalEnvironmentObject) template
<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)...); } MDefinition* templateObj()
const { return getOperand(0); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MNewClassBodyEnvironmentObject
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MNewClassBodyEnvironmentObject(MDefinition* templateObj
) : MUnaryInstruction(classOpcode, templateObj) { setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(NewClassBodyEnvironmentObject
) template <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)...); } MDefinition* templateObj()
const { return getOperand(0); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MNewVarEnvironmentObject
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MNewVarEnvironmentObject(MDefinition* templateObj
) : MUnaryInstruction(classOpcode, templateObj) { setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(NewVarEnvironmentObject
) template <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)...); } MDefinition* templateObj()
const { return getOperand(0); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MHomeObject : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MHomeObject(MDefinition* function) : MUnaryInstruction(classOpcode
, function) { setMovable(); setResultType(MIRType::Object); }
public: INSTRUCTION_HEADER(HomeObject) template <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)...); } MDefinition* function() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); }};class MAllocateAndStoreSlot : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { uint32_t slotOffset_; CompilerGCPointer<Shape*>
shape_; uint32_t numNewSlots_; explicit MAllocateAndStoreSlot
(MDefinition* object, MDefinition* value, uint32_t slotOffset
, Shape* shape, uint32_t numNewSlots) : MBinaryInstruction(classOpcode
, object, value), slotOffset_(slotOffset), shape_(shape), numNewSlots_
(numNewSlots) { } public: uint32_t slotOffset() const { return
slotOffset_; } Shape* shape() const { return shape_; } uint32_t
numNewSlots() const { return numNewSlots_; } INSTRUCTION_HEADER
(AllocateAndStoreSlot) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* value() const { return getOperand(1); } AliasSet
getAliasSet() const override; bool possiblyCalls() const override
{ return true; }};class MAddSlotAndCallAddPropHook : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { CompilerGCPointer<Shape*> shape_; explicit MAddSlotAndCallAddPropHook
(MDefinition* object, MDefinition* value, Shape* shape) : MBinaryInstruction
(classOpcode, object, value), shape_(shape) { } public: Shape
* shape() const { return shape_; } INSTRUCTION_HEADER(AddSlotAndCallAddPropHook
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* value() const { return
getOperand(1); } bool possiblyCalls() const override { return
true; }};class MGetNameCache : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MGetNameCache(MDefinition
* envObj) : MUnaryInstruction(classOpcode, envObj) { setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(GetNameCache) template
<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)...); } MDefinition* envObj() const
{ return getOperand(0); }};class MCallGetIntrinsicValue : public
MNullaryInstruction { CompilerGCPointer<PropertyName*>
name_; explicit MCallGetIntrinsicValue(PropertyName* name) :
MNullaryInstruction(classOpcode), name_(name) { setResultType
(MIRType::Value); } public: PropertyName* name() const { return
name_; } INSTRUCTION_HEADER(CallGetIntrinsicValue) template <
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)...); } bool possiblyCalls() const
override { return true; }};class MDeleteProperty : public MUnaryInstruction
, public BoxPolicy<0>::Data { CompilerGCPointer<PropertyName
*> name_; bool strict_; explicit MDeleteProperty(MDefinition
* value, PropertyName* name, bool strict) : MUnaryInstruction
(classOpcode, value), name_(name), strict_(strict) { setResultType
(MIRType::Boolean); } public: PropertyName* name() const { return
name_; } bool strict() const { return strict_; } INSTRUCTION_HEADER
(DeleteProperty) template <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)...); } MDefinition
* value() const { return getOperand(0); }};class MDeleteElement
: public MBinaryInstruction, public MixPolicy<BoxPolicy<
0>, BoxPolicy<1>>::Data { bool strict_; explicit MDeleteElement
(MDefinition* value, MDefinition* index, bool strict) : MBinaryInstruction
(classOpcode, value, index), strict_(strict) { setResultType(
MIRType::Boolean); } public: bool strict() const { return strict_
; } INSTRUCTION_HEADER(DeleteElement) template <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)...); } MDefinition* value() const { return getOperand
(0); } MDefinition* index() const { return getOperand(1); }};
class MValueToIterator : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MValueToIterator(MDefinition* value
) : MUnaryInstruction(classOpcode, value) { setResultType(MIRType
::Object); } public: INSTRUCTION_HEADER(ValueToIterator) template
<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)...); } MDefinition* value() const
{ return getOperand(0); }};class MIteratorHasIndices : public
MBinaryInstruction, public MixPolicy<ObjectPolicy<0>
, ObjectPolicy<1>>::Data { explicit MIteratorHasIndices
(MDefinition* object, MDefinition* iterator) : MBinaryInstruction
(classOpcode, object, iterator) { setResultType(MIRType::Boolean
); } public: INSTRUCTION_HEADER(IteratorHasIndices) template <
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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* iterator() const { return
getOperand(1); } AliasSet getAliasSet() const override;};class
MLoadSlotByIteratorIndex : public MBinaryInstruction, public
MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>>
::Data { explicit MLoadSlotByIteratorIndex(MDefinition* object
, MDefinition* iterator) : MBinaryInstruction(classOpcode, object
, iterator) { setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(LoadSlotByIteratorIndex) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* iterator() const { return getOperand(1); } AliasSet
getAliasSet() const override;};class MStoreSlotByIteratorIndex
: public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, ObjectPolicy<1>, BoxPolicy<2>>::Data
{ explicit MStoreSlotByIteratorIndex(MDefinition* object, MDefinition
* iterator, MDefinition* value) : MTernaryInstruction(classOpcode
, object, iterator, value) { } public: INSTRUCTION_HEADER(StoreSlotByIteratorIndex
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* iterator() const { return
getOperand(1); } MDefinition* value() const { return getOperand
(2); } AliasSet getAliasSet() const override;};class MLoadDOMExpandoValue
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MLoadDOMExpandoValue(MDefinition* proxy) : MUnaryInstruction
(classOpcode, proxy) { setMovable(); setResultType(MIRType::Value
); } public: INSTRUCTION_HEADER(LoadDOMExpandoValue) template
<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)...); } MDefinition* proxy() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MLoadDOMExpandoValueIgnoreGeneration
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MLoadDOMExpandoValueIgnoreGeneration(MDefinition*
proxy) : MUnaryInstruction(classOpcode, proxy) { setMovable(
); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(LoadDOMExpandoValueIgnoreGeneration) template <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)...); } MDefinition* proxy() const { return getOperand
(0); } AliasSet getAliasSet() const override; bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGuardDOMExpandoMissingOrGuardShape : public MUnaryInstruction
, public BoxPolicy<0>::Data { CompilerGCPointer<Shape
*> shape_; explicit MGuardDOMExpandoMissingOrGuardShape(MDefinition
* expando, Shape* shape) : MUnaryInstruction(classOpcode, expando
), shape_(shape) { setGuard(); setMovable(); setResultType(MIRType
::Value); } public: Shape* shape() const { return shape_; } INSTRUCTION_HEADER
(GuardDOMExpandoMissingOrGuardShape) template <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)...); } MDefinition* expando() const { return getOperand
(0); } AliasSet getAliasSet() const override; bool congruentTo
(const MDefinition* ins) const override;};class MStringLength
: public MUnaryInstruction, public StringPolicy<0>::Data
{ explicit MStringLength(MDefinition* string) : MUnaryInstruction
(classOpcode, string) { setMovable(); setResultType(MIRType::
Int32); } public: INSTRUCTION_HEADER(StringLength) template <
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)...); } MDefinition* string() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); } void
computeRange(TempAllocator& alloc) override; [[nodiscard
]] bool writeRecoverData( CompactBufferWriter& writer) const
override; bool canRecoverOnBailout() const override { return
true; } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStringLength
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MOptimizeSpreadCallCache
: public MUnaryInstruction, public BoxPolicy<0>::Data {
explicit MOptimizeSpreadCallCache(MDefinition* value) : MUnaryInstruction
(classOpcode, value) { setResultType(MIRType::Value); } public
: INSTRUCTION_HEADER(OptimizeSpreadCallCache) template <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)...); } MDefinition* value() const { return
getOperand(0); }};class MIteratorMore : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MIteratorMore
(MDefinition* iterator) : MUnaryInstruction(classOpcode, iterator
) { setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(IteratorMore) template <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)...); } MDefinition
* iterator() const { return getOperand(0); }};class MIsNoIter
: public MUnaryInstruction, public NoTypePolicy::Data { explicit
MIsNoIter(MDefinition* def) : MUnaryInstruction(classOpcode,
def) { setMovable(); setResultType(MIRType::Boolean); } public
: INSTRUCTION_HEADER(IsNoIter) template <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
)...); } MDefinition* def() const { return getOperand(0); } AliasSet
getAliasSet() const override { return AliasSet::None(); }};class
MIteratorEnd : public MUnaryInstruction, public ObjectPolicy
<0>::Data { explicit MIteratorEnd(MDefinition* iterator
) : MUnaryInstruction(classOpcode, iterator) { } public: INSTRUCTION_HEADER
(IteratorEnd) template <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)...); } MDefinition
* iterator() const { return getOperand(0); }};class MCloseIterCache
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ uint8_t completionKind_; explicit MCloseIterCache(MDefinition
* iter, uint8_t completionKind) : MUnaryInstruction(classOpcode
, iter), completionKind_(completionKind) { } public: uint8_t completionKind
() const { return completionKind_; } INSTRUCTION_HEADER(CloseIterCache
) template <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)...); } MDefinition* iter() const {
return getOperand(0); } bool possiblyCalls() const override {
return true; }};class MOptimizeGetIteratorCache : public MUnaryInstruction
, public BoxPolicy<0>::Data { explicit MOptimizeGetIteratorCache
(MDefinition* value) : MUnaryInstruction(classOpcode, value) {
setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(OptimizeGetIteratorCache) template <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
)...); } MDefinition* value() const { return getOperand(0); }
};class MNewPrivateName : public MNullaryInstruction { CompilerGCPointer
<JSAtom*> name_; explicit MNewPrivateName(JSAtom* name)
: MNullaryInstruction(classOpcode), name_(name) { setResultType
(MIRType::Symbol); } public: JSAtom* name() const { return name_
; } INSTRUCTION_HEADER(NewPrivateName) template <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)...); } bool possiblyCalls() const override { return
true; }};class MInstanceOfCache : public MBinaryInstruction,
public MixPolicy<BoxPolicy<0>, ObjectPolicy<1>>
::Data { explicit MInstanceOfCache(MDefinition* obj, MDefinition
* proto) : MBinaryInstruction(classOpcode, obj, proto) { setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(InstanceOfCache
) template <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)...); } MDefinition* obj() const {
return getOperand(0); } MDefinition* proto() const { return getOperand
(1); }};class MArgumentsLength : public MNullaryInstruction {
explicit MArgumentsLength() : MNullaryInstruction(classOpcode
) { setMovable(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(ArgumentsLength) template <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)...); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } void computeRange(TempAllocator& alloc) override
; [[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
{ return true; }};class MGetFrameArgument : public MUnaryInstruction
, public UnboxedInt32Policy<0>::Data { explicit MGetFrameArgument
(MDefinition* index) : MUnaryInstruction(classOpcode, index) {
setMovable(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(GetFrameArgument) template <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)...); } MDefinition
* index() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGetFrameArgumentHole : public MBinaryInstruction
, public MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy
<1>>::Data { explicit MGetFrameArgumentHole(MDefinition
* index, MDefinition* length) : MBinaryInstruction(classOpcode
, index, length) { setGuard(); setMovable(); setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(GetFrameArgumentHole) template
<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)...); } MDefinition* index() const
{ return getOperand(0); } MDefinition* length() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MNewTarget : public MNullaryInstruction { explicit MNewTarget
() : MNullaryInstruction(classOpcode) { setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(NewTarget) template
<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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MRest : public MUnaryInstruction, public UnboxedInt32Policy
<0>::Data { unsigned numFormals_; CompilerGCPointer<
Shape*> shape_; explicit MRest(MDefinition* numActuals, unsigned
numFormals, Shape* shape) : MUnaryInstruction(classOpcode, numActuals
), numFormals_(numFormals), shape_(shape) { setResultType(MIRType
::Object); } public: unsigned numFormals() const { return numFormals_
; } Shape* shape() const { return shape_; } INSTRUCTION_HEADER
(Rest) template <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)...); } MDefinition
* numActuals() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool possiblyCalls
() const override { return true; } [[nodiscard]] bool writeRecoverData
( CompactBufferWriter& writer) const override; bool canRecoverOnBailout
() const override { return true; }};class MAssertCanElidePostWriteBarrier
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>>::Data { explicit MAssertCanElidePostWriteBarrier
(MDefinition* object, MDefinition* value) : MBinaryInstruction
(classOpcode, object, value) { setGuard(); setResultType(MIRType
::None); } public: INSTRUCTION_HEADER(AssertCanElidePostWriteBarrier
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* value() const { return
getOperand(1); } AliasSet getAliasSet() const override { return
AliasSet::None(); }};class MNewNamedLambdaObject : public MNullaryInstruction
{ CompilerGCPointer<NamedLambdaObject*> templateObj_; explicit
MNewNamedLambdaObject(NamedLambdaObject* templateObj) : MNullaryInstruction
(classOpcode), templateObj_(templateObj) { setResultType(MIRType
::Object); } public: NamedLambdaObject* templateObj() const {
return templateObj_; } INSTRUCTION_HEADER(NewNamedLambdaObject
) template <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)...); } AliasSet getAliasSet() const
override { return AliasSet::None(); }};class MIsConstructor :
public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MIsConstructor(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setMovable(); setResultType(MIRType::
Boolean); } public: INSTRUCTION_HEADER(IsConstructor) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MIsCrossRealmArrayConstructor : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MIsCrossRealmArrayConstructor
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(IsCrossRealmArrayConstructor) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MIsObject :
public MUnaryInstruction, public BoxPolicy<0>::Data { explicit
MIsObject(MDefinition* object) : MUnaryInstruction(classOpcode
, object) { setMovable(); setResultType(MIRType::Boolean); } public
: INSTRUCTION_HEADER(IsObject) template <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
)...); } MDefinition* object() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MIsNullOrUndefined :
public MUnaryInstruction, public NoTypePolicy::Data { explicit
MIsNullOrUndefined(MDefinition* value) : MUnaryInstruction(classOpcode
, value) { setMovable(); setResultType(MIRType::Boolean); } public
: INSTRUCTION_HEADER(IsNullOrUndefined) template <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)...); } MDefinition* value() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } MDefinition* foldsTo(TempAllocator& alloc
) override; bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); } bool canConsumeFloat32
(MUse* use) const override { return true; }};class MObjectClassToString
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MObjectClassToString(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setGuard(); setMovable(); setResultType
(MIRType::String); } public: INSTRUCTION_HEADER(ObjectClassToString
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); } bool possiblyCalls() const override
{ return true; }};class MCheckReturn : public MBinaryInstruction
, public MixPolicy<BoxPolicy<0>, BoxPolicy<1>>
::Data { explicit MCheckReturn(MDefinition* returnValue, MDefinition
* thisValue) : MBinaryInstruction(classOpcode, returnValue, thisValue
) { setGuard(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(CheckReturn) template <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)...); } MDefinition
* returnValue() const { return getOperand(0); } MDefinition* thisValue
() const { return getOperand(1); } AliasSet getAliasSet() const
override; MDefinition* foldsTo(TempAllocator& alloc) override
;};class MCheckThis : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MCheckThis(MDefinition* thisValue)
: MUnaryInstruction(classOpcode, thisValue) { setGuard(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(CheckThis) template
<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)...); } MDefinition* thisValue() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; MDefinition* foldsTo(TempAllocator& alloc) override;};class
MAsyncResolve : public MBinaryInstruction, public MixPolicy<
ObjectPolicy<0>, BoxPolicy<1>>::Data { explicit
MAsyncResolve(MDefinition* generator, MDefinition* value) : MBinaryInstruction
(classOpcode, generator, value) { setResultType(MIRType::Object
); } public: INSTRUCTION_HEADER(AsyncResolve) template <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)...); } MDefinition* generator() const { return
getOperand(0); } MDefinition* value() const { return getOperand
(1); }};class MAsyncReject : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, BoxPolicy
<2>>::Data { explicit MAsyncReject(MDefinition* generator
, MDefinition* reason, MDefinition* stack) : MTernaryInstruction
(classOpcode, generator, reason, stack) { setResultType(MIRType
::Object); } public: INSTRUCTION_HEADER(AsyncReject) template
<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)...); } MDefinition* generator() const
{ return getOperand(0); } MDefinition* reason() const { return
getOperand(1); } MDefinition* stack() const { return getOperand
(2); }};class MGeneratorReturn : public MUnaryInstruction, public
BoxPolicy<0>::Data { explicit MGeneratorReturn(MDefinition
* input) : MUnaryInstruction(classOpcode, input) { setGuard()
; } public: INSTRUCTION_HEADER(GeneratorReturn) template <
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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); }};class MAsyncAwait : public MBinaryInstruction
, public MixPolicy<BoxPolicy<0>, ObjectPolicy<1>>
::Data { explicit MAsyncAwait(MDefinition* value, MDefinition
* generator) : MBinaryInstruction(classOpcode, value, generator
) { setResultType(MIRType::Object); } public: INSTRUCTION_HEADER
(AsyncAwait) template <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)...); } MDefinition
* value() const { return getOperand(0); } MDefinition* generator
() const { return getOperand(1); }};class MCheckThisReinit : public
MUnaryInstruction, public BoxPolicy<0>::Data { explicit
MCheckThisReinit(MDefinition* thisValue) : MUnaryInstruction
(classOpcode, thisValue) { setGuard(); setResultType(MIRType::
Value); } public: INSTRUCTION_HEADER(CheckThisReinit) template
<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)...); } MDefinition* thisValue() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; MDefinition* foldsTo(TempAllocator& alloc) override;};class
MCanSkipAwait : public MUnaryInstruction, public BoxPolicy<
0>::Data { explicit MCanSkipAwait(MDefinition* value) : MUnaryInstruction
(classOpcode, value) { setResultType(MIRType::Boolean); } public
: INSTRUCTION_HEADER(CanSkipAwait) template <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
)...); } MDefinition* value() const { return getOperand(0); }
};class MIncrementWarmUpCounter : public MNullaryInstruction {
CompilerGCPointer<JSScript*> script_; explicit MIncrementWarmUpCounter
(JSScript* script) : MNullaryInstruction(classOpcode), script_
(script) { } public: JSScript* script() const { return script_
; } INSTRUCTION_HEADER(IncrementWarmUpCounter) template <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)...); } AliasSet getAliasSet() const override
{ return AliasSet::None(); }};class MCheckIsObj : public MUnaryInstruction
, public BoxPolicy<0>::Data { uint8_t checkKind_; explicit
MCheckIsObj(MDefinition* value, uint8_t checkKind) : MUnaryInstruction
(classOpcode, value), checkKind_(checkKind) { setGuard(); setResultType
(MIRType::Object); } public: uint8_t checkKind() const { return
checkKind_; } INSTRUCTION_HEADER(CheckIsObj) template <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)...); } MDefinition* value() const { return
getOperand(0); } AliasSet getAliasSet() const override; MDefinition
* foldsTo(TempAllocator& alloc) override;};class MCheckObjCoercible
: public MUnaryInstruction, public BoxPolicy<0>::Data {
explicit MCheckObjCoercible(MDefinition* checkValue) : MUnaryInstruction
(classOpcode, checkValue) { setGuard(); setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(CheckObjCoercible) template
<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)...); } MDefinition* checkValue() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; MDefinition* foldsTo(TempAllocator& alloc) override;};class
MCheckClassHeritage : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MCheckClassHeritage(MDefinition* heritage
) : MUnaryInstruction(classOpcode, heritage) { setGuard(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(CheckClassHeritage
) template <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)...); } MDefinition* heritage() const
{ return getOperand(0); }};class MDebugCheckSelfHosted : public
MUnaryInstruction, public BoxPolicy<0>::Data { explicit
MDebugCheckSelfHosted(MDefinition* checkValue) : MUnaryInstruction
(classOpcode, checkValue) { setGuard(); setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(DebugCheckSelfHosted) template
<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)...); } MDefinition* checkValue() const
{ return getOperand(0); }};class MIsPackedArray : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MIsPackedArray
(MDefinition* object) : MUnaryInstruction(classOpcode, object
) { setMovable(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(IsPackedArray) template <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)...); } MDefinition
* object() const { return getOperand(0); } AliasSet getAliasSet
() const override;};class MGuardArrayIsPacked : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MGuardArrayIsPacked
(MDefinition* array) : MUnaryInstruction(classOpcode, array) {
setGuard(); setMovable(); setResultType(MIRType::Object); } public
: INSTRUCTION_HEADER(GuardArrayIsPacked) template <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)...); } MDefinition* array() const { return
getOperand(0); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGetPrototypeOf : public MUnaryInstruction, public
ObjectPolicy<0>::Data { explicit MGetPrototypeOf(MDefinition
* target) : MUnaryInstruction(classOpcode, target) { setGuard
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(GetPrototypeOf) template <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)...); } MDefinition
* target() const { return getOperand(0); }};class MObjectWithProto
: public MUnaryInstruction, public BoxPolicy<0>::Data {
explicit MObjectWithProto(MDefinition* prototype) : MUnaryInstruction
(classOpcode, prototype) { setGuard(); setResultType(MIRType::
Object); } public: INSTRUCTION_HEADER(ObjectWithProto) template
<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)...); } MDefinition* prototype() const
{ return getOperand(0); } bool possiblyCalls() const override
{ return true; }};class MBuiltinObject : public MNullaryInstruction
{ BuiltinObjectKind builtinObjectKind_; explicit MBuiltinObject
(BuiltinObjectKind builtinObjectKind) : MNullaryInstruction(classOpcode
), builtinObjectKind_(builtinObjectKind) { setResultType(MIRType
::Object); } public: BuiltinObjectKind builtinObjectKind() const
{ return builtinObjectKind_; } INSTRUCTION_HEADER(BuiltinObject
) template <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)...); } bool possiblyCalls() const
override { return true; }};class MSuperFunction : public MUnaryInstruction
, public ObjectPolicy<0>::Data { explicit MSuperFunction
(MDefinition* callee) : MUnaryInstruction(classOpcode, callee
) { setMovable(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(SuperFunction) template <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)...); } MDefinition
* callee() const { return getOperand(0); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); }};class MInitHomeObject
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>>::Data { explicit MInitHomeObject
(MDefinition* function, MDefinition* homeObject) : MBinaryInstruction
(classOpcode, function, homeObject) { setResultType(MIRType::
Object); } public: INSTRUCTION_HEADER(InitHomeObject) template
<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)...); } MDefinition* function() const
{ return getOperand(0); } MDefinition* homeObject() const { return
getOperand(1); } AliasSet getAliasSet() const override;};class
MIsTypedArrayConstructor : public MUnaryInstruction, public ObjectPolicy
<0>::Data { explicit MIsTypedArrayConstructor(MDefinition
* object) : MUnaryInstruction(classOpcode, object) { setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(IsTypedArrayConstructor
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); }};class MLoadValueTag : public MUnaryInstruction
, public BoxPolicy<0>::Data { explicit MLoadValueTag(MDefinition
* value) : MUnaryInstruction(classOpcode, value) { setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(LoadValueTag) template <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)...); } MDefinition
* value() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } bool congruentTo
(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MLoadWrapperTarget : public MUnaryInstruction
, public ObjectPolicy<0>::Data { bool fallible_; explicit
MLoadWrapperTarget(MDefinition* object, bool fallible) : MUnaryInstruction
(classOpcode, object), fallible_(fallible) { setMovable(); setResultType
(MIRType::Object); } public: bool fallible() const { return fallible_
; } INSTRUCTION_HEADER(LoadWrapperTarget) template <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)...); } MDefinition* object() const { return
getOperand(0); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override;};class MGuardHasGetterSetter
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ jsid propId_; CompilerGCPointer<GetterSetter*> getterSetter_
; explicit MGuardHasGetterSetter(MDefinition* object, jsid propId
, GetterSetter* getterSetter) : MUnaryInstruction(classOpcode
, object), propId_(propId), getterSetter_(getterSetter) { setGuard
(); setMovable(); setResultType(MIRType::Object); } public: jsid
propId() const { return propId_; } GetterSetter* getterSetter
() const { return getterSetter_; } INSTRUCTION_HEADER(GuardHasGetterSetter
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override; bool
possiblyCalls() const override { return true; }};class MGuardIsExtensible
: public MUnaryInstruction, public ObjectPolicy<0>::Data
{ explicit MGuardIsExtensible(MDefinition* object) : MUnaryInstruction
(classOpcode, object) { setGuard(); setMovable(); setResultType
(MIRType::Object); } public: INSTRUCTION_HEADER(GuardIsExtensible
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } AliasSet getAliasSet() const override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MGuardInt32IsNonNegative
: public MUnaryInstruction, public UnboxedInt32Policy<0>
::Data { explicit MGuardInt32IsNonNegative(MDefinition* index
) : MUnaryInstruction(classOpcode, index) { setGuard(); setMovable
(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(GuardInt32IsNonNegative) template <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
)...); } MDefinition* index() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MGuardInt32Range : public
MUnaryInstruction, public UnboxedInt32Policy<0>::Data {
int32_t minimum_; int32_t maximum_; explicit MGuardInt32Range
(MDefinition* input, int32_t minimum, int32_t maximum) : MUnaryInstruction
(classOpcode, input), minimum_(minimum), maximum_(maximum) { setGuard
(); setMovable(); setResultType(MIRType::Int32); } public: int32_t
minimum() const { return minimum_; } int32_t maximum() const
{ return maximum_; } INSTRUCTION_HEADER(GuardInt32Range) template
<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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } MDefinition* foldsTo(TempAllocator
& alloc) override; bool congruentTo(const MDefinition* ins
) const override { return congruentIfOperandsEqual(ins); }};class
MGuardIndexIsNotDenseElement : public MBinaryInstruction, public
MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>>
::Data { explicit MGuardIndexIsNotDenseElement(MDefinition* object
, MDefinition* index) : MBinaryInstruction(classOpcode, object
, index) { setGuard(); setMovable(); setResultType(MIRType::Int32
); } public: INSTRUCTION_HEADER(GuardIndexIsNotDenseElement) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MGuardIndexIsValidUpdateOrAdd : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MGuardIndexIsValidUpdateOrAdd(
MDefinition* object, MDefinition* index) : MBinaryInstruction
(classOpcode, object, index) { setGuard(); setMovable(); setResultType
(MIRType::Int32); } public: INSTRUCTION_HEADER(GuardIndexIsValidUpdateOrAdd
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MCallAddOrUpdateSparseElement : public MTernaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>, BoxPolicy<2>>::Data { bool strict_; explicit
MCallAddOrUpdateSparseElement(MDefinition* object, MDefinition
* index, MDefinition* value, bool strict) : MTernaryInstruction
(classOpcode, object, index, value), strict_(strict) { } public
: bool strict() const { return strict_; } INSTRUCTION_HEADER(
CallAddOrUpdateSparseElement) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* index() const { return getOperand(1); } MDefinition
* value() const { return getOperand(2); } bool possiblyCalls(
) const override { return true; }};class MCallGetSparseElement
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, UnboxedInt32Policy<1>>::Data { explicit MCallGetSparseElement
(MDefinition* object, MDefinition* index) : MBinaryInstruction
(classOpcode, object, index) { setResultType(MIRType::Value);
} public: INSTRUCTION_HEADER(CallGetSparseElement) template <
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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } bool possiblyCalls() const override { return
true; }};class MCallNativeGetElement : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MCallNativeGetElement(MDefinition
* object, MDefinition* index) : MBinaryInstruction(classOpcode
, object, index) { setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(CallNativeGetElement) template <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
)...); } MDefinition* object() const { return getOperand(0); }
MDefinition* index() const { return getOperand(1); } bool possiblyCalls
() const override { return true; }};class MCallNativeGetElementSuper
: public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, UnboxedInt32Policy<1>, BoxPolicy<2>>
::Data { explicit MCallNativeGetElementSuper(MDefinition* object
, MDefinition* index, MDefinition* receiver) : MTernaryInstruction
(classOpcode, object, index, receiver) { setResultType(MIRType
::Value); } public: INSTRUCTION_HEADER(CallNativeGetElementSuper
) template <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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } MDefinition* receiver() const { return getOperand
(2); } bool possiblyCalls() const override { return true; }};
class MCallObjectHasSparseElement : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy
<1>>::Data { explicit MCallObjectHasSparseElement(MDefinition
* object, MDefinition* index) : MBinaryInstruction(classOpcode
, object, index) { setGuard(); setResultType(MIRType::Boolean
); } public: INSTRUCTION_HEADER(CallObjectHasSparseElement) template
<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)...); } MDefinition* object() const
{ return getOperand(0); } MDefinition* index() const { return
getOperand(1); } AliasSet getAliasSet() const override; bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
};class MBigIntAsIntN : public MBinaryInstruction, public MixPolicy
<UnboxedInt32Policy<0>, BigIntPolicy<1>>::Data
{ explicit MBigIntAsIntN(MDefinition* bits, MDefinition* input
) : MBinaryInstruction(classOpcode, bits, input) { setMovable
(); setResultType(MIRType::BigInt); } public: INSTRUCTION_HEADER
(BigIntAsIntN) template <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)...); } MDefinition
* bits() const { return getOperand(0); } MDefinition* input()
const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
[[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
{ return true; } bool canClone() const override { return true
; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector
& inputs) const override { MInstruction* res = new (alloc
) MBigIntAsIntN(*this); for (size_t i = 0; i < numOperands
(); i++) res->replaceOperand(i, inputs[i]); return res; }}
;class MBigIntAsUintN : public MBinaryInstruction, public MixPolicy
<UnboxedInt32Policy<0>, BigIntPolicy<1>>::Data
{ explicit MBigIntAsUintN(MDefinition* bits, MDefinition* input
) : MBinaryInstruction(classOpcode, bits, input) { setMovable
(); setResultType(MIRType::BigInt); } public: INSTRUCTION_HEADER
(BigIntAsUintN) template <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)...); } MDefinition
* bits() const { return getOperand(0); } MDefinition* input()
const { return getOperand(1); } AliasSet getAliasSet() const
override { return AliasSet::None(); } bool congruentTo(const
MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); } bool possiblyCalls() const override { return true; }
[[nodiscard]] bool writeRecoverData( CompactBufferWriter&
writer) const override; bool canRecoverOnBailout() const override
{ return true; } bool canClone() const override { return true
; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector
& inputs) const override { MInstruction* res = new (alloc
) MBigIntAsUintN(*this); for (size_t i = 0; i < numOperands
(); i++) res->replaceOperand(i, inputs[i]); return res; }}
;class MGuardNonGCThing : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MGuardNonGCThing(MDefinition* input
) : MUnaryInstruction(classOpcode, input) { setGuard(); setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(GuardNonGCThing) template <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)...); } MDefinition
* input() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } MDefinition* foldsTo
(TempAllocator& alloc) override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MToHashableNonGCThing : public MUnaryInstruction, public
BoxPolicy<0>::Data { explicit MToHashableNonGCThing(MDefinition
* input) : MUnaryInstruction(classOpcode, input) { setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(ToHashableNonGCThing) template <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
)...); } MDefinition* input() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } bool congruentTo(const MDefinition* ins) const override
{ return congruentIfOperandsEqual(ins); }};class MToHashableString
: public MUnaryInstruction, public StringPolicy<0>::Data
{ explicit MToHashableString(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::String
); } public: INSTRUCTION_HEADER(ToHashableString) template <
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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} bool possiblyCalls() const override { return true; }};class
MToHashableValue : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MToHashableValue(MDefinition* input
) : MUnaryInstruction(classOpcode, input) { setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(ToHashableValue
) template <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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
} bool possiblyCalls() const override { return true; }};class
MHashNonGCThing : public MUnaryInstruction, public BoxPolicy
<0>::Data { explicit MHashNonGCThing(MDefinition* input
) : MUnaryInstruction(classOpcode, input) { setMovable(); setResultType
(MIRType::Int32); } public: INSTRUCTION_HEADER(HashNonGCThing
) template <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)...); } MDefinition* input() const
{ return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MHashString : public MUnaryInstruction, public StringPolicy
<0>::Data { explicit MHashString(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::Int32
); } public: INSTRUCTION_HEADER(HashString) template <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)...); } MDefinition* input() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MHashSymbol : public MUnaryInstruction, public SymbolPolicy<
0>::Data { explicit MHashSymbol(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::Int32
); } public: INSTRUCTION_HEADER(HashSymbol) template <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)...); } MDefinition* input() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MHashBigInt : public MUnaryInstruction, public BigIntPolicy<
0>::Data { explicit MHashBigInt(MDefinition* input) : MUnaryInstruction
(classOpcode, input) { setMovable(); setResultType(MIRType::Int32
); } public: INSTRUCTION_HEADER(HashBigInt) template <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)...); } MDefinition* input() const { return
getOperand(0); } AliasSet getAliasSet() const override { return
AliasSet::None(); } bool congruentTo(const MDefinition* ins)
const override { return congruentIfOperandsEqual(ins); }};class
MHashObject : public MBinaryInstruction, public MixPolicy<
ObjectPolicy<0>, BoxPolicy<1>>::Data { explicit
MHashObject(MDefinition* set, MDefinition* input) : MBinaryInstruction
(classOpcode, set, input) { setResultType(MIRType::Int32); } public
: INSTRUCTION_HEADER(HashObject) template <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
)...); } MDefinition* set() const { return getOperand(0); } MDefinition
* input() const { return getOperand(1); } AliasSet getAliasSet
() const override { return AliasSet::None(); }};class MHashValue
: public MBinaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>>::Data { explicit MHashValue
(MDefinition* set, MDefinition* input) : MBinaryInstruction(classOpcode
, set, input) { setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(HashValue) template <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)...); } MDefinition
* set() const { return getOperand(0); } MDefinition* input() const
{ return getOperand(1); } AliasSet getAliasSet() const override
{ return AliasSet::None(); }};class MSetObjectHasNonBigInt :
public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>, UnboxedInt32Policy<2>>
::Data { explicit MSetObjectHasNonBigInt(MDefinition* set, MDefinition
* value, MDefinition* hash) : MTernaryInstruction(classOpcode
, set, value, hash) { setMovable(); setResultType(MIRType::Boolean
); } public: INSTRUCTION_HEADER(SetObjectHasNonBigInt) template
<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)...); } MDefinition* set() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MSetObjectHasBigInt : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MSetObjectHasBigInt(MDefinition
* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, set, value, hash) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(SetObjectHasBigInt
) template <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)...); } MDefinition* set() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MSetObjectHasValue : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MSetObjectHasValue(MDefinition
* set, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, set, value, hash) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(SetObjectHasValue
) template <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)...); } MDefinition* set() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MSetObjectHasValueVMCall : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { explicit MSetObjectHasValueVMCall(MDefinition* set, MDefinition
* value) : MBinaryInstruction(classOpcode, set, value) { setMovable
(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(SetObjectHasValueVMCall) template <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
)...); } MDefinition* set() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); } bool possiblyCalls
() const override { return true; }};class MSetObjectSize : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MSetObjectSize(MDefinition* set) : MUnaryInstruction(classOpcode
, set) { setMovable(); setResultType(MIRType::Int32); } public
: INSTRUCTION_HEADER(SetObjectSize) template <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
)...); } MDefinition* set() const { return getOperand(0); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectHasNonBigInt : public MTernaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>
, UnboxedInt32Policy<2>>::Data { explicit MMapObjectHasNonBigInt
(MDefinition* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, map, value, hash) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(MapObjectHasNonBigInt
) template <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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectHasBigInt : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MMapObjectHasBigInt(MDefinition
* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, map, value, hash) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(MapObjectHasBigInt
) template <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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectHasValue : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MMapObjectHasValue(MDefinition
* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, map, value, hash) { setMovable(); setResultType
(MIRType::Boolean); } public: INSTRUCTION_HEADER(MapObjectHasValue
) template <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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectHasValueVMCall : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { explicit MMapObjectHasValueVMCall(MDefinition* map, MDefinition
* value) : MBinaryInstruction(classOpcode, map, value) { setMovable
(); setResultType(MIRType::Boolean); } public: INSTRUCTION_HEADER
(MapObjectHasValueVMCall) template <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
)...); } MDefinition* map() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); } bool possiblyCalls
() const override { return true; }};class MMapObjectGetNonBigInt
: public MTernaryInstruction, public MixPolicy<ObjectPolicy
<0>, BoxPolicy<1>, UnboxedInt32Policy<2>>
::Data { explicit MMapObjectGetNonBigInt(MDefinition* map, MDefinition
* value, MDefinition* hash) : MTernaryInstruction(classOpcode
, map, value, hash) { setMovable(); setResultType(MIRType::Value
); } public: INSTRUCTION_HEADER(MapObjectGetNonBigInt) template
<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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectGetBigInt : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MMapObjectGetBigInt(MDefinition
* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, map, value, hash) { setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(MapObjectGetBigInt
) template <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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectGetValue : public MTernaryInstruction, public
MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, UnboxedInt32Policy
<2>>::Data { explicit MMapObjectGetValue(MDefinition
* map, MDefinition* value, MDefinition* hash) : MTernaryInstruction
(classOpcode, map, value, hash) { setMovable(); setResultType
(MIRType::Value); } public: INSTRUCTION_HEADER(MapObjectGetValue
) template <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)...); } MDefinition* map() const {
return getOperand(0); } MDefinition* value() const { return getOperand
(1); } MDefinition* hash() const { return getOperand(2); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MMapObjectGetValueVMCall : public MBinaryInstruction
, public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>
::Data { explicit MMapObjectGetValueVMCall(MDefinition* map, MDefinition
* value) : MBinaryInstruction(classOpcode, map, value) { setMovable
(); setResultType(MIRType::Value); } public: INSTRUCTION_HEADER
(MapObjectGetValueVMCall) template <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
)...); } MDefinition* map() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); } AliasSet getAliasSet
() const override; bool congruentTo(const MDefinition* ins) const
override { return congruentIfOperandsEqual(ins); } bool possiblyCalls
() const override { return true; }};class MMapObjectSize : public
MUnaryInstruction, public ObjectPolicy<0>::Data { explicit
MMapObjectSize(MDefinition* map) : MUnaryInstruction(classOpcode
, map) { setMovable(); setResultType(MIRType::Int32); } public
: INSTRUCTION_HEADER(MapObjectSize) template <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
)...); } MDefinition* map() const { return getOperand(0); } AliasSet
getAliasSet() const override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MWasmBoundsCheckRange32 : public MTernaryInstruction
, public NoTypePolicy::Data { wasm::BytecodeOffset bytecodeOffset_
; explicit MWasmBoundsCheckRange32(MDefinition* index, MDefinition
* length, MDefinition* limit, wasm::BytecodeOffset bytecodeOffset
) : MTernaryInstruction(classOpcode, index, length, limit), bytecodeOffset_
(bytecodeOffset) { setResultType(MIRType::Int32); } public: wasm
::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_
; } INSTRUCTION_HEADER(WasmBoundsCheckRange32) template <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)...); } MDefinition* index() const { return
getOperand(0); } MDefinition* length() const { return getOperand
(1); } MDefinition* limit() const { return getOperand(2); } bool
congruentTo(const MDefinition* ins) const override { return congruentIfOperandsEqual
(ins); }};class MWasmExtendU32Index : public MUnaryInstruction
, public NoTypePolicy::Data { explicit MWasmExtendU32Index(MDefinition
* input) : MUnaryInstruction(classOpcode, input) { setMovable
(); setResultType(MIRType::Int64); } public: INSTRUCTION_HEADER
(WasmExtendU32Index) template <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
)...); } MDefinition* input() const { return getOperand(0); }
AliasSet getAliasSet() const override { return AliasSet::None
(); } MDefinition* foldsTo(TempAllocator& alloc) override
; bool congruentTo(const MDefinition* ins) const override { return
congruentIfOperandsEqual(ins); }};class MWasmWrapU32Index : public
MUnaryInstruction, public NoTypePolicy::Data { explicit MWasmWrapU32Index
(MDefinition* input) : MUnaryInstruction(classOpcode, input) {
setMovable(); setResultType(MIRType::Int32); } public: INSTRUCTION_HEADER
(WasmWrapU32Index) template <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)...); } MDefinition
* input() const { return getOperand(0); } AliasSet getAliasSet
() const override { return AliasSet::None(); } MDefinition* foldsTo
(TempAllocator& alloc) override; bool congruentTo(const MDefinition
* ins) const override { return congruentIfOperandsEqual(ins);
}};class MWasmFence : public MNullaryInstruction { explicit MWasmFence
() : MNullaryInstruction(classOpcode) { setGuard(); } public:
INSTRUCTION_HEADER(WasmFence) template <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
)...); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MWasmFence
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MWasmStackSwitchToMain
: public MTernaryInstruction, public NoTypePolicy::Data { explicit
MWasmStackSwitchToMain(MDefinition* suspender, MDefinition* fn
, MDefinition* data) : MTernaryInstruction(classOpcode, suspender
, fn, data) { } public: INSTRUCTION_HEADER(WasmStackSwitchToMain
) template <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)...); } MDefinition* suspender() const
{ return getOperand(0); } MDefinition* fn() const { return getOperand
(1); } MDefinition* data() const { return getOperand(2); }};class
MWasmStackSwitchToSuspendable : public MTernaryInstruction, public
NoTypePolicy::Data { explicit MWasmStackSwitchToSuspendable(
MDefinition* suspender, MDefinition* fn, MDefinition* data) :
MTernaryInstruction(classOpcode, suspender, fn, data) { } public
: INSTRUCTION_HEADER(WasmStackSwitchToSuspendable) template <
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)...); } MDefinition* suspender() const
{ return getOperand(0); } MDefinition* fn() const { return getOperand
(1); } MDefinition* data() const { return getOperand(2); }};class
MWasmStackContinueOnSuspendable : public MUnaryInstruction, public
NoTypePolicy::Data { explicit MWasmStackContinueOnSuspendable
(MDefinition* suspender) : MUnaryInstruction(classOpcode, suspender
) { } public: INSTRUCTION_HEADER(WasmStackContinueOnSuspendable
) template <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)...); } MDefinition* suspender() const
{ return getOperand(0); }};class MWasmShiftSimd128 : public MBinaryInstruction
, public NoTypePolicy::Data { wasm::SimdOp simdOp_; explicit MWasmShiftSimd128
(MDefinition* lhs, MDefinition* rhs, wasm::SimdOp simdOp) : MBinaryInstruction
(classOpcode, lhs, rhs), simdOp_(simdOp) { setMovable(); setResultType
(MIRType::Simd128); } public: wasm::SimdOp simdOp() const { return
simdOp_; } INSTRUCTION_HEADER(WasmShiftSimd128) template <
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)...); } MDefinition* lhs() const {
return getOperand(0); } MDefinition* rhs() const { return getOperand
(1); } AliasSet getAliasSet() const override { return AliasSet
::None(); } bool congruentTo(const MDefinition* ins) const override
; bool canClone() const override { return true; } MInstruction
* clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MWasmShiftSimd128
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }};class MWasmShuffleSimd128
: public MBinaryInstruction, public NoTypePolicy::Data { SimdShuffle
shuffle_; explicit MWasmShuffleSimd128(MDefinition* lhs, MDefinition
* rhs, SimdShuffle shuffle) : MBinaryInstruction(classOpcode,
lhs, rhs), shuffle_(shuffle) { setMovable(); setResultType(MIRType
::Simd128); } public: SimdShuffle shuffle() const { return shuffle_
; } INSTRUCTION_HEADER(WasmShuffleSimd128) template <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)...); } MDefinition* lhs() const { return getOperand
(0); } MDefinition* rhs() const { return getOperand(1); } AliasSet
getAliasSet() const override { return AliasSet::None(); } bool
congruentTo(const MDefinition* ins) const override; bool canClone
() const override { return true; } MInstruction* clone(TempAllocator
& alloc, const MDefinitionVector& inputs) const override
{ MInstruction* res = new (alloc) MWasmShuffleSimd128(*this)
; for (size_t i = 0; i < numOperands(); i++) res->replaceOperand
(i, inputs[i]); return res; }};class MWasmUnarySimd128 : public
MUnaryInstruction, public NoTypePolicy::Data { wasm::SimdOp simdOp_
; explicit MWasmUnarySimd128(MDefinition* src, wasm::SimdOp simdOp
) : MUnaryInstruction(classOpcode, src), simdOp_(simdOp) { setMovable
(); setResultType(MIRType::Simd128); } public: wasm::SimdOp simdOp
() const { return simdOp_; } INSTRUCTION_HEADER(WasmUnarySimd128
) template <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)...); } MDefinition* src() const {
return getOperand(0); } AliasSet getAliasSet() const override
{ return AliasSet::None(); } bool congruentTo(const MDefinition
* ins) const override; bool canClone() const override { return
true; } MInstruction* clone(TempAllocator& alloc, const MDefinitionVector
& inputs) const override { MInstruction* res = new (alloc
) MWasmUnarySimd128(*this); for (size_t i = 0; i < numOperands
(); i++) res->replaceOperand(i, inputs[i]); return res; }}
;
1320
1321// Truncation barrier. This is intended for protecting its input against
1322// follow-up truncation optimizations.
1323class MLimitedTruncate : public MUnaryInstruction,
1324 public ConvertToInt32Policy<0>::Data {
1325 TruncateKind truncate_;
1326 TruncateKind truncateLimit_;
1327
1328 MLimitedTruncate(MDefinition* input, TruncateKind limit)
1329 : MUnaryInstruction(classOpcode, input),
1330 truncate_(TruncateKind::NoTruncate),
1331 truncateLimit_(limit) {
1332 setResultType(MIRType::Int32);
1333 setMovable();
1334 }
1335
1336 public:
1337 INSTRUCTION_HEADER(LimitedTruncate)
1338 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)...); }
1339
1340 AliasSet getAliasSet() const override { return AliasSet::None(); }
1341
1342 void computeRange(TempAllocator& alloc) override;
1343 bool canTruncate() const override;
1344 void truncate(TruncateKind kind) override;
1345 TruncateKind operandTruncateKind(size_t index) const override;
1346 TruncateKind truncateKind() const { return truncate_; }
1347 void setTruncateKind(TruncateKind kind) { truncate_ = kind; }
1348};
1349
1350// A constant js::Value.
1351class MConstant : public MNullaryInstruction {
1352 struct Payload {
1353 union {
1354 bool b;
1355 int32_t i32;
1356 int64_t i64;
1357 intptr_t iptr;
1358 float f;
1359 double d;
1360 JSString* str;
1361 JS::Symbol* sym;
1362 BigInt* bi;
1363 JSObject* obj;
1364 Shape* shape;
1365 uint64_t asBits;
1366 };
1367 Payload() : asBits(0) {}
1368 };
1369
1370 Payload payload_;
1371
1372 static_assert(sizeof(Payload) == sizeof(uint64_t),
1373 "asBits must be big enough for all payload bits");
1374
1375#ifdef DEBUG1
1376 void assertInitializedPayload() const;
1377#else
1378 void assertInitializedPayload() const {}
1379#endif
1380
1381 MConstant(TempAllocator& alloc, const Value& v);
1382 explicit MConstant(JSObject* obj);
1383 explicit MConstant(Shape* shape);
1384 explicit MConstant(float f);
1385 explicit MConstant(MIRType type, int64_t i);
1386
1387 public:
1388 INSTRUCTION_HEADER(Constant)
1389 static MConstant* New(TempAllocator& alloc, const Value& v);
1390 static MConstant* New(TempAllocator::Fallible alloc, const Value& v);
1391 static MConstant* New(TempAllocator& alloc, const Value& v, MIRType type);
1392 static MConstant* NewFloat32(TempAllocator& alloc, double d);
1393 static MConstant* NewInt64(TempAllocator& alloc, int64_t i);
1394 static MConstant* NewIntPtr(TempAllocator& alloc, intptr_t i);
1395 static MConstant* NewObject(TempAllocator& alloc, JSObject* v);
1396 static MConstant* NewShape(TempAllocator& alloc, Shape* s);
1397 static MConstant* Copy(TempAllocator& alloc, MConstant* src) {
1398 return new (alloc) MConstant(*src);
1399 }
1400
1401 // Try to convert this constant to boolean, similar to js::ToBoolean.
1402 // Returns false if the type is MIRType::Magic* or MIRType::Object.
1403 [[nodiscard]] bool valueToBoolean(bool* res) const;
1404
1405#ifdef JS_JITSPEW1
1406 void printOpcode(GenericPrinter& out) const override;
1407#endif
1408
1409 HashNumber valueHash() const override;
1410 bool congruentTo(const MDefinition* ins) const override;
1411
1412 AliasSet getAliasSet() const override { return AliasSet::None(); }
1413
1414 void computeRange(TempAllocator& alloc) override;
1415 bool canTruncate() const override;
1416 void truncate(TruncateKind kind) override;
1417
1418 bool canProduceFloat32() const override;
1419
1420 ALLOW_CLONE(MConstant)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MConstant
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
1421
1422 bool equals(const MConstant* other) const {
1423 assertInitializedPayload();
1424 return type() == other->type() && payload_.asBits == other->payload_.asBits;
1425 }
1426
1427 bool toBoolean() const {
1428 MOZ_ASSERT(type() == MIRType::Boolean)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Boolean)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Boolean))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Boolean"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1428); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Boolean"
")"); do { *((volatile int*)__null) = 1428; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1429 return payload_.b;
1430 }
1431 int32_t toInt32() const {
1432 MOZ_ASSERT(type() == MIRType::Int32)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.h"
, 1432); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 1432; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1433 return payload_.i32;
1434 }
1435 int64_t toInt64() const {
1436 MOZ_ASSERT(type() == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Int64)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Int64))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Int64"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1436); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 1436; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1437 return payload_.i64;
1438 }
1439 intptr_t toIntPtr() const {
1440 MOZ_ASSERT(type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::IntPtr)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::IntPtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1440); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 1440; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1441 return payload_.iptr;
1442 }
1443 bool isInt32(int32_t i) const {
1444 return type() == MIRType::Int32 && payload_.i32 == i;
1445 }
1446 bool isInt64(int64_t i) const {
1447 return type() == MIRType::Int64 && payload_.i64 == i;
1448 }
1449 const double& toDouble() const {
1450 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.h"
, 1450); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Double"
")"); do { *((volatile int*)__null) = 1450; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1451 return payload_.d;
1452 }
1453 const float& toFloat32() const {
1454 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.h"
, 1454); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Float32"
")"); do { *((volatile int*)__null) = 1454; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1455 return payload_.f;
1456 }
1457 JSString* toString() const {
1458 MOZ_ASSERT(type() == MIRType::String)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::String)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::String)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::String"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1458); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::String"
")"); do { *((volatile int*)__null) = 1458; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1459 return payload_.str;
1460 }
1461 JS::Symbol* toSymbol() const {
1462 MOZ_ASSERT(type() == MIRType::Symbol)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Symbol)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Symbol)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Symbol"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Symbol"
")"); do { *((volatile int*)__null) = 1462; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1463 return payload_.sym;
1464 }
1465 BigInt* toBigInt() const {
1466 MOZ_ASSERT(type() == MIRType::BigInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::BigInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::BigInt)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::BigInt"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::BigInt"
")"); do { *((volatile int*)__null) = 1466; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1467 return payload_.bi;
1468 }
1469 JSObject& toObject() const {
1470 MOZ_ASSERT(type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Object)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1470); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 1470; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1471 return *payload_.obj;
1472 }
1473 JSObject* toObjectOrNull() const {
1474 if (type() == MIRType::Object) {
1475 return payload_.obj;
1476 }
1477 MOZ_ASSERT(type() == MIRType::Null)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Null)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Null))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Null"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1477); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Null"
")"); do { *((volatile int*)__null) = 1477; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1478 return nullptr;
1479 }
1480 Shape* toShape() const {
1481 MOZ_ASSERT(type() == MIRType::Shape)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type() == MIRType::Shape)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type() == MIRType::Shape))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("type() == MIRType::Shape"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1481); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Shape"
")"); do { *((volatile int*)__null) = 1481; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1482 return payload_.shape;
1483 }
1484
1485 bool isTypeRepresentableAsDouble() const {
1486 return IsTypeRepresentableAsDouble(type());
1487 }
1488 double numberToDouble() const {
1489 MOZ_ASSERT(isTypeRepresentableAsDouble())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isTypeRepresentableAsDouble())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isTypeRepresentableAsDouble(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isTypeRepresentableAsDouble()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1489); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isTypeRepresentableAsDouble()"
")"); do { *((volatile int*)__null) = 1489; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1490 if (type() == MIRType::Int32) {
1491 return toInt32();
1492 }
1493 if (type() == MIRType::Double) {
1494 return toDouble();
1495 }
1496 return toFloat32();
1497 }
1498
1499 // Convert this constant to a js::Value. Float32 constants will be stored
1500 // as DoubleValue and NaNs are canonicalized. Callers must be careful: not
1501 // all constants can be represented by js::Value (wasm supports int64).
1502 Value toJSValue() const;
1503};
1504
1505class MWasmNullConstant : public MNullaryInstruction {
1506 explicit MWasmNullConstant() : MNullaryInstruction(classOpcode) {
1507 setResultType(MIRType::WasmAnyRef);
1508 setMovable();
1509 }
1510
1511 public:
1512 INSTRUCTION_HEADER(WasmNullConstant)
1513 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)...); }
1514
1515 HashNumber valueHash() const override;
1516 bool congruentTo(const MDefinition* ins) const override {
1517 return ins->isWasmNullConstant();
1518 }
1519 AliasSet getAliasSet() const override { return AliasSet::None(); }
1520
1521 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; }
1522};
1523
1524// Floating-point value as created by wasm. Just a constant value, used to
1525// effectively inhibit all the MIR optimizations. This uses the same LIR nodes
1526// as a MConstant of the same type would.
1527class MWasmFloatConstant : public MNullaryInstruction {
1528 union {
1529 float f32_;
1530 double f64_;
1531#ifdef ENABLE_WASM_SIMD1
1532 int8_t s128_[16];
1533 uint64_t bits_[2];
1534#else
1535 uint64_t bits_[1];
1536#endif
1537 } u;
1538
1539 explicit MWasmFloatConstant(MIRType type) : MNullaryInstruction(classOpcode) {
1540 u.bits_[0] = 0;
1541#ifdef ENABLE_WASM_SIMD1
1542 u.bits_[1] = 0;
1543#endif
1544 setResultType(type);
1545 }
1546
1547 public:
1548 INSTRUCTION_HEADER(WasmFloatConstant)
1549
1550 static MWasmFloatConstant* NewDouble(TempAllocator& alloc, double d) {
1551 auto* ret = new (alloc) MWasmFloatConstant(MIRType::Double);
1552 ret->u.f64_ = d;
1553 return ret;
1554 }
1555
1556 static MWasmFloatConstant* NewFloat32(TempAllocator& alloc, float f) {
1557 auto* ret = new (alloc) MWasmFloatConstant(MIRType::Float32);
1558 ret->u.f32_ = f;
1559 return ret;
1560 }
1561
1562#ifdef ENABLE_WASM_SIMD1
1563 static MWasmFloatConstant* NewSimd128(TempAllocator& alloc,
1564 const SimdConstant& s) {
1565 auto* ret = new (alloc) MWasmFloatConstant(MIRType::Simd128);
1566 memcpy(ret->u.s128_, s.bytes(), 16);
1567 return ret;
1568 }
1569#endif
1570
1571 HashNumber valueHash() const override;
1572 bool congruentTo(const MDefinition* ins) const override;
1573 AliasSet getAliasSet() const override { return AliasSet::None(); }
1574
1575 const double& toDouble() const {
1576 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.h"
, 1576); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Double"
")"); do { *((volatile int*)__null) = 1576; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1577 return u.f64_;
1578 }
1579 const float& toFloat32() const {
1580 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.h"
, 1580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Float32"
")"); do { *((volatile int*)__null) = 1580; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1581 return u.f32_;
1582 }
1583#ifdef ENABLE_WASM_SIMD1
1584 const SimdConstant toSimd128() const {
1585 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.h"
, 1585); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Simd128"
")"); do { *((volatile int*)__null) = 1585; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1586 return SimdConstant::CreateX16(u.s128_);
1587 }
1588#endif
1589#ifdef JS_JITSPEW1
1590 void getExtras(ExtrasCollector* extras) override {
1591 char buf[64];
1592 switch (type()) {
1593 case MIRType::Float32:
1594 SprintfLiteral(buf, "f32{%e}", (double)u.f32_);
1595 break;
1596 case MIRType::Double:
1597 SprintfLiteral(buf, "f64{%e}", u.f64_);
1598 break;
1599# ifdef ENABLE_WASM_SIMD1
1600 case MIRType::Simd128:
1601 SprintfLiteral(buf, "v128{[1]=%016llx:[0]=%016llx}",
1602 (unsigned long long int)u.bits_[1],
1603 (unsigned long long int)u.bits_[0]);
1604 break;
1605# endif
1606 default:
1607 SprintfLiteral(buf, "!!getExtras: missing case!!");
1608 break;
1609 }
1610 extras->add(buf);
1611 }
1612#endif
1613};
1614
1615class MParameter : public MNullaryInstruction {
1616 int32_t index_;
1617
1618 explicit MParameter(int32_t index)
1619 : MNullaryInstruction(classOpcode), index_(index) {
1620 setResultType(MIRType::Value);
1621 }
1622
1623 public:
1624 INSTRUCTION_HEADER(Parameter)
1625 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)...); }
1626
1627 static const int32_t THIS_SLOT = -1;
1628 int32_t index() const { return index_; }
1629#ifdef JS_JITSPEW1
1630 void printOpcode(GenericPrinter& out) const override;
1631#endif
1632 HashNumber valueHash() const override;
1633 bool congruentTo(const MDefinition* ins) const override;
1634};
1635
1636class MControlInstruction : public MInstruction {
1637 protected:
1638 explicit MControlInstruction(Opcode op) : MInstruction(op) {}
1639
1640 public:
1641 virtual size_t numSuccessors() const = 0;
1642 virtual MBasicBlock* getSuccessor(size_t i) const = 0;
1643 virtual void replaceSuccessor(size_t i, MBasicBlock* successor) = 0;
1644
1645 void initSuccessor(size_t i, MBasicBlock* successor) {
1646 MOZ_ASSERT(!getSuccessor(i))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!getSuccessor(i))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!getSuccessor(i)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("!getSuccessor(i)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1646); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!getSuccessor(i)"
")"); do { *((volatile int*)__null) = 1646; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1647 replaceSuccessor(i, successor);
1648 }
1649
1650 bool isControlInstruction() const override { return true; }
1651
1652#ifdef JS_JITSPEW1
1653 void printOpcode(GenericPrinter& out) const override;
1654#endif
1655};
1656
1657class MTableSwitch final : public MControlInstruction,
1658 public NoFloatPolicy<0>::Data {
1659 // The successors of the tableswitch
1660 // - First successor = the default case
1661 // - Successors 2 and higher = the cases
1662 Vector<MBasicBlock*, 0, JitAllocPolicy> successors_;
1663 // Index into successors_ sorted on case index
1664 Vector<size_t, 0, JitAllocPolicy> cases_;
1665
1666 MUse operand_;
1667 int32_t low_;
1668 int32_t high_;
1669
1670 void initOperand(size_t index, MDefinition* operand) {
1671 MOZ_ASSERT(index == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1671); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == 0"
")"); do { *((volatile int*)__null) = 1671; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1672 operand_.init(operand, this);
1673 }
1674
1675 MTableSwitch(TempAllocator& alloc, MDefinition* ins, int32_t low,
1676 int32_t high)
1677 : MControlInstruction(classOpcode),
1678 successors_(alloc),
1679 cases_(alloc),
1680 low_(low),
1681 high_(high) {
1682 initOperand(0, ins);
1683 }
1684
1685 protected:
1686 MUse* getUseFor(size_t index) override {
1687 MOZ_ASSERT(index == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1687); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == 0"
")"); do { *((volatile int*)__null) = 1687; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1688 return &operand_;
1689 }
1690
1691 const MUse* getUseFor(size_t index) const override {
1692 MOZ_ASSERT(index == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1692); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == 0"
")"); do { *((volatile int*)__null) = 1692; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1693 return &operand_;
1694 }
1695
1696 public:
1697 INSTRUCTION_HEADER(TableSwitch)
1698
1699 static MTableSwitch* New(TempAllocator& alloc, MDefinition* ins, int32_t low,
1700 int32_t high) {
1701 return new (alloc) MTableSwitch(alloc, ins, low, high);
1702 }
1703
1704 size_t numSuccessors() const override { return successors_.length(); }
1705
1706 [[nodiscard]] bool addSuccessor(MBasicBlock* successor, size_t* index) {
1707 MOZ_ASSERT(successors_.length() < (size_t)(high_ - low_ + 2))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(successors_.length() < (size_t)(high_ - low_ + 2)
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(successors_.length() < (size_t)(high_ - low_ + 2)
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"successors_.length() < (size_t)(high_ - low_ + 2)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1707); AnnotateMozCrashReason("MOZ_ASSERT" "(" "successors_.length() < (size_t)(high_ - low_ + 2)"
")"); do { *((volatile int*)__null) = 1707; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1708 MOZ_ASSERT(!successors_.empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!successors_.empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!successors_.empty()))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("!successors_.empty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1708); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!successors_.empty()"
")"); do { *((volatile int*)__null) = 1708; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1709 *index = successors_.length();
1710 return successors_.append(successor);
1711 }
1712
1713 MBasicBlock* getSuccessor(size_t i) const override {
1714 MOZ_ASSERT(i < numSuccessors())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(i < numSuccessors())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(i < numSuccessors()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("i < numSuccessors()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "i < numSuccessors()"
")"); do { *((volatile int*)__null) = 1714; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1715 return successors_[i];
1716 }
1717
1718 void replaceSuccessor(size_t i, MBasicBlock* successor) override {
1719 MOZ_ASSERT(i < numSuccessors())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(i < numSuccessors())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(i < numSuccessors()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("i < numSuccessors()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1719); AnnotateMozCrashReason("MOZ_ASSERT" "(" "i < numSuccessors()"
")"); do { *((volatile int*)__null) = 1719; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1720 successors_[i] = successor;
1721 }
1722
1723 int32_t low() const { return low_; }
1724
1725 int32_t high() const { return high_; }
1726
1727 MBasicBlock* getDefault() const { return getSuccessor(0); }
1728
1729 MBasicBlock* getCase(size_t i) const { return getSuccessor(cases_[i]); }
1730
1731 [[nodiscard]] bool addDefault(MBasicBlock* block, size_t* index = nullptr) {
1732 MOZ_ASSERT(successors_.empty())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(successors_.empty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(successors_.empty()))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("successors_.empty()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "successors_.empty()"
")"); do { *((volatile int*)__null) = 1732; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1733 if (index) {
1734 *index = 0;
1735 }
1736 return successors_.append(block);
1737 }
1738
1739 [[nodiscard]] bool addCase(size_t successorIndex) {
1740 return cases_.append(successorIndex);
1741 }
1742
1743 size_t numCases() const { return high() - low() + 1; }
1744
1745 MDefinition* getOperand(size_t index) const override {
1746 MOZ_ASSERT(index == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == 0"
")"); do { *((volatile int*)__null) = 1746; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1747 return operand_.producer();
1748 }
1749
1750 size_t numOperands() const override { return 1; }
1751
1752 size_t indexOf(const MUse* u) const final {
1753 MOZ_ASSERT(u == getUseFor(0))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u == getUseFor(0))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u == getUseFor(0)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("u == getUseFor(0)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1753); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u == getUseFor(0)"
")"); do { *((volatile int*)__null) = 1753; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1754 return 0;
1755 }
1756
1757 void replaceOperand(size_t index, MDefinition* operand) final {
1758 MOZ_ASSERT(index == 0)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index == 0))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index == 0", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index == 0"
")"); do { *((volatile int*)__null) = 1758; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1759 operand_.replaceProducer(operand);
1760 }
1761
1762 MDefinition* foldsTo(TempAllocator& alloc) override;
1763
1764 // It does read memory in that it must read an entry from the jump table,
1765 // but that's effectively data that is private to this MIR. And it should
1766 // certainly never be modified by any other MIR. Hence it is effect-free
1767 // from an alias-analysis standpoint.
1768 AliasSet getAliasSet() const override { return AliasSet::None(); }
1769};
1770
1771template <size_t Arity, size_t Successors>
1772class MAryControlInstruction : public MControlInstruction {
1773 mozilla::Array<MUse, Arity> operands_;
1774 mozilla::Array<MBasicBlock*, Successors> successors_;
1775
1776 protected:
1777 explicit MAryControlInstruction(Opcode op) : MControlInstruction(op) {}
1778 void setSuccessor(size_t index, MBasicBlock* successor) {
1779 successors_[index] = successor;
1780 }
1781
1782 MUse* getUseFor(size_t index) final { return &operands_[index]; }
1783 const MUse* getUseFor(size_t index) const final { return &operands_[index]; }
1784 void initOperand(size_t index, MDefinition* operand) {
1785 operands_[index].init(operand, this);
1786 }
1787
1788 public:
1789 MDefinition* getOperand(size_t index) const final {
1790 return operands_[index].producer();
1791 }
1792 size_t numOperands() const final { return Arity; }
1793 size_t indexOf(const MUse* u) const final {
1794 MOZ_ASSERT(u >= &operands_[0])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u >= &operands_[0])>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u >= &operands_[0])))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("u >= &operands_[0]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1794); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u >= &operands_[0]"
")"); do { *((volatile int*)__null) = 1794; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1795 MOZ_ASSERT(u <= &operands_[numOperands() - 1])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u <= &operands_[numOperands() - 1])>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(u <= &operands_[numOperands() - 1]))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("u <= &operands_[numOperands() - 1]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 1795); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u <= &operands_[numOperands() - 1]"
")"); do { *((volatile int*)__null) = 1795; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1796 return u - &operands_[0];
1797 }
1798 void replaceOperand(size_t index, MDefinition* operand) final {
1799 operands_[index].replaceProducer(operand);
1800 }
1801 size_t numSuccessors() const final { return Successors; }
1802 MBasicBlock* getSuccessor(size_t i) const final { return successors_[i]; }
1803 void replaceSuccessor(size_t i, MBasicBlock* succ) final {
1804 successors_[i] = succ;
1805 }
1806};
1807
1808template <size_t Successors>
1809class MVariadicControlInstruction : public MVariadicT<MControlInstruction> {
1810 mozilla::Array<MBasicBlock*, Successors> successors_;
1811
1812 protected:
1813 explicit MVariadicControlInstruction(Opcode op)
1814 : MVariadicT<MControlInstruction>(op) {}
1815 void setSuccessor(size_t index, MBasicBlock* successor) {
1816 successors_[index] = successor;
1817 }
1818
1819 public:
1820 size_t numSuccessors() const final { return Successors; }
1821 MBasicBlock* getSuccessor(size_t i) const final { return successors_[i]; }
1822 void replaceSuccessor(size_t i, MBasicBlock* succ) final {
1823 successors_[i] = succ;
1824 }
1825};
1826
1827// Jump to the start of another basic block.
1828class MGoto : public MAryControlInstruction<0, 1>, public NoTypePolicy::Data {
1829 explicit MGoto(MBasicBlock* target) : MAryControlInstruction(classOpcode) {
1830 setSuccessor(TargetIndex, target);
1831 }
1832
1833 public:
1834 INSTRUCTION_HEADER(Goto)
1835 static MGoto* New(TempAllocator& alloc, MBasicBlock* target);
1836 static MGoto* New(TempAllocator::Fallible alloc, MBasicBlock* target);
1837
1838 // Variant that may patch the target later.
1839 static MGoto* New(TempAllocator& alloc);
1840
1841 static constexpr size_t TargetIndex = 0;
1842
1843 MBasicBlock* target() { return getSuccessor(TargetIndex); }
1844 AliasSet getAliasSet() const override { return AliasSet::None(); }
1845
1846#ifdef JS_JITSPEW1
1847 void getExtras(ExtrasCollector* extras) override {
1848 char buf[64];
1849 SprintfLiteral(buf, "Block%u", GetMBasicBlockId(target()));
1850 extras->add(buf);
1851 }
1852#endif
1853};
1854
1855// Tests if the input instruction evaluates to true or false, and jumps to the
1856// start of a corresponding basic block.
1857class MTest : public MAryControlInstruction<1, 2>, public TestPolicy::Data {
1858 // It is allowable to specify `trueBranch` or `falseBranch` as nullptr and
1859 // patch it in later.
1860 MTest(MDefinition* ins, MBasicBlock* trueBranch, MBasicBlock* falseBranch)
1861 : MAryControlInstruction(classOpcode) {
1862 initOperand(0, ins);
1863 setSuccessor(TrueBranchIndex, trueBranch);
1864 setSuccessor(FalseBranchIndex, falseBranch);
1865 }
1866
1867 TypeDataList observedTypes_;
1868
1869 public:
1870 INSTRUCTION_HEADER(Test)
1871 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)...); }
1872 NAMED_OPERANDS((0, input))MDefinition* input() const { return getOperand(0); }
1873
1874 const TypeDataList& observedTypes() const { return observedTypes_; }
1875 void setObservedTypes(const TypeDataList& observed) {
1876 observedTypes_ = observed;
1877 }
1878
1879 static constexpr size_t TrueBranchIndex = 0;
1880 static constexpr size_t FalseBranchIndex = 1;
1881
1882 MBasicBlock* ifTrue() const { return getSuccessor(TrueBranchIndex); }
1883 MBasicBlock* ifFalse() const { return getSuccessor(FalseBranchIndex); }
1884 MBasicBlock* branchSuccessor(BranchDirection dir) const {
1885 return (dir == TRUE_BRANCH) ? ifTrue() : ifFalse();
1886 }
1887
1888 AliasSet getAliasSet() const override { return AliasSet::None(); }
1889
1890 MDefinition* foldsDoubleNegation(TempAllocator& alloc);
1891 MDefinition* foldsConstant(TempAllocator& alloc);
1892 MDefinition* foldsTypes(TempAllocator& alloc);
1893 MDefinition* foldsNeedlessControlFlow(TempAllocator& alloc);
1894 MDefinition* foldsRedundantTest(TempAllocator& alloc);
1895 MDefinition* foldsTo(TempAllocator& alloc) override;
1896
1897#ifdef DEBUG1
1898 bool isConsistentFloat32Use(MUse* use) const override { return true; }
1899#endif
1900
1901#ifdef JS_JITSPEW1
1902 void getExtras(ExtrasCollector* extras) override {
1903 char buf[64];
1904 SprintfLiteral(buf, "true->Block%u false->Block%u",
1905 GetMBasicBlockId(ifTrue()), GetMBasicBlockId(ifFalse()));
1906 extras->add(buf);
1907 }
1908#endif
1909};
1910
1911// Returns from this function to the previous caller.
1912class MReturn : public MAryControlInstruction<1, 0>,
1913 public BoxInputsPolicy::Data {
1914 explicit MReturn(MDefinition* ins) : MAryControlInstruction(classOpcode) {
1915 initOperand(0, ins);
1916 }
1917
1918 public:
1919 INSTRUCTION_HEADER(Return)
1920 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)...); }
1921 NAMED_OPERANDS((0, input))MDefinition* input() const { return getOperand(0); }
1922
1923 AliasSet getAliasSet() const override { return AliasSet::None(); }
1924};
1925
1926class MNewArray : public MUnaryInstruction, public NoTypePolicy::Data {
1927 private:
1928 // Number of elements to allocate for the array.
1929 uint32_t length_;
1930
1931 // Heap where the array should be allocated.
1932 gc::Heap initialHeap_;
1933
1934 bool vmCall_;
1935
1936 MNewArray(uint32_t length, MConstant* templateConst, gc::Heap initialHeap,
1937 bool vmCall = false);
1938
1939 public:
1940 INSTRUCTION_HEADER(NewArray)
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 static MNewArray* NewVM(TempAllocator& alloc, uint32_t length,
1944 MConstant* templateConst, gc::Heap initialHeap) {
1945 return new (alloc) MNewArray(length, templateConst, initialHeap, true);
1946 }
1947
1948 uint32_t length() const { return length_; }
1949
1950 JSObject* templateObject() const {
1951 return getOperand(0)->toConstant()->toObjectOrNull();
1952 }
1953
1954 gc::Heap initialHeap() const { return initialHeap_; }
1955
1956 bool isVMCall() const { return vmCall_; }
1957
1958 // NewArray is marked as non-effectful because all our allocations are
1959 // either lazy when we are using "new Array(length)" or bounded by the
1960 // script or the stack size when we are using "new Array(...)" or "[...]"
1961 // notations. So we might have to allocate the array twice if we bail
1962 // during the computation of the first element of the square braket
1963 // notation.
1964 virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
1965
1966 [[nodiscard]] bool writeRecoverData(
1967 CompactBufferWriter& writer) const override;
1968 bool canRecoverOnBailout() const override {
1969 // The template object can safely be used in the recover instruction
1970 // because it can never be mutated by any other function execution.
1971 return templateObject() != nullptr;
1972 }
1973};
1974
1975class MNewTypedArray : public MUnaryInstruction, public NoTypePolicy::Data {
1976 gc::Heap initialHeap_;
1977
1978 MNewTypedArray(MConstant* templateConst, gc::Heap initialHeap)
1979 : MUnaryInstruction(classOpcode, templateConst),
1980 initialHeap_(initialHeap) {
1981 setResultType(MIRType::Object);
1982 }
1983
1984 public:
1985 INSTRUCTION_HEADER(NewTypedArray)
1986 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)...); }
1987
1988 TypedArrayObject* templateObject() const {
1989 return &getOperand(0)->toConstant()->toObject().as<TypedArrayObject>();
1990 }
1991
1992 gc::Heap initialHeap() const { return initialHeap_; }
1993
1994 virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
1995
1996 [[nodiscard]] bool writeRecoverData(
1997 CompactBufferWriter& writer) const override;
1998 bool canRecoverOnBailout() const override { return true; }
1999};
2000
2001class MNewObject : public MUnaryInstruction, public NoTypePolicy::Data {
2002 public:
2003 enum Mode { ObjectLiteral, ObjectCreate };
2004
2005 private:
2006 gc::Heap initialHeap_;
2007 Mode mode_;
2008 bool vmCall_;
2009
2010 MNewObject(MConstant* templateConst, gc::Heap initialHeap, Mode mode,
2011 bool vmCall = false)
2012 : MUnaryInstruction(classOpcode, templateConst),
2013 initialHeap_(initialHeap),
2014 mode_(mode),
2015 vmCall_(vmCall) {
2016 if (mode == ObjectLiteral) {
2017 MOZ_ASSERT(!templateObject())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!templateObject())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!templateObject()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!templateObject()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2017); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!templateObject()"
")"); do { *((volatile int*)__null) = 2017; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2018 } else {
2019 MOZ_ASSERT(templateObject())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(templateObject())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(templateObject()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("templateObject()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2019); AnnotateMozCrashReason("MOZ_ASSERT" "(" "templateObject()"
")"); do { *((volatile int*)__null) = 2019; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2020 }
2021 setResultType(MIRType::Object);
2022
2023 // The constant is kept separated in a MConstant, this way we can safely
2024 // mark it during GC if we recover the object allocation. Otherwise, by
2025 // making it emittedAtUses, we do not produce register allocations for
2026 // it and inline its content inside the code produced by the
2027 // CodeGenerator.
2028 if (templateConst->toConstant()->type() == MIRType::Object) {
2029 templateConst->setEmittedAtUses();
2030 }
2031 }
2032
2033 public:
2034 INSTRUCTION_HEADER(NewObject)
2035 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)...); }
2036
2037 static MNewObject* NewVM(TempAllocator& alloc, MConstant* templateConst,
2038 gc::Heap initialHeap, Mode mode) {
2039 return new (alloc) MNewObject(templateConst, initialHeap, mode, true);
2040 }
2041
2042 Mode mode() const { return mode_; }
2043
2044 JSObject* templateObject() const {
2045 return getOperand(0)->toConstant()->toObjectOrNull();
2046 }
2047
2048 gc::Heap initialHeap() const { return initialHeap_; }
2049
2050 bool isVMCall() const { return vmCall_; }
2051
2052 [[nodiscard]] bool writeRecoverData(
2053 CompactBufferWriter& writer) const override;
2054 bool canRecoverOnBailout() const override {
2055 // The template object can safely be used in the recover instruction
2056 // because it can never be mutated by any other function execution.
2057 return templateObject() != nullptr;
2058 }
2059};
2060
2061class MNewPlainObject : public MUnaryInstruction, public NoTypePolicy::Data {
2062 private:
2063 uint32_t numFixedSlots_;
2064 uint32_t numDynamicSlots_;
2065 gc::AllocKind allocKind_;
2066 gc::Heap initialHeap_;
2067
2068 MNewPlainObject(MConstant* shapeConst, uint32_t numFixedSlots,
2069 uint32_t numDynamicSlots, gc::AllocKind allocKind,
2070 gc::Heap initialHeap)
2071 : MUnaryInstruction(classOpcode, shapeConst),
2072 numFixedSlots_(numFixedSlots),
2073 numDynamicSlots_(numDynamicSlots),
2074 allocKind_(allocKind),
2075 initialHeap_(initialHeap) {
2076 setResultType(MIRType::Object);
2077
2078 // The shape constant is kept separated in a MConstant. This way we can
2079 // safely mark it during GC if we recover the object allocation. Otherwise,
2080 // by making it emittedAtUses, we do not produce register allocations for it
2081 // and inline its content inside the code produced by the CodeGenerator.
2082 MOZ_ASSERT(shapeConst->toConstant()->type() == MIRType::Shape)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(shapeConst->toConstant()->type() == MIRType::Shape
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(shapeConst->toConstant()->type() == MIRType::Shape
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"shapeConst->toConstant()->type() == MIRType::Shape", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2082); AnnotateMozCrashReason("MOZ_ASSERT" "(" "shapeConst->toConstant()->type() == MIRType::Shape"
")"); do { *((volatile int*)__null) = 2082; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2083 shapeConst->setEmittedAtUses();
2084 }
2085
2086 public:
2087 INSTRUCTION_HEADER(NewPlainObject)
2088 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)...); }
2089
2090 const Shape* shape() const { return getOperand(0)->toConstant()->toShape(); }
2091
2092 uint32_t numFixedSlots() const { return numFixedSlots_; }
2093 uint32_t numDynamicSlots() const { return numDynamicSlots_; }
2094 gc::AllocKind allocKind() const { return allocKind_; }
2095 gc::Heap initialHeap() const { return initialHeap_; }
2096
2097 [[nodiscard]] bool writeRecoverData(
2098 CompactBufferWriter& writer) const override;
2099 bool canRecoverOnBailout() const override { return true; }
2100
2101 AliasSet getAliasSet() const override { return AliasSet::None(); }
2102};
2103
2104class MNewArrayObject : public MUnaryInstruction, public NoTypePolicy::Data {
2105 private:
2106 uint32_t length_;
2107 gc::Heap initialHeap_;
2108
2109 MNewArrayObject(TempAllocator& alloc, MConstant* shapeConst, uint32_t length,
2110 gc::Heap initialHeap)
2111 : MUnaryInstruction(classOpcode, shapeConst),
2112 length_(length),
2113 initialHeap_(initialHeap) {
2114 setResultType(MIRType::Object);
2115 MOZ_ASSERT(shapeConst->toConstant()->type() == MIRType::Shape)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(shapeConst->toConstant()->type() == MIRType::Shape
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(shapeConst->toConstant()->type() == MIRType::Shape
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"shapeConst->toConstant()->type() == MIRType::Shape", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2115); AnnotateMozCrashReason("MOZ_ASSERT" "(" "shapeConst->toConstant()->type() == MIRType::Shape"
")"); do { *((volatile int*)__null) = 2115; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2116 shapeConst->setEmittedAtUses();
2117 }
2118
2119 public:
2120 INSTRUCTION_HEADER(NewArrayObject)
2121 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)...); }
2122
2123 static MNewArrayObject* New(TempAllocator& alloc, MConstant* shapeConst,
2124 uint32_t length, gc::Heap initialHeap) {
2125 return new (alloc) MNewArrayObject(alloc, shapeConst, length, initialHeap);
2126 }
2127
2128 const Shape* shape() const { return getOperand(0)->toConstant()->toShape(); }
2129
2130 // See MNewArray::getAliasSet comment.
2131 AliasSet getAliasSet() const override { return AliasSet::None(); }
2132
2133 uint32_t length() const { return length_; }
2134 gc::Heap initialHeap() const { return initialHeap_; }
2135
2136 [[nodiscard]] bool writeRecoverData(
2137 CompactBufferWriter& writer) const override;
2138 bool canRecoverOnBailout() const override { return true; }
2139};
2140
2141class MNewIterator : public MUnaryInstruction, public NoTypePolicy::Data {
2142 public:
2143 enum Type {
2144 ArrayIterator,
2145 StringIterator,
2146 RegExpStringIterator,
2147 };
2148
2149 private:
2150 Type type_;
2151
2152 MNewIterator(MConstant* templateConst, Type type)
2153 : MUnaryInstruction(classOpcode, templateConst), type_(type) {
2154 setResultType(MIRType::Object);
2155 templateConst->setEmittedAtUses();
2156 }
2157
2158 public:
2159 INSTRUCTION_HEADER(NewIterator)
2160 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)...); }
2161
2162 Type type() const { return type_; }
2163
2164 JSObject* templateObject() {
2165 return getOperand(0)->toConstant()->toObjectOrNull();
2166 }
2167
2168 AliasSet getAliasSet() const override { return AliasSet::None(); }
2169
2170 [[nodiscard]] bool writeRecoverData(
2171 CompactBufferWriter& writer) const override;
2172 bool canRecoverOnBailout() const override { return true; }
2173};
2174
2175// Represent the content of all slots of an object. This instruction is not
2176// lowered and is not used to generate code.
2177class MObjectState : public MVariadicInstruction,
2178 public NoFloatPolicyAfter<1>::Data {
2179 private:
2180 uint32_t numSlots_;
2181 uint32_t numFixedSlots_;
2182
2183 explicit MObjectState(JSObject* templateObject);
2184 explicit MObjectState(const Shape* shape);
2185 explicit MObjectState(MObjectState* state);
2186
2187 [[nodiscard]] bool init(TempAllocator& alloc, MDefinition* obj);
2188
2189 void initSlot(uint32_t slot, MDefinition* def) { initOperand(slot + 1, def); }
2190
2191 public:
2192 INSTRUCTION_HEADER(ObjectState)
2193 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
2194
2195 // Return the template object of any object creation which can be recovered
2196 // on bailout.
2197 static JSObject* templateObjectOf(MDefinition* obj);
2198
2199 static MObjectState* New(TempAllocator& alloc, MDefinition* obj);
2200 static MObjectState* Copy(TempAllocator& alloc, MObjectState* state);
2201
2202 // As we might do read of uninitialized properties, we have to copy the
2203 // initial values from the template object.
2204 void initFromTemplateObject(TempAllocator& alloc, MDefinition* undefinedVal);
2205
2206 size_t numFixedSlots() const { return numFixedSlots_; }
2207 size_t numSlots() const { return numSlots_; }
2208
2209 MDefinition* getSlot(uint32_t slot) const { return getOperand(slot + 1); }
2210 void setSlot(uint32_t slot, MDefinition* def) {
2211 replaceOperand(slot + 1, def);
2212 }
2213
2214 bool hasFixedSlot(uint32_t slot) const {
2215 return slot < numSlots() && slot < numFixedSlots();
2216 }
2217 MDefinition* getFixedSlot(uint32_t slot) const {
2218 MOZ_ASSERT(slot < numFixedSlots())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slot < numFixedSlots())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slot < numFixedSlots())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("slot < numFixedSlots()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot < numFixedSlots()"
")"); do { *((volatile int*)__null) = 2218; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2219 return getSlot(slot);
2220 }
2221 void setFixedSlot(uint32_t slot, MDefinition* def) {
2222 MOZ_ASSERT(slot < numFixedSlots())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slot < numFixedSlots())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slot < numFixedSlots())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("slot < numFixedSlots()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2222); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slot < numFixedSlots()"
")"); do { *((volatile int*)__null) = 2222; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2223 setSlot(slot, def);
2224 }
2225
2226 bool hasDynamicSlot(uint32_t slot) const {
2227 return numFixedSlots() < numSlots() && slot < numSlots() - numFixedSlots();
2228 }
2229 MDefinition* getDynamicSlot(uint32_t slot) const {
2230 return getSlot(slot + numFixedSlots());
2231 }
2232 void setDynamicSlot(uint32_t slot, MDefinition* def) {
2233 setSlot(slot + numFixedSlots(), def);
2234 }
2235
2236 [[nodiscard]] bool writeRecoverData(
2237 CompactBufferWriter& writer) const override;
2238 bool canRecoverOnBailout() const override { return true; }
2239};
2240
2241// Represent the contents of all elements of an array. This instruction is not
2242// lowered and is not used to generate code.
2243class MArrayState : public MVariadicInstruction,
2244 public NoFloatPolicyAfter<2>::Data {
2245 private:
2246 uint32_t numElements_;
2247
2248 explicit MArrayState(MDefinition* arr);
2249
2250 [[nodiscard]] bool init(TempAllocator& alloc, MDefinition* obj,
2251 MDefinition* len);
2252
2253 void initElement(uint32_t index, MDefinition* def) {
2254 initOperand(index + 2, def);
2255 }
2256
2257 public:
2258 INSTRUCTION_HEADER(ArrayState)
2259 NAMED_OPERANDS((0, array), (1, initializedLength))MDefinition* array() const { return getOperand(0); } MDefinition
* initializedLength() const { return getOperand(1); }
2260
2261 static MArrayState* New(TempAllocator& alloc, MDefinition* arr,
2262 MDefinition* initLength);
2263 static MArrayState* Copy(TempAllocator& alloc, MArrayState* state);
2264
2265 void initFromTemplateObject(TempAllocator& alloc, MDefinition* undefinedVal);
2266
2267 void setInitializedLength(MDefinition* def) { replaceOperand(1, def); }
2268
2269 size_t numElements() const { return numElements_; }
2270
2271 MDefinition* getElement(uint32_t index) const {
2272 return getOperand(index + 2);
2273 }
2274 void setElement(uint32_t index, MDefinition* def) {
2275 replaceOperand(index + 2, def);
2276 }
2277
2278 [[nodiscard]] bool writeRecoverData(
2279 CompactBufferWriter& writer) const override;
2280 bool canRecoverOnBailout() const override { return true; }
2281};
2282
2283// WrappedFunction stores information about a function that can safely be used
2284// off-thread. In particular, a function's flags can be modified on the main
2285// thread as functions are relazified and delazified, so we must be careful not
2286// to access these flags off-thread.
2287class WrappedFunction : public TempObject {
2288 // If this is a native function without a JitEntry, the JSFunction*.
2289 CompilerFunction nativeFun_;
2290 uint16_t nargs_;
2291 js::FunctionFlags flags_;
2292
2293 public:
2294 WrappedFunction(JSFunction* nativeFun, uint16_t nargs, FunctionFlags flags);
2295
2296 // Note: When adding new accessors be sure to add consistency asserts
2297 // to the constructor.
2298
2299 size_t nargs() const { return nargs_; }
2300
2301 bool isNativeWithoutJitEntry() const {
2302 return flags_.isNativeWithoutJitEntry();
2303 }
2304 bool hasJitEntry() const { return flags_.hasJitEntry(); }
2305 bool isConstructor() const { return flags_.isConstructor(); }
2306 bool isClassConstructor() const { return flags_.isClassConstructor(); }
2307
2308 // These fields never change, they can be accessed off-main thread.
2309 JSNative native() const {
2310 MOZ_ASSERT(isNativeWithoutJitEntry())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isNativeWithoutJitEntry())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isNativeWithoutJitEntry())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("isNativeWithoutJitEntry()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2310); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isNativeWithoutJitEntry()"
")"); do { *((volatile int*)__null) = 2310; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2311 return nativeFun_->nativeUnchecked();
2312 }
2313 bool hasJitInfo() const {
2314 return flags_.canHaveJitInfo() && nativeFun_->jitInfoUnchecked();
2315 }
2316 const JSJitInfo* jitInfo() const {
2317 MOZ_ASSERT(hasJitInfo())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(hasJitInfo())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(hasJitInfo()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("hasJitInfo()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasJitInfo()"
")"); do { *((volatile int*)__null) = 2317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2318 return nativeFun_->jitInfoUnchecked();
2319 }
2320
2321 JSFunction* rawNativeJSFunction() const { return nativeFun_; }
2322};
2323
2324enum class DOMObjectKind : uint8_t { Proxy, Native };
2325
2326class MCallBase : public MVariadicInstruction, public CallPolicy::Data {
2327 protected:
2328 // The callee, this, and the actual arguments are all operands of MCall.
2329 static const size_t CalleeOperandIndex = 0;
2330 static const size_t NumNonArgumentOperands = 1;
2331
2332 explicit MCallBase(Opcode op) : MVariadicInstruction(op) {}
2333
2334 public:
2335 void initCallee(MDefinition* func) { initOperand(CalleeOperandIndex, func); }
2336 MDefinition* getCallee() const { return getOperand(CalleeOperandIndex); }
2337
2338 void replaceCallee(MInstruction* newfunc) {
2339 replaceOperand(CalleeOperandIndex, newfunc);
2340 }
2341
2342 void addArg(size_t argnum, MDefinition* arg);
2343
2344 MDefinition* getArg(uint32_t index) const {
2345 return getOperand(NumNonArgumentOperands + index);
2346 }
2347
2348 // The number of stack arguments is the max between the number of formal
2349 // arguments and the number of actual arguments. The number of stack
2350 // argument includes the |undefined| padding added in case of underflow.
2351 // Includes |this|.
2352 uint32_t numStackArgs() const {
2353 return numOperands() - NumNonArgumentOperands;
2354 }
2355 uint32_t paddedNumStackArgs() const {
2356 if (JitStackValueAlignment > 1) {
2357 return AlignBytes(numStackArgs(), JitStackValueAlignment);
2358 }
2359 return numStackArgs();
2360 }
2361
2362 static size_t IndexOfThis() { return NumNonArgumentOperands; }
2363 static size_t IndexOfArgument(size_t index) {
2364 return NumNonArgumentOperands + index + 1; // +1 to skip |this|.
2365 }
2366 static size_t IndexOfStackArg(size_t index) {
2367 return NumNonArgumentOperands + index;
2368 }
2369};
2370
2371class MCall : public MCallBase {
2372 protected:
2373 // Monomorphic cache for MCalls with a single JSFunction target.
2374 WrappedFunction* target_;
2375
2376 // Original value of argc from the bytecode.
2377 uint32_t numActualArgs_;
2378
2379 // True if the call is for JSOp::New or JSOp::SuperCall.
2380 bool construct_ : 1;
2381
2382 // True if the caller does not use the return value.
2383 bool ignoresReturnValue_ : 1;
2384
2385 bool needsClassCheck_ : 1;
2386 bool maybeCrossRealm_ : 1;
2387 bool needsThisCheck_ : 1;
2388
2389 MCall(WrappedFunction* target, uint32_t numActualArgs, bool construct,
2390 bool ignoresReturnValue)
2391 : MCallBase(classOpcode),
2392 target_(target),
2393 numActualArgs_(numActualArgs),
2394 construct_(construct),
2395 ignoresReturnValue_(ignoresReturnValue),
2396 needsClassCheck_(true),
2397 maybeCrossRealm_(true),
2398 needsThisCheck_(false) {
2399 setResultType(MIRType::Value);
2400 }
2401
2402 public:
2403 INSTRUCTION_HEADER(Call)
2404 static MCall* New(TempAllocator& alloc, WrappedFunction* target,
2405 size_t maxArgc, size_t numActualArgs, bool construct,
2406 bool ignoresReturnValue, bool isDOMCall,
2407 mozilla::Maybe<DOMObjectKind> objectKind);
2408
2409 bool needsClassCheck() const { return needsClassCheck_; }
2410 void disableClassCheck() { needsClassCheck_ = false; }
2411
2412 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2413 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2414
2415 bool needsThisCheck() const { return needsThisCheck_; }
2416 void setNeedsThisCheck() {
2417 MOZ_ASSERT(construct_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(construct_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(construct_))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("construct_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2417); AnnotateMozCrashReason("MOZ_ASSERT" "(" "construct_"
")"); do { *((volatile int*)__null) = 2417; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2418 needsThisCheck_ = true;
2419 }
2420
2421 // For monomorphic callsites.
2422 WrappedFunction* getSingleTarget() const { return target_; }
2423
2424 bool isConstructing() const { return construct_; }
2425
2426 bool ignoresReturnValue() const { return ignoresReturnValue_; }
2427
2428 // Does not include |this|.
2429 uint32_t numActualArgs() const { return numActualArgs_; }
2430
2431 bool possiblyCalls() const override { return true; }
2432
2433 virtual bool isCallDOMNative() const { return false; }
2434
2435 // A method that can be called to tell the MCall to figure out whether it's
2436 // movable or not. This can't be done in the constructor, because it
2437 // depends on the arguments to the call, and those aren't passed to the
2438 // constructor but are set up later via addArg.
2439 virtual void computeMovable() {}
2440};
2441
2442class MCallDOMNative : public MCall {
2443 // A helper class for MCalls for DOM natives. Note that this is NOT
2444 // actually a separate MIR op from MCall, because all sorts of places use
2445 // isCall() to check for calls and all we really want is to overload a few
2446 // virtual things from MCall.
2447
2448 DOMObjectKind objectKind_;
2449
2450 MCallDOMNative(WrappedFunction* target, uint32_t numActualArgs,
2451 DOMObjectKind objectKind)
2452 : MCall(target, numActualArgs, false, false), objectKind_(objectKind) {
2453 MOZ_ASSERT(getJitInfo()->type() != JSJitInfo::InlinableNative)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(getJitInfo()->type() != JSJitInfo::InlinableNative
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(getJitInfo()->type() != JSJitInfo::InlinableNative
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"getJitInfo()->type() != JSJitInfo::InlinableNative", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "getJitInfo()->type() != JSJitInfo::InlinableNative"
")"); do { *((volatile int*)__null) = 2453; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2454
2455 // If our jitinfo is not marked eliminatable, that means that our C++
2456 // implementation is fallible or that it never wants to be eliminated or
2457 // that we have no hope of ever doing the sort of argument analysis that
2458 // would allow us to detemine that we're side-effect-free. In the
2459 // latter case we wouldn't get DCEd no matter what, but for the former
2460 // two cases we have to explicitly say that we can't be DCEd.
2461 if (!getJitInfo()->isEliminatable) {
2462 setGuard();
2463 }
2464 }
2465
2466 friend MCall* MCall::New(TempAllocator& alloc, WrappedFunction* target,
2467 size_t maxArgc, size_t numActualArgs, bool construct,
2468 bool ignoresReturnValue, bool isDOMCall,
2469 mozilla::Maybe<DOMObjectKind> objectKind);
2470
2471 const JSJitInfo* getJitInfo() const;
2472
2473 public:
2474 DOMObjectKind objectKind() const { return objectKind_; }
2475
2476 virtual AliasSet getAliasSet() const override;
2477
2478 virtual bool congruentTo(const MDefinition* ins) const override;
2479
2480 virtual bool isCallDOMNative() const override { return true; }
2481
2482 virtual void computeMovable() override;
2483};
2484
2485// Used to invoke a JSClass call/construct hook.
2486class MCallClassHook : public MCallBase {
2487 const JSNative target_;
2488 bool constructing_ : 1;
2489 bool ignoresReturnValue_ : 1;
2490
2491 MCallClassHook(JSNative target, bool constructing)
2492 : MCallBase(classOpcode),
2493 target_(target),
2494 constructing_(constructing),
2495 ignoresReturnValue_(false) {
2496 setResultType(MIRType::Value);
2497 }
2498
2499 public:
2500 INSTRUCTION_HEADER(CallClassHook)
2501 static MCallClassHook* New(TempAllocator& alloc, JSNative target,
2502 uint32_t argc, bool constructing);
2503
2504 JSNative target() const { return target_; }
2505 bool isConstructing() const { return constructing_; }
2506
2507 uint32_t numActualArgs() const {
2508 uint32_t thisAndNewTarget = 1 + constructing_;
2509 MOZ_ASSERT(numStackArgs() >= thisAndNewTarget)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(numStackArgs() >= thisAndNewTarget)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(numStackArgs() >= thisAndNewTarget))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("numStackArgs() >= thisAndNewTarget"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2509); AnnotateMozCrashReason("MOZ_ASSERT" "(" "numStackArgs() >= thisAndNewTarget"
")"); do { *((volatile int*)__null) = 2509; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2510 return numStackArgs() - thisAndNewTarget;
2511 }
2512
2513 bool maybeCrossRealm() const { return true; }
2514
2515 bool ignoresReturnValue() const { return ignoresReturnValue_; }
2516 void setIgnoresReturnValue() { ignoresReturnValue_ = true; }
2517
2518 bool possiblyCalls() const override { return true; }
2519};
2520
2521// fun.apply(self, arguments)
2522class MApplyArgs : public MTernaryInstruction,
2523 public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>,
2524 BoxPolicy<2>>::Data {
2525 // Single target from CacheIR, or nullptr
2526 WrappedFunction* target_;
2527 // Number of extra initial formals to skip.
2528 uint32_t numExtraFormals_;
2529 bool maybeCrossRealm_ = true;
2530 bool ignoresReturnValue_ = false;
2531
2532 MApplyArgs(WrappedFunction* target, MDefinition* fun, MDefinition* argc,
2533 MDefinition* self, uint32_t numExtraFormals = 0)
2534 : MTernaryInstruction(classOpcode, fun, argc, self),
2535 target_(target),
2536 numExtraFormals_(numExtraFormals) {
2537 MOZ_ASSERT(argc->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argc->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argc->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("argc->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2537); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argc->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 2537; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2538 setResultType(MIRType::Value);
2539 }
2540
2541 public:
2542 INSTRUCTION_HEADER(ApplyArgs)
2543 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)...); }
2544 NAMED_OPERANDS((0, getFunction), (1, getArgc), (2, getThis))MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getArgc() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); }
2545
2546 WrappedFunction* getSingleTarget() const { return target_; }
2547
2548 uint32_t numExtraFormals() const { return numExtraFormals_; }
2549
2550 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2551 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2552
2553 bool ignoresReturnValue() const { return ignoresReturnValue_; }
2554 void setIgnoresReturnValue() { ignoresReturnValue_ = true; }
2555
2556 bool isConstructing() const { return false; }
2557
2558 bool possiblyCalls() const override { return true; }
2559};
2560
2561class MApplyArgsObj
2562 : public MTernaryInstruction,
2563 public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>, BoxPolicy<2>>::Data {
2564 WrappedFunction* target_;
2565 bool maybeCrossRealm_ = true;
2566 bool ignoresReturnValue_ = false;
2567
2568 MApplyArgsObj(WrappedFunction* target, MDefinition* fun, MDefinition* argsObj,
2569 MDefinition* thisArg)
2570 : MTernaryInstruction(classOpcode, fun, argsObj, thisArg),
2571 target_(target) {
2572 MOZ_ASSERT(argsObj->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argsObj->type() == MIRType::Object)>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(argsObj->type() == MIRType::Object))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("argsObj->type() == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2572); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argsObj->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 2572; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2573 setResultType(MIRType::Value);
2574 }
2575
2576 public:
2577 INSTRUCTION_HEADER(ApplyArgsObj)
2578 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)...); }
2579 NAMED_OPERANDS((0, getFunction), (1, getArgsObj), (2, getThis))MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getArgsObj() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); }
2580
2581 WrappedFunction* getSingleTarget() const { return target_; }
2582
2583 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2584 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2585
2586 bool ignoresReturnValue() const { return ignoresReturnValue_; }
2587 void setIgnoresReturnValue() { ignoresReturnValue_ = true; }
2588
2589 bool isConstructing() const { return false; }
2590
2591 bool possiblyCalls() const override { return true; }
2592};
2593
2594// fun.apply(fn, array)
2595class MApplyArray : public MTernaryInstruction,
2596 public MixPolicy<ObjectPolicy<0>, BoxPolicy<2>>::Data {
2597 // Single target from CacheIR, or nullptr
2598 WrappedFunction* target_;
2599 bool maybeCrossRealm_ = true;
2600 bool ignoresReturnValue_ = false;
2601
2602 MApplyArray(WrappedFunction* target, MDefinition* fun, MDefinition* elements,
2603 MDefinition* self)
2604 : MTernaryInstruction(classOpcode, fun, elements, self), target_(target) {
2605 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2605); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 2605; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2606 setResultType(MIRType::Value);
2607 }
2608
2609 public:
2610 INSTRUCTION_HEADER(ApplyArray)
2611 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)...); }
2612 NAMED_OPERANDS((0, getFunction), (1, getElements), (2, getThis))MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getElements() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); }
2613
2614 WrappedFunction* getSingleTarget() const { return target_; }
2615
2616 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2617 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2618
2619 bool ignoresReturnValue() const { return ignoresReturnValue_; }
2620 void setIgnoresReturnValue() { ignoresReturnValue_ = true; }
2621
2622 bool isConstructing() const { return false; }
2623
2624 bool possiblyCalls() const override { return true; }
2625};
2626
2627// |new F(...arguments)| and |super(...arguments)|.
2628class MConstructArgs : public MQuaternaryInstruction,
2629 public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<1>,
2630 BoxPolicy<2>, ObjectPolicy<3>>::Data {
2631 // Single target from CacheIR, or nullptr
2632 WrappedFunction* target_;
2633 // Number of extra initial formals to skip.
2634 uint32_t numExtraFormals_;
2635 bool maybeCrossRealm_ = true;
2636
2637 MConstructArgs(WrappedFunction* target, MDefinition* fun, MDefinition* argc,
2638 MDefinition* thisValue, MDefinition* newTarget,
2639 uint32_t numExtraFormals = 0)
2640 : MQuaternaryInstruction(classOpcode, fun, argc, thisValue, newTarget),
2641 target_(target),
2642 numExtraFormals_(numExtraFormals) {
2643 MOZ_ASSERT(argc->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(argc->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(argc->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("argc->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2643); AnnotateMozCrashReason("MOZ_ASSERT" "(" "argc->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 2643; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2644 setResultType(MIRType::Value);
2645 }
2646
2647 public:
2648 INSTRUCTION_HEADER(ConstructArgs)
2649 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)...); }
2650 NAMED_OPERANDS((0, getFunction), (1, getArgc), (2, getThis),MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getArgc() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); } MDefinition* getNewTarget(
) const { return getOperand(3); }
2651 (3, getNewTarget))MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getArgc() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); } MDefinition* getNewTarget(
) const { return getOperand(3); }
2652
2653 WrappedFunction* getSingleTarget() const { return target_; }
2654
2655 uint32_t numExtraFormals() const { return numExtraFormals_; }
2656
2657 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2658 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2659
2660 bool ignoresReturnValue() const { return false; }
2661 bool isConstructing() const { return true; }
2662
2663 bool possiblyCalls() const override { return true; }
2664};
2665
2666// |new F(...args)| and |super(...args)|.
2667class MConstructArray
2668 : public MQuaternaryInstruction,
2669 public MixPolicy<ObjectPolicy<0>, BoxPolicy<2>, ObjectPolicy<3>>::Data {
2670 // Single target from CacheIR, or nullptr
2671 WrappedFunction* target_;
2672 bool maybeCrossRealm_ = true;
2673 bool needsThisCheck_ = false;
2674
2675 MConstructArray(WrappedFunction* target, MDefinition* fun,
2676 MDefinition* elements, MDefinition* thisValue,
2677 MDefinition* newTarget)
2678 : MQuaternaryInstruction(classOpcode, fun, elements, thisValue,
2679 newTarget),
2680 target_(target) {
2681 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2681); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 2681; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2682 setResultType(MIRType::Value);
2683 }
2684
2685 public:
2686 INSTRUCTION_HEADER(ConstructArray)
2687 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)...); }
2688 NAMED_OPERANDS((0, getFunction), (1, getElements), (2, getThis),MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getElements() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); } MDefinition* getNewTarget(
) const { return getOperand(3); }
2689 (3, getNewTarget))MDefinition* getFunction() const { return getOperand(0); } MDefinition
* getElements() const { return getOperand(1); } MDefinition* getThis
() const { return getOperand(2); } MDefinition* getNewTarget(
) const { return getOperand(3); }
2690
2691 WrappedFunction* getSingleTarget() const { return target_; }
2692
2693 bool maybeCrossRealm() const { return maybeCrossRealm_; }
2694 void setNotCrossRealm() { maybeCrossRealm_ = false; }
2695
2696 bool needsThisCheck() const { return needsThisCheck_; }
2697 void setNeedsThisCheck() { needsThisCheck_ = true; }
2698
2699 bool ignoresReturnValue() const { return false; }
2700 bool isConstructing() const { return true; }
2701
2702 bool possiblyCalls() const override { return true; }
2703};
2704
2705class MBail : public MNullaryInstruction {
2706 explicit MBail(BailoutKind kind) : MNullaryInstruction(classOpcode) {
2707 setBailoutKind(kind);
2708 setGuard();
2709 }
2710
2711 public:
2712 INSTRUCTION_HEADER(Bail)
2713
2714 static MBail* New(TempAllocator& alloc, BailoutKind kind) {
2715 return new (alloc) MBail(kind);
2716 }
2717 static MBail* New(TempAllocator& alloc) {
2718 return new (alloc) MBail(BailoutKind::Inevitable);
2719 }
2720
2721 AliasSet getAliasSet() const override { return AliasSet::None(); }
2722};
2723
2724class MUnreachable : public MAryControlInstruction<0, 0>,
2725 public NoTypePolicy::Data {
2726 MUnreachable() : MAryControlInstruction(classOpcode) {}
2727
2728 public:
2729 INSTRUCTION_HEADER(Unreachable)
2730 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)...); }
2731
2732 AliasSet getAliasSet() const override { return AliasSet::None(); }
2733};
2734
2735class MAssertRecoveredOnBailout : public MUnaryInstruction,
2736 public NoTypePolicy::Data {
2737 bool mustBeRecovered_;
2738
2739 MAssertRecoveredOnBailout(MDefinition* ins, bool mustBeRecovered)
2740 : MUnaryInstruction(classOpcode, ins), mustBeRecovered_(mustBeRecovered) {
2741 setResultType(MIRType::Value);
2742 setRecoveredOnBailout();
2743 setGuard();
2744 }
2745
2746 public:
2747 INSTRUCTION_HEADER(AssertRecoveredOnBailout)
2748 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)...); }
2749
2750 // Needed to assert that float32 instructions are correctly recovered.
2751 bool canConsumeFloat32(MUse* use) const override { return true; }
2752
2753 [[nodiscard]] bool writeRecoverData(
2754 CompactBufferWriter& writer) const override;
2755 bool canRecoverOnBailout() const override { return true; }
2756};
2757
2758class MAssertFloat32 : public MUnaryInstruction, public NoTypePolicy::Data {
2759 bool mustBeFloat32_;
2760
2761 MAssertFloat32(MDefinition* value, bool mustBeFloat32)
2762 : MUnaryInstruction(classOpcode, value), mustBeFloat32_(mustBeFloat32) {}
2763
2764 public:
2765 INSTRUCTION_HEADER(AssertFloat32)
2766 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)...); }
2767
2768 bool canConsumeFloat32(MUse* use) const override { return true; }
2769
2770 bool mustBeFloat32() const { return mustBeFloat32_; }
2771};
2772
2773class MCompare : public MBinaryInstruction, public ComparePolicy::Data {
2774 public:
2775 enum CompareType {
2776
2777 // Anything compared to Undefined
2778 Compare_Undefined,
2779
2780 // Anything compared to Null
2781 Compare_Null,
2782
2783 // Int32 compared to Int32
2784 // Boolean compared to Boolean
2785 Compare_Int32,
2786
2787 // Int32 compared as unsigneds
2788 Compare_UInt32,
2789
2790 // Int64 compared to Int64.
2791 Compare_Int64,
2792
2793 // Int64 compared as unsigneds.
2794 Compare_UInt64,
2795
2796 // IntPtr compared as unsigneds.
2797 Compare_UIntPtr,
2798
2799 // Double compared to Double
2800 Compare_Double,
2801
2802 // Float compared to Float
2803 Compare_Float32,
2804
2805 // String compared to String
2806 Compare_String,
2807
2808 // Symbol compared to Symbol
2809 Compare_Symbol,
2810
2811 // Object compared to Object
2812 Compare_Object,
2813
2814 // BigInt compared to BigInt
2815 Compare_BigInt,
2816
2817 // BigInt compared to Int32
2818 Compare_BigInt_Int32,
2819
2820 // BigInt compared to Double
2821 Compare_BigInt_Double,
2822
2823 // BigInt compared to String
2824 Compare_BigInt_String,
2825
2826 // Wasm Ref/AnyRef/NullRef compared to Ref/AnyRef/NullRef
2827 Compare_WasmAnyRef,
2828 };
2829
2830 private:
2831 CompareType compareType_;
2832 JSOp jsop_;
2833 bool operandsAreNeverNaN_;
2834
2835 // When a floating-point comparison is converted to an integer comparison
2836 // (when range analysis proves it safe), we need to convert the operands
2837 // to integer as well.
2838 bool truncateOperands_;
2839
2840 MCompare(MDefinition* left, MDefinition* right, JSOp jsop,
2841 CompareType compareType)
2842 : MBinaryInstruction(classOpcode, left, right),
2843 compareType_(compareType),
2844 jsop_(jsop),
2845 operandsAreNeverNaN_(false),
2846 truncateOperands_(false) {
2847 setResultType(MIRType::Boolean);
2848 setMovable();
2849 }
2850
2851 public:
2852 INSTRUCTION_HEADER(Compare)
2853 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)...); }
2854
2855 static MCompare* NewWasm(TempAllocator& alloc, MDefinition* left,
2856 MDefinition* right, JSOp jsop,
2857 CompareType compareType) {
2858 MOZ_ASSERT(compareType == Compare_Int32 || compareType == Compare_UInt32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compareType == Compare_Int32 || compareType == Compare_UInt32
|| compareType == Compare_Int64 || compareType == Compare_UInt64
|| compareType == Compare_Double || compareType == Compare_Float32
|| compareType == Compare_WasmAnyRef)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compareType == Compare_Int32
|| compareType == Compare_UInt32 || compareType == Compare_Int64
|| compareType == Compare_UInt64 || compareType == Compare_Double
|| compareType == Compare_Float32 || compareType == Compare_WasmAnyRef
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2859 compareType == Compare_Int64 || compareType == Compare_UInt64 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compareType == Compare_Int32 || compareType == Compare_UInt32
|| compareType == Compare_Int64 || compareType == Compare_UInt64
|| compareType == Compare_Double || compareType == Compare_Float32
|| compareType == Compare_WasmAnyRef)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compareType == Compare_Int32
|| compareType == Compare_UInt32 || compareType == Compare_Int64
|| compareType == Compare_UInt64 || compareType == Compare_Double
|| compareType == Compare_Float32 || compareType == Compare_WasmAnyRef
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2860 compareType == Compare_Double ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compareType == Compare_Int32 || compareType == Compare_UInt32
|| compareType == Compare_Int64 || compareType == Compare_UInt64
|| compareType == Compare_Double || compareType == Compare_Float32
|| compareType == Compare_WasmAnyRef)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compareType == Compare_Int32
|| compareType == Compare_UInt32 || compareType == Compare_Int64
|| compareType == Compare_UInt64 || compareType == Compare_Double
|| compareType == Compare_Float32 || compareType == Compare_WasmAnyRef
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2861 compareType == Compare_Float32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compareType == Compare_Int32 || compareType == Compare_UInt32
|| compareType == Compare_Int64 || compareType == Compare_UInt64
|| compareType == Compare_Double || compareType == Compare_Float32
|| compareType == Compare_WasmAnyRef)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compareType == Compare_Int32
|| compareType == Compare_UInt32 || compareType == Compare_Int64
|| compareType == Compare_UInt64 || compareType == Compare_Double
|| compareType == Compare_Float32 || compareType == Compare_WasmAnyRef
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
2862 compareType == Compare_WasmAnyRef)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(compareType == Compare_Int32 || compareType == Compare_UInt32
|| compareType == Compare_Int64 || compareType == Compare_UInt64
|| compareType == Compare_Double || compareType == Compare_Float32
|| compareType == Compare_WasmAnyRef)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(compareType == Compare_Int32
|| compareType == Compare_UInt32 || compareType == Compare_Int64
|| compareType == Compare_UInt64 || compareType == Compare_Double
|| compareType == Compare_Float32 || compareType == Compare_WasmAnyRef
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "compareType == Compare_Int32 || compareType == Compare_UInt32 || compareType == Compare_Int64 || compareType == Compare_UInt64 || compareType == Compare_Double || compareType == Compare_Float32 || compareType == Compare_WasmAnyRef"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2863 auto* ins = MCompare::New(alloc, left, right, jsop, compareType);
2864 ins->setResultType(MIRType::Int32);
2865 return ins;
2866 }
2867
2868 [[nodiscard]] bool tryFold(bool* result);
2869 [[nodiscard]] bool evaluateConstantOperands(TempAllocator& alloc,
2870 bool* result);
2871 MDefinition* foldsTo(TempAllocator& alloc) override;
2872
2873 CompareType compareType() const { return compareType_; }
2874 bool isInt32Comparison() const { return compareType() == Compare_Int32; }
2875 bool isDoubleComparison() const { return compareType() == Compare_Double; }
2876 bool isFloat32Comparison() const { return compareType() == Compare_Float32; }
2877 bool isNumericComparison() const {
2878 return isInt32Comparison() || isDoubleComparison() || isFloat32Comparison();
2879 }
2880 MIRType inputType();
2881
2882 JSOp jsop() const { return jsop_; }
2883 bool operandsAreNeverNaN() const { return operandsAreNeverNaN_; }
2884 AliasSet getAliasSet() const override { return AliasSet::None(); }
2885
2886#ifdef JS_JITSPEW1
2887 void printOpcode(GenericPrinter& out) const override;
2888#endif
2889 void collectRangeInfoPreTrunc() override;
2890
2891 void trySpecializeFloat32(TempAllocator& alloc) override;
2892 bool isFloat32Commutative() const override { return true; }
2893 bool canTruncate() const override;
2894 void truncate(TruncateKind kind) override;
2895 TruncateKind operandTruncateKind(size_t index) const override;
2896
2897#ifdef DEBUG1
2898 bool isConsistentFloat32Use(MUse* use) const override {
2899 // Both sides of the compare can be Float32
2900 return compareType_ == Compare_Float32;
2901 }
2902#endif
2903
2904 ALLOW_CLONE(MCompare)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MCompare
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
2905
2906 private:
2907 [[nodiscard]] bool tryFoldEqualOperands(bool* result);
2908 [[nodiscard]] bool tryFoldTypeOf(bool* result);
2909 [[nodiscard]] MDefinition* tryFoldTypeOf(TempAllocator& alloc);
2910 [[nodiscard]] MDefinition* tryFoldCharCompare(TempAllocator& alloc);
2911 [[nodiscard]] MDefinition* tryFoldStringCompare(TempAllocator& alloc);
2912 [[nodiscard]] MDefinition* tryFoldStringSubstring(TempAllocator& alloc);
2913 [[nodiscard]] MDefinition* tryFoldStringIndexOf(TempAllocator& alloc);
2914
2915 public:
2916 bool congruentTo(const MDefinition* ins) const override {
2917 if (!binaryCongruentTo(ins)) {
2918 return false;
2919 }
2920 return compareType() == ins->toCompare()->compareType() &&
2921 jsop() == ins->toCompare()->jsop();
2922 }
2923
2924 [[nodiscard]] bool writeRecoverData(
2925 CompactBufferWriter& writer) const override;
2926 bool canRecoverOnBailout() const override {
2927 switch (compareType_) {
2928 case Compare_Undefined:
2929 case Compare_Null:
2930 case Compare_Int32:
2931 case Compare_UInt32:
2932 case Compare_Double:
2933 case Compare_Float32:
2934 case Compare_String:
2935 case Compare_Symbol:
2936 case Compare_Object:
2937 case Compare_BigInt:
2938 case Compare_BigInt_Int32:
2939 case Compare_BigInt_Double:
2940 case Compare_BigInt_String:
2941 return true;
2942
2943 case Compare_Int64:
2944 case Compare_UInt64:
2945 case Compare_UIntPtr:
2946 case Compare_WasmAnyRef:
2947 return false;
2948 }
2949 MOZ_CRASH("unexpected compare type")do { do { } while (false); MOZ_ReportCrash("" "unexpected compare type"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 2949); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected compare type"
")"); do { *((volatile int*)__null) = 2949; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
;
2950 }
2951
2952#ifdef JS_JITSPEW1
2953 void getExtras(ExtrasCollector* extras) override {
2954 const char* ty = nullptr;
2955 switch (compareType_) {
2956 case Compare_Undefined:
2957 ty = "Undefined";
2958 break;
2959 case Compare_Null:
2960 ty = "Null";
2961 break;
2962 case Compare_Int32:
2963 ty = "Int32";
2964 break;
2965 case Compare_UInt32:
2966 ty = "UInt32";
2967 break;
2968 case Compare_Int64:
2969 ty = "Int64";
2970 break;
2971 case Compare_UInt64:
2972 ty = "UInt64";
2973 break;
2974 case Compare_UIntPtr:
2975 ty = "UIntPtr";
2976 break;
2977 case Compare_Double:
2978 ty = "Double";
2979 break;
2980 case Compare_Float32:
2981 ty = "Float32";
2982 break;
2983 case Compare_String:
2984 ty = "String";
2985 break;
2986 case Compare_Symbol:
2987 ty = "Symbol";
2988 break;
2989 case Compare_Object:
2990 ty = "Object";
2991 break;
2992 case Compare_BigInt:
2993 ty = "BigInt";
2994 break;
2995 case Compare_BigInt_Int32:
2996 ty = "BigInt_Int32";
2997 break;
2998 case Compare_BigInt_Double:
2999 ty = "BigInt_Double";
3000 break;
3001 case Compare_BigInt_String:
3002 ty = "BigInt_String";
3003 break;
3004 case Compare_WasmAnyRef:
3005 ty = "WasmAnyRef";
3006 break;
3007 default:
3008 ty = "!!unknown!!";
3009 break;
3010 };
3011 char buf[64];
3012 SprintfLiteral(buf, "ty=%s jsop=%s", ty, CodeName(jsop()));
3013 extras->add(buf);
3014 }
3015#endif
3016};
3017
3018// Takes a typed value and returns an untyped value.
3019class MBox : public MUnaryInstruction, public NoTypePolicy::Data {
3020 explicit MBox(MDefinition* ins) : MUnaryInstruction(classOpcode, ins) {
3021 // Cannot box a box.
3022 MOZ_ASSERT(ins->type() != MIRType::Value)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(ins->type() != MIRType::Value)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(ins->type() != MIRType::Value
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"ins->type() != MIRType::Value", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3022); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ins->type() != MIRType::Value"
")"); do { *((volatile int*)__null) = 3022; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3023
3024 setResultType(MIRType::Value);
3025 setMovable();
3026 }
3027
3028 public:
3029 INSTRUCTION_HEADER(Box)
3030 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)...); }
3031
3032 bool congruentTo(const MDefinition* ins) const override {
3033 return congruentIfOperandsEqual(ins);
3034 }
3035
3036 MDefinition* foldsTo(TempAllocator& alloc) override;
3037
3038 AliasSet getAliasSet() const override { return AliasSet::None(); }
3039
3040 ALLOW_CLONE(MBox)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBox
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3041};
3042
3043// Note: the op may have been inverted during lowering (to put constants in a
3044// position where they can be immediates), so it is important to use the
3045// lir->jsop() instead of the mir->jsop() when it is present.
3046static inline Assembler::Condition JSOpToCondition(
3047 MCompare::CompareType compareType, JSOp op) {
3048 bool isSigned = (compareType != MCompare::Compare_UInt32 &&
3049 compareType != MCompare::Compare_UInt64 &&
3050 compareType != MCompare::Compare_UIntPtr);
3051 return JSOpToCondition(op, isSigned);
3052}
3053
3054// Takes a typed value and checks if it is a certain type. If so, the payload
3055// is unpacked and returned as that type. Otherwise, it is considered a
3056// deoptimization.
3057class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data {
3058 public:
3059 enum Mode {
3060 Fallible, // Check the type, and deoptimize if unexpected.
3061 Infallible, // Type guard is not necessary.
3062 };
3063
3064 private:
3065 Mode mode_;
3066
3067 MUnbox(MDefinition* ins, MIRType type, Mode mode)
3068 : MUnaryInstruction(classOpcode, ins), mode_(mode) {
3069 // Only allow unboxing a non MIRType::Value when input and output types
3070 // don't match. This is often used to force a bailout. Boxing happens
3071 // during type analysis.
3072 MOZ_ASSERT_IF(ins->type() != MIRType::Value, type != ins->type())do { if (ins->type() != MIRType::Value) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(type !=
ins->type())>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(type != ins->type()))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type != ins->type()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3072); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type != ins->type()"
")"); do { *((volatile int*)__null) = 3072; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
3073
3074 MOZ_ASSERT(type == MIRType::Boolean || type == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Boolean || type == MIRType::Int32 ||
type == MIRType::Double || type == MIRType::String || type ==
MIRType::Symbol || type == MIRType::BigInt || type == MIRType
::Object)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(type == MIRType::Boolean || type == MIRType
::Int32 || type == MIRType::Double || type == MIRType::String
|| type == MIRType::Symbol || type == MIRType::BigInt || type
== MIRType::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
")"); do { *((volatile int*)__null) = 3077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3075 type == MIRType::Double || type == MIRType::String ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Boolean || type == MIRType::Int32 ||
type == MIRType::Double || type == MIRType::String || type ==
MIRType::Symbol || type == MIRType::BigInt || type == MIRType
::Object)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(type == MIRType::Boolean || type == MIRType
::Int32 || type == MIRType::Double || type == MIRType::String
|| type == MIRType::Symbol || type == MIRType::BigInt || type
== MIRType::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
")"); do { *((volatile int*)__null) = 3077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3076 type == MIRType::Symbol || type == MIRType::BigInt ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Boolean || type == MIRType::Int32 ||
type == MIRType::Double || type == MIRType::String || type ==
MIRType::Symbol || type == MIRType::BigInt || type == MIRType
::Object)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(type == MIRType::Boolean || type == MIRType
::Int32 || type == MIRType::Double || type == MIRType::String
|| type == MIRType::Symbol || type == MIRType::BigInt || type
== MIRType::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
")"); do { *((volatile int*)__null) = 3077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
3077 type == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Boolean || type == MIRType::Int32 ||
type == MIRType::Double || type == MIRType::String || type ==
MIRType::Symbol || type == MIRType::BigInt || type == MIRType
::Object)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(type == MIRType::Boolean || type == MIRType
::Int32 || type == MIRType::Double || type == MIRType::String
|| type == MIRType::Symbol || type == MIRType::BigInt || type
== MIRType::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Boolean || type == MIRType::Int32 || type == MIRType::Double || type == MIRType::String || type == MIRType::Symbol || type == MIRType::BigInt || type == MIRType::Object"
")"); do { *((volatile int*)__null) = 3077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3078
3079 setResultType(type);
3080 setMovable();
3081
3082 if (mode_ == Fallible) {
3083 setGuard();
3084 }
3085 }
3086
3087 public:
3088 INSTRUCTION_HEADER(Unbox)
3089 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)...); }
3090
3091 Mode mode() const { return mode_; }
3092 bool fallible() const { return mode() != Infallible; }
3093 bool congruentTo(const MDefinition* ins) const override {
3094 if (!ins->isUnbox() || ins->toUnbox()->mode() != mode()) {
3095 return false;
3096 }
3097 return congruentIfOperandsEqual(ins);
3098 }
3099
3100 MDefinition* foldsTo(TempAllocator& alloc) override;
3101
3102 AliasSet getAliasSet() const override { return AliasSet::None(); }
3103#ifdef JS_JITSPEW1
3104 void printOpcode(GenericPrinter& out) const override;
3105#endif
3106
3107 ALLOW_CLONE(MUnbox)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MUnbox
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3108};
3109
3110class MAssertRange : public MUnaryInstruction, public NoTypePolicy::Data {
3111 // This is the range checked by the assertion. Don't confuse this with the
3112 // range_ member or the range() accessor. Since MAssertRange doesn't return
3113 // a value, it doesn't use those.
3114 const Range* assertedRange_;
3115
3116 MAssertRange(MDefinition* ins, const Range* assertedRange)
3117 : MUnaryInstruction(classOpcode, ins), assertedRange_(assertedRange) {
3118 setGuard();
3119 setResultType(MIRType::None);
3120 }
3121
3122 public:
3123 INSTRUCTION_HEADER(AssertRange)
3124 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)...); }
3125
3126 const Range* assertedRange() const { return assertedRange_; }
3127
3128 AliasSet getAliasSet() const override { return AliasSet::None(); }
3129
3130#ifdef JS_JITSPEW1
3131 void printOpcode(GenericPrinter& out) const override;
3132#endif
3133};
3134
3135class MAssertClass : public MUnaryInstruction, public NoTypePolicy::Data {
3136 const JSClass* class_;
3137
3138 MAssertClass(MDefinition* obj, const JSClass* clasp)
3139 : MUnaryInstruction(classOpcode, obj), class_(clasp) {
3140 MOZ_ASSERT(obj->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(obj->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(obj->type() == MIRType::Object
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"obj->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 3140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3141
3142 setGuard();
3143 setResultType(MIRType::None);
3144 }
3145
3146 public:
3147 INSTRUCTION_HEADER(AssertClass)
3148 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)...); }
3149
3150 const JSClass* getClass() const { return class_; }
3151 AliasSet getAliasSet() const override { return AliasSet::None(); }
3152};
3153
3154class MAssertShape : public MUnaryInstruction, public NoTypePolicy::Data {
3155 CompilerShape shape_;
3156
3157 MAssertShape(MDefinition* obj, Shape* shape)
3158 : MUnaryInstruction(classOpcode, obj), shape_(shape) {
3159 MOZ_ASSERT(obj->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(obj->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(obj->type() == MIRType::Object
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"obj->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3159); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 3159; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3160
3161 setGuard();
3162 setResultType(MIRType::None);
3163 }
3164
3165 public:
3166 INSTRUCTION_HEADER(AssertShape)
3167 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)...); }
3168
3169 const Shape* shape() const { return shape_; }
3170 AliasSet getAliasSet() const override { return AliasSet::None(); }
3171};
3172
3173// Eager initialization of arguments object.
3174class MCreateArgumentsObject : public MUnaryInstruction,
3175 public ObjectPolicy<0>::Data {
3176 CompilerGCPointer<ArgumentsObject*> templateObj_;
3177
3178 MCreateArgumentsObject(MDefinition* callObj, ArgumentsObject* templateObj)
3179 : MUnaryInstruction(classOpcode, callObj), templateObj_(templateObj) {
3180 setResultType(MIRType::Object);
3181 }
3182
3183 public:
3184 INSTRUCTION_HEADER(CreateArgumentsObject)
3185 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)...); }
3186 NAMED_OPERANDS((0, getCallObject))MDefinition* getCallObject() const { return getOperand(0); }
3187
3188 ArgumentsObject* templateObject() const { return templateObj_; }
3189
3190 AliasSet getAliasSet() const override { return AliasSet::None(); }
3191
3192 bool possiblyCalls() const override { return true; }
3193
3194 [[nodiscard]] bool writeRecoverData(
3195 CompactBufferWriter& writer) const override;
3196 bool canRecoverOnBailout() const override { return true; }
3197};
3198
3199// Eager initialization of arguments object for inlined function
3200class MCreateInlinedArgumentsObject : public MVariadicInstruction,
3201 public NoFloatPolicyAfter<0>::Data {
3202 CompilerGCPointer<ArgumentsObject*> templateObj_;
3203
3204 explicit MCreateInlinedArgumentsObject(ArgumentsObject* templateObj)
3205 : MVariadicInstruction(classOpcode), templateObj_(templateObj) {
3206 setResultType(MIRType::Object);
3207 }
3208
3209 static const size_t NumNonArgumentOperands = 2;
3210
3211 public:
3212 INSTRUCTION_HEADER(CreateInlinedArgumentsObject)
3213 static MCreateInlinedArgumentsObject* New(TempAllocator& alloc,
3214 MDefinition* callObj,
3215 MDefinition* callee,
3216 MDefinitionVector& args,
3217 ArgumentsObject* templateObj);
3218 NAMED_OPERANDS((0, getCallObject), (1, getCallee))MDefinition* getCallObject() const { return getOperand(0); } MDefinition
* getCallee() const { return getOperand(1); }
3219
3220 ArgumentsObject* templateObject() const { return templateObj_; }
3221
3222 MDefinition* getArg(uint32_t idx) const {
3223 return getOperand(idx + NumNonArgumentOperands);
3224 }
3225 uint32_t numActuals() const { return numOperands() - NumNonArgumentOperands; }
3226
3227 AliasSet getAliasSet() const override { return AliasSet::None(); }
3228
3229 bool possiblyCalls() const override { return true; }
3230
3231 [[nodiscard]] bool writeRecoverData(
3232 CompactBufferWriter& writer) const override;
3233 bool canRecoverOnBailout() const override { return true; }
3234};
3235
3236class MGetInlinedArgument
3237 : public MVariadicInstruction,
3238 public MixPolicy<UnboxedInt32Policy<0>, NoFloatPolicyAfter<1>>::Data {
3239 MGetInlinedArgument() : MVariadicInstruction(classOpcode) {
3240 setResultType(MIRType::Value);
3241 }
3242
3243 static const size_t NumNonArgumentOperands = 1;
3244
3245 public:
3246 INSTRUCTION_HEADER(GetInlinedArgument)
3247 static MGetInlinedArgument* New(TempAllocator& alloc, MDefinition* index,
3248 MCreateInlinedArgumentsObject* args);
3249 static MGetInlinedArgument* New(TempAllocator& alloc, MDefinition* index,
3250 const CallInfo& callInfo);
3251 NAMED_OPERANDS((0, index))MDefinition* index() const { return getOperand(0); }
3252
3253 MDefinition* getArg(uint32_t idx) const {
3254 return getOperand(idx + NumNonArgumentOperands);
3255 }
3256 uint32_t numActuals() const { return numOperands() - NumNonArgumentOperands; }
3257
3258 bool congruentTo(const MDefinition* ins) const override {
3259 return congruentIfOperandsEqual(ins);
3260 }
3261 AliasSet getAliasSet() const override { return AliasSet::None(); }
3262
3263 MDefinition* foldsTo(TempAllocator& alloc) override;
3264};
3265
3266class MGetInlinedArgumentHole
3267 : public MVariadicInstruction,
3268 public MixPolicy<UnboxedInt32Policy<0>, NoFloatPolicyAfter<1>>::Data {
3269 MGetInlinedArgumentHole() : MVariadicInstruction(classOpcode) {
3270 setGuard();
3271 setResultType(MIRType::Value);
3272 }
3273
3274 static const size_t NumNonArgumentOperands = 1;
3275
3276 public:
3277 INSTRUCTION_HEADER(GetInlinedArgumentHole)
3278 static MGetInlinedArgumentHole* New(TempAllocator& alloc, MDefinition* index,
3279 MCreateInlinedArgumentsObject* args);
3280 NAMED_OPERANDS((0, index))MDefinition* index() const { return getOperand(0); }
3281
3282 MDefinition* getArg(uint32_t idx) const {
3283 return getOperand(idx + NumNonArgumentOperands);
3284 }
3285 uint32_t numActuals() const { return numOperands() - NumNonArgumentOperands; }
3286
3287 bool congruentTo(const MDefinition* ins) const override {
3288 return congruentIfOperandsEqual(ins);
3289 }
3290 AliasSet getAliasSet() const override { return AliasSet::None(); }
3291
3292 MDefinition* foldsTo(TempAllocator& alloc) override;
3293};
3294
3295class MInlineArgumentsSlice
3296 : public MVariadicInstruction,
3297 public MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>,
3298 NoFloatPolicyAfter<2>>::Data {
3299 JSObject* templateObj_;
3300 gc::Heap initialHeap_;
3301
3302 MInlineArgumentsSlice(JSObject* templateObj, gc::Heap initialHeap)
3303 : MVariadicInstruction(classOpcode),
3304 templateObj_(templateObj),
3305 initialHeap_(initialHeap) {
3306 setResultType(MIRType::Object);
3307 }
3308
3309 static const size_t NumNonArgumentOperands = 2;
3310
3311 public:
3312 INSTRUCTION_HEADER(InlineArgumentsSlice)
3313 static MInlineArgumentsSlice* New(TempAllocator& alloc, MDefinition* begin,
3314 MDefinition* count,
3315 MCreateInlinedArgumentsObject* args,
3316 JSObject* templateObj,
3317 gc::Heap initialHeap);
3318 NAMED_OPERANDS((0, begin), (1, count))MDefinition* begin() const { return getOperand(0); } MDefinition
* count() const { return getOperand(1); }
3319
3320 JSObject* templateObj() const { return templateObj_; }
3321 gc::Heap initialHeap() const { return initialHeap_; }
3322
3323 MDefinition* getArg(uint32_t idx) const {
3324 return getOperand(idx + NumNonArgumentOperands);
3325 }
3326 uint32_t numActuals() const { return numOperands() - NumNonArgumentOperands; }
3327
3328 AliasSet getAliasSet() const override { return AliasSet::None(); }
3329
3330 bool possiblyCalls() const override { return true; }
3331};
3332
3333// Allocates a new BoundFunctionObject and calls
3334// BoundFunctionObject::functionBindImpl. This instruction can have arbitrary
3335// side-effects because the GetProperty calls for length/name can call into JS.
3336class MBindFunction
3337 : public MVariadicInstruction,
3338 public MixPolicy<ObjectPolicy<0>, NoFloatPolicyAfter<1>>::Data {
3339 CompilerGCPointer<JSObject*> templateObj_;
3340
3341 explicit MBindFunction(JSObject* templateObj)
3342 : MVariadicInstruction(classOpcode), templateObj_(templateObj) {
3343 setResultType(MIRType::Object);
3344 }
3345
3346 // The target object is operand 0.
3347 static const size_t NumNonArgumentOperands = 1;
3348
3349 public:
3350 INSTRUCTION_HEADER(BindFunction)
3351 static MBindFunction* New(TempAllocator& alloc, MDefinition* target,
3352 uint32_t argc, JSObject* templateObj);
3353 NAMED_OPERANDS((0, target))MDefinition* target() const { return getOperand(0); }
3354
3355 JSObject* templateObject() const { return templateObj_; }
3356
3357 MDefinition* getArg(uint32_t idx) const {
3358 return getOperand(idx + NumNonArgumentOperands);
3359 }
3360 void initArg(size_t i, MDefinition* arg) {
3361 initOperand(NumNonArgumentOperands + i, arg);
3362 }
3363 uint32_t numStackArgs() const {
3364 return numOperands() - NumNonArgumentOperands;
3365 }
3366
3367 bool possiblyCalls() const override { return true; }
3368};
3369
3370class MToFPInstruction : public MUnaryInstruction, public ToDoublePolicy::Data {
3371 public:
3372 // Types of values which can be converted.
3373 enum ConversionKind { NonStringPrimitives, NumbersOnly };
3374
3375 private:
3376 ConversionKind conversion_;
3377
3378 protected:
3379 MToFPInstruction(Opcode op, MDefinition* def,
3380 ConversionKind conversion = NonStringPrimitives)
3381 : MUnaryInstruction(op, def), conversion_(conversion) {}
3382
3383 public:
3384 ConversionKind conversion() const { return conversion_; }
3385};
3386
3387// Converts a primitive (either typed or untyped) to a double. If the input is
3388// not primitive at runtime, a bailout occurs.
3389class MToDouble : public MToFPInstruction {
3390 private:
3391 TruncateKind implicitTruncate_;
3392
3393 explicit MToDouble(MDefinition* def,
3394 ConversionKind conversion = NonStringPrimitives)
3395 : MToFPInstruction(classOpcode, def, conversion),
3396 implicitTruncate_(TruncateKind::NoTruncate) {
3397 setResultType(MIRType::Double);
3398 setMovable();
3399
3400 // Guard unless the conversion is known to be non-effectful & non-throwing.
3401 if (!def->definitelyType({MIRType::Undefined, MIRType::Null,
3402 MIRType::Boolean, MIRType::Int32, MIRType::Double,
3403 MIRType::Float32, MIRType::String})) {
3404 setGuard();
3405 }
3406 }
3407
3408 public:
3409 INSTRUCTION_HEADER(ToDouble)
3410 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)...); }
3411
3412 MDefinition* foldsTo(TempAllocator& alloc) override;
3413 bool congruentTo(const MDefinition* ins) const override {
3414 if (!ins->isToDouble() || ins->toToDouble()->conversion() != conversion()) {
3415 return false;
3416 }
3417 return congruentIfOperandsEqual(ins);
3418 }
3419 AliasSet getAliasSet() const override { return AliasSet::None(); }
3420
3421 void computeRange(TempAllocator& alloc) override;
3422 bool canTruncate() const override;
3423 void truncate(TruncateKind kind) override;
3424 TruncateKind operandTruncateKind(size_t index) const override;
3425
3426#ifdef DEBUG1
3427 bool isConsistentFloat32Use(MUse* use) const override { return true; }
3428#endif
3429
3430 TruncateKind truncateKind() const { return implicitTruncate_; }
3431 void setTruncateKind(TruncateKind kind) {
3432 implicitTruncate_ = std::max(implicitTruncate_, kind);
3433 }
3434
3435 [[nodiscard]] bool writeRecoverData(
3436 CompactBufferWriter& writer) const override;
3437 bool canRecoverOnBailout() const override {
3438 if (input()->type() == MIRType::Value) {
3439 return false;
3440 }
3441 if (input()->type() == MIRType::Symbol) {
3442 return false;
3443 }
3444 if (input()->type() == MIRType::BigInt) {
3445 return false;
3446 }
3447
3448 return true;
3449 }
3450
3451 ALLOW_CLONE(MToDouble)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToDouble
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3452};
3453
3454// Converts a primitive (either typed or untyped) to a float32. If the input is
3455// not primitive at runtime, a bailout occurs.
3456class MToFloat32 : public MToFPInstruction {
3457 bool mustPreserveNaN_;
3458
3459 explicit MToFloat32(MDefinition* def,
3460 ConversionKind conversion = NonStringPrimitives)
3461 : MToFPInstruction(classOpcode, def, conversion),
3462 mustPreserveNaN_(false) {
3463 setResultType(MIRType::Float32);
3464 setMovable();
3465
3466 // Guard unless the conversion is known to be non-effectful & non-throwing.
3467 if (!def->definitelyType({MIRType::Undefined, MIRType::Null,
3468 MIRType::Boolean, MIRType::Int32, MIRType::Double,
3469 MIRType::Float32, MIRType::String})) {
3470 setGuard();
3471 }
3472 }
3473
3474 explicit MToFloat32(MDefinition* def, bool mustPreserveNaN)
3475 : MToFloat32(def) {
3476 mustPreserveNaN_ = mustPreserveNaN;
3477 }
3478
3479 public:
3480 INSTRUCTION_HEADER(ToFloat32)
3481 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)...); }
3482
3483 virtual MDefinition* foldsTo(TempAllocator& alloc) override;
3484 bool congruentTo(const MDefinition* ins) const override {
3485 if (!congruentIfOperandsEqual(ins)) {
3486 return false;
3487 }
3488 auto* other = ins->toToFloat32();
3489 return other->conversion() == conversion() &&
3490 other->mustPreserveNaN_ == mustPreserveNaN_;
3491 }
3492 AliasSet getAliasSet() const override { return AliasSet::None(); }
3493
3494 void computeRange(TempAllocator& alloc) override;
3495
3496 bool canConsumeFloat32(MUse* use) const override { return true; }
3497 bool canProduceFloat32() const override { return true; }
3498
3499 [[nodiscard]] bool writeRecoverData(
3500 CompactBufferWriter& writer) const override;
3501 bool canRecoverOnBailout() const override { return true; }
3502
3503 ALLOW_CLONE(MToFloat32)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToFloat32
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3504};
3505
3506// Converts a uint32 to a float32 (coming from wasm).
3507class MWasmUnsignedToFloat32 : public MUnaryInstruction,
3508 public NoTypePolicy::Data {
3509 explicit MWasmUnsignedToFloat32(MDefinition* def)
3510 : MUnaryInstruction(classOpcode, def) {
3511 setResultType(MIRType::Float32);
3512 setMovable();
3513 }
3514
3515 public:
3516 INSTRUCTION_HEADER(WasmUnsignedToFloat32)
3517 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)...); }
3518
3519 MDefinition* foldsTo(TempAllocator& alloc) override;
3520 bool congruentTo(const MDefinition* ins) const override {
3521 return congruentIfOperandsEqual(ins);
3522 }
3523 AliasSet getAliasSet() const override { return AliasSet::None(); }
3524
3525 bool canProduceFloat32() const override { return true; }
3526};
3527
3528class MWrapInt64ToInt32 : public MUnaryInstruction, public NoTypePolicy::Data {
3529 bool bottomHalf_;
3530
3531 explicit MWrapInt64ToInt32(MDefinition* def, bool bottomHalf = true)
3532 : MUnaryInstruction(classOpcode, def), bottomHalf_(bottomHalf) {
3533 setResultType(MIRType::Int32);
3534 setMovable();
3535 }
3536
3537 public:
3538 INSTRUCTION_HEADER(WrapInt64ToInt32)
3539 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)...); }
3540
3541 MDefinition* foldsTo(TempAllocator& alloc) override;
3542 bool congruentTo(const MDefinition* ins) const override {
3543 if (!ins->isWrapInt64ToInt32()) {
3544 return false;
3545 }
3546 if (ins->toWrapInt64ToInt32()->bottomHalf() != bottomHalf()) {
3547 return false;
3548 }
3549 return congruentIfOperandsEqual(ins);
3550 }
3551 AliasSet getAliasSet() const override { return AliasSet::None(); }
3552
3553 bool bottomHalf() const { return bottomHalf_; }
3554};
3555
3556class MExtendInt32ToInt64 : public MUnaryInstruction,
3557 public NoTypePolicy::Data {
3558 bool isUnsigned_;
3559
3560 MExtendInt32ToInt64(MDefinition* def, bool isUnsigned)
3561 : MUnaryInstruction(classOpcode, def), isUnsigned_(isUnsigned) {
3562 setResultType(MIRType::Int64);
3563 setMovable();
3564 }
3565
3566 public:
3567 INSTRUCTION_HEADER(ExtendInt32ToInt64)
3568 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)...); }
3569
3570 bool isUnsigned() const { return isUnsigned_; }
3571
3572 MDefinition* foldsTo(TempAllocator& alloc) override;
3573 bool congruentTo(const MDefinition* ins) const override {
3574 if (!ins->isExtendInt32ToInt64()) {
3575 return false;
3576 }
3577 if (ins->toExtendInt32ToInt64()->isUnsigned_ != isUnsigned_) {
3578 return false;
3579 }
3580 return congruentIfOperandsEqual(ins);
3581 }
3582 AliasSet getAliasSet() const override { return AliasSet::None(); }
3583};
3584
3585// The same as MWasmTruncateToInt64 but with the Instance dependency.
3586// It used only for arm now because on arm we need to call builtin to truncate
3587// to i64.
3588class MWasmBuiltinTruncateToInt64 : public MAryInstruction<2>,
3589 public NoTypePolicy::Data {
3590 TruncFlags flags_;
3591 wasm::BytecodeOffset bytecodeOffset_;
3592
3593 MWasmBuiltinTruncateToInt64(MDefinition* def, MDefinition* instance,
3594 TruncFlags flags,
3595 wasm::BytecodeOffset bytecodeOffset)
3596 : MAryInstruction(classOpcode),
3597 flags_(flags),
3598 bytecodeOffset_(bytecodeOffset) {
3599 initOperand(0, def);
3600 initOperand(1, instance);
3601
3602 setResultType(MIRType::Int64);
3603 setGuard(); // neither removable nor movable because of possible
3604 // side-effects.
3605 }
3606
3607 public:
3608 INSTRUCTION_HEADER(WasmBuiltinTruncateToInt64)
3609 NAMED_OPERANDS((0, input), (1, instance))MDefinition* input() const { return getOperand(0); } MDefinition
* instance() const { return getOperand(1); }
;
3610 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)...); }
3611
3612 bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; }
3613 bool isSaturating() const { return flags_ & TRUNC_SATURATING; }
3614 TruncFlags flags() const { return flags_; }
3615 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3616
3617 bool congruentTo(const MDefinition* ins) const override {
3618 return congruentIfOperandsEqual(ins) &&
3619 ins->toWasmBuiltinTruncateToInt64()->flags() == flags_;
3620 }
3621 AliasSet getAliasSet() const override { return AliasSet::None(); }
3622};
3623
3624class MWasmTruncateToInt64 : public MUnaryInstruction,
3625 public NoTypePolicy::Data {
3626 TruncFlags flags_;
3627 wasm::BytecodeOffset bytecodeOffset_;
3628
3629 MWasmTruncateToInt64(MDefinition* def, TruncFlags flags,
3630 wasm::BytecodeOffset bytecodeOffset)
3631 : MUnaryInstruction(classOpcode, def),
3632 flags_(flags),
3633 bytecodeOffset_(bytecodeOffset) {
3634 setResultType(MIRType::Int64);
3635 setGuard(); // neither removable nor movable because of possible
3636 // side-effects.
3637 }
3638
3639 public:
3640 INSTRUCTION_HEADER(WasmTruncateToInt64)
3641 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)...); }
3642
3643 bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; }
3644 bool isSaturating() const { return flags_ & TRUNC_SATURATING; }
3645 TruncFlags flags() const { return flags_; }
3646 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3647
3648 bool congruentTo(const MDefinition* ins) const override {
3649 return congruentIfOperandsEqual(ins) &&
3650 ins->toWasmTruncateToInt64()->flags() == flags_;
3651 }
3652 AliasSet getAliasSet() const override { return AliasSet::None(); }
3653};
3654
3655// Truncate a value to an int32, with wasm semantics: this will trap when the
3656// value is out of range.
3657class MWasmTruncateToInt32 : public MUnaryInstruction,
3658 public NoTypePolicy::Data {
3659 TruncFlags flags_;
3660 wasm::BytecodeOffset bytecodeOffset_;
3661
3662 explicit MWasmTruncateToInt32(MDefinition* def, TruncFlags flags,
3663 wasm::BytecodeOffset bytecodeOffset)
3664 : MUnaryInstruction(classOpcode, def),
3665 flags_(flags),
3666 bytecodeOffset_(bytecodeOffset) {
3667 setResultType(MIRType::Int32);
3668 setGuard(); // neither removable nor movable because of possible
3669 // side-effects.
3670 }
3671
3672 public:
3673 INSTRUCTION_HEADER(WasmTruncateToInt32)
3674 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)...); }
3675
3676 bool isUnsigned() const { return flags_ & TRUNC_UNSIGNED; }
3677 bool isSaturating() const { return flags_ & TRUNC_SATURATING; }
3678 TruncFlags flags() const { return flags_; }
3679 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3680
3681 MDefinition* foldsTo(TempAllocator& alloc) override;
3682
3683 bool congruentTo(const MDefinition* ins) const override {
3684 return congruentIfOperandsEqual(ins) &&
3685 ins->toWasmTruncateToInt32()->flags() == flags_;
3686 }
3687
3688 AliasSet getAliasSet() const override { return AliasSet::None(); }
3689};
3690
3691// Converts an int32 value to intptr by sign-extending it.
3692class MInt32ToIntPtr : public MUnaryInstruction,
3693 public UnboxedInt32Policy<0>::Data {
3694 bool canBeNegative_ = true;
3695
3696 explicit MInt32ToIntPtr(MDefinition* def)
3697 : MUnaryInstruction(classOpcode, def) {
3698 setResultType(MIRType::IntPtr);
3699 setMovable();
3700 }
3701
3702 public:
3703 INSTRUCTION_HEADER(Int32ToIntPtr)
3704 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)...); }
3705
3706 bool canBeNegative() const { return canBeNegative_; }
3707 void setCanNotBeNegative() { canBeNegative_ = false; }
3708
3709 void computeRange(TempAllocator& alloc) override;
3710 void collectRangeInfoPreTrunc() override;
3711
3712 MDefinition* foldsTo(TempAllocator& alloc) override;
3713
3714 bool congruentTo(const MDefinition* ins) const override {
3715 return congruentIfOperandsEqual(ins);
3716 }
3717 AliasSet getAliasSet() const override { return AliasSet::None(); }
3718};
3719
3720// Converts an IntPtr value >= 0 to Int32. Bails out if the value > INT32_MAX.
3721class MNonNegativeIntPtrToInt32 : public MUnaryInstruction,
3722 public NoTypePolicy::Data {
3723 explicit MNonNegativeIntPtrToInt32(MDefinition* def)
3724 : MUnaryInstruction(classOpcode, def) {
3725 MOZ_ASSERT(def->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(def->type() == MIRType::IntPtr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"def->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3725); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 3725; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3726 setResultType(MIRType::Int32);
3727 setMovable();
3728 }
3729
3730 public:
3731 INSTRUCTION_HEADER(NonNegativeIntPtrToInt32)
3732 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)...); }
3733
3734 void computeRange(TempAllocator& alloc) override;
3735
3736 bool congruentTo(const MDefinition* ins) const override {
3737 return congruentIfOperandsEqual(ins);
3738 }
3739 AliasSet getAliasSet() const override { return AliasSet::None(); }
3740};
3741
3742// Converts an IntPtr value to Double.
3743class MIntPtrToDouble : public MUnaryInstruction, public NoTypePolicy::Data {
3744 explicit MIntPtrToDouble(MDefinition* def)
3745 : MUnaryInstruction(classOpcode, def) {
3746 MOZ_ASSERT(def->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(def->type() == MIRType::IntPtr
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"def->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3746); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 3746; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3747 setResultType(MIRType::Double);
3748 setMovable();
3749 }
3750
3751 public:
3752 INSTRUCTION_HEADER(IntPtrToDouble)
3753 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)...); }
3754
3755 bool congruentTo(const MDefinition* ins) const override {
3756 return congruentIfOperandsEqual(ins);
3757 }
3758 AliasSet getAliasSet() const override { return AliasSet::None(); }
3759};
3760
3761// Subtracts (byteSize - 1) from the input value. Bails out if the result is
3762// negative. This is used to implement bounds checks for DataView accesses.
3763class MAdjustDataViewLength : public MUnaryInstruction,
3764 public NoTypePolicy::Data {
3765 const uint32_t byteSize_;
3766
3767 MAdjustDataViewLength(MDefinition* input, uint32_t byteSize)
3768 : MUnaryInstruction(classOpcode, input), byteSize_(byteSize) {
3769 MOZ_ASSERT(input->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(input->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(input->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("input->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3769); AnnotateMozCrashReason("MOZ_ASSERT" "(" "input->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 3769; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3770 MOZ_ASSERT(byteSize > 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(byteSize > 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(byteSize > 1))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("byteSize > 1"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3770); AnnotateMozCrashReason("MOZ_ASSERT" "(" "byteSize > 1"
")"); do { *((volatile int*)__null) = 3770; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3771 setResultType(MIRType::IntPtr);
3772 setMovable();
3773 setGuard();
3774 }
3775
3776 public:
3777 INSTRUCTION_HEADER(AdjustDataViewLength)
3778 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)...); }
3779
3780 uint32_t byteSize() const { return byteSize_; }
3781
3782 bool congruentTo(const MDefinition* ins) const override {
3783 if (!ins->isAdjustDataViewLength()) {
3784 return false;
3785 }
3786 if (ins->toAdjustDataViewLength()->byteSize() != byteSize()) {
3787 return false;
3788 }
3789 return congruentIfOperandsEqual(ins);
3790 }
3791 AliasSet getAliasSet() const override { return AliasSet::None(); }
3792};
3793
3794class MInt64ToFloatingPoint : public MUnaryInstruction,
3795 public NoTypePolicy::Data {
3796 bool isUnsigned_;
3797 wasm::BytecodeOffset bytecodeOffset_;
3798
3799 MInt64ToFloatingPoint(MDefinition* def, MIRType type,
3800 wasm::BytecodeOffset bytecodeOffset, bool isUnsigned)
3801 : MUnaryInstruction(classOpcode, def),
3802 isUnsigned_(isUnsigned),
3803 bytecodeOffset_(bytecodeOffset) {
3804 MOZ_ASSERT(IsFloatingPointType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFloatingPointType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFloatingPointType(type))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsFloatingPointType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3804); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFloatingPointType(type)"
")"); do { *((volatile int*)__null) = 3804; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3805 setResultType(type);
3806 setMovable();
3807 }
3808
3809 public:
3810 INSTRUCTION_HEADER(Int64ToFloatingPoint)
3811 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)...); }
3812
3813 bool isUnsigned() const { return isUnsigned_; }
3814 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3815
3816 bool congruentTo(const MDefinition* ins) const override {
3817 if (!ins->isInt64ToFloatingPoint()) {
3818 return false;
3819 }
3820 if (ins->toInt64ToFloatingPoint()->isUnsigned_ != isUnsigned_) {
3821 return false;
3822 }
3823 return congruentIfOperandsEqual(ins);
3824 }
3825 AliasSet getAliasSet() const override { return AliasSet::None(); }
3826};
3827
3828// It used only for arm now because on arm we need to call builtin to convert
3829// i64 to float.
3830class MBuiltinInt64ToFloatingPoint : public MAryInstruction<2>,
3831 public NoTypePolicy::Data {
3832 bool isUnsigned_;
3833 wasm::BytecodeOffset bytecodeOffset_;
3834
3835 MBuiltinInt64ToFloatingPoint(MDefinition* def, MDefinition* instance,
3836 MIRType type,
3837 wasm::BytecodeOffset bytecodeOffset,
3838 bool isUnsigned)
3839 : MAryInstruction(classOpcode),
3840 isUnsigned_(isUnsigned),
3841 bytecodeOffset_(bytecodeOffset) {
3842 MOZ_ASSERT(IsFloatingPointType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFloatingPointType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFloatingPointType(type))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsFloatingPointType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 3842); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFloatingPointType(type)"
")"); do { *((volatile int*)__null) = 3842; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
3843 initOperand(0, def);
3844 initOperand(1, instance);
3845 setResultType(type);
3846 setMovable();
3847 }
3848
3849 public:
3850 INSTRUCTION_HEADER(BuiltinInt64ToFloatingPoint)
3851 NAMED_OPERANDS((0, input), (1, instance))MDefinition* input() const { return getOperand(0); } MDefinition
* instance() const { return getOperand(1); }
;
3852 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)...); }
3853
3854 bool isUnsigned() const { return isUnsigned_; }
3855 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3856
3857 bool congruentTo(const MDefinition* ins) const override {
3858 if (!ins->isBuiltinInt64ToFloatingPoint()) {
3859 return false;
3860 }
3861 if (ins->toBuiltinInt64ToFloatingPoint()->isUnsigned_ != isUnsigned_) {
3862 return false;
3863 }
3864 return congruentIfOperandsEqual(ins);
3865 }
3866 AliasSet getAliasSet() const override { return AliasSet::None(); }
3867};
3868
3869// Applies ECMA's ToNumber on a primitive (either typed or untyped) and expects
3870// the result to be precisely representable as an Int32, otherwise bails.
3871//
3872// If the input is not primitive at runtime, a bailout occurs. If the input
3873// cannot be converted to an int32 without loss (i.e. 5.5 or undefined) then a
3874// bailout occurs.
3875class MToNumberInt32 : public MUnaryInstruction, public ToInt32Policy::Data {
3876 bool needsNegativeZeroCheck_;
3877 IntConversionInputKind conversion_;
3878
3879 explicit MToNumberInt32(MDefinition* def, IntConversionInputKind conversion =
3880 IntConversionInputKind::Any)
3881 : MUnaryInstruction(classOpcode, def),
3882 needsNegativeZeroCheck_(true),
3883 conversion_(conversion) {
3884 setResultType(MIRType::Int32);
3885 setMovable();
3886
3887 // Guard unless the conversion is known to be non-effectful & non-throwing.
3888 if (!def->definitelyType({MIRType::Undefined, MIRType::Null,
3889 MIRType::Boolean, MIRType::Int32, MIRType::Double,
3890 MIRType::Float32, MIRType::String})) {
3891 setGuard();
3892 }
3893 }
3894
3895 public:
3896 INSTRUCTION_HEADER(ToNumberInt32)
3897 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)...); }
3898
3899 MDefinition* foldsTo(TempAllocator& alloc) override;
3900
3901 // this only has backwards information flow.
3902 void analyzeEdgeCasesBackward() override;
3903
3904 bool needsNegativeZeroCheck() const { return needsNegativeZeroCheck_; }
3905 void setNeedsNegativeZeroCheck(bool needsCheck) {
3906 needsNegativeZeroCheck_ = needsCheck;
3907 }
3908
3909 IntConversionInputKind conversion() const { return conversion_; }
3910
3911 bool congruentTo(const MDefinition* ins) const override {
3912 if (!ins->isToNumberInt32() ||
3913 ins->toToNumberInt32()->conversion() != conversion()) {
3914 return false;
3915 }
3916 return congruentIfOperandsEqual(ins);
3917 }
3918
3919 AliasSet getAliasSet() const override { return AliasSet::None(); }
3920 void computeRange(TempAllocator& alloc) override;
3921 void collectRangeInfoPreTrunc() override;
3922
3923#ifdef DEBUG1
3924 bool isConsistentFloat32Use(MUse* use) const override { return true; }
3925#endif
3926
3927 ALLOW_CLONE(MToNumberInt32)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToNumberInt32
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3928};
3929
3930// Converts a value or typed input to a truncated int32, for use with bitwise
3931// operations. This is an infallible ValueToECMAInt32.
3932class MTruncateToInt32 : public MUnaryInstruction, public ToInt32Policy::Data {
3933 wasm::BytecodeOffset bytecodeOffset_;
3934
3935 explicit MTruncateToInt32(
3936 MDefinition* def,
3937 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset())
3938 : MUnaryInstruction(classOpcode, def), bytecodeOffset_(bytecodeOffset) {
3939 setResultType(MIRType::Int32);
3940 setMovable();
3941
3942 // Guard unless the conversion is known to be non-effectful & non-throwing.
3943 if (mightHaveSideEffects(def)) {
3944 setGuard();
3945 }
3946 }
3947
3948 public:
3949 INSTRUCTION_HEADER(TruncateToInt32)
3950 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)...); }
3951
3952 static bool mightHaveSideEffects(MDefinition* def) {
3953 return !def->definitelyType(
3954 {MIRType::Undefined, MIRType::Null, MIRType::Boolean, MIRType::Int32,
3955 MIRType::Double, MIRType::Float32, MIRType::String});
3956 }
3957
3958 MDefinition* foldsTo(TempAllocator& alloc) override;
3959
3960 bool congruentTo(const MDefinition* ins) const override {
3961 return congruentIfOperandsEqual(ins);
3962 }
3963 AliasSet getAliasSet() const override { return AliasSet::None(); }
3964
3965 void computeRange(TempAllocator& alloc) override;
3966 TruncateKind operandTruncateKind(size_t index) const override;
3967#ifdef DEBUG1
3968 bool isConsistentFloat32Use(MUse* use) const override { return true; }
3969#endif
3970
3971 [[nodiscard]] bool writeRecoverData(
3972 CompactBufferWriter& writer) const override;
3973 bool canRecoverOnBailout() const override {
3974 return input()->type() < MIRType::Symbol;
3975 }
3976
3977 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
3978
3979 ALLOW_CLONE(MTruncateToInt32)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MTruncateToInt32
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
3980};
3981
3982// It is like MTruncateToInt32 but with instance dependency.
3983class MWasmBuiltinTruncateToInt32 : public MAryInstruction<2>,
3984 public ToInt32Policy::Data {
3985 wasm::BytecodeOffset bytecodeOffset_;
3986
3987 MWasmBuiltinTruncateToInt32(
3988 MDefinition* def, MDefinition* instance,
3989 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset())
3990 : MAryInstruction(classOpcode), bytecodeOffset_(bytecodeOffset) {
3991 initOperand(0, def);
3992 initOperand(1, instance);
3993 setResultType(MIRType::Int32);
3994 setMovable();
3995
3996 // Guard unless the conversion is known to be non-effectful & non-throwing.
3997 if (MTruncateToInt32::mightHaveSideEffects(def)) {
3998 setGuard();
3999 }
4000 }
4001
4002 public:
4003 INSTRUCTION_HEADER(WasmBuiltinTruncateToInt32)
4004 NAMED_OPERANDS((0, input), (1, instance))MDefinition* input() const { return getOperand(0); } MDefinition
* instance() const { return getOperand(1); }
4005 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)...); }
4006
4007 bool congruentTo(const MDefinition* ins) const override {
4008 return congruentIfOperandsEqual(ins);
4009 }
4010 AliasSet getAliasSet() const override { return AliasSet::None(); }
4011
4012 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
4013
4014 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; }
4015};
4016
4017// Converts a primitive (either typed or untyped) to a BigInt. If the input is
4018// not primitive at runtime, a bailout occurs.
4019class MToBigInt : public MUnaryInstruction, public ToBigIntPolicy::Data {
4020 private:
4021 explicit MToBigInt(MDefinition* def) : MUnaryInstruction(classOpcode, def) {
4022 setResultType(MIRType::BigInt);
4023 setMovable();
4024
4025 // Guard unless the conversion is known to be non-effectful & non-throwing.
4026 if (!def->definitelyType({MIRType::Boolean, MIRType::BigInt})) {
4027 setGuard();
4028 }
4029 }
4030
4031 public:
4032 INSTRUCTION_HEADER(ToBigInt)
4033 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)...); }
4034
4035 bool congruentTo(const MDefinition* ins) const override {
4036 return congruentIfOperandsEqual(ins);
4037 }
4038 AliasSet getAliasSet() const override { return AliasSet::None(); }
4039
4040 ALLOW_CLONE(MToBigInt)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToBigInt
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4041};
4042
4043// Takes a Value or typed input and returns a suitable Int64 using the
4044// ToBigInt algorithm, possibly calling out to the VM for string, etc inputs.
4045class MToInt64 : public MUnaryInstruction, public ToInt64Policy::Data {
4046 explicit MToInt64(MDefinition* def) : MUnaryInstruction(classOpcode, def) {
4047 setResultType(MIRType::Int64);
4048 setMovable();
4049
4050 // Guard unless the conversion is known to be non-effectful & non-throwing.
4051 if (!def->definitelyType(
4052 {MIRType::Boolean, MIRType::BigInt, MIRType::Int64})) {
4053 setGuard();
4054 }
4055 }
4056
4057 public:
4058 INSTRUCTION_HEADER(ToInt64)
4059 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)...); }
4060
4061 bool congruentTo(const MDefinition* ins) const override {
4062 return congruentIfOperandsEqual(ins);
4063 }
4064
4065 AliasSet getAliasSet() const override { return AliasSet::None(); }
4066
4067 MDefinition* foldsTo(TempAllocator& alloc) override;
4068
4069 ALLOW_CLONE(MToInt64)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToInt64
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4070};
4071
4072// Takes a BigInt pointer and returns its toInt64 value.
4073class MTruncateBigIntToInt64 : public MUnaryInstruction,
4074 public NoTypePolicy::Data {
4075 explicit MTruncateBigIntToInt64(MDefinition* def)
4076 : MUnaryInstruction(classOpcode, def) {
4077 MOZ_ASSERT(def->type() == MIRType::BigInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::BigInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(def->type() == MIRType::BigInt
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"def->type() == MIRType::BigInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4077); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::BigInt"
")"); do { *((volatile int*)__null) = 4077; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4078 setResultType(MIRType::Int64);
4079 setMovable();
4080 }
4081
4082 public:
4083 INSTRUCTION_HEADER(TruncateBigIntToInt64)
4084 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)...); }
4085
4086 bool congruentTo(const MDefinition* ins) const override {
4087 return congruentIfOperandsEqual(ins);
4088 }
4089
4090 AliasSet getAliasSet() const override { return AliasSet::None(); }
4091
4092 MDefinition* foldsTo(TempAllocator& alloc) override;
4093
4094 ALLOW_CLONE(MTruncateBigIntToInt64)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MTruncateBigIntToInt64
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4095};
4096
4097// Takes an Int64 and returns a fresh BigInt pointer.
4098class MInt64ToBigInt : public MUnaryInstruction, public NoTypePolicy::Data {
4099 explicit MInt64ToBigInt(MDefinition* def)
4100 : MUnaryInstruction(classOpcode, def) {
4101 MOZ_ASSERT(def->type() == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::Int64)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(def->type() == MIRType::Int64
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"def->type() == MIRType::Int64", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4101); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 4101; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4102 setResultType(MIRType::BigInt);
4103 setMovable();
4104 }
4105
4106 public:
4107 INSTRUCTION_HEADER(Int64ToBigInt)
4108 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)...); }
4109
4110 bool congruentTo(const MDefinition* ins) const override {
4111 return congruentIfOperandsEqual(ins);
4112 }
4113
4114 AliasSet getAliasSet() const override { return AliasSet::None(); }
4115
4116 ALLOW_CLONE(MInt64ToBigInt)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MInt64ToBigInt
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4117};
4118
4119// Converts any type to a string
4120class MToString : public MUnaryInstruction, public ToStringPolicy::Data {
4121 public:
4122 // MToString has two modes for handling of object/symbol arguments: if the
4123 // to-string conversion happens as part of another opcode, we have to bail out
4124 // to Baseline. If the conversion is for a stand-alone JSOp we can support
4125 // side-effects.
4126 enum class SideEffectHandling { Bailout, Supported };
4127
4128 private:
4129 SideEffectHandling sideEffects_;
4130 bool mightHaveSideEffects_ = false;
4131
4132 MToString(MDefinition* def, SideEffectHandling sideEffects)
4133 : MUnaryInstruction(classOpcode, def), sideEffects_(sideEffects) {
4134 setResultType(MIRType::String);
4135
4136 if (!def->definitelyType({MIRType::Undefined, MIRType::Null,
4137 MIRType::Boolean, MIRType::Int32, MIRType::Double,
4138 MIRType::Float32, MIRType::String,
4139 MIRType::BigInt})) {
4140 mightHaveSideEffects_ = true;
4141 }
4142
4143 // If this instruction is not effectful, mark it as movable and set the
4144 // Guard flag if needed. If the operation is effectful it won't be
4145 // optimized anyway so there's no need to set any flags.
4146 if (!isEffectful()) {
4147 setMovable();
4148 // Objects might override toString; Symbol throws. We bailout in those
4149 // cases and run side-effects in baseline instead.
4150 if (mightHaveSideEffects_) {
4151 setGuard();
4152 }
4153 }
4154 }
4155
4156 public:
4157 INSTRUCTION_HEADER(ToString)
4158 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)...); }
4159
4160 MDefinition* foldsTo(TempAllocator& alloc) override;
4161
4162 bool congruentTo(const MDefinition* ins) const override {
4163 if (!ins->isToString()) {
4164 return false;
4165 }
4166 if (sideEffects_ != ins->toToString()->sideEffects_) {
4167 return false;
4168 }
4169 return congruentIfOperandsEqual(ins);
4170 }
4171
4172 AliasSet getAliasSet() const override {
4173 if (supportSideEffects() && mightHaveSideEffects_) {
4174 return AliasSet::Store(AliasSet::Any);
4175 }
4176 return AliasSet::None();
4177 }
4178
4179 bool mightHaveSideEffects() const { return mightHaveSideEffects_; }
4180
4181 bool supportSideEffects() const {
4182 return sideEffects_ == SideEffectHandling::Supported;
4183 }
4184
4185 bool needsSnapshot() const {
4186 return sideEffects_ == SideEffectHandling::Bailout && mightHaveSideEffects_;
4187 }
4188
4189 ALLOW_CLONE(MToString)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MToString
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4190};
4191
4192class MBitNot : public MUnaryInstruction, public BitwisePolicy::Data {
4193 explicit MBitNot(MDefinition* input) : MUnaryInstruction(classOpcode, input) {
4194 setResultType(MIRType::Int32);
4195 if (input->type() == MIRType::Int64) {
4196 setResultType(MIRType::Int64);
4197 }
4198 setMovable();
4199 }
4200
4201 public:
4202 INSTRUCTION_HEADER(BitNot)
4203 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)...); }
4204
4205 MDefinition* foldsTo(TempAllocator& alloc) override;
4206
4207 bool congruentTo(const MDefinition* ins) const override {
4208 return congruentIfOperandsEqual(ins);
4209 }
4210 AliasSet getAliasSet() const override { return AliasSet::None(); }
4211 void computeRange(TempAllocator& alloc) override;
4212
4213 [[nodiscard]] bool writeRecoverData(
4214 CompactBufferWriter& writer) const override;
4215 bool canRecoverOnBailout() const override { return true; }
4216
4217 ALLOW_CLONE(MBitNot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBitNot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4218};
4219
4220class MTypeOf : public MUnaryInstruction,
4221 public BoxExceptPolicy<0, MIRType::Object>::Data {
4222 explicit MTypeOf(MDefinition* def) : MUnaryInstruction(classOpcode, def) {
4223 setResultType(MIRType::Int32);
4224 setMovable();
4225 }
4226 TypeDataList observed_;
4227
4228 public:
4229 INSTRUCTION_HEADER(TypeOf)
4230 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)...); }
4231
4232 void setObservedTypes(const TypeDataList& observed) { observed_ = observed; }
4233 bool hasObservedTypes() const { return observed_.count() > 0; }
4234 const TypeDataList& observedTypes() const { return observed_; }
4235
4236 MDefinition* foldsTo(TempAllocator& alloc) override;
4237
4238 AliasSet getAliasSet() const override { return AliasSet::None(); }
4239
4240 bool congruentTo(const MDefinition* ins) const override {
4241 return congruentIfOperandsEqual(ins);
4242 }
4243
4244 [[nodiscard]] bool writeRecoverData(
4245 CompactBufferWriter& writer) const override;
4246 bool canRecoverOnBailout() const override { return true; }
4247};
4248
4249class MTypeOfIs : public MUnaryInstruction, public NoTypePolicy::Data {
4250 JSOp jsop_;
4251 JSType jstype_;
4252
4253 MTypeOfIs(MDefinition* def, JSOp jsop, JSType jstype)
4254 : MUnaryInstruction(classOpcode, def), jsop_(jsop), jstype_(jstype) {
4255 MOZ_ASSERT(def->type() == MIRType::Object || def->type() == MIRType::Value)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::Object || def->type() ==
MIRType::Value)>::isValid, "invalid assertion condition")
; if ((__builtin_expect(!!(!(!!(def->type() == MIRType::Object
|| def->type() == MIRType::Value))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("def->type() == MIRType::Object || def->type() == MIRType::Value"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::Object || def->type() == MIRType::Value"
")"); do { *((volatile int*)__null) = 4255; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4256
4257 setResultType(MIRType::Boolean);
4258 setMovable();
4259 }
4260
4261 public:
4262 INSTRUCTION_HEADER(TypeOfIs)
4263 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)...); }
4264
4265 JSOp jsop() const { return jsop_; }
4266 JSType jstype() const { return jstype_; }
4267
4268 AliasSet getAliasSet() const override { return AliasSet::None(); }
4269
4270 bool congruentTo(const MDefinition* ins) const override {
4271 if (!congruentIfOperandsEqual(ins)) {
4272 return false;
4273 }
4274 return jsop() == ins->toTypeOfIs()->jsop() &&
4275 jstype() == ins->toTypeOfIs()->jstype();
4276 }
4277
4278#ifdef JS_JITSPEW1
4279 void printOpcode(GenericPrinter& out) const override;
4280#endif
4281};
4282
4283class MBinaryBitwiseInstruction : public MBinaryInstruction,
4284 public BitwisePolicy::Data {
4285 protected:
4286 MBinaryBitwiseInstruction(Opcode op, MDefinition* left, MDefinition* right,
4287 MIRType type)
4288 : MBinaryInstruction(op, left, right),
4289 maskMatchesLeftRange(false),
4290 maskMatchesRightRange(false) {
4291 MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Int64 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Int32 || type == MIRType::Int64 || (
isUrsh() && type == MIRType::Double))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == MIRType::Int32 || type
== MIRType::Int64 || (isUrsh() && type == MIRType::Double
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Int32 || type == MIRType::Int64 || (isUrsh() && type == MIRType::Double)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32 || type == MIRType::Int64 || (isUrsh() && type == MIRType::Double)"
")"); do { *((volatile int*)__null) = 4292; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4292 (isUrsh() && type == MIRType::Double))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Int32 || type == MIRType::Int64 || (
isUrsh() && type == MIRType::Double))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type == MIRType::Int32 || type
== MIRType::Int64 || (isUrsh() && type == MIRType::Double
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("type == MIRType::Int32 || type == MIRType::Int64 || (isUrsh() && type == MIRType::Double)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4292); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32 || type == MIRType::Int64 || (isUrsh() && type == MIRType::Double)"
")"); do { *((volatile int*)__null) = 4292; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4293 setResultType(type);
4294 setMovable();
4295 }
4296
4297 bool maskMatchesLeftRange;
4298 bool maskMatchesRightRange;
4299
4300 public:
4301 MDefinition* foldsTo(TempAllocator& alloc) override;
4302 MDefinition* foldUnnecessaryBitop();
4303 virtual MDefinition* foldIfZero(size_t operand) = 0;
4304 virtual MDefinition* foldIfNegOne(size_t operand) = 0;
4305 virtual MDefinition* foldIfEqual() = 0;
4306 virtual MDefinition* foldIfAllBitsSet(size_t operand) = 0;
4307 void collectRangeInfoPreTrunc() override;
4308
4309 bool congruentTo(const MDefinition* ins) const override {
4310 return binaryCongruentTo(ins);
4311 }
4312 AliasSet getAliasSet() const override { return AliasSet::None(); }
4313
4314 TruncateKind operandTruncateKind(size_t index) const override;
4315};
4316
4317class MBitAnd : public MBinaryBitwiseInstruction {
4318 MBitAnd(MDefinition* left, MDefinition* right, MIRType type)
4319 : MBinaryBitwiseInstruction(classOpcode, left, right, type) {
4320 setCommutative();
4321 }
4322
4323 public:
4324 INSTRUCTION_HEADER(BitAnd)
4325 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)...); }
4326
4327 MDefinition* foldIfZero(size_t operand) override {
4328 return getOperand(operand); // 0 & x => 0;
4329 }
4330 MDefinition* foldIfNegOne(size_t operand) override {
4331 return getOperand(1 - operand); // x & -1 => x
4332 }
4333 MDefinition* foldIfEqual() override {
4334 return getOperand(0); // x & x => x;
4335 }
4336 MDefinition* foldIfAllBitsSet(size_t operand) override {
4337 // e.g. for uint16: x & 0xffff => x;
4338 return getOperand(1 - operand);
4339 }
4340 void computeRange(TempAllocator& alloc) override;
4341
4342 [[nodiscard]] bool writeRecoverData(
4343 CompactBufferWriter& writer) const override;
4344 bool canRecoverOnBailout() const override { return true; }
4345
4346 ALLOW_CLONE(MBitAnd)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBitAnd
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4347};
4348
4349class MBitOr : public MBinaryBitwiseInstruction {
4350 MBitOr(MDefinition* left, MDefinition* right, MIRType type)
4351 : MBinaryBitwiseInstruction(classOpcode, left, right, type) {
4352 setCommutative();
4353 }
4354
4355 public:
4356 INSTRUCTION_HEADER(BitOr)
4357 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)...); }
4358
4359 MDefinition* foldIfZero(size_t operand) override {
4360 return getOperand(1 -
4361 operand); // 0 | x => x, so if ith is 0, return (1-i)th
4362 }
4363 MDefinition* foldIfNegOne(size_t operand) override {
4364 return getOperand(operand); // x | -1 => -1
4365 }
4366 MDefinition* foldIfEqual() override {
4367 return getOperand(0); // x | x => x
4368 }
4369 MDefinition* foldIfAllBitsSet(size_t operand) override { return this; }
4370 void computeRange(TempAllocator& alloc) override;
4371 [[nodiscard]] bool writeRecoverData(
4372 CompactBufferWriter& writer) const override;
4373 bool canRecoverOnBailout() const override { return true; }
4374
4375 ALLOW_CLONE(MBitOr)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBitOr
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4376};
4377
4378class MBitXor : public MBinaryBitwiseInstruction {
4379 MBitXor(MDefinition* left, MDefinition* right, MIRType type)
4380 : MBinaryBitwiseInstruction(classOpcode, left, right, type) {
4381 setCommutative();
4382 }
4383
4384 public:
4385 INSTRUCTION_HEADER(BitXor)
4386 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)...); }
4387
4388 MDefinition* foldIfZero(size_t operand) override {
4389 return getOperand(1 - operand); // 0 ^ x => x
4390 }
4391 MDefinition* foldIfNegOne(size_t operand) override { return this; }
4392 MDefinition* foldIfEqual() override { return this; }
4393 MDefinition* foldIfAllBitsSet(size_t operand) override { return this; }
4394 void computeRange(TempAllocator& alloc) override;
4395
4396 [[nodiscard]] bool writeRecoverData(
4397 CompactBufferWriter& writer) const override;
4398 bool canRecoverOnBailout() const override { return true; }
4399
4400 ALLOW_CLONE(MBitXor)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBitXor
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4401};
4402
4403class MShiftInstruction : public MBinaryBitwiseInstruction {
4404 protected:
4405 MShiftInstruction(Opcode op, MDefinition* left, MDefinition* right,
4406 MIRType type)
4407 : MBinaryBitwiseInstruction(op, left, right, type) {}
4408
4409 public:
4410 MDefinition* foldIfNegOne(size_t operand) override { return this; }
4411 MDefinition* foldIfEqual() override { return this; }
4412 MDefinition* foldIfAllBitsSet(size_t operand) override { return this; }
4413};
4414
4415class MLsh : public MShiftInstruction {
4416 MLsh(MDefinition* left, MDefinition* right, MIRType type)
4417 : MShiftInstruction(classOpcode, left, right, type) {}
4418
4419 public:
4420 INSTRUCTION_HEADER(Lsh)
4421 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)...); }
4422
4423 MDefinition* foldIfZero(size_t operand) override {
4424 // 0 << x => 0
4425 // x << 0 => x
4426 return getOperand(0);
4427 }
4428
4429 void computeRange(TempAllocator& alloc) override;
4430 [[nodiscard]] bool writeRecoverData(
4431 CompactBufferWriter& writer) const override;
4432 bool canRecoverOnBailout() const override { return true; }
4433
4434 ALLOW_CLONE(MLsh)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLsh
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4435};
4436
4437class MRsh : public MShiftInstruction {
4438 MRsh(MDefinition* left, MDefinition* right, MIRType type)
4439 : MShiftInstruction(classOpcode, left, right, type) {}
4440
4441 public:
4442 INSTRUCTION_HEADER(Rsh)
4443 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)...); }
4444
4445 MDefinition* foldIfZero(size_t operand) override {
4446 // 0 >> x => 0
4447 // x >> 0 => x
4448 return getOperand(0);
4449 }
4450 void computeRange(TempAllocator& alloc) override;
4451
4452 [[nodiscard]] bool writeRecoverData(
4453 CompactBufferWriter& writer) const override;
4454 bool canRecoverOnBailout() const override { return true; }
4455
4456 MDefinition* foldsTo(TempAllocator& alloc) override;
4457
4458 ALLOW_CLONE(MRsh)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MRsh
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4459};
4460
4461class MUrsh : public MShiftInstruction {
4462 bool bailoutsDisabled_;
4463
4464 MUrsh(MDefinition* left, MDefinition* right, MIRType type)
4465 : MShiftInstruction(classOpcode, left, right, type),
4466 bailoutsDisabled_(false) {}
4467
4468 public:
4469 INSTRUCTION_HEADER(Ursh)
4470 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)...); }
4471
4472 static MUrsh* NewWasm(TempAllocator& alloc, MDefinition* left,
4473 MDefinition* right, MIRType type);
4474
4475 MDefinition* foldIfZero(size_t operand) override {
4476 // 0 >>> x => 0
4477 if (operand == 0) {
4478 return getOperand(0);
4479 }
4480
4481 return this;
4482 }
4483
4484 bool bailoutsDisabled() const { return bailoutsDisabled_; }
4485
4486 bool fallible() const;
4487
4488 void computeRange(TempAllocator& alloc) override;
4489 void collectRangeInfoPreTrunc() override;
4490
4491 [[nodiscard]] bool writeRecoverData(
4492 CompactBufferWriter& writer) const override;
4493 bool canRecoverOnBailout() const override { return true; }
4494
4495 ALLOW_CLONE(MUrsh)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MUrsh
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4496};
4497
4498class MSignExtendInt32 : public MUnaryInstruction, public NoTypePolicy::Data {
4499 public:
4500 enum Mode { Byte, Half };
4501
4502 private:
4503 Mode mode_;
4504
4505 MSignExtendInt32(MDefinition* op, Mode mode)
4506 : MUnaryInstruction(classOpcode, op), mode_(mode) {
4507 setResultType(MIRType::Int32);
4508 setMovable();
4509 }
4510
4511 public:
4512 INSTRUCTION_HEADER(SignExtendInt32)
4513 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)...); }
4514
4515 Mode mode() const { return mode_; }
4516
4517 MDefinition* foldsTo(TempAllocator& alloc) override;
4518 bool congruentTo(const MDefinition* ins) const override {
4519 if (!congruentIfOperandsEqual(ins)) {
4520 return false;
4521 }
4522 return ins->isSignExtendInt32() && ins->toSignExtendInt32()->mode_ == mode_;
4523 }
4524 AliasSet getAliasSet() const override { return AliasSet::None(); }
4525
4526 [[nodiscard]] bool writeRecoverData(
4527 CompactBufferWriter& writer) const override;
4528 bool canRecoverOnBailout() const override { return true; }
4529
4530 ALLOW_CLONE(MSignExtendInt32)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSignExtendInt32
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4531};
4532
4533class MSignExtendInt64 : public MUnaryInstruction, public NoTypePolicy::Data {
4534 public:
4535 enum Mode { Byte, Half, Word };
4536
4537 private:
4538 Mode mode_;
4539
4540 MSignExtendInt64(MDefinition* op, Mode mode)
4541 : MUnaryInstruction(classOpcode, op), mode_(mode) {
4542 setResultType(MIRType::Int64);
4543 setMovable();
4544 }
4545
4546 public:
4547 INSTRUCTION_HEADER(SignExtendInt64)
4548 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)...); }
4549
4550 Mode mode() const { return mode_; }
4551
4552 MDefinition* foldsTo(TempAllocator& alloc) override;
4553 bool congruentTo(const MDefinition* ins) const override {
4554 if (!congruentIfOperandsEqual(ins)) {
4555 return false;
4556 }
4557 return ins->isSignExtendInt64() && ins->toSignExtendInt64()->mode_ == mode_;
4558 }
4559 AliasSet getAliasSet() const override { return AliasSet::None(); }
4560
4561 ALLOW_CLONE(MSignExtendInt64)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSignExtendInt64
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4562};
4563
4564class MBinaryArithInstruction : public MBinaryInstruction,
4565 public ArithPolicy::Data {
4566 // Implicit truncate flag is set by the truncate backward range analysis
4567 // optimization phase, and by wasm pre-processing. It is used in
4568 // NeedNegativeZeroCheck to check if the result of a multiplication needs to
4569 // produce -0 double value, and for avoiding overflow checks.
4570
4571 // This optimization happens when the multiplication cannot be truncated
4572 // even if all uses are truncating its result, such as when the range
4573 // analysis detect a precision loss in the multiplication.
4574 TruncateKind implicitTruncate_;
4575
4576 // Whether we must preserve NaN semantics, and in particular not fold
4577 // (x op id) or (id op x) to x, or replace a division by a multiply of the
4578 // exact reciprocal.
4579 bool mustPreserveNaN_;
4580
4581 protected:
4582 MBinaryArithInstruction(Opcode op, MDefinition* left, MDefinition* right,
4583 MIRType type)
4584 : MBinaryInstruction(op, left, right),
4585 implicitTruncate_(TruncateKind::NoTruncate),
4586 mustPreserveNaN_(false) {
4587 MOZ_ASSERT(IsNumberType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(type)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type)"
")"); do { *((volatile int*)__null) = 4587; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4588 setResultType(type);
4589 setMovable();
4590 }
4591
4592 public:
4593 void setMustPreserveNaN(bool b) { mustPreserveNaN_ = b; }
4594 bool mustPreserveNaN() const { return mustPreserveNaN_; }
4595
4596 MDefinition* foldsTo(TempAllocator& alloc) override;
4597#ifdef JS_JITSPEW1
4598 void printOpcode(GenericPrinter& out) const override;
4599#endif
4600
4601 virtual double getIdentity() = 0;
4602
4603 void setSpecialization(MIRType type) {
4604 MOZ_ASSERT(IsNumberType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(type)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4604); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type)"
")"); do { *((volatile int*)__null) = 4604; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4605 setResultType(type);
4606 }
4607
4608 virtual void trySpecializeFloat32(TempAllocator& alloc) override;
4609
4610 bool congruentTo(const MDefinition* ins) const override {
4611 if (!binaryCongruentTo(ins)) {
4612 return false;
4613 }
4614 const auto* other = static_cast<const MBinaryArithInstruction*>(ins);
4615 return other->mustPreserveNaN_ == mustPreserveNaN_;
4616 }
4617 AliasSet getAliasSet() const override { return AliasSet::None(); }
4618
4619 bool isTruncated() const {
4620 return implicitTruncate_ == TruncateKind::Truncate;
4621 }
4622 TruncateKind truncateKind() const { return implicitTruncate_; }
4623 void setTruncateKind(TruncateKind kind) {
4624 implicitTruncate_ = std::max(implicitTruncate_, kind);
4625 }
4626};
4627
4628class MMinMax : public MBinaryInstruction, public ArithPolicy::Data {
4629 bool isMax_;
4630
4631 MMinMax(MDefinition* left, MDefinition* right, MIRType type, bool isMax)
4632 : MBinaryInstruction(classOpcode, left, right), isMax_(isMax) {
4633 MOZ_ASSERT(IsNumberType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(type)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4633); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type)"
")"); do { *((volatile int*)__null) = 4633; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4634 setResultType(type);
4635 setMovable();
4636 }
4637
4638 public:
4639 INSTRUCTION_HEADER(MinMax)
4640 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)...); }
4641
4642 static MMinMax* NewWasm(TempAllocator& alloc, MDefinition* left,
4643 MDefinition* right, MIRType type, bool isMax) {
4644 return New(alloc, left, right, type, isMax);
4645 }
4646
4647 bool isMax() const { return isMax_; }
4648
4649 bool congruentTo(const MDefinition* ins) const override {
4650 if (!congruentIfOperandsEqual(ins)) {
4651 return false;
4652 }
4653 const MMinMax* other = ins->toMinMax();
4654 return other->isMax() == isMax();
4655 }
4656
4657 AliasSet getAliasSet() const override { return AliasSet::None(); }
4658 MDefinition* foldsTo(TempAllocator& alloc) override;
4659 void computeRange(TempAllocator& alloc) override;
4660 [[nodiscard]] bool writeRecoverData(
4661 CompactBufferWriter& writer) const override;
4662 bool canRecoverOnBailout() const override { return true; }
4663
4664 bool isFloat32Commutative() const override { return true; }
4665 void trySpecializeFloat32(TempAllocator& alloc) override;
4666
4667#ifdef JS_JITSPEW1
4668 void printOpcode(GenericPrinter& out) const override;
4669#endif
4670
4671 ALLOW_CLONE(MMinMax)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MMinMax
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4672};
4673
4674class MMinMaxArray : public MUnaryInstruction, public SingleObjectPolicy::Data {
4675 bool isMax_;
4676
4677 MMinMaxArray(MDefinition* array, MIRType type, bool isMax)
4678 : MUnaryInstruction(classOpcode, array), isMax_(isMax) {
4679 MOZ_ASSERT(type == MIRType::Int32 || type == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type == MIRType::Int32 || type == MIRType::Double)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(type == MIRType::Int32 || type == MIRType::Double)))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("type == MIRType::Int32 || type == MIRType::Double"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32 || type == MIRType::Double"
")"); do { *((volatile int*)__null) = 4679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4680 setResultType(type);
4681
4682 // We can't DCE this, even if the result is unused, in case one of the
4683 // elements of the array is an object with a `valueOf` function that
4684 // must be called.
4685 setGuard();
4686 }
4687
4688 public:
4689 INSTRUCTION_HEADER(MinMaxArray)
4690 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)...); }
4691 NAMED_OPERANDS((0, array))MDefinition* array() const { return getOperand(0); }
4692
4693 bool isMax() const { return isMax_; }
4694
4695 bool congruentTo(const MDefinition* ins) const override {
4696 if (!ins->isMinMaxArray() || ins->toMinMaxArray()->isMax() != isMax()) {
4697 return false;
4698 }
4699 return congruentIfOperandsEqual(ins);
4700 }
4701
4702 AliasSet getAliasSet() const override {
4703 return AliasSet::Load(AliasSet::ObjectFields | AliasSet::Element);
4704 }
4705
4706#ifdef JS_JITSPEW1
4707 void printOpcode(GenericPrinter& out) const override;
4708#endif
4709};
4710
4711class MAbs : public MUnaryInstruction, public ArithPolicy::Data {
4712 bool implicitTruncate_;
4713
4714 MAbs(MDefinition* num, MIRType type)
4715 : MUnaryInstruction(classOpcode, num), implicitTruncate_(false) {
4716 MOZ_ASSERT(IsNumberType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(type)))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("IsNumberType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4716); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type)"
")"); do { *((volatile int*)__null) = 4716; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4717 setResultType(type);
4718 setMovable();
4719 }
4720
4721 public:
4722 INSTRUCTION_HEADER(Abs)
4723 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)...); }
4724
4725 static MAbs* NewWasm(TempAllocator& alloc, MDefinition* num, MIRType type) {
4726 auto* ins = new (alloc) MAbs(num, type);
4727 if (type == MIRType::Int32) {
4728 ins->implicitTruncate_ = true;
4729 }
4730 return ins;
4731 }
4732
4733 bool congruentTo(const MDefinition* ins) const override {
4734 return congruentIfOperandsEqual(ins);
4735 }
4736 bool fallible() const;
4737
4738 AliasSet getAliasSet() const override { return AliasSet::None(); }
4739 void computeRange(TempAllocator& alloc) override;
4740 bool isFloat32Commutative() const override { return true; }
4741 void trySpecializeFloat32(TempAllocator& alloc) override;
4742
4743 [[nodiscard]] bool writeRecoverData(
4744 CompactBufferWriter& writer) const override;
4745 bool canRecoverOnBailout() const override { return true; }
4746
4747 ALLOW_CLONE(MAbs)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MAbs
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4748};
4749
4750class MClz : public MUnaryInstruction, public BitwisePolicy::Data {
4751 bool operandIsNeverZero_;
4752
4753 explicit MClz(MDefinition* num, MIRType type)
4754 : MUnaryInstruction(classOpcode, num), operandIsNeverZero_(false) {
4755 MOZ_ASSERT(IsIntType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsIntType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsIntType(type)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsIntType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4755); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsIntType(type)"
")"); do { *((volatile int*)__null) = 4755; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4756 MOZ_ASSERT(IsNumberType(num->type()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(num->type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(num->type())
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsNumberType(num->type())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(num->type())"
")"); do { *((volatile int*)__null) = 4756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4757 setResultType(type);
4758 setMovable();
4759 }
4760
4761 public:
4762 INSTRUCTION_HEADER(Clz)
4763 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)...); }
4764 NAMED_OPERANDS((0, num))MDefinition* num() const { return getOperand(0); }
4765
4766 bool congruentTo(const MDefinition* ins) const override {
4767 return congruentIfOperandsEqual(ins);
4768 }
4769
4770 AliasSet getAliasSet() const override { return AliasSet::None(); }
4771
4772 bool operandIsNeverZero() const { return operandIsNeverZero_; }
4773
4774 MDefinition* foldsTo(TempAllocator& alloc) override;
4775 void computeRange(TempAllocator& alloc) override;
4776 void collectRangeInfoPreTrunc() override;
4777};
4778
4779class MCtz : public MUnaryInstruction, public BitwisePolicy::Data {
4780 bool operandIsNeverZero_;
4781
4782 explicit MCtz(MDefinition* num, MIRType type)
4783 : MUnaryInstruction(classOpcode, num), operandIsNeverZero_(false) {
4784 MOZ_ASSERT(IsIntType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsIntType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsIntType(type)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsIntType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsIntType(type)"
")"); do { *((volatile int*)__null) = 4784; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4785 MOZ_ASSERT(IsNumberType(num->type()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(num->type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(num->type())
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsNumberType(num->type())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4785); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(num->type())"
")"); do { *((volatile int*)__null) = 4785; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4786 setResultType(type);
4787 setMovable();
4788 }
4789
4790 public:
4791 INSTRUCTION_HEADER(Ctz)
4792 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)...); }
4793 NAMED_OPERANDS((0, num))MDefinition* num() const { return getOperand(0); }
4794
4795 bool congruentTo(const MDefinition* ins) const override {
4796 return congruentIfOperandsEqual(ins);
4797 }
4798
4799 AliasSet getAliasSet() const override { return AliasSet::None(); }
4800
4801 bool operandIsNeverZero() const { return operandIsNeverZero_; }
4802
4803 MDefinition* foldsTo(TempAllocator& alloc) override;
4804 void computeRange(TempAllocator& alloc) override;
4805 void collectRangeInfoPreTrunc() override;
4806};
4807
4808class MPopcnt : public MUnaryInstruction, public BitwisePolicy::Data {
4809 explicit MPopcnt(MDefinition* num, MIRType type)
4810 : MUnaryInstruction(classOpcode, num) {
4811 MOZ_ASSERT(IsNumberType(num->type()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(num->type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(num->type())
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"IsNumberType(num->type())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4811); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(num->type())"
")"); do { *((volatile int*)__null) = 4811; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4812 MOZ_ASSERT(IsIntType(type))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsIntType(type))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsIntType(type)))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("IsIntType(type)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4812); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsIntType(type)"
")"); do { *((volatile int*)__null) = 4812; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4813 setResultType(type);
4814 setMovable();
4815 }
4816
4817 public:
4818 INSTRUCTION_HEADER(Popcnt)
4819 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)...); }
4820 NAMED_OPERANDS((0, num))MDefinition* num() const { return getOperand(0); }
4821
4822 bool congruentTo(const MDefinition* ins) const override {
4823 return congruentIfOperandsEqual(ins);
4824 }
4825
4826 AliasSet getAliasSet() const override { return AliasSet::None(); }
4827
4828 MDefinition* foldsTo(TempAllocator& alloc) override;
4829 void computeRange(TempAllocator& alloc) override;
4830};
4831
4832// Inline implementation of Math.sqrt().
4833class MSqrt : public MUnaryInstruction, public FloatingPointPolicy<0>::Data {
4834 MSqrt(MDefinition* num, MIRType type) : MUnaryInstruction(classOpcode, num) {
4835 setResultType(type);
4836 specialization_ = type;
4837 setMovable();
4838 }
4839
4840 public:
4841 INSTRUCTION_HEADER(Sqrt)
4842 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)...); }
4843
4844 bool congruentTo(const MDefinition* ins) const override {
4845 return congruentIfOperandsEqual(ins);
4846 }
4847
4848 AliasSet getAliasSet() const override { return AliasSet::None(); }
4849 void computeRange(TempAllocator& alloc) override;
4850
4851 bool isFloat32Commutative() const override { return true; }
4852 void trySpecializeFloat32(TempAllocator& alloc) override;
4853
4854 [[nodiscard]] bool writeRecoverData(
4855 CompactBufferWriter& writer) const override;
4856 bool canRecoverOnBailout() const override { return true; }
4857
4858 ALLOW_CLONE(MSqrt)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSqrt
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4859};
4860
4861class MCopySign : public MBinaryInstruction, public NoTypePolicy::Data {
4862 MCopySign(MDefinition* lhs, MDefinition* rhs, MIRType type)
4863 : MBinaryInstruction(classOpcode, lhs, rhs) {
4864 setResultType(type);
4865 setMovable();
4866 }
4867
4868 public:
4869 INSTRUCTION_HEADER(CopySign)
4870 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)...); }
4871
4872 bool congruentTo(const MDefinition* ins) const override {
4873 return congruentIfOperandsEqual(ins);
4874 }
4875 AliasSet getAliasSet() const override { return AliasSet::None(); }
4876
4877 ALLOW_CLONE(MCopySign)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MCopySign
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4878};
4879
4880// Inline implementation of Math.hypot().
4881class MHypot : public MVariadicInstruction, public AllDoublePolicy::Data {
4882 MHypot() : MVariadicInstruction(classOpcode) {
4883 setResultType(MIRType::Double);
4884 setMovable();
4885 }
4886
4887 public:
4888 INSTRUCTION_HEADER(Hypot)
4889 static MHypot* New(TempAllocator& alloc, const MDefinitionVector& vector);
4890
4891 bool congruentTo(const MDefinition* ins) const override {
4892 return congruentIfOperandsEqual(ins);
4893 }
4894
4895 AliasSet getAliasSet() const override { return AliasSet::None(); }
4896
4897 bool possiblyCalls() const override { return true; }
4898
4899 [[nodiscard]] bool writeRecoverData(
4900 CompactBufferWriter& writer) const override;
4901 bool canRecoverOnBailout() const override { return true; }
4902
4903 bool canClone() const override { return true; }
4904
4905 MInstruction* clone(TempAllocator& alloc,
4906 const MDefinitionVector& inputs) const override {
4907 return MHypot::New(alloc, inputs);
4908 }
4909};
4910
4911// Inline implementation of Math.pow().
4912//
4913// Supports the following three specializations:
4914//
4915// 1. MPow(FloatingPoint, FloatingPoint) -> Double
4916// - The most general mode, calls js::ecmaPow.
4917// - Never performs a bailout.
4918// 2. MPow(FloatingPoint, Int32) -> Double
4919// - Optimization to call js::powi instead of js::ecmaPow.
4920// - Never performs a bailout.
4921// 3. MPow(Int32, Int32) -> Int32
4922// - Performs the complete exponentiation operation in assembly code.
4923// - Bails out if the result doesn't fit in Int32.
4924class MPow : public MBinaryInstruction, public PowPolicy::Data {
4925 // If true, the result is guaranteed to never be negative zero, as long as the
4926 // power is a positive number.
4927 bool canBeNegativeZero_;
4928
4929 MPow(MDefinition* input, MDefinition* power, MIRType specialization)
4930 : MBinaryInstruction(classOpcode, input, power) {
4931 MOZ_ASSERT(specialization == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(specialization == MIRType::Int32 || specialization ==
MIRType::Double)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(specialization == MIRType::Int32
|| specialization == MIRType::Double))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("specialization == MIRType::Int32 || specialization == MIRType::Double"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "specialization == MIRType::Int32 || specialization == MIRType::Double"
")"); do { *((volatile int*)__null) = 4932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
4932 specialization == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(specialization == MIRType::Int32 || specialization ==
MIRType::Double)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(specialization == MIRType::Int32
|| specialization == MIRType::Double))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("specialization == MIRType::Int32 || specialization == MIRType::Double"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 4932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "specialization == MIRType::Int32 || specialization == MIRType::Double"
")"); do { *((volatile int*)__null) = 4932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
4933 setResultType(specialization);
4934 setMovable();
4935
4936 // The result can't be negative zero if the base is an Int32 value.
4937 canBeNegativeZero_ = input->type() != MIRType::Int32;
4938 }
4939
4940 // Helpers for `foldsTo`
4941 MDefinition* foldsConstant(TempAllocator& alloc);
4942 MDefinition* foldsConstantPower(TempAllocator& alloc);
4943
4944 bool canBeNegativeZero() const { return canBeNegativeZero_; }
4945
4946 public:
4947 INSTRUCTION_HEADER(Pow)
4948 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)...); }
4949
4950 MDefinition* input() const { return lhs(); }
4951 MDefinition* power() const { return rhs(); }
4952
4953 bool congruentTo(const MDefinition* ins) const override {
4954 return congruentIfOperandsEqual(ins);
4955 }
4956 AliasSet getAliasSet() const override { return AliasSet::None(); }
4957 bool possiblyCalls() const override { return type() != MIRType::Int32; }
4958 [[nodiscard]] bool writeRecoverData(
4959 CompactBufferWriter& writer) const override;
4960 bool canRecoverOnBailout() const override { return true; }
4961
4962 MDefinition* foldsTo(TempAllocator& alloc) override;
4963
4964 ALLOW_CLONE(MPow)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MPow
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
4965};
4966
4967// Inline implementation of Math.pow(x, 0.5), which subtly differs from
4968// Math.sqrt(x).
4969class MPowHalf : public MUnaryInstruction, public DoublePolicy<0>::Data {
4970 bool operandIsNeverNegativeInfinity_;
4971 bool operandIsNeverNegativeZero_;
4972 bool operandIsNeverNaN_;
4973
4974 explicit MPowHalf(MDefinition* input)
4975 : MUnaryInstruction(classOpcode, input),
4976 operandIsNeverNegativeInfinity_(false),
4977 operandIsNeverNegativeZero_(false),
4978 operandIsNeverNaN_(false) {
4979 setResultType(MIRType::Double);
4980 setMovable();
4981 }
4982
4983 public:
4984 INSTRUCTION_HEADER(PowHalf)
4985 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)...); }
4986
4987 bool congruentTo(const MDefinition* ins) const override {
4988 return congruentIfOperandsEqual(ins);
4989 }
4990 bool operandIsNeverNegativeInfinity() const {
4991 return operandIsNeverNegativeInfinity_;
4992 }
4993 bool operandIsNeverNegativeZero() const {
4994 return operandIsNeverNegativeZero_;
4995 }
4996 bool operandIsNeverNaN() const { return operandIsNeverNaN_; }
4997 AliasSet getAliasSet() const override { return AliasSet::None(); }
4998 void collectRangeInfoPreTrunc() override;
4999 [[nodiscard]] bool writeRecoverData(
5000 CompactBufferWriter& writer) const override;
5001 bool canRecoverOnBailout() const override { return true; }
5002
5003 ALLOW_CLONE(MPowHalf)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MPowHalf
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5004};
5005
5006class MSign : public MUnaryInstruction, public SignPolicy::Data {
5007 private:
5008 MSign(MDefinition* input, MIRType resultType)
5009 : MUnaryInstruction(classOpcode, input) {
5010 MOZ_ASSERT(IsNumberType(input->type()))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsNumberType(input->type()))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsNumberType(input->type(
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsNumberType(input->type())", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(input->type())"
")"); do { *((volatile int*)__null) = 5010; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5011 MOZ_ASSERT(resultType == MIRType::Int32 || resultType == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(resultType == MIRType::Int32 || resultType == MIRType
::Double)>::isValid, "invalid assertion condition"); if ((
__builtin_expect(!!(!(!!(resultType == MIRType::Int32 || resultType
== MIRType::Double))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("resultType == MIRType::Int32 || resultType == MIRType::Double"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "resultType == MIRType::Int32 || resultType == MIRType::Double"
")"); do { *((volatile int*)__null) = 5011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5012 specialization_ = input->type();
5013 setResultType(resultType);
5014 setMovable();
5015 }
5016
5017 public:
5018 INSTRUCTION_HEADER(Sign)
5019 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)...); }
5020
5021 bool congruentTo(const MDefinition* ins) const override {
5022 return congruentIfOperandsEqual(ins);
5023 }
5024
5025 AliasSet getAliasSet() const override { return AliasSet::None(); }
5026
5027 MDefinition* foldsTo(TempAllocator& alloc) override;
5028
5029 void computeRange(TempAllocator& alloc) override;
5030 [[nodiscard]] bool writeRecoverData(
5031 CompactBufferWriter& writer) const override;
5032 bool canRecoverOnBailout() const override { return true; }
5033
5034 ALLOW_CLONE(MSign)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSign
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5035};
5036
5037class MMathFunction : public MUnaryInstruction,
5038 public FloatingPointPolicy<0>::Data {
5039 UnaryMathFunction function_;
5040
5041 // A nullptr cache means this function will neither access nor update the
5042 // cache.
5043 MMathFunction(MDefinition* input, UnaryMathFunction function)
5044 : MUnaryInstruction(classOpcode, input), function_(function) {
5045 setResultType(MIRType::Double);
5046 specialization_ = MIRType::Double;
5047 setMovable();
5048 }
5049
5050 public:
5051 INSTRUCTION_HEADER(MathFunction)
5052 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)...); }
5053
5054 UnaryMathFunction function() const { return function_; }
5055
5056 bool congruentTo(const MDefinition* ins) const override {
5057 if (!ins->isMathFunction()) {
5058 return false;
5059 }
5060 if (ins->toMathFunction()->function() != function()) {
5061 return false;
5062 }
5063 return congruentIfOperandsEqual(ins);
5064 }
5065
5066 AliasSet getAliasSet() const override { return AliasSet::None(); }
5067
5068 bool possiblyCalls() const override { return true; }
5069
5070 MDefinition* foldsTo(TempAllocator& alloc) override;
5071
5072#ifdef JS_JITSPEW1
5073 void printOpcode(GenericPrinter& out) const override;
5074#endif
5075
5076 static const char* FunctionName(UnaryMathFunction function);
5077
5078 bool isFloat32Commutative() const override;
5079 void trySpecializeFloat32(TempAllocator& alloc) override;
5080
5081 void computeRange(TempAllocator& alloc) override;
5082
5083 [[nodiscard]] bool writeRecoverData(
5084 CompactBufferWriter& writer) const override;
5085 bool canRecoverOnBailout() const override { return true; }
5086
5087 ALLOW_CLONE(MMathFunction)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MMathFunction
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5088};
5089
5090class MAdd : public MBinaryArithInstruction {
5091 MAdd(MDefinition* left, MDefinition* right, MIRType type)
5092 : MBinaryArithInstruction(classOpcode, left, right, type) {
5093 setCommutative();
5094 }
5095
5096 MAdd(MDefinition* left, MDefinition* right, TruncateKind truncateKind)
5097 : MAdd(left, right, MIRType::Int32) {
5098 setTruncateKind(truncateKind);
5099 }
5100
5101 public:
5102 INSTRUCTION_HEADER(Add)
5103 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)...); }
5104
5105 static MAdd* NewWasm(TempAllocator& alloc, MDefinition* left,
5106 MDefinition* right, MIRType type) {
5107 auto* ret = new (alloc) MAdd(left, right, type);
5108 if (type == MIRType::Int32) {
5109 ret->setTruncateKind(TruncateKind::Truncate);
5110 }
5111 return ret;
5112 }
5113
5114 bool isFloat32Commutative() const override { return true; }
5115
5116 double getIdentity() override { return 0; }
5117
5118 bool fallible() const;
5119 void computeRange(TempAllocator& alloc) override;
5120 bool canTruncate() const override;
5121 void truncate(TruncateKind kind) override;
5122 TruncateKind operandTruncateKind(size_t index) const override;
5123
5124 [[nodiscard]] bool writeRecoverData(
5125 CompactBufferWriter& writer) const override;
5126 bool canRecoverOnBailout() const override { return true; }
5127
5128 ALLOW_CLONE(MAdd)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MAdd
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5129};
5130
5131class MSub : public MBinaryArithInstruction {
5132 MSub(MDefinition* left, MDefinition* right, MIRType type)
5133 : MBinaryArithInstruction(classOpcode, left, right, type) {}
5134
5135 public:
5136 INSTRUCTION_HEADER(Sub)
5137 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)...); }
5138
5139 static MSub* NewWasm(TempAllocator& alloc, MDefinition* left,
5140 MDefinition* right, MIRType type, bool mustPreserveNaN) {
5141 auto* ret = new (alloc) MSub(left, right, type);
5142 ret->setMustPreserveNaN(mustPreserveNaN);
5143 if (type == MIRType::Int32) {
5144 ret->setTruncateKind(TruncateKind::Truncate);
5145 }
5146 return ret;
5147 }
5148
5149 MDefinition* foldsTo(TempAllocator& alloc) override;
5150
5151 double getIdentity() override { return 0; }
5152
5153 bool isFloat32Commutative() const override { return true; }
5154
5155 bool fallible() const;
5156 void computeRange(TempAllocator& alloc) override;
5157 bool canTruncate() const override;
5158 void truncate(TruncateKind kind) override;
5159 TruncateKind operandTruncateKind(size_t index) const override;
5160
5161 [[nodiscard]] bool writeRecoverData(
5162 CompactBufferWriter& writer) const override;
5163 bool canRecoverOnBailout() const override { return true; }
5164
5165 ALLOW_CLONE(MSub)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSub
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5166};
5167
5168class MMul : public MBinaryArithInstruction {
5169 public:
5170 enum Mode { Normal, Integer };
5171
5172 private:
5173 // Annotation the result could be a negative zero
5174 // and we need to guard this during execution.
5175 bool canBeNegativeZero_;
5176
5177 Mode mode_;
5178
5179 MMul(MDefinition* left, MDefinition* right, MIRType type, Mode mode)
5180 : MBinaryArithInstruction(classOpcode, left, right, type),
5181 canBeNegativeZero_(true),
5182 mode_(mode) {
5183 setCommutative();
5184 if (mode == Integer) {
5185 // This implements the required behavior for Math.imul, which
5186 // can never fail and always truncates its output to int32.
5187 canBeNegativeZero_ = false;
5188 setTruncateKind(TruncateKind::Truncate);
5189 }
5190 MOZ_ASSERT_IF(mode != Integer, mode == Normal)do { if (mode != Integer) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(mode == Normal)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(mode == Normal))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("mode == Normal", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5190); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mode == Normal"
")"); do { *((volatile int*)__null) = 5190; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
5191 }
5192
5193 public:
5194 INSTRUCTION_HEADER(Mul)
5195
5196 static MMul* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
5197 MIRType type, Mode mode = Normal) {
5198 return new (alloc) MMul(left, right, type, mode);
5199 }
5200 static MMul* NewWasm(TempAllocator& alloc, MDefinition* left,
5201 MDefinition* right, MIRType type, Mode mode,
5202 bool mustPreserveNaN) {
5203 auto* ret = new (alloc) MMul(left, right, type, mode);
5204 ret->setMustPreserveNaN(mustPreserveNaN);
5205 return ret;
5206 }
5207
5208 MDefinition* foldsTo(TempAllocator& alloc) override;
5209 void analyzeEdgeCasesForward() override;
5210 void analyzeEdgeCasesBackward() override;
5211 void collectRangeInfoPreTrunc() override;
5212
5213 double getIdentity() override { return 1; }
5214
5215 bool congruentTo(const MDefinition* ins) const override {
5216 if (!ins->isMul()) {
5217 return false;
5218 }
5219
5220 const MMul* mul = ins->toMul();
5221 if (canBeNegativeZero_ != mul->canBeNegativeZero()) {
5222 return false;
5223 }
5224
5225 if (mode_ != mul->mode()) {
5226 return false;
5227 }
5228
5229 if (mustPreserveNaN() != mul->mustPreserveNaN()) {
5230 return false;
5231 }
5232
5233 return binaryCongruentTo(ins);
5234 }
5235
5236 bool canOverflow() const;
5237
5238 bool canBeNegativeZero() const { return canBeNegativeZero_; }
5239 void setCanBeNegativeZero(bool negativeZero) {
5240 canBeNegativeZero_ = negativeZero;
5241 }
5242
5243 bool fallible() const { return canBeNegativeZero_ || canOverflow(); }
5244
5245 bool isFloat32Commutative() const override { return true; }
5246
5247 void computeRange(TempAllocator& alloc) override;
5248 bool canTruncate() const override;
5249 void truncate(TruncateKind kind) override;
5250 TruncateKind operandTruncateKind(size_t index) const override;
5251
5252 Mode mode() const { return mode_; }
5253
5254 [[nodiscard]] bool writeRecoverData(
5255 CompactBufferWriter& writer) const override;
5256 bool canRecoverOnBailout() const override { return true; }
5257
5258 ALLOW_CLONE(MMul)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MMul
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5259};
5260
5261class MDiv : public MBinaryArithInstruction {
5262 bool canBeNegativeZero_;
5263 bool canBeNegativeOverflow_;
5264 bool canBeDivideByZero_;
5265 bool canBeNegativeDividend_;
5266 bool unsigned_; // If false, signedness will be derived from operands
5267 bool trapOnError_;
5268 wasm::BytecodeOffset bytecodeOffset_;
5269
5270 MDiv(MDefinition* left, MDefinition* right, MIRType type)
5271 : MBinaryArithInstruction(classOpcode, left, right, type),
5272 canBeNegativeZero_(true),
5273 canBeNegativeOverflow_(true),
5274 canBeDivideByZero_(true),
5275 canBeNegativeDividend_(true),
5276 unsigned_(false),
5277 trapOnError_(false) {}
5278
5279 public:
5280 INSTRUCTION_HEADER(Div)
5281
5282 static MDiv* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
5283 MIRType type) {
5284 return new (alloc) MDiv(left, right, type);
5285 }
5286 static MDiv* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
5287 MIRType type, bool unsignd, bool trapOnError = false,
5288 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset(),
5289 bool mustPreserveNaN = false) {
5290 auto* div = new (alloc) MDiv(left, right, type);
5291 div->unsigned_ = unsignd;
5292 div->trapOnError_ = trapOnError;
5293 div->bytecodeOffset_ = bytecodeOffset;
5294 if (trapOnError) {
5295 div->setGuard(); // not removable because of possible side-effects.
5296 div->setNotMovable();
5297 }
5298 div->setMustPreserveNaN(mustPreserveNaN);
5299 if (type == MIRType::Int32) {
5300 div->setTruncateKind(TruncateKind::Truncate);
5301 }
5302 return div;
5303 }
5304
5305 MDefinition* foldsTo(TempAllocator& alloc) override;
5306 void analyzeEdgeCasesForward() override;
5307 void analyzeEdgeCasesBackward() override;
5308
5309 double getIdentity() override { MOZ_CRASH("not used")do { do { } while (false); MOZ_ReportCrash("" "not used", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5309); AnnotateMozCrashReason("MOZ_CRASH(" "not used" ")");
do { *((volatile int*)__null) = 5309; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
; }
5310
5311 bool canBeNegativeZero() const { return canBeNegativeZero_; }
5312 void setCanBeNegativeZero(bool negativeZero) {
5313 canBeNegativeZero_ = negativeZero;
5314 }
5315
5316 bool canBeNegativeOverflow() const { return canBeNegativeOverflow_; }
5317
5318 bool canBeDivideByZero() const { return canBeDivideByZero_; }
5319
5320 bool canBeNegativeDividend() const {
5321 // "Dividend" is an ambiguous concept for unsigned truncated
5322 // division, because of the truncation procedure:
5323 // ((x>>>0)/2)|0, for example, gets transformed in
5324 // MDiv::truncate into a node with lhs representing x (not
5325 // x>>>0) and rhs representing the constant 2; in other words,
5326 // the MIR node corresponds to "cast operands to unsigned and
5327 // divide" operation. In this case, is the dividend x or is it
5328 // x>>>0? In order to resolve such ambiguities, we disallow
5329 // the usage of this method for unsigned division.
5330 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.h"
, 5330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_"
")"); do { *((volatile int*)__null) = 5330; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5331 return canBeNegativeDividend_;
5332 }
5333
5334 bool isUnsigned() const { return unsigned_; }
5335
5336 bool isTruncatedIndirectly() const {
5337 return truncateKind() >= TruncateKind::IndirectTruncate;
5338 }
5339
5340 bool canTruncateInfinities() const { return isTruncated(); }
5341 bool canTruncateRemainder() const { return isTruncated(); }
5342 bool canTruncateOverflow() const {
5343 return isTruncated() || isTruncatedIndirectly();
5344 }
5345 bool canTruncateNegativeZero() const {
5346 return isTruncated() || isTruncatedIndirectly();
5347 }
5348
5349 bool trapOnError() const { return trapOnError_; }
5350 wasm::BytecodeOffset bytecodeOffset() const {
5351 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.h"
, 5351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()"
")"); do { *((volatile int*)__null) = 5351; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5352 return bytecodeOffset_;
5353 }
5354
5355 bool isFloat32Commutative() const override { return true; }
5356
5357 void computeRange(TempAllocator& alloc) override;
5358 bool fallible() const;
5359 bool canTruncate() const override;
5360 void truncate(TruncateKind kind) override;
5361 void collectRangeInfoPreTrunc() override;
5362 TruncateKind operandTruncateKind(size_t index) const override;
5363
5364 [[nodiscard]] bool writeRecoverData(
5365 CompactBufferWriter& writer) const override;
5366 bool canRecoverOnBailout() const override { return true; }
5367
5368 bool congruentTo(const MDefinition* ins) const override {
5369 if (!MBinaryArithInstruction::congruentTo(ins)) {
5370 return false;
5371 }
5372 const MDiv* other = ins->toDiv();
5373 MOZ_ASSERT(other->trapOnError() == trapOnError_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(other->trapOnError() == trapOnError_)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(other->trapOnError() == trapOnError_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("other->trapOnError() == trapOnError_"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5373); AnnotateMozCrashReason("MOZ_ASSERT" "(" "other->trapOnError() == trapOnError_"
")"); do { *((volatile int*)__null) = 5373; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5374 return unsigned_ == other->isUnsigned();
5375 }
5376
5377 ALLOW_CLONE(MDiv)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MDiv
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5378};
5379
5380class MWasmBuiltinDivI64 : public MAryInstruction<3>, public ArithPolicy::Data {
5381 bool canBeNegativeZero_;
5382 bool canBeNegativeOverflow_;
5383 bool canBeDivideByZero_;
5384 bool canBeNegativeDividend_;
5385 bool unsigned_; // If false, signedness will be derived from operands
5386 bool trapOnError_;
5387 wasm::BytecodeOffset bytecodeOffset_;
5388
5389 MWasmBuiltinDivI64(MDefinition* left, MDefinition* right,
5390 MDefinition* instance)
5391 : MAryInstruction(classOpcode),
5392 canBeNegativeZero_(true),
5393 canBeNegativeOverflow_(true),
5394 canBeDivideByZero_(true),
5395 canBeNegativeDividend_(true),
5396 unsigned_(false),
5397 trapOnError_(false) {
5398 initOperand(0, left);
5399 initOperand(1, right);
5400 initOperand(2, instance);
5401
5402 setResultType(MIRType::Int64);
5403 setMovable();
5404 }
5405
5406 public:
5407 INSTRUCTION_HEADER(WasmBuiltinDivI64)
5408
5409 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); }
5410
5411 static MWasmBuiltinDivI64* New(
5412 TempAllocator& alloc, MDefinition* left, MDefinition* right,
5413 MDefinition* instance, bool unsignd, bool trapOnError = false,
5414 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) {
5415 auto* wasm64Div = new (alloc) MWasmBuiltinDivI64(left, right, instance);
5416 wasm64Div->unsigned_ = unsignd;
5417 wasm64Div->trapOnError_ = trapOnError;
5418 wasm64Div->bytecodeOffset_ = bytecodeOffset;
5419 if (trapOnError) {
5420 wasm64Div->setGuard(); // not removable because of possible side-effects.
5421 wasm64Div->setNotMovable();
5422 }
5423 return wasm64Div;
5424 }
5425
5426 bool canBeNegativeZero() const { return canBeNegativeZero_; }
5427 void setCanBeNegativeZero(bool negativeZero) {
5428 canBeNegativeZero_ = negativeZero;
5429 }
5430
5431 bool canBeNegativeOverflow() const { return canBeNegativeOverflow_; }
5432
5433 bool canBeDivideByZero() const { return canBeDivideByZero_; }
5434
5435 bool canBeNegativeDividend() const {
5436 // "Dividend" is an ambiguous concept for unsigned truncated
5437 // division, because of the truncation procedure:
5438 // ((x>>>0)/2)|0, for example, gets transformed in
5439 // MWasmDiv::truncate into a node with lhs representing x (not
5440 // x>>>0) and rhs representing the constant 2; in other words,
5441 // the MIR node corresponds to "cast operands to unsigned and
5442 // divide" operation. In this case, is the dividend x or is it
5443 // x>>>0? In order to resolve such ambiguities, we disallow
5444 // the usage of this method for unsigned division.
5445 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.h"
, 5445); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_"
")"); do { *((volatile int*)__null) = 5445; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5446 return canBeNegativeDividend_;
5447 }
5448
5449 bool isUnsigned() const { return unsigned_; }
5450
5451 bool trapOnError() const { return trapOnError_; }
5452 wasm::BytecodeOffset bytecodeOffset() const {
5453 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.h"
, 5453); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()"
")"); do { *((volatile int*)__null) = 5453; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5454 return bytecodeOffset_;
5455 }
5456
5457 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; }
5458};
5459
5460class MMod : public MBinaryArithInstruction {
5461 bool unsigned_; // If false, signedness will be derived from operands
5462 bool canBeNegativeDividend_;
5463 bool canBePowerOfTwoDivisor_;
5464 bool canBeDivideByZero_;
5465 bool trapOnError_;
5466 wasm::BytecodeOffset bytecodeOffset_;
5467
5468 MMod(MDefinition* left, MDefinition* right, MIRType type)
5469 : MBinaryArithInstruction(classOpcode, left, right, type),
5470 unsigned_(false),
5471 canBeNegativeDividend_(true),
5472 canBePowerOfTwoDivisor_(true),
5473 canBeDivideByZero_(true),
5474 trapOnError_(false) {}
5475
5476 public:
5477 INSTRUCTION_HEADER(Mod)
5478
5479 static MMod* New(TempAllocator& alloc, MDefinition* left, MDefinition* right,
5480 MIRType type) {
5481 return new (alloc) MMod(left, right, type);
5482 }
5483 static MMod* New(
5484 TempAllocator& alloc, MDefinition* left, MDefinition* right, MIRType type,
5485 bool unsignd, bool trapOnError = false,
5486 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) {
5487 auto* mod = new (alloc) MMod(left, right, type);
5488 mod->unsigned_ = unsignd;
5489 mod->trapOnError_ = trapOnError;
5490 mod->bytecodeOffset_ = bytecodeOffset;
5491 if (trapOnError) {
5492 mod->setGuard(); // not removable because of possible side-effects.
5493 mod->setNotMovable();
5494 }
5495 if (type == MIRType::Int32) {
5496 mod->setTruncateKind(TruncateKind::Truncate);
5497 }
5498 return mod;
5499 }
5500
5501 MDefinition* foldsTo(TempAllocator& alloc) override;
5502
5503 double getIdentity() override { MOZ_CRASH("not used")do { do { } while (false); MOZ_ReportCrash("" "not used", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5503); AnnotateMozCrashReason("MOZ_CRASH(" "not used" ")");
do { *((volatile int*)__null) = 5503; __attribute__((nomerge
)) ::abort(); } while (false); } while (false)
; }
5504
5505 bool canBeNegativeDividend() const {
5506 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.h"
, 5506); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Int32 || type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 5506; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5507 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.h"
, 5507); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_"
")"); do { *((volatile int*)__null) = 5507; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5508 return canBeNegativeDividend_;
5509 }
5510
5511 bool canBeDivideByZero() const {
5512 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.h"
, 5512); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Int32 || type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 5512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5513 return canBeDivideByZero_;
5514 }
5515
5516 bool canBePowerOfTwoDivisor() const {
5517 MOZ_ASSERT(type() == MIRType::Int32)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.h"
, 5517); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 5517; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5518 return canBePowerOfTwoDivisor_;
5519 }
5520
5521 void analyzeEdgeCasesForward() override;
5522
5523 bool isUnsigned() const { return unsigned_; }
5524
5525 bool trapOnError() const { return trapOnError_; }
5526 wasm::BytecodeOffset bytecodeOffset() const {
5527 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.h"
, 5527); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()"
")"); do { *((volatile int*)__null) = 5527; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5528 return bytecodeOffset_;
5529 }
5530
5531 [[nodiscard]] bool writeRecoverData(
5532 CompactBufferWriter& writer) const override;
5533 bool canRecoverOnBailout() const override { return true; }
5534
5535 bool fallible() const;
5536
5537 void computeRange(TempAllocator& alloc) override;
5538 bool canTruncate() const override;
5539 void truncate(TruncateKind kind) override;
5540 void collectRangeInfoPreTrunc() override;
5541 TruncateKind operandTruncateKind(size_t index) const override;
5542
5543 bool congruentTo(const MDefinition* ins) const override {
5544 return MBinaryArithInstruction::congruentTo(ins) &&
5545 unsigned_ == ins->toMod()->isUnsigned();
5546 }
5547
5548 bool possiblyCalls() const override { return type() == MIRType::Double; }
5549
5550 ALLOW_CLONE(MMod)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MMod
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5551};
5552
5553class MWasmBuiltinModD : public MAryInstruction<3>, public ArithPolicy::Data {
5554 wasm::BytecodeOffset bytecodeOffset_;
5555
5556 MWasmBuiltinModD(MDefinition* left, MDefinition* right, MDefinition* instance,
5557 MIRType type)
5558 : MAryInstruction(classOpcode) {
5559 initOperand(0, left);
5560 initOperand(1, right);
5561 initOperand(2, instance);
5562
5563 setResultType(type);
5564 setMovable();
5565 }
5566
5567 public:
5568 INSTRUCTION_HEADER(WasmBuiltinModD)
5569 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); }
5570
5571 static MWasmBuiltinModD* New(
5572 TempAllocator& alloc, MDefinition* left, MDefinition* right,
5573 MDefinition* instance, MIRType type,
5574 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) {
5575 auto* wasmBuiltinModD =
5576 new (alloc) MWasmBuiltinModD(left, right, instance, type);
5577 wasmBuiltinModD->bytecodeOffset_ = bytecodeOffset;
5578 return wasmBuiltinModD;
5579 }
5580
5581 wasm::BytecodeOffset bytecodeOffset() const {
5582 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.h"
, 5582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()"
")"); do { *((volatile int*)__null) = 5582; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5583 return bytecodeOffset_;
5584 }
5585
5586 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; }
5587};
5588
5589class MWasmBuiltinModI64 : public MAryInstruction<3>, public ArithPolicy::Data {
5590 bool unsigned_; // If false, signedness will be derived from operands
5591 bool canBeNegativeDividend_;
5592 bool canBeDivideByZero_;
5593 bool trapOnError_;
5594 wasm::BytecodeOffset bytecodeOffset_;
5595
5596 MWasmBuiltinModI64(MDefinition* left, MDefinition* right,
5597 MDefinition* instance)
5598 : MAryInstruction(classOpcode),
5599 unsigned_(false),
5600 canBeNegativeDividend_(true),
5601 canBeDivideByZero_(true),
5602 trapOnError_(false) {
5603 initOperand(0, left);
5604 initOperand(1, right);
5605 initOperand(2, instance);
5606
5607 setResultType(MIRType::Int64);
5608 setMovable();
5609 }
5610
5611 public:
5612 INSTRUCTION_HEADER(WasmBuiltinModI64)
5613
5614 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); }
5615
5616 static MWasmBuiltinModI64* New(
5617 TempAllocator& alloc, MDefinition* left, MDefinition* right,
5618 MDefinition* instance, bool unsignd, bool trapOnError = false,
5619 wasm::BytecodeOffset bytecodeOffset = wasm::BytecodeOffset()) {
5620 auto* mod = new (alloc) MWasmBuiltinModI64(left, right, instance);
5621 mod->unsigned_ = unsignd;
5622 mod->trapOnError_ = trapOnError;
5623 mod->bytecodeOffset_ = bytecodeOffset;
5624 if (trapOnError) {
5625 mod->setGuard(); // not removable because of possible side-effects.
5626 mod->setNotMovable();
5627 }
5628 return mod;
5629 }
5630
5631 bool canBeNegativeDividend() const {
5632 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.h"
, 5632); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!unsigned_"
")"); do { *((volatile int*)__null) = 5632; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5633 return canBeNegativeDividend_;
5634 }
5635
5636 bool canBeDivideByZero() const { return canBeDivideByZero_; }
5637
5638 bool isUnsigned() const { return unsigned_; }
5639
5640 bool trapOnError() const { return trapOnError_; }
5641 wasm::BytecodeOffset bytecodeOffset() const {
5642 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.h"
, 5642); AnnotateMozCrashReason("MOZ_ASSERT" "(" "bytecodeOffset_.isValid()"
")"); do { *((volatile int*)__null) = 5642; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5643 return bytecodeOffset_;
5644 }
5645
5646 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; }
5647};
5648
5649class MBigIntBinaryArithInstruction : public MBinaryInstruction,
5650 public BigIntArithPolicy::Data {
5651 protected:
5652 MBigIntBinaryArithInstruction(Opcode op, MDefinition* left,
5653 MDefinition* right)
5654 : MBinaryInstruction(op, left, right) {
5655 setResultType(MIRType::BigInt);
5656 setMovable();
5657 }
5658
5659 public:
5660 bool congruentTo(const MDefinition* ins) const override {
5661 return binaryCongruentTo(ins);
5662 }
5663
5664 AliasSet getAliasSet() const override { return AliasSet::None(); }
5665};
5666
5667class MBigIntAdd : public MBigIntBinaryArithInstruction {
5668 MBigIntAdd(MDefinition* left, MDefinition* right)
5669 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5670 setCommutative();
5671
5672 // Don't guard this instruction even though adding two BigInts can throw
5673 // JSMSG_BIGINT_TOO_LARGE. This matches the behavior when adding too large
5674 // strings in MConcat.
5675 }
5676
5677 public:
5678 INSTRUCTION_HEADER(BigIntAdd)
5679 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)...); }
5680
5681 [[nodiscard]] bool writeRecoverData(
5682 CompactBufferWriter& writer) const override;
5683 bool canRecoverOnBailout() const override { return true; }
5684
5685 ALLOW_CLONE(MBigIntAdd)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntAdd
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5686};
5687
5688class MBigIntSub : public MBigIntBinaryArithInstruction {
5689 MBigIntSub(MDefinition* left, MDefinition* right)
5690 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5691 // See MBigIntAdd for why we don't guard this instruction.
5692 }
5693
5694 public:
5695 INSTRUCTION_HEADER(BigIntSub)
5696 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)...); }
5697
5698 [[nodiscard]] bool writeRecoverData(
5699 CompactBufferWriter& writer) const override;
5700 bool canRecoverOnBailout() const override { return true; }
5701
5702 ALLOW_CLONE(MBigIntSub)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntSub
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5703};
5704
5705class MBigIntMul : public MBigIntBinaryArithInstruction {
5706 MBigIntMul(MDefinition* left, MDefinition* right)
5707 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5708 setCommutative();
5709
5710 // See MBigIntAdd for why we don't guard this instruction.
5711 }
5712
5713 public:
5714 INSTRUCTION_HEADER(BigIntMul)
5715 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)...); }
5716
5717 [[nodiscard]] bool writeRecoverData(
5718 CompactBufferWriter& writer) const override;
5719 bool canRecoverOnBailout() const override { return true; }
5720
5721 ALLOW_CLONE(MBigIntMul)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntMul
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5722};
5723
5724class MBigIntDiv : public MBigIntBinaryArithInstruction {
5725 bool canBeDivideByZero_;
5726
5727 MBigIntDiv(MDefinition* left, MDefinition* right)
5728 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5729 MOZ_ASSERT(right->type() == MIRType::BigInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(right->type() == MIRType::BigInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(right->type() == MIRType::
BigInt))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("right->type() == MIRType::BigInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5729); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right->type() == MIRType::BigInt"
")"); do { *((volatile int*)__null) = 5729; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5730 canBeDivideByZero_ =
5731 !right->isConstant() || right->toConstant()->toBigInt()->isZero();
5732
5733 // Throws when the divisor is zero.
5734 if (canBeDivideByZero_) {
5735 setGuard();
5736 setNotMovable();
5737 }
5738 }
5739
5740 public:
5741 INSTRUCTION_HEADER(BigIntDiv)
5742 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)...); }
5743
5744 bool canBeDivideByZero() const { return canBeDivideByZero_; }
5745
5746 AliasSet getAliasSet() const override {
5747 if (canBeDivideByZero()) {
5748 return AliasSet::Store(AliasSet::ExceptionState);
5749 }
5750 return AliasSet::None();
5751 }
5752
5753 [[nodiscard]] bool writeRecoverData(
5754 CompactBufferWriter& writer) const override;
5755 bool canRecoverOnBailout() const override { return !canBeDivideByZero(); }
5756
5757 ALLOW_CLONE(MBigIntDiv)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntDiv
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5758};
5759
5760class MBigIntMod : public MBigIntBinaryArithInstruction {
5761 bool canBeDivideByZero_;
5762
5763 MBigIntMod(MDefinition* left, MDefinition* right)
5764 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5765 MOZ_ASSERT(right->type() == MIRType::BigInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(right->type() == MIRType::BigInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(right->type() == MIRType::
BigInt))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("right->type() == MIRType::BigInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5765); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right->type() == MIRType::BigInt"
")"); do { *((volatile int*)__null) = 5765; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5766 canBeDivideByZero_ =
5767 !right->isConstant() || right->toConstant()->toBigInt()->isZero();
5768
5769 // Throws when the divisor is zero.
5770 if (canBeDivideByZero_) {
5771 setGuard();
5772 setNotMovable();
5773 }
5774 }
5775
5776 public:
5777 INSTRUCTION_HEADER(BigIntMod)
5778 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)...); }
5779
5780 bool canBeDivideByZero() const { return canBeDivideByZero_; }
5781
5782 AliasSet getAliasSet() const override {
5783 if (canBeDivideByZero()) {
5784 return AliasSet::Store(AliasSet::ExceptionState);
5785 }
5786 return AliasSet::None();
5787 }
5788
5789 [[nodiscard]] bool writeRecoverData(
5790 CompactBufferWriter& writer) const override;
5791 bool canRecoverOnBailout() const override { return !canBeDivideByZero(); }
5792
5793 ALLOW_CLONE(MBigIntMod)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntMod
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5794};
5795
5796class MBigIntPow : public MBigIntBinaryArithInstruction {
5797 bool canBeNegativeExponent_;
5798
5799 MBigIntPow(MDefinition* left, MDefinition* right)
5800 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5801 MOZ_ASSERT(right->type() == MIRType::BigInt)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(right->type() == MIRType::BigInt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(right->type() == MIRType::
BigInt))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("right->type() == MIRType::BigInt", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 5801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "right->type() == MIRType::BigInt"
")"); do { *((volatile int*)__null) = 5801; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
5802 canBeNegativeExponent_ =
5803 !right->isConstant() || right->toConstant()->toBigInt()->isNegative();
5804
5805 // Throws when the exponent is negative.
5806 if (canBeNegativeExponent_) {
5807 setGuard();
5808 setNotMovable();
5809 }
5810 }
5811
5812 public:
5813 INSTRUCTION_HEADER(BigIntPow)
5814 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)...); }
5815
5816 bool canBeNegativeExponent() const { return canBeNegativeExponent_; }
5817
5818 AliasSet getAliasSet() const override {
5819 if (canBeNegativeExponent()) {
5820 return AliasSet::Store(AliasSet::ExceptionState);
5821 }
5822 return AliasSet::None();
5823 }
5824
5825 [[nodiscard]] bool writeRecoverData(
5826 CompactBufferWriter& writer) const override;
5827 bool canRecoverOnBailout() const override { return !canBeNegativeExponent(); }
5828
5829 ALLOW_CLONE(MBigIntPow)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntPow
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5830};
5831
5832class MBigIntBitAnd : public MBigIntBinaryArithInstruction {
5833 MBigIntBitAnd(MDefinition* left, MDefinition* right)
5834 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5835 setCommutative();
5836
5837 // We don't need to guard this instruction because it can only fail on OOM.
5838 }
5839
5840 public:
5841 INSTRUCTION_HEADER(BigIntBitAnd)
5842 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)...); }
5843
5844 [[nodiscard]] bool writeRecoverData(
5845 CompactBufferWriter& writer) const override;
5846 bool canRecoverOnBailout() const override { return true; }
5847
5848 ALLOW_CLONE(MBigIntBitAnd)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntBitAnd
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5849};
5850
5851class MBigIntBitOr : public MBigIntBinaryArithInstruction {
5852 MBigIntBitOr(MDefinition* left, MDefinition* right)
5853 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5854 setCommutative();
5855
5856 // We don't need to guard this instruction because it can only fail on OOM.
5857 }
5858
5859 public:
5860 INSTRUCTION_HEADER(BigIntBitOr)
5861 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)...); }
5862
5863 [[nodiscard]] bool writeRecoverData(
5864 CompactBufferWriter& writer) const override;
5865 bool canRecoverOnBailout() const override { return true; }
5866
5867 ALLOW_CLONE(MBigIntBitOr)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntBitOr
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5868};
5869
5870class MBigIntBitXor : public MBigIntBinaryArithInstruction {
5871 MBigIntBitXor(MDefinition* left, MDefinition* right)
5872 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5873 setCommutative();
5874
5875 // We don't need to guard this instruction because it can only fail on OOM.
5876 }
5877
5878 public:
5879 INSTRUCTION_HEADER(BigIntBitXor)
5880 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)...); }
5881
5882 [[nodiscard]] bool writeRecoverData(
5883 CompactBufferWriter& writer) const override;
5884 bool canRecoverOnBailout() const override { return true; }
5885
5886 ALLOW_CLONE(MBigIntBitXor)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntBitXor
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5887};
5888
5889class MBigIntLsh : public MBigIntBinaryArithInstruction {
5890 MBigIntLsh(MDefinition* left, MDefinition* right)
5891 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5892 // See MBigIntAdd for why we don't guard this instruction.
5893 }
5894
5895 public:
5896 INSTRUCTION_HEADER(BigIntLsh)
5897 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)...); }
5898
5899 [[nodiscard]] bool writeRecoverData(
5900 CompactBufferWriter& writer) const override;
5901 bool canRecoverOnBailout() const override { return true; }
5902
5903 ALLOW_CLONE(MBigIntLsh)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntLsh
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5904};
5905
5906class MBigIntRsh : public MBigIntBinaryArithInstruction {
5907 MBigIntRsh(MDefinition* left, MDefinition* right)
5908 : MBigIntBinaryArithInstruction(classOpcode, left, right) {
5909 // See MBigIntAdd for why we don't guard this instruction.
5910 }
5911
5912 public:
5913 INSTRUCTION_HEADER(BigIntRsh)
5914 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)...); }
5915
5916 [[nodiscard]] bool writeRecoverData(
5917 CompactBufferWriter& writer) const override;
5918 bool canRecoverOnBailout() const override { return true; }
5919
5920 ALLOW_CLONE(MBigIntRsh)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntRsh
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5921};
5922
5923class MBigIntUnaryArithInstruction : public MUnaryInstruction,
5924 public BigIntArithPolicy::Data {
5925 protected:
5926 MBigIntUnaryArithInstruction(Opcode op, MDefinition* input)
5927 : MUnaryInstruction(op, input) {
5928 setResultType(MIRType::BigInt);
5929 setMovable();
5930 }
5931
5932 public:
5933 bool congruentTo(const MDefinition* ins) const override {
5934 return congruentIfOperandsEqual(ins);
5935 }
5936
5937 AliasSet getAliasSet() const override { return AliasSet::None(); }
5938};
5939
5940class MBigIntIncrement : public MBigIntUnaryArithInstruction {
5941 explicit MBigIntIncrement(MDefinition* input)
5942 : MBigIntUnaryArithInstruction(classOpcode, input) {
5943 // See MBigIntAdd for why we don't guard this instruction.
5944 }
5945
5946 public:
5947 INSTRUCTION_HEADER(BigIntIncrement)
5948 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)...); }
5949
5950 [[nodiscard]] bool writeRecoverData(
5951 CompactBufferWriter& writer) const override;
5952 bool canRecoverOnBailout() const override { return true; }
5953
5954 ALLOW_CLONE(MBigIntIncrement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntIncrement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5955};
5956
5957class MBigIntDecrement : public MBigIntUnaryArithInstruction {
5958 explicit MBigIntDecrement(MDefinition* input)
5959 : MBigIntUnaryArithInstruction(classOpcode, input) {
5960 // See MBigIntAdd for why we don't guard this instruction.
5961 }
5962
5963 public:
5964 INSTRUCTION_HEADER(BigIntDecrement)
5965 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)...); }
5966
5967 [[nodiscard]] bool writeRecoverData(
5968 CompactBufferWriter& writer) const override;
5969 bool canRecoverOnBailout() const override { return true; }
5970
5971 ALLOW_CLONE(MBigIntDecrement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntDecrement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5972};
5973
5974class MBigIntNegate : public MBigIntUnaryArithInstruction {
5975 explicit MBigIntNegate(MDefinition* input)
5976 : MBigIntUnaryArithInstruction(classOpcode, input) {
5977 // We don't need to guard this instruction because it can only fail on OOM.
5978 }
5979
5980 public:
5981 INSTRUCTION_HEADER(BigIntNegate)
5982 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)...); }
5983
5984 [[nodiscard]] bool writeRecoverData(
5985 CompactBufferWriter& writer) const override;
5986 bool canRecoverOnBailout() const override { return true; }
5987
5988 ALLOW_CLONE(MBigIntNegate)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntNegate
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
5989};
5990
5991class MBigIntBitNot : public MBigIntUnaryArithInstruction {
5992 explicit MBigIntBitNot(MDefinition* input)
5993 : MBigIntUnaryArithInstruction(classOpcode, input) {
5994 // See MBigIntAdd for why we don't guard this instruction.
5995 }
5996
5997 public:
5998 INSTRUCTION_HEADER(BigIntBitNot)
5999 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)...); }
6000
6001 [[nodiscard]] bool writeRecoverData(
6002 CompactBufferWriter& writer) const override;
6003 bool canRecoverOnBailout() const override { return true; }
6004
6005 ALLOW_CLONE(MBigIntBitNot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBigIntBitNot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6006};
6007
6008class MConcat : public MBinaryInstruction,
6009 public MixPolicy<ConvertToStringPolicy<0>,
6010 ConvertToStringPolicy<1>>::Data {
6011 MConcat(MDefinition* left, MDefinition* right)
6012 : MBinaryInstruction(classOpcode, left, right) {
6013 // At least one input should be definitely string
6014 MOZ_ASSERT(left->type() == MIRType::String ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(left->type() == MIRType::String || right->type
() == MIRType::String)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(left->type() == MIRType::
String || right->type() == MIRType::String))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("left->type() == MIRType::String || right->type() == MIRType::String"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "left->type() == MIRType::String || right->type() == MIRType::String"
")"); do { *((volatile int*)__null) = 6015; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6015 right->type() == MIRType::String)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(left->type() == MIRType::String || right->type
() == MIRType::String)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(left->type() == MIRType::
String || right->type() == MIRType::String))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("left->type() == MIRType::String || right->type() == MIRType::String"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6015); AnnotateMozCrashReason("MOZ_ASSERT" "(" "left->type() == MIRType::String || right->type() == MIRType::String"
")"); do { *((volatile int*)__null) = 6015; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6016
6017 setMovable();
6018 setResultType(MIRType::String);
6019 }
6020
6021 public:
6022 INSTRUCTION_HEADER(Concat)
6023 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)...); }
6024
6025 MDefinition* foldsTo(TempAllocator& alloc) override;
6026 bool congruentTo(const MDefinition* ins) const override {
6027 return congruentIfOperandsEqual(ins);
6028 }
6029 AliasSet getAliasSet() const override { return AliasSet::None(); }
6030
6031 [[nodiscard]] bool writeRecoverData(
6032 CompactBufferWriter& writer) const override;
6033 bool canRecoverOnBailout() const override { return true; }
6034
6035 ALLOW_CLONE(MConcat)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MConcat
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6036};
6037
6038class MStringConvertCase : public MUnaryInstruction,
6039 public StringPolicy<0>::Data {
6040 public:
6041 enum Mode { LowerCase, UpperCase };
6042
6043 private:
6044 Mode mode_;
6045
6046 MStringConvertCase(MDefinition* string, Mode mode)
6047 : MUnaryInstruction(classOpcode, string), mode_(mode) {
6048 setResultType(MIRType::String);
6049 setMovable();
6050 }
6051
6052 public:
6053 INSTRUCTION_HEADER(StringConvertCase)
6054 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)...); }
6055 NAMED_OPERANDS((0, string))MDefinition* string() const { return getOperand(0); }
6056
6057 MDefinition* foldsTo(TempAllocator& alloc) override;
6058 bool congruentTo(const MDefinition* ins) const override {
6059 return congruentIfOperandsEqual(ins) &&
6060 ins->toStringConvertCase()->mode() == mode();
6061 }
6062 AliasSet getAliasSet() const override { return AliasSet::None(); }
6063 bool possiblyCalls() const override { return true; }
6064 Mode mode() const { return mode_; }
6065};
6066
6067class MCharCodeConvertCase : public MUnaryInstruction,
6068 public UnboxedInt32Policy<0>::Data {
6069 public:
6070 enum Mode { LowerCase, UpperCase };
6071
6072 private:
6073 Mode mode_;
6074
6075 MCharCodeConvertCase(MDefinition* code, Mode mode)
6076 : MUnaryInstruction(classOpcode, code), mode_(mode) {
6077 setResultType(MIRType::String);
6078 setMovable();
6079 }
6080
6081 public:
6082 INSTRUCTION_HEADER(CharCodeConvertCase)
6083 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)...); }
6084 NAMED_OPERANDS((0, code))MDefinition* code() const { return getOperand(0); }
6085
6086 bool congruentTo(const MDefinition* ins) const override {
6087 return congruentIfOperandsEqual(ins) &&
6088 ins->toCharCodeConvertCase()->mode() == mode();
6089 }
6090 AliasSet getAliasSet() const override { return AliasSet::None(); }
6091 Mode mode() const { return mode_; }
6092};
6093
6094// This is a 3 state flag used by FlagPhiInputsAsImplicitlyUsed to record and
6095// propagate the information about the consumers of a Phi instruction. This is
6096// then used to set ImplicitlyUsed flags on the inputs of such Phi instructions.
6097enum class PhiUsage : uint8_t { Unknown, Unused, Used };
6098
6099using PhiVector = Vector<MPhi*, 4, JitAllocPolicy>;
6100
6101class MPhi final : public MDefinition,
6102 public InlineListNode<MPhi>,
6103 public NoTypePolicy::Data {
6104 using InputVector = js::Vector<MUse, 2, JitAllocPolicy>;
6105 InputVector inputs_;
6106
6107 TruncateKind truncateKind_;
6108 bool triedToSpecialize_;
6109 bool isIterator_;
6110 bool canProduceFloat32_;
6111 bool canConsumeFloat32_;
6112 // Record the state of the data flow before any mutation made to the control
6113 // flow, such that removing branches is properly accounted for.
6114 PhiUsage usageAnalysis_;
6115
6116 protected:
6117 MUse* getUseFor(size_t index) override {
6118 MOZ_ASSERT(index < numOperands())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index < numOperands())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index < numOperands()))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("index < numOperands()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6118); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < numOperands()"
")"); do { *((volatile int*)__null) = 6118; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6119 return &inputs_[index];
6120 }
6121 const MUse* getUseFor(size_t index) const override { return &inputs_[index]; }
6122
6123 public:
6124 INSTRUCTION_HEADER_WITHOUT_TYPEPOLICY(Phi)static const Opcode classOpcode = Opcode::Phi; using MThisOpcode
= MPhi;
6125 virtual const TypePolicy* typePolicy();
6126 virtual MIRType typePolicySpecialization();
6127
6128 MPhi(TempAllocator& alloc, MIRType resultType)
6129 : MDefinition(classOpcode),
6130 inputs_(alloc),
6131 truncateKind_(TruncateKind::NoTruncate),
6132 triedToSpecialize_(false),
6133 isIterator_(false),
6134 canProduceFloat32_(false),
6135 canConsumeFloat32_(false),
6136 usageAnalysis_(PhiUsage::Unknown) {
6137 setResultType(resultType);
6138 }
6139
6140 static MPhi* New(TempAllocator& alloc, MIRType resultType = MIRType::Value) {
6141 return new (alloc) MPhi(alloc, resultType);
6142 }
6143 static MPhi* New(TempAllocator::Fallible alloc,
6144 MIRType resultType = MIRType::Value) {
6145 return new (alloc) MPhi(alloc.alloc, resultType);
6146 }
6147
6148 void removeOperand(size_t index);
6149 void removeAllOperands();
6150
6151 MDefinition* getOperand(size_t index) const override {
6152 return inputs_[index].producer();
6153 }
6154 size_t numOperands() const override { return inputs_.length(); }
6155 size_t indexOf(const MUse* u) const final {
6156 MOZ_ASSERT(u >= &inputs_[0])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u >= &inputs_[0])>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u >= &inputs_[0]))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("u >= &inputs_[0]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6156); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u >= &inputs_[0]"
")"); do { *((volatile int*)__null) = 6156; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6157 MOZ_ASSERT(u <= &inputs_[numOperands() - 1])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u <= &inputs_[numOperands() - 1])>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(u <= &inputs_[numOperands() - 1]))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("u <= &inputs_[numOperands() - 1]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u <= &inputs_[numOperands() - 1]"
")"); do { *((volatile int*)__null) = 6157; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6158 return u - &inputs_[0];
6159 }
6160 void replaceOperand(size_t index, MDefinition* operand) final {
6161 inputs_[index].replaceProducer(operand);
6162 }
6163 bool triedToSpecialize() const { return triedToSpecialize_; }
6164 void specialize(MIRType type) {
6165 triedToSpecialize_ = true;
6166 setResultType(type);
6167 }
6168
6169#ifdef DEBUG1
6170 // Assert that this is a phi in a loop header with a unique predecessor and
6171 // a unique backedge.
6172 void assertLoopPhi() const;
6173#else
6174 void assertLoopPhi() const {}
6175#endif
6176
6177 // Assuming this phi is in a loop header with a unique loop entry, return
6178 // the phi operand along the loop entry.
6179 MDefinition* getLoopPredecessorOperand() const;
6180
6181 // Assuming this phi is in a loop header with a unique loop entry, return
6182 // the phi operand along the loop backedge.
6183 MDefinition* getLoopBackedgeOperand() const;
6184
6185 // Whether this phi's type already includes information for def.
6186 bool typeIncludes(MDefinition* def);
6187
6188 // Mark all phis in |iterators|, and the phis they flow into, as having
6189 // implicit uses.
6190 [[nodiscard]] static bool markIteratorPhis(const PhiVector& iterators);
6191
6192 // Initializes the operands vector to the given capacity,
6193 // permitting use of addInput() instead of addInputSlow().
6194 [[nodiscard]] bool reserveLength(size_t length) {
6195 return inputs_.reserve(length);
6196 }
6197
6198 // Use only if capacity has been reserved by reserveLength
6199 void addInput(MDefinition* ins) {
6200 MOZ_ASSERT_IF(type() != MIRType::Value, ins->type() == type())do { if (type() != MIRType::Value) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(ins->type() ==
type())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ins->type() == type()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("ins->type() == type()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6200); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ins->type() == type()"
")"); do { *((volatile int*)__null) = 6200; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6201 inputs_.infallibleEmplaceBack(ins, this);
6202 }
6203
6204 // Appends a new input to the input vector. May perform reallocation.
6205 // Prefer reserveLength() and addInput() instead, where possible.
6206 [[nodiscard]] bool addInputSlow(MDefinition* ins) {
6207 MOZ_ASSERT_IF(type() != MIRType::Value, ins->type() == type())do { if (type() != MIRType::Value) { do { static_assert( mozilla
::detail::AssertionConditionType<decltype(ins->type() ==
type())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(ins->type() == type()))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("ins->type() == type()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6207); AnnotateMozCrashReason("MOZ_ASSERT" "(" "ins->type() == type()"
")"); do { *((volatile int*)__null) = 6207; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
6208 return inputs_.emplaceBack(ins, this);
6209 }
6210
6211 // Appends a new input to the input vector. Infallible because
6212 // we know the inputs fits in the vector's inline storage.
6213 void addInlineInput(MDefinition* ins) {
6214 MOZ_ASSERT(inputs_.length() < InputVector::InlineLength)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(inputs_.length() < InputVector::InlineLength)>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(inputs_.length() < InputVector::InlineLength))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("inputs_.length() < InputVector::InlineLength"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6214); AnnotateMozCrashReason("MOZ_ASSERT" "(" "inputs_.length() < InputVector::InlineLength"
")"); do { *((volatile int*)__null) = 6214; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6215 MOZ_ALWAYS_TRUE(addInputSlow(ins))do { if ((__builtin_expect(!!(addInputSlow(ins)), 1))) { } else
{ do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "addInputSlow(ins)"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6215); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "false"
") (" "addInputSlow(ins)" ")"); do { *((volatile int*)__null
) = 6215; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false); } } while (false)
;
6216 }
6217
6218 MDefinition* foldsTo(TempAllocator& alloc) override;
6219 MDefinition* foldsTernary(TempAllocator& alloc);
6220
6221 bool congruentTo(const MDefinition* ins) const override;
6222
6223 // Mark this phi-node as having replaced all uses of |other|, as during GVN.
6224 // For use when GVN eliminates phis which are not equivalent to one another.
6225 void updateForReplacement(MPhi* other);
6226
6227 bool isIterator() const { return isIterator_; }
6228 void setIterator() { isIterator_ = true; }
6229
6230 AliasSet getAliasSet() const override { return AliasSet::None(); }
6231 void computeRange(TempAllocator& alloc) override;
6232
6233 MDefinition* operandIfRedundant();
6234
6235 bool canProduceFloat32() const override { return canProduceFloat32_; }
6236
6237 void setCanProduceFloat32(bool can) { canProduceFloat32_ = can; }
6238
6239 bool canConsumeFloat32(MUse* use) const override {
6240 return canConsumeFloat32_;
6241 }
6242
6243 void setCanConsumeFloat32(bool can) { canConsumeFloat32_ = can; }
6244
6245 TruncateKind operandTruncateKind(size_t index) const override;
6246 bool canTruncate() const override;
6247 void truncate(TruncateKind kind) override;
6248
6249 PhiUsage getUsageAnalysis() const { return usageAnalysis_; }
6250 void setUsageAnalysis(PhiUsage pu) {
6251 MOZ_ASSERT(usageAnalysis_ == PhiUsage::Unknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(usageAnalysis_ == PhiUsage::Unknown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(usageAnalysis_ == PhiUsage::
Unknown))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("usageAnalysis_ == PhiUsage::Unknown", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6251); AnnotateMozCrashReason("MOZ_ASSERT" "(" "usageAnalysis_ == PhiUsage::Unknown"
")"); do { *((volatile int*)__null) = 6251; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6252 usageAnalysis_ = pu;
6253 MOZ_ASSERT(usageAnalysis_ != PhiUsage::Unknown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(usageAnalysis_ != PhiUsage::Unknown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(usageAnalysis_ != PhiUsage::
Unknown))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("usageAnalysis_ != PhiUsage::Unknown", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6253); AnnotateMozCrashReason("MOZ_ASSERT" "(" "usageAnalysis_ != PhiUsage::Unknown"
")"); do { *((volatile int*)__null) = 6253; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6254 }
6255};
6256
6257// The goal of a Beta node is to split a def at a conditionally taken
6258// branch, so that uses dominated by it have a different name.
6259class MBeta : public MUnaryInstruction, public NoTypePolicy::Data {
6260 private:
6261 // This is the range induced by a comparison and branch in a preceding
6262 // block. Note that this does not reflect any range constraints from
6263 // the input value itself, so this value may differ from the range()
6264 // range after it is computed.
6265 const Range* comparison_;
6266
6267 MBeta(MDefinition* val, const Range* comp)
6268 : MUnaryInstruction(classOpcode, val), comparison_(comp) {
6269 setResultType(val->type());
6270 }
6271
6272 public:
6273 INSTRUCTION_HEADER(Beta)
6274 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)...); }
6275
6276#ifdef JS_JITSPEW1
6277 void printOpcode(GenericPrinter& out) const override;
6278#endif
6279
6280 AliasSet getAliasSet() const override { return AliasSet::None(); }
6281
6282 void computeRange(TempAllocator& alloc) override;
6283};
6284
6285// If input evaluates to false (i.e. it's NaN, 0 or -0), 0 is returned, else the
6286// input is returned
6287class MNaNToZero : public MUnaryInstruction, public DoublePolicy<0>::Data {
6288 bool operandIsNeverNaN_;
6289 bool operandIsNeverNegativeZero_;
6290
6291 explicit MNaNToZero(MDefinition* input)
6292 : MUnaryInstruction(classOpcode, input),
6293 operandIsNeverNaN_(false),
6294 operandIsNeverNegativeZero_(false) {
6295 setResultType(MIRType::Double);
6296 setMovable();
6297 }
6298
6299 public:
6300 INSTRUCTION_HEADER(NaNToZero)
6301 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)...); }
6302
6303 bool operandIsNeverNaN() const { return operandIsNeverNaN_; }
6304
6305 bool operandIsNeverNegativeZero() const {
6306 return operandIsNeverNegativeZero_;
6307 }
6308
6309 void collectRangeInfoPreTrunc() override;
6310
6311 AliasSet getAliasSet() const override { return AliasSet::None(); }
6312
6313 void computeRange(TempAllocator& alloc) override;
6314
6315 bool writeRecoverData(CompactBufferWriter& writer) const override;
6316 bool canRecoverOnBailout() const override { return true; }
6317
6318 ALLOW_CLONE(MNaNToZero)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MNaNToZero
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6319};
6320
6321// MIR representation of a Value on the OSR BaselineFrame.
6322// The Value is indexed off of OsrFrameReg.
6323class MOsrValue : public MUnaryInstruction, public NoTypePolicy::Data {
6324 private:
6325 ptrdiff_t frameOffset_;
6326
6327 MOsrValue(MOsrEntry* entry, ptrdiff_t frameOffset)
6328 : MUnaryInstruction(classOpcode, entry), frameOffset_(frameOffset) {
6329 setResultType(MIRType::Value);
6330 }
6331
6332 public:
6333 INSTRUCTION_HEADER(OsrValue)
6334 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)...); }
6335
6336 ptrdiff_t frameOffset() const { return frameOffset_; }
6337
6338 MOsrEntry* entry() { return getOperand(0)->toOsrEntry(); }
6339
6340 AliasSet getAliasSet() const override { return AliasSet::None(); }
6341};
6342
6343// MIR representation of a JSObject scope chain pointer on the OSR
6344// BaselineFrame. The pointer is indexed off of OsrFrameReg.
6345class MOsrEnvironmentChain : public MUnaryInstruction,
6346 public NoTypePolicy::Data {
6347 private:
6348 explicit MOsrEnvironmentChain(MOsrEntry* entry)
6349 : MUnaryInstruction(classOpcode, entry) {
6350 setResultType(MIRType::Object);
6351 }
6352
6353 public:
6354 INSTRUCTION_HEADER(OsrEnvironmentChain)
6355 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)...); }
6356
6357 MOsrEntry* entry() { return getOperand(0)->toOsrEntry(); }
6358};
6359
6360// MIR representation of a JSObject ArgumentsObject pointer on the OSR
6361// BaselineFrame. The pointer is indexed off of OsrFrameReg.
6362class MOsrArgumentsObject : public MUnaryInstruction,
6363 public NoTypePolicy::Data {
6364 private:
6365 explicit MOsrArgumentsObject(MOsrEntry* entry)
6366 : MUnaryInstruction(classOpcode, entry) {
6367 setResultType(MIRType::Object);
6368 }
6369
6370 public:
6371 INSTRUCTION_HEADER(OsrArgumentsObject)
6372 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)...); }
6373
6374 MOsrEntry* entry() { return getOperand(0)->toOsrEntry(); }
6375};
6376
6377// MIR representation of the return value on the OSR BaselineFrame.
6378// The Value is indexed off of OsrFrameReg.
6379class MOsrReturnValue : public MUnaryInstruction, public NoTypePolicy::Data {
6380 private:
6381 explicit MOsrReturnValue(MOsrEntry* entry)
6382 : MUnaryInstruction(classOpcode, entry) {
6383 setResultType(MIRType::Value);
6384 }
6385
6386 public:
6387 INSTRUCTION_HEADER(OsrReturnValue)
6388 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)...); }
6389
6390 MOsrEntry* entry() { return getOperand(0)->toOsrEntry(); }
6391};
6392
6393class MBinaryCache : public MBinaryInstruction,
6394 public MixPolicy<BoxPolicy<0>, BoxPolicy<1>>::Data {
6395 explicit MBinaryCache(MDefinition* left, MDefinition* right, MIRType resType)
6396 : MBinaryInstruction(classOpcode, left, right) {
6397 setResultType(resType);
6398 }
6399
6400 public:
6401 INSTRUCTION_HEADER(BinaryCache)
6402 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)...); }
6403};
6404
6405// Check whether we need to fire the interrupt handler (in wasm code).
6406class MWasmInterruptCheck : public MUnaryInstruction,
6407 public NoTypePolicy::Data {
6408 wasm::BytecodeOffset bytecodeOffset_;
6409
6410 MWasmInterruptCheck(MDefinition* instance,
6411 wasm::BytecodeOffset bytecodeOffset)
6412 : MUnaryInstruction(classOpcode, instance),
6413 bytecodeOffset_(bytecodeOffset) {
6414 setGuard();
6415 }
6416
6417 public:
6418 INSTRUCTION_HEADER(WasmInterruptCheck)
6419 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)...); }
6420 NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); }
6421
6422 AliasSet getAliasSet() const override { return AliasSet::None(); }
6423 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
6424};
6425
6426// Directly jumps to the indicated trap, leaving Wasm code and reporting a
6427// runtime error.
6428
6429class MWasmTrap : public MAryControlInstruction<0, 0>,
6430 public NoTypePolicy::Data {
6431 wasm::Trap trap_;
6432 wasm::BytecodeOffset bytecodeOffset_;
6433
6434 explicit MWasmTrap(wasm::Trap trap, wasm::BytecodeOffset bytecodeOffset)
6435 : MAryControlInstruction(classOpcode),
6436 trap_(trap),
6437 bytecodeOffset_(bytecodeOffset) {}
6438
6439 public:
6440 INSTRUCTION_HEADER(WasmTrap)
6441 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)...); }
6442
6443 AliasSet getAliasSet() const override { return AliasSet::None(); }
6444
6445 wasm::Trap trap() const { return trap_; }
6446 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
6447};
6448
6449// Checks if a value is JS_UNINITIALIZED_LEXICAL, bailout out if so, leaving
6450// it to baseline to throw at the correct pc.
6451class MLexicalCheck : public MUnaryInstruction, public BoxPolicy<0>::Data {
6452 explicit MLexicalCheck(MDefinition* input)
6453 : MUnaryInstruction(classOpcode, input) {
6454 setResultType(MIRType::Value);
6455 setMovable();
6456 setGuard();
6457
6458 // If this instruction bails out, we will set a flag to prevent
6459 // lexical checks in this script from being moved.
6460 setBailoutKind(BailoutKind::UninitializedLexical);
6461 }
6462
6463 public:
6464 INSTRUCTION_HEADER(LexicalCheck)
6465 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)...); }
6466
6467 AliasSet getAliasSet() const override { return AliasSet::None(); }
6468
6469 bool congruentTo(const MDefinition* ins) const override {
6470 return congruentIfOperandsEqual(ins);
6471 }
6472};
6473
6474// Unconditionally throw a known error number.
6475class MThrowMsg : public MNullaryInstruction {
6476 const ThrowMsgKind throwMsgKind_;
6477
6478 explicit MThrowMsg(ThrowMsgKind throwMsgKind)
6479 : MNullaryInstruction(classOpcode), throwMsgKind_(throwMsgKind) {
6480 setGuard();
6481 setResultType(MIRType::None);
6482 }
6483
6484 public:
6485 INSTRUCTION_HEADER(ThrowMsg)
6486 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)...); }
6487
6488 ThrowMsgKind throwMsgKind() const { return throwMsgKind_; }
6489
6490 AliasSet getAliasSet() const override {
6491 return AliasSet::Store(AliasSet::ExceptionState);
6492 }
6493};
6494
6495class MGetFirstDollarIndex : public MUnaryInstruction,
6496 public StringPolicy<0>::Data {
6497 explicit MGetFirstDollarIndex(MDefinition* str)
6498 : MUnaryInstruction(classOpcode, str) {
6499 setResultType(MIRType::Int32);
6500
6501 // Codegen assumes string length > 0. Don't allow LICM to move this
6502 // before the .length > 1 check in RegExpReplace in RegExp.js.
6503 MOZ_ASSERT(!isMovable())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isMovable())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isMovable()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!isMovable()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6503); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isMovable()"
")"); do { *((volatile int*)__null) = 6503; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6504 }
6505
6506 public:
6507 INSTRUCTION_HEADER(GetFirstDollarIndex)
6508 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)...); }
6509 NAMED_OPERANDS((0, str))MDefinition* str() const { return getOperand(0); }
6510
6511 AliasSet getAliasSet() const override { return AliasSet::None(); }
6512
6513 MDefinition* foldsTo(TempAllocator& alloc) override;
6514};
6515
6516class MStringReplace : public MTernaryInstruction,
6517 public MixPolicy<StringPolicy<0>, StringPolicy<1>,
6518 StringPolicy<2>>::Data {
6519 private:
6520 bool isFlatReplacement_;
6521
6522 MStringReplace(MDefinition* string, MDefinition* pattern,
6523 MDefinition* replacement)
6524 : MTernaryInstruction(classOpcode, string, pattern, replacement),
6525 isFlatReplacement_(false) {
6526 setMovable();
6527 setResultType(MIRType::String);
6528 }
6529
6530 public:
6531 INSTRUCTION_HEADER(StringReplace)
6532 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)...); }
6533 NAMED_OPERANDS((0, string), (1, pattern), (2, replacement))MDefinition* string() const { return getOperand(0); } MDefinition
* pattern() const { return getOperand(1); } MDefinition* replacement
() const { return getOperand(2); }
6534
6535 void setFlatReplacement() {
6536 MOZ_ASSERT(!isFlatReplacement_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isFlatReplacement_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isFlatReplacement_))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!isFlatReplacement_"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6536); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isFlatReplacement_"
")"); do { *((volatile int*)__null) = 6536; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6537 isFlatReplacement_ = true;
6538 }
6539
6540 bool isFlatReplacement() const { return isFlatReplacement_; }
6541
6542 bool congruentTo(const MDefinition* ins) const override {
6543 if (!ins->isStringReplace()) {
6544 return false;
6545 }
6546 if (isFlatReplacement_ != ins->toStringReplace()->isFlatReplacement()) {
6547 return false;
6548 }
6549 return congruentIfOperandsEqual(ins);
6550 }
6551
6552 AliasSet getAliasSet() const override { return AliasSet::None(); }
6553
6554 [[nodiscard]] bool writeRecoverData(
6555 CompactBufferWriter& writer) const override;
6556 bool canRecoverOnBailout() const override {
6557 if (isFlatReplacement_) {
6558 MOZ_ASSERT(!pattern()->isRegExp())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!pattern()->isRegExp())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!pattern()->isRegExp())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!pattern()->isRegExp()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6558); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!pattern()->isRegExp()"
")"); do { *((volatile int*)__null) = 6558; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6559 return true;
6560 }
6561 return false;
6562 }
6563
6564 bool possiblyCalls() const override { return true; }
6565};
6566
6567class MLambda : public MBinaryInstruction, public SingleObjectPolicy::Data {
6568 MLambda(MDefinition* envChain, MConstant* cst)
6569 : MBinaryInstruction(classOpcode, envChain, cst) {
6570 setResultType(MIRType::Object);
6571 }
6572
6573 public:
6574 INSTRUCTION_HEADER(Lambda)
6575 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)...); }
6576 NAMED_OPERANDS((0, environmentChain))MDefinition* environmentChain() const { return getOperand(0);
}
6577
6578 MConstant* functionOperand() const { return getOperand(1)->toConstant(); }
6579 JSFunction* templateFunction() const {
6580 return &functionOperand()->toObject().as<JSFunction>();
6581 }
6582
6583 [[nodiscard]] bool writeRecoverData(
6584 CompactBufferWriter& writer) const override;
6585 bool canRecoverOnBailout() const override { return true; }
6586};
6587
6588class MFunctionWithProto : public MTernaryInstruction,
6589 public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>,
6590 ObjectPolicy<2>>::Data {
6591 CompilerFunction fun_;
6592
6593 MFunctionWithProto(MDefinition* envChain, MDefinition* prototype,
6594 MConstant* cst)
6595 : MTernaryInstruction(classOpcode, envChain, prototype, cst),
6596 fun_(&cst->toObject().as<JSFunction>()) {
6597 setResultType(MIRType::Object);
6598 }
6599
6600 public:
6601 INSTRUCTION_HEADER(FunctionWithProto)
6602 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)...); }
6603 NAMED_OPERANDS((0, environmentChain), (1, prototype))MDefinition* environmentChain() const { return getOperand(0);
} MDefinition* prototype() const { return getOperand(1); }
6604
6605 MConstant* functionOperand() const { return getOperand(2)->toConstant(); }
6606 JSFunction* function() const { return fun_; }
6607 [[nodiscard]] bool writeRecoverData(
6608 CompactBufferWriter& writer) const override;
6609 bool canRecoverOnBailout() const override { return true; }
6610
6611 bool possiblyCalls() const override { return true; }
6612};
6613
6614class MGetNextEntryForIterator
6615 : public MBinaryInstruction,
6616 public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>>::Data {
6617 public:
6618 enum Mode { Map, Set };
6619
6620 private:
6621 Mode mode_;
6622
6623 explicit MGetNextEntryForIterator(MDefinition* iter, MDefinition* result,
6624 Mode mode)
6625 : MBinaryInstruction(classOpcode, iter, result), mode_(mode) {
6626 setResultType(MIRType::Boolean);
6627 }
6628
6629 public:
6630 INSTRUCTION_HEADER(GetNextEntryForIterator)
6631 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)...); }
6632 NAMED_OPERANDS((0, iter), (1, result))MDefinition* iter() const { return getOperand(0); } MDefinition
* result() const { return getOperand(1); }
6633
6634 Mode mode() const { return mode_; }
6635};
6636
6637// Convert a Double into an IntPtr value for accessing a TypedArray or DataView
6638// element. If the input is non-finite, not an integer, negative, or outside the
6639// IntPtr range, either bails out or produces a value which is known to trigger
6640// an out-of-bounds access (this depends on the supportOOB flag).
6641class MGuardNumberToIntPtrIndex : public MUnaryInstruction,
6642 public DoublePolicy<0>::Data {
6643 // If true, produce an out-of-bounds index for non-IntPtr doubles instead of
6644 // bailing out.
6645 const bool supportOOB_;
6646
6647 MGuardNumberToIntPtrIndex(MDefinition* def, bool supportOOB)
6648 : MUnaryInstruction(classOpcode, def), supportOOB_(supportOOB) {
6649 MOZ_ASSERT(def->type() == MIRType::Double)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(def->type() == MIRType::Double)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(def->type() == MIRType::Double
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"def->type() == MIRType::Double", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "def->type() == MIRType::Double"
")"); do { *((volatile int*)__null) = 6649; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6650 setResultType(MIRType::IntPtr);
6651 setMovable();
6652 if (!supportOOB) {
6653 setGuard();
6654 }
6655 }
6656
6657 public:
6658 INSTRUCTION_HEADER(GuardNumberToIntPtrIndex)
6659 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)...); }
6660
6661 bool supportOOB() const { return supportOOB_; }
6662
6663 MDefinition* foldsTo(TempAllocator& alloc) override;
6664
6665 bool congruentTo(const MDefinition* ins) const override {
6666 if (!ins->isGuardNumberToIntPtrIndex()) {
6667 return false;
6668 }
6669 if (ins->toGuardNumberToIntPtrIndex()->supportOOB() != supportOOB()) {
6670 return false;
6671 }
6672 return congruentIfOperandsEqual(ins);
6673 }
6674
6675 AliasSet getAliasSet() const override { return AliasSet::None(); }
6676
6677 ALLOW_CLONE(MGuardNumberToIntPtrIndex)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MGuardNumberToIntPtrIndex
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6678};
6679
6680// Perform !-operation
6681class MNot : public MUnaryInstruction, public TestPolicy::Data {
6682 bool operandIsNeverNaN_;
6683 TypeDataList observedTypes_;
6684
6685 explicit MNot(MDefinition* input)
6686 : MUnaryInstruction(classOpcode, input), operandIsNeverNaN_(false) {
6687 setResultType(MIRType::Boolean);
6688 setMovable();
6689 }
6690
6691 public:
6692 static MNot* NewInt32(TempAllocator& alloc, MDefinition* input) {
6693 MOZ_ASSERT(input->type() == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(input->type() == MIRType::Int32 || input->type
() == MIRType::Int64)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(input->type() == MIRType::
Int32 || input->type() == MIRType::Int64))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("input->type() == MIRType::Int32 || input->type() == MIRType::Int64"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "input->type() == MIRType::Int32 || input->type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 6694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6694 input->type() == MIRType::Int64)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(input->type() == MIRType::Int32 || input->type
() == MIRType::Int64)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(input->type() == MIRType::
Int32 || input->type() == MIRType::Int64))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("input->type() == MIRType::Int32 || input->type() == MIRType::Int64"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6694); AnnotateMozCrashReason("MOZ_ASSERT" "(" "input->type() == MIRType::Int32 || input->type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 6694; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6695 auto* ins = new (alloc) MNot(input);
6696 ins->setResultType(MIRType::Int32);
6697 return ins;
6698 }
6699
6700 INSTRUCTION_HEADER(Not)
6701 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)...); }
6702
6703 void setObservedTypes(const TypeDataList& observed) {
6704 observedTypes_ = observed;
6705 }
6706 const TypeDataList& observedTypes() const { return observedTypes_; }
6707
6708 MDefinition* foldsTo(TempAllocator& alloc) override;
6709
6710 bool operandIsNeverNaN() const { return operandIsNeverNaN_; }
6711
6712 virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
6713 void collectRangeInfoPreTrunc() override;
6714
6715 void trySpecializeFloat32(TempAllocator& alloc) override;
6716 bool isFloat32Commutative() const override { return true; }
6717#ifdef DEBUG1
6718 bool isConsistentFloat32Use(MUse* use) const override { return true; }
6719#endif
6720 bool congruentTo(const MDefinition* ins) const override {
6721 return congruentIfOperandsEqual(ins);
6722 }
6723 [[nodiscard]] bool writeRecoverData(
6724 CompactBufferWriter& writer) const override;
6725 bool canRecoverOnBailout() const override { return true; }
6726};
6727
6728// Bailout if index + minimum < 0 or index + maximum >= length. The length used
6729// in a bounds check must not be negative, or the wrong result may be computed
6730// (unsigned comparisons may be used).
6731class MBoundsCheck
6732 : public MBinaryInstruction,
6733 public MixPolicy<Int32OrIntPtrPolicy<0>, Int32OrIntPtrPolicy<1>>::Data {
6734 // Range over which to perform the bounds check, may be modified by GVN.
6735 int32_t minimum_;
6736 int32_t maximum_;
6737 bool fallible_;
6738
6739 MBoundsCheck(MDefinition* index, MDefinition* length)
6740 : MBinaryInstruction(classOpcode, index, length),
6741 minimum_(0),
6742 maximum_(0),
6743 fallible_(true) {
6744 setGuard();
6745 setMovable();
6746 MOZ_ASSERT(index->type() == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32 || index->type
() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32 || index->type() == MIRType::IntPtr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 6747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6747 index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32 || index->type
() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32 || index->type() == MIRType::IntPtr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6747); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 6747; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6748 MOZ_ASSERT(index->type() == length->type())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == length->type())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(index->type() == length->type()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("index->type() == length->type()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6748); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == length->type()"
")"); do { *((volatile int*)__null) = 6748; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6749
6750 // Returns the checked index.
6751 setResultType(index->type());
6752 }
6753
6754 public:
6755 INSTRUCTION_HEADER(BoundsCheck)
6756 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)...); }
6757 NAMED_OPERANDS((0, index), (1, length))MDefinition* index() const { return getOperand(0); } MDefinition
* length() const { return getOperand(1); }
6758
6759 int32_t minimum() const { return minimum_; }
6760 void setMinimum(int32_t n) {
6761 MOZ_ASSERT(fallible_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fallible_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(fallible_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("fallible_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6761); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fallible_" ")"
); do { *((volatile int*)__null) = 6761; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6762 minimum_ = n;
6763 }
6764 int32_t maximum() const { return maximum_; }
6765 void setMaximum(int32_t n) {
6766 MOZ_ASSERT(fallible_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(fallible_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(fallible_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("fallible_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6766); AnnotateMozCrashReason("MOZ_ASSERT" "(" "fallible_" ")"
); do { *((volatile int*)__null) = 6766; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6767 maximum_ = n;
6768 }
6769 MDefinition* foldsTo(TempAllocator& alloc) override;
6770 bool congruentTo(const MDefinition* ins) const override {
6771 if (!ins->isBoundsCheck()) {
6772 return false;
6773 }
6774 const MBoundsCheck* other = ins->toBoundsCheck();
6775 if (minimum() != other->minimum() || maximum() != other->maximum()) {
6776 return false;
6777 }
6778 if (fallible() != other->fallible()) {
6779 return false;
6780 }
6781 return congruentIfOperandsEqual(other);
6782 }
6783 virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
6784 void computeRange(TempAllocator& alloc) override;
6785 bool fallible() const { return fallible_; }
6786 void collectRangeInfoPreTrunc() override;
6787
6788 ALLOW_CLONE(MBoundsCheck)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MBoundsCheck
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6789};
6790
6791// Bailout if index < minimum.
6792class MBoundsCheckLower : public MUnaryInstruction,
6793 public UnboxedInt32Policy<0>::Data {
6794 int32_t minimum_;
6795 bool fallible_;
6796
6797 explicit MBoundsCheckLower(MDefinition* index)
6798 : MUnaryInstruction(classOpcode, index), minimum_(0), fallible_(true) {
6799 setGuard();
6800 setMovable();
6801 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6801); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 6801; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6802 }
6803
6804 public:
6805 INSTRUCTION_HEADER(BoundsCheckLower)
6806 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)...); }
6807 NAMED_OPERANDS((0, index))MDefinition* index() const { return getOperand(0); }
6808
6809 int32_t minimum() const { return minimum_; }
6810 void setMinimum(int32_t n) { minimum_ = n; }
6811 AliasSet getAliasSet() const override { return AliasSet::None(); }
6812 bool fallible() const { return fallible_; }
6813 void collectRangeInfoPreTrunc() override;
6814};
6815
6816class MSpectreMaskIndex
6817 : public MBinaryInstruction,
6818 public MixPolicy<Int32OrIntPtrPolicy<0>, Int32OrIntPtrPolicy<1>>::Data {
6819 MSpectreMaskIndex(MDefinition* index, MDefinition* length)
6820 : MBinaryInstruction(classOpcode, index, length) {
6821 // Note: this instruction does not need setGuard(): if there are no uses
6822 // it's fine for DCE to eliminate this instruction.
6823 setMovable();
6824 MOZ_ASSERT(index->type() == MIRType::Int32 ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32 || index->type
() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32 || index->type() == MIRType::IntPtr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 6825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
6825 index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32 || index->type
() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32 || index->type() == MIRType::IntPtr))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32 || index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 6825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6826 MOZ_ASSERT(index->type() == length->type())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == length->type())>::isValid,
"invalid assertion condition"); if ((__builtin_expect(!!(!(!
!(index->type() == length->type()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("index->type() == length->type()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6826); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == length->type()"
")"); do { *((volatile int*)__null) = 6826; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6827
6828 // Returns the masked index.
6829 setResultType(index->type());
6830 }
6831
6832 public:
6833 INSTRUCTION_HEADER(SpectreMaskIndex)
6834 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)...); }
6835 NAMED_OPERANDS((0, index), (1, length))MDefinition* index() const { return getOperand(0); } MDefinition
* length() const { return getOperand(1); }
6836
6837 bool congruentTo(const MDefinition* ins) const override {
6838 return congruentIfOperandsEqual(ins);
6839 }
6840 virtual AliasSet getAliasSet() const override { return AliasSet::None(); }
6841 void computeRange(TempAllocator& alloc) override;
6842
6843 ALLOW_CLONE(MSpectreMaskIndex)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MSpectreMaskIndex
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6844};
6845
6846// Load a value from a dense array's element vector. Bails out if the element is
6847// a hole.
6848class MLoadElement : public MBinaryInstruction, public NoTypePolicy::Data {
6849 MLoadElement(MDefinition* elements, MDefinition* index)
6850 : MBinaryInstruction(classOpcode, elements, index) {
6851 // Uses may be optimized away based on this instruction's result
6852 // type. This means it's invalid to DCE this instruction, as we
6853 // have to invalidate when we read a hole.
6854 setGuard();
6855 setResultType(MIRType::Value);
6856 setMovable();
6857 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6857); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 6857; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6858 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6858); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 6858; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6859 }
6860
6861 public:
6862 INSTRUCTION_HEADER(LoadElement)
6863 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)...); }
6864 NAMED_OPERANDS((0, elements), (1, index))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); }
6865
6866 bool congruentTo(const MDefinition* ins) const override {
6867 return congruentIfOperandsEqual(ins);
6868 }
6869 AliasType mightAlias(const MDefinition* store) const override;
6870 MDefinition* foldsTo(TempAllocator& alloc) override;
6871 AliasSet getAliasSet() const override {
6872 return AliasSet::Load(AliasSet::Element);
6873 }
6874
6875 ALLOW_CLONE(MLoadElement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadElement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6876};
6877
6878class MLoadElementAndUnbox : public MBinaryInstruction,
6879 public NoTypePolicy::Data {
6880 MUnbox::Mode mode_;
6881
6882 MLoadElementAndUnbox(MDefinition* elements, MDefinition* index,
6883 MUnbox::Mode mode, MIRType type)
6884 : MBinaryInstruction(classOpcode, elements, index), mode_(mode) {
6885 setResultType(type);
6886 setMovable();
6887 if (mode_ == MUnbox::Fallible) {
6888 setGuard();
6889 }
6890 }
6891
6892 public:
6893 INSTRUCTION_HEADER(LoadElementAndUnbox)
6894 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)...); }
6895 NAMED_OPERANDS((0, elements), (1, index))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); }
6896
6897 MUnbox::Mode mode() const { return mode_; }
6898 bool fallible() const { return mode_ != MUnbox::Infallible; }
6899
6900 bool congruentTo(const MDefinition* ins) const override {
6901 if (!ins->isLoadElementAndUnbox() ||
6902 mode() != ins->toLoadElementAndUnbox()->mode()) {
6903 return false;
6904 }
6905 return congruentIfOperandsEqual(ins);
6906 }
6907
6908 AliasSet getAliasSet() const override {
6909 return AliasSet::Load(AliasSet::Element);
6910 }
6911
6912 ALLOW_CLONE(MLoadElementAndUnbox)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadElementAndUnbox
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
;
6913};
6914
6915// Load a value from the elements vector of a native object. If the index is
6916// out-of-bounds, or the indexed slot has a hole, undefined is returned instead.
6917class MLoadElementHole : public MTernaryInstruction, public NoTypePolicy::Data {
6918 bool needsNegativeIntCheck_ = true;
6919
6920 MLoadElementHole(MDefinition* elements, MDefinition* index,
6921 MDefinition* initLength)
6922 : MTernaryInstruction(classOpcode, elements, index, initLength) {
6923 setResultType(MIRType::Value);
6924 setMovable();
6925
6926 // Set the guard flag to make sure we bail when we see a negative
6927 // index. We can clear this flag (and needsNegativeIntCheck_) in
6928 // collectRangeInfoPreTrunc.
6929 setGuard();
6930
6931 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6931); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 6931; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6932 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6932); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 6932; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6933 MOZ_ASSERT(initLength->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initLength->type() == MIRType::Int32)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(initLength->type() == MIRType::Int32))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("initLength->type() == MIRType::Int32"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6933); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initLength->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 6933; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6934 }
6935
6936 public:
6937 INSTRUCTION_HEADER(LoadElementHole)
6938 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)...); }
6939 NAMED_OPERANDS((0, elements), (1, index), (2, initLength))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* initLength
() const { return getOperand(2); }
6940
6941 bool needsNegativeIntCheck() const { return needsNegativeIntCheck_; }
6942 bool congruentTo(const MDefinition* ins) const override {
6943 if (!ins->isLoadElementHole()) {
6944 return false;
6945 }
6946 const MLoadElementHole* other = ins->toLoadElementHole();
6947 if (needsNegativeIntCheck() != other->needsNegativeIntCheck()) {
6948 return false;
6949 }
6950 return congruentIfOperandsEqual(other);
6951 }
6952 AliasSet getAliasSet() const override {
6953 return AliasSet::Load(AliasSet::Element);
6954 }
6955 void collectRangeInfoPreTrunc() override;
6956
6957 ALLOW_CLONE(MLoadElementHole)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadElementHole
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
6958};
6959
6960// Store a value to a dense array slots vector.
6961class MStoreElement : public MTernaryInstruction,
6962 public NoFloatPolicy<2>::Data {
6963 bool needsHoleCheck_;
6964 bool needsBarrier_;
6965
6966 MStoreElement(MDefinition* elements, MDefinition* index, MDefinition* value,
6967 bool needsHoleCheck, bool needsBarrier)
6968 : MTernaryInstruction(classOpcode, elements, index, value) {
6969 needsHoleCheck_ = needsHoleCheck;
6970 needsBarrier_ = needsBarrier;
6971 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6971); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 6971; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6972 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6972); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 6972; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6973 MOZ_ASSERT(value->type() != MIRType::MagicHole)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(value->type() != MIRType::MagicHole)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(value->type() != MIRType::MagicHole))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("value->type() != MIRType::MagicHole"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 6973); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::MagicHole"
")"); do { *((volatile int*)__null) = 6973; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
6974 }
6975
6976 public:
6977 INSTRUCTION_HEADER(StoreElement)
6978 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)...); }
6979 NAMED_OPERANDS((0, elements), (1, index), (2, value))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
6980
6981 static MStoreElement* NewUnbarriered(TempAllocator& alloc,
6982 MDefinition* elements,
6983 MDefinition* index, MDefinition* value,
6984 bool needsHoleCheck) {
6985 return new (alloc)
6986 MStoreElement(elements, index, value, needsHoleCheck, false);
6987 }
6988
6989 static MStoreElement* NewBarriered(TempAllocator& alloc,
6990 MDefinition* elements, MDefinition* index,
6991 MDefinition* value, bool needsHoleCheck) {
6992 return new (alloc)
6993 MStoreElement(elements, index, value, needsHoleCheck, true);
6994 }
6995
6996 AliasSet getAliasSet() const override {
6997 return AliasSet::Store(AliasSet::Element);
6998 }
6999 bool needsBarrier() const { return needsBarrier_; }
7000 bool needsHoleCheck() const { return needsHoleCheck_; }
7001 bool fallible() const { return needsHoleCheck(); }
7002
7003 ALLOW_CLONE(MStoreElement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreElement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7004};
7005
7006// Stores MagicValue(JS_ELEMENTS_HOLE) and marks the elements as non-packed.
7007class MStoreHoleValueElement : public MBinaryInstruction,
7008 public NoTypePolicy::Data {
7009 MStoreHoleValueElement(MDefinition* elements, MDefinition* index)
7010 : MBinaryInstruction(classOpcode, elements, index) {
7011 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7011); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7011; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7012 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7012); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 7012; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7013 }
7014
7015 public:
7016 INSTRUCTION_HEADER(StoreHoleValueElement)
7017 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)...); }
7018 NAMED_OPERANDS((0, elements), (1, index))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); }
7019
7020 AliasSet getAliasSet() const override {
7021 return AliasSet::Store(AliasSet::Element | AliasSet::ObjectFields);
7022 }
7023
7024 ALLOW_CLONE(MStoreHoleValueElement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreHoleValueElement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7025};
7026
7027// Like MStoreElement, but also supports index == initialized length. The
7028// downside is that we cannot hoist the elements vector and bounds check, since
7029// this instruction may update the (initialized) length and reallocate the
7030// elements vector.
7031class MStoreElementHole
7032 : public MQuaternaryInstruction,
7033 public MixPolicy<SingleObjectPolicy, NoFloatPolicy<3>>::Data {
7034 MStoreElementHole(MDefinition* object, MDefinition* elements,
7035 MDefinition* index, MDefinition* value)
7036 : MQuaternaryInstruction(classOpcode, object, elements, index, value) {
7037 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7037); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7037; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7038 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 7038; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7039 MOZ_ASSERT(value->type() != MIRType::MagicHole)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(value->type() != MIRType::MagicHole)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(value->type() != MIRType::MagicHole))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("value->type() != MIRType::MagicHole"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7039); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::MagicHole"
")"); do { *((volatile int*)__null) = 7039; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7040 }
7041
7042 public:
7043 INSTRUCTION_HEADER(StoreElementHole)
7044 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)...); }
7045 NAMED_OPERANDS((0, object), (1, elements), (2, index), (3, value))MDefinition* object() const { return getOperand(0); } MDefinition
* elements() const { return getOperand(1); } MDefinition* index
() const { return getOperand(2); } MDefinition* value() const
{ return getOperand(3); }
7046
7047 AliasSet getAliasSet() const override {
7048 // StoreElementHole can update the initialized length, the array length
7049 // or reallocate obj->elements.
7050 return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
7051 }
7052
7053 ALLOW_CLONE(MStoreElementHole)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreElementHole
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7054};
7055
7056// Array.prototype.pop or Array.prototype.shift on a dense array.
7057class MArrayPopShift : public MUnaryInstruction,
7058 public SingleObjectPolicy::Data {
7059 public:
7060 enum Mode { Pop, Shift };
7061
7062 private:
7063 Mode mode_;
7064
7065 MArrayPopShift(MDefinition* object, Mode mode)
7066 : MUnaryInstruction(classOpcode, object), mode_(mode) {
7067 setResultType(MIRType::Value);
7068 }
7069
7070 public:
7071 INSTRUCTION_HEADER(ArrayPopShift)
7072 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)...); }
7073 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
7074
7075 bool mode() const { return mode_; }
7076 AliasSet getAliasSet() const override {
7077 return AliasSet::Store(AliasSet::ObjectFields | AliasSet::Element);
7078 }
7079
7080 ALLOW_CLONE(MArrayPopShift)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MArrayPopShift
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7081};
7082
7083// Load an unboxed scalar value from an array buffer view or other object.
7084class MLoadUnboxedScalar : public MBinaryInstruction,
7085 public NoTypePolicy::Data {
7086 int32_t offsetAdjustment_ = 0;
7087 Scalar::Type storageType_;
7088 MemoryBarrierRequirement requiresBarrier_;
7089
7090 MLoadUnboxedScalar(MDefinition* elements, MDefinition* index,
7091 Scalar::Type storageType,
7092 MemoryBarrierRequirement requiresBarrier =
7093 MemoryBarrierRequirement::NotRequired)
7094 : MBinaryInstruction(classOpcode, elements, index),
7095 storageType_(storageType),
7096 requiresBarrier_(requiresBarrier) {
7097 setResultType(MIRType::Value);
7098 if (requiresBarrier_ == MemoryBarrierRequirement::Required) {
7099 setGuard(); // Not removable or movable
7100 } else {
7101 setMovable();
7102 }
7103 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7103); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7103; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7104 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7104); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7104; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7105 MOZ_ASSERT(storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storageType >= 0 && storageType < Scalar
::MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(storageType >= 0 &&
storageType < Scalar::MaxTypedArrayViewType))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7105); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7105; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7106 }
7107
7108 public:
7109 INSTRUCTION_HEADER(LoadUnboxedScalar)
7110 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)...); }
7111 NAMED_OPERANDS((0, elements), (1, index))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); }
7112
7113 Scalar::Type storageType() const { return storageType_; }
7114 bool fallible() const {
7115 // Bailout if the result does not fit in an int32.
7116 return storageType_ == Scalar::Uint32 && type() == MIRType::Int32;
7117 }
7118 auto requiresMemoryBarrier() const { return requiresBarrier_; }
7119 int32_t offsetAdjustment() const { return offsetAdjustment_; }
7120 void setOffsetAdjustment(int32_t offsetAdjustment) {
7121 offsetAdjustment_ = offsetAdjustment;
7122 }
7123 AliasSet getAliasSet() const override {
7124 // When a barrier is needed make the instruction effectful by
7125 // giving it a "store" effect.
7126 if (requiresBarrier_ == MemoryBarrierRequirement::Required) {
7127 return AliasSet::Store(AliasSet::UnboxedElement);
7128 }
7129 return AliasSet::Load(AliasSet::UnboxedElement);
7130 }
7131
7132 bool congruentTo(const MDefinition* ins) const override {
7133 if (requiresBarrier_ == MemoryBarrierRequirement::Required) {
7134 return false;
7135 }
7136 if (!ins->isLoadUnboxedScalar()) {
7137 return false;
7138 }
7139 const MLoadUnboxedScalar* other = ins->toLoadUnboxedScalar();
7140 if (storageType_ != other->storageType_) {
7141 return false;
7142 }
7143 if (offsetAdjustment() != other->offsetAdjustment()) {
7144 return false;
7145 }
7146 return congruentIfOperandsEqual(other);
7147 }
7148
7149#ifdef JS_JITSPEW1
7150 void printOpcode(GenericPrinter& out) const override;
7151#endif
7152
7153 void computeRange(TempAllocator& alloc) override;
7154
7155 bool canProduceFloat32() const override {
7156 return storageType_ == Scalar::Float32;
7157 }
7158
7159 ALLOW_CLONE(MLoadUnboxedScalar)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadUnboxedScalar
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7160};
7161
7162// Load an unboxed scalar value from a dataview object.
7163class MLoadDataViewElement : public MTernaryInstruction,
7164 public NoTypePolicy::Data {
7165 Scalar::Type storageType_;
7166
7167 MLoadDataViewElement(MDefinition* elements, MDefinition* index,
7168 MDefinition* littleEndian, Scalar::Type storageType)
7169 : MTernaryInstruction(classOpcode, elements, index, littleEndian),
7170 storageType_(storageType) {
7171 setResultType(MIRType::Value);
7172 setMovable();
7173 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7173); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7173; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7174 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7174); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7174; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7175 MOZ_ASSERT(littleEndian->type() == MIRType::Boolean)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(littleEndian->type() == MIRType::Boolean)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(littleEndian->type() == MIRType::Boolean))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("littleEndian->type() == MIRType::Boolean"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7175); AnnotateMozCrashReason("MOZ_ASSERT" "(" "littleEndian->type() == MIRType::Boolean"
")"); do { *((volatile int*)__null) = 7175; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7176 MOZ_ASSERT(storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storageType >= 0 && storageType < Scalar
::MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(storageType >= 0 &&
storageType < Scalar::MaxTypedArrayViewType))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7176); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7176; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7177 MOZ_ASSERT(Scalar::byteSize(storageType) > 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Scalar::byteSize(storageType) > 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Scalar::byteSize(storageType
) > 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("Scalar::byteSize(storageType) > 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7177); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Scalar::byteSize(storageType) > 1"
")"); do { *((volatile int*)__null) = 7177; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7178 }
7179
7180 public:
7181 INSTRUCTION_HEADER(LoadDataViewElement)
7182 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)...); }
7183 NAMED_OPERANDS((0, elements), (1, index), (2, littleEndian))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* littleEndian
() const { return getOperand(2); }
7184
7185 Scalar::Type storageType() const { return storageType_; }
7186 bool fallible() const {
7187 // Bailout if the result does not fit in an int32.
7188 return storageType_ == Scalar::Uint32 && type() == MIRType::Int32;
7189 }
7190 AliasSet getAliasSet() const override {
7191 return AliasSet::Load(AliasSet::UnboxedElement);
7192 }
7193
7194 bool congruentTo(const MDefinition* ins) const override {
7195 if (!ins->isLoadDataViewElement()) {
7196 return false;
7197 }
7198 const MLoadDataViewElement* other = ins->toLoadDataViewElement();
7199 if (storageType_ != other->storageType_) {
7200 return false;
7201 }
7202 return congruentIfOperandsEqual(other);
7203 }
7204
7205#ifdef JS_JITSPEW1
7206 void printOpcode(GenericPrinter& out) const override;
7207#endif
7208
7209 void computeRange(TempAllocator& alloc) override;
7210
7211 bool canProduceFloat32() const override {
7212 return storageType_ == Scalar::Float32;
7213 }
7214
7215 ALLOW_CLONE(MLoadDataViewElement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadDataViewElement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7216};
7217
7218// Load a value from a typed array. Out-of-bounds accesses are handled in-line.
7219class MLoadTypedArrayElementHole : public MTernaryInstruction,
7220 public NoTypePolicy::Data {
7221 Scalar::Type arrayType_;
7222 bool forceDouble_;
7223
7224 MLoadTypedArrayElementHole(MDefinition* elements, MDefinition* index,
7225 MDefinition* length, Scalar::Type arrayType,
7226 bool forceDouble)
7227 : MTernaryInstruction(classOpcode, elements, index, length),
7228 arrayType_(arrayType),
7229 forceDouble_(forceDouble) {
7230 setResultType(MIRType::Value);
7231 setMovable();
7232 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7232); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7232; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7233 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7233); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7233; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7234 MOZ_ASSERT(length->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(length->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(length->type() == MIRType
::IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("length->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7234); AnnotateMozCrashReason("MOZ_ASSERT" "(" "length->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7234; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7235 MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(arrayType >= 0 && arrayType < Scalar::
MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(arrayType >= 0 &&
arrayType < Scalar::MaxTypedArrayViewType))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7235); AnnotateMozCrashReason("MOZ_ASSERT" "(" "arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7235; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7236 }
7237
7238 public:
7239 INSTRUCTION_HEADER(LoadTypedArrayElementHole)
7240 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)...); }
7241 NAMED_OPERANDS((0, elements), (1, index), (2, length))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* length
() const { return getOperand(2); }
7242
7243 Scalar::Type arrayType() const { return arrayType_; }
7244 bool forceDouble() const { return forceDouble_; }
7245 bool fallible() const {
7246 return arrayType_ == Scalar::Uint32 && !forceDouble_;
7247 }
7248 bool congruentTo(const MDefinition* ins) const override {
7249 if (!ins->isLoadTypedArrayElementHole()) {
7250 return false;
7251 }
7252 const MLoadTypedArrayElementHole* other =
7253 ins->toLoadTypedArrayElementHole();
7254 if (arrayType() != other->arrayType()) {
7255 return false;
7256 }
7257 if (forceDouble() != other->forceDouble()) {
7258 return false;
7259 }
7260 return congruentIfOperandsEqual(other);
7261 }
7262 AliasSet getAliasSet() const override {
7263 return AliasSet::Load(AliasSet::UnboxedElement);
7264 }
7265 bool canProduceFloat32() const override {
7266 return arrayType_ == Scalar::Float32;
7267 }
7268
7269 ALLOW_CLONE(MLoadTypedArrayElementHole)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadTypedArrayElementHole
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7270};
7271
7272// Base class for MIR ops that write unboxed scalar values.
7273class StoreUnboxedScalarBase {
7274 Scalar::Type writeType_;
7275
7276 protected:
7277 explicit StoreUnboxedScalarBase(Scalar::Type writeType)
7278 : writeType_(writeType) {
7279 MOZ_ASSERT(isIntegerWrite() || isFloatWrite() || isBigIntWrite())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isIntegerWrite() || isFloatWrite() || isBigIntWrite(
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(isIntegerWrite() || isFloatWrite() || isBigIntWrite(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("isIntegerWrite() || isFloatWrite() || isBigIntWrite()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isIntegerWrite() || isFloatWrite() || isBigIntWrite()"
")"); do { *((volatile int*)__null) = 7279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7280 }
7281
7282 public:
7283 Scalar::Type writeType() const { return writeType_; }
7284 bool isByteWrite() const {
7285 return writeType_ == Scalar::Int8 || writeType_ == Scalar::Uint8 ||
7286 writeType_ == Scalar::Uint8Clamped;
7287 }
7288 bool isIntegerWrite() const {
7289 return isByteWrite() || writeType_ == Scalar::Int16 ||
7290 writeType_ == Scalar::Uint16 || writeType_ == Scalar::Int32 ||
7291 writeType_ == Scalar::Uint32;
7292 }
7293 bool isFloatWrite() const {
7294 return writeType_ == Scalar::Float32 || writeType_ == Scalar::Float64;
7295 }
7296 bool isBigIntWrite() const { return Scalar::isBigIntType(writeType_); }
7297};
7298
7299// Store an unboxed scalar value to an array buffer view or other object.
7300class MStoreUnboxedScalar : public MTernaryInstruction,
7301 public StoreUnboxedScalarBase,
7302 public StoreUnboxedScalarPolicy::Data {
7303 MemoryBarrierRequirement requiresBarrier_;
7304
7305 MStoreUnboxedScalar(MDefinition* elements, MDefinition* index,
7306 MDefinition* value, Scalar::Type storageType,
7307 MemoryBarrierRequirement requiresBarrier =
7308 MemoryBarrierRequirement::NotRequired)
7309 : MTernaryInstruction(classOpcode, elements, index, value),
7310 StoreUnboxedScalarBase(storageType),
7311 requiresBarrier_(requiresBarrier) {
7312 if (requiresBarrier_ == MemoryBarrierRequirement::Required) {
7313 setGuard(); // Not removable or movable
7314 }
7315 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7315); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7315; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7316 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7316); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7316; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7317 MOZ_ASSERT(storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storageType >= 0 && storageType < Scalar
::MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(storageType >= 0 &&
storageType < Scalar::MaxTypedArrayViewType))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7317); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7317; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7318 }
7319
7320 public:
7321 INSTRUCTION_HEADER(StoreUnboxedScalar)
7322 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)...); }
7323 NAMED_OPERANDS((0, elements), (1, index), (2, value))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
7324
7325 AliasSet getAliasSet() const override {
7326 return AliasSet::Store(AliasSet::UnboxedElement);
7327 }
7328 auto requiresMemoryBarrier() const { return requiresBarrier_; }
7329 TruncateKind operandTruncateKind(size_t index) const override;
7330
7331 bool canConsumeFloat32(MUse* use) const override {
7332 return use == getUseFor(2) && writeType() == Scalar::Float32;
7333 }
7334
7335 ALLOW_CLONE(MStoreUnboxedScalar)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreUnboxedScalar
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7336};
7337
7338// Store an unboxed scalar value to a dataview object.
7339class MStoreDataViewElement : public MQuaternaryInstruction,
7340 public StoreUnboxedScalarBase,
7341 public StoreDataViewElementPolicy::Data {
7342 MStoreDataViewElement(MDefinition* elements, MDefinition* index,
7343 MDefinition* value, MDefinition* littleEndian,
7344 Scalar::Type storageType)
7345 : MQuaternaryInstruction(classOpcode, elements, index, value,
7346 littleEndian),
7347 StoreUnboxedScalarBase(storageType) {
7348 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7348); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7348; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7349 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7349); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7349; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7350 MOZ_ASSERT(storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(storageType >= 0 && storageType < Scalar
::MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(storageType >= 0 &&
storageType < Scalar::MaxTypedArrayViewType))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7350); AnnotateMozCrashReason("MOZ_ASSERT" "(" "storageType >= 0 && storageType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7350; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7351 MOZ_ASSERT(Scalar::byteSize(storageType) > 1)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(Scalar::byteSize(storageType) > 1)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(Scalar::byteSize(storageType
) > 1))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("Scalar::byteSize(storageType) > 1", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7351); AnnotateMozCrashReason("MOZ_ASSERT" "(" "Scalar::byteSize(storageType) > 1"
")"); do { *((volatile int*)__null) = 7351; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7352 }
7353
7354 public:
7355 INSTRUCTION_HEADER(StoreDataViewElement)
7356 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)...); }
7357 NAMED_OPERANDS((0, elements), (1, index), (2, value), (3, littleEndian))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); } MDefinition* littleEndian()
const { return getOperand(3); }
7358
7359 AliasSet getAliasSet() const override {
7360 return AliasSet::Store(AliasSet::UnboxedElement);
7361 }
7362 TruncateKind operandTruncateKind(size_t index) const override;
7363
7364 bool canConsumeFloat32(MUse* use) const override {
7365 return use == getUseFor(2) && writeType() == Scalar::Float32;
7366 }
7367
7368 ALLOW_CLONE(MStoreDataViewElement)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreDataViewElement
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7369};
7370
7371class MStoreTypedArrayElementHole : public MQuaternaryInstruction,
7372 public StoreUnboxedScalarBase,
7373 public StoreTypedArrayHolePolicy::Data {
7374 MStoreTypedArrayElementHole(MDefinition* elements, MDefinition* length,
7375 MDefinition* index, MDefinition* value,
7376 Scalar::Type arrayType)
7377 : MQuaternaryInstruction(classOpcode, elements, length, index, value),
7378 StoreUnboxedScalarBase(arrayType) {
7379 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7379); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 7379; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7380 MOZ_ASSERT(length->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(length->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(length->type() == MIRType
::IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("length->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7380); AnnotateMozCrashReason("MOZ_ASSERT" "(" "length->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7380; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7381 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7381); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 7381; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7382 MOZ_ASSERT(arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(arrayType >= 0 && arrayType < Scalar::
MaxTypedArrayViewType)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(arrayType >= 0 &&
arrayType < Scalar::MaxTypedArrayViewType))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7382); AnnotateMozCrashReason("MOZ_ASSERT" "(" "arrayType >= 0 && arrayType < Scalar::MaxTypedArrayViewType"
")"); do { *((volatile int*)__null) = 7382; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7383 }
7384
7385 public:
7386 INSTRUCTION_HEADER(StoreTypedArrayElementHole)
7387 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)...); }
7388 NAMED_OPERANDS((0, elements), (1, length), (2, index), (3, value))MDefinition* elements() const { return getOperand(0); } MDefinition
* length() const { return getOperand(1); } MDefinition* index
() const { return getOperand(2); } MDefinition* value() const
{ return getOperand(3); }
7389
7390 Scalar::Type arrayType() const { return writeType(); }
7391 AliasSet getAliasSet() const override {
7392 return AliasSet::Store(AliasSet::UnboxedElement);
7393 }
7394 TruncateKind operandTruncateKind(size_t index) const override;
7395
7396 bool canConsumeFloat32(MUse* use) const override {
7397 return use == getUseFor(3) && arrayType() == Scalar::Float32;
7398 }
7399
7400 ALLOW_CLONE(MStoreTypedArrayElementHole)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreTypedArrayElementHole
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7401};
7402
7403// Compute an "effective address", i.e., a compound computation of the form:
7404// base + index * scale + displacement
7405class MEffectiveAddress : public MBinaryInstruction, public NoTypePolicy::Data {
7406 MEffectiveAddress(MDefinition* base, MDefinition* index, Scale scale,
7407 int32_t displacement)
7408 : MBinaryInstruction(classOpcode, base, index),
7409 scale_(scale),
7410 displacement_(displacement) {
7411 MOZ_ASSERT(base->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(base->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(base->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("base->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7411); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 7411; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7412 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7412); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 7412; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7413 setMovable();
7414 setResultType(MIRType::Int32);
7415 }
7416
7417 Scale scale_;
7418 int32_t displacement_;
7419
7420 public:
7421 INSTRUCTION_HEADER(EffectiveAddress)
7422 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)...); }
7423
7424 MDefinition* base() const { return lhs(); }
7425 MDefinition* index() const { return rhs(); }
7426 Scale scale() const { return scale_; }
7427 int32_t displacement() const { return displacement_; }
7428
7429 ALLOW_CLONE(MEffectiveAddress)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MEffectiveAddress
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7430};
7431
7432// Clamp input to range [0, 255] for Uint8ClampedArray.
7433class MClampToUint8 : public MUnaryInstruction, public ClampPolicy::Data {
7434 explicit MClampToUint8(MDefinition* input)
7435 : MUnaryInstruction(classOpcode, input) {
7436 setResultType(MIRType::Int32);
7437 setMovable();
7438 }
7439
7440 public:
7441 INSTRUCTION_HEADER(ClampToUint8)
7442 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)...); }
7443
7444 MDefinition* foldsTo(TempAllocator& alloc) override;
7445
7446 bool congruentTo(const MDefinition* ins) const override {
7447 return congruentIfOperandsEqual(ins);
7448 }
7449 AliasSet getAliasSet() const override { return AliasSet::None(); }
7450 void computeRange(TempAllocator& alloc) override;
7451
7452 ALLOW_CLONE(MClampToUint8)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MClampToUint8
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7453};
7454
7455class MLoadFixedSlot : public MUnaryInstruction,
7456 public SingleObjectPolicy::Data {
7457 size_t slot_;
7458 bool usedAsPropertyKey_ = false;
7459
7460 protected:
7461 MLoadFixedSlot(MDefinition* obj, size_t slot)
7462 : MUnaryInstruction(classOpcode, obj), slot_(slot) {
7463 setResultType(MIRType::Value);
7464 setMovable();
7465 }
7466
7467 public:
7468 INSTRUCTION_HEADER(LoadFixedSlot)
7469 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)...); }
7470 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
7471
7472 size_t slot() const { return slot_; }
7473 bool congruentTo(const MDefinition* ins) const override {
7474 if (!ins->isLoadFixedSlot()) {
7475 return false;
7476 }
7477 if (slot() != ins->toLoadFixedSlot()->slot()) {
7478 return false;
7479 }
7480 return congruentIfOperandsEqual(ins);
7481 }
7482
7483 MDefinition* foldsTo(TempAllocator& alloc) override;
7484
7485 AliasSet getAliasSet() const override {
7486 return AliasSet::Load(AliasSet::FixedSlot);
7487 }
7488
7489 AliasType mightAlias(const MDefinition* store) const override;
7490
7491#ifdef JS_JITSPEW1
7492 void printOpcode(GenericPrinter& out) const override;
7493#endif
7494
7495 void setUsedAsPropertyKey() { usedAsPropertyKey_ = true; }
7496 bool usedAsPropertyKey() const { return usedAsPropertyKey_; }
7497
7498 ALLOW_CLONE(MLoadFixedSlot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadFixedSlot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7499};
7500
7501class MLoadFixedSlotAndUnbox : public MUnaryInstruction,
7502 public SingleObjectPolicy::Data {
7503 size_t slot_;
7504 MUnbox::Mode mode_;
7505 bool usedAsPropertyKey_;
7506
7507 MLoadFixedSlotAndUnbox(MDefinition* obj, size_t slot, MUnbox::Mode mode,
7508 MIRType type, bool usedAsPropertyKey = false)
7509 : MUnaryInstruction(classOpcode, obj),
7510 slot_(slot),
7511 mode_(mode),
7512 usedAsPropertyKey_(usedAsPropertyKey) {
7513 setResultType(type);
7514 setMovable();
7515 if (mode_ == MUnbox::Fallible) {
7516 setGuard();
7517 }
7518 }
7519
7520 public:
7521 INSTRUCTION_HEADER(LoadFixedSlotAndUnbox)
7522 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)...); }
7523 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
7524
7525 size_t slot() const { return slot_; }
7526 MUnbox::Mode mode() const { return mode_; }
7527 bool fallible() const { return mode_ != MUnbox::Infallible; }
7528 bool congruentTo(const MDefinition* ins) const override {
7529 if (!ins->isLoadFixedSlotAndUnbox() ||
7530 slot() != ins->toLoadFixedSlotAndUnbox()->slot() ||
7531 mode() != ins->toLoadFixedSlotAndUnbox()->mode()) {
7532 return false;
7533 }
7534 return congruentIfOperandsEqual(ins);
7535 }
7536
7537 MDefinition* foldsTo(TempAllocator& alloc) override;
7538
7539 AliasSet getAliasSet() const override {
7540 return AliasSet::Load(AliasSet::FixedSlot);
7541 }
7542
7543 AliasType mightAlias(const MDefinition* store) const override;
7544
7545#ifdef JS_JITSPEW1
7546 void printOpcode(GenericPrinter& out) const override;
7547#endif
7548
7549 bool usedAsPropertyKey() const { return usedAsPropertyKey_; }
7550
7551 ALLOW_CLONE(MLoadFixedSlotAndUnbox)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadFixedSlotAndUnbox
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
;
7552};
7553
7554class MLoadDynamicSlotAndUnbox : public MUnaryInstruction,
7555 public NoTypePolicy::Data {
7556 size_t slot_;
7557 MUnbox::Mode mode_;
7558 bool usedAsPropertyKey_ = false;
7559
7560 MLoadDynamicSlotAndUnbox(MDefinition* slots, size_t slot, MUnbox::Mode mode,
7561 MIRType type, bool usedAsPropertyKey = false)
7562 : MUnaryInstruction(classOpcode, slots),
7563 slot_(slot),
7564 mode_(mode),
7565 usedAsPropertyKey_(usedAsPropertyKey) {
7566 setResultType(type);
7567 setMovable();
7568 if (mode_ == MUnbox::Fallible) {
7569 setGuard();
7570 }
7571 }
7572
7573 public:
7574 INSTRUCTION_HEADER(LoadDynamicSlotAndUnbox)
7575 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)...); }
7576 NAMED_OPERANDS((0, slots))MDefinition* slots() const { return getOperand(0); }
7577
7578 size_t slot() const { return slot_; }
7579 MUnbox::Mode mode() const { return mode_; }
7580 bool fallible() const { return mode_ != MUnbox::Infallible; }
7581
7582 bool congruentTo(const MDefinition* ins) const override {
7583 if (!ins->isLoadDynamicSlotAndUnbox() ||
7584 slot() != ins->toLoadDynamicSlotAndUnbox()->slot() ||
7585 mode() != ins->toLoadDynamicSlotAndUnbox()->mode()) {
7586 return false;
7587 }
7588 return congruentIfOperandsEqual(ins);
7589 }
7590
7591 AliasSet getAliasSet() const override {
7592 return AliasSet::Load(AliasSet::DynamicSlot);
7593 }
7594
7595#ifdef JS_JITSPEW1
7596 void printOpcode(GenericPrinter& out) const override;
7597#endif
7598
7599 bool usedAsPropertyKey() const { return usedAsPropertyKey_; }
7600
7601 ALLOW_CLONE(MLoadDynamicSlotAndUnbox)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadDynamicSlotAndUnbox
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
;
7602};
7603
7604class MStoreFixedSlot
7605 : public MBinaryInstruction,
7606 public MixPolicy<SingleObjectPolicy, NoFloatPolicy<1>>::Data {
7607 bool needsBarrier_;
7608 size_t slot_;
7609
7610 MStoreFixedSlot(MDefinition* obj, MDefinition* rval, size_t slot,
7611 bool barrier)
7612 : MBinaryInstruction(classOpcode, obj, rval),
7613 needsBarrier_(barrier),
7614 slot_(slot) {}
7615
7616 public:
7617 INSTRUCTION_HEADER(StoreFixedSlot)
7618 NAMED_OPERANDS((0, object), (1, value))MDefinition* object() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
7619
7620 static MStoreFixedSlot* NewUnbarriered(TempAllocator& alloc, MDefinition* obj,
7621 size_t slot, MDefinition* rval) {
7622 return new (alloc) MStoreFixedSlot(obj, rval, slot, false);
7623 }
7624 static MStoreFixedSlot* NewBarriered(TempAllocator& alloc, MDefinition* obj,
7625 size_t slot, MDefinition* rval) {
7626 return new (alloc) MStoreFixedSlot(obj, rval, slot, true);
7627 }
7628
7629 size_t slot() const { return slot_; }
7630
7631 AliasSet getAliasSet() const override {
7632 return AliasSet::Store(AliasSet::FixedSlot);
7633 }
7634 bool needsBarrier() const { return needsBarrier_; }
7635 void setNeedsBarrier(bool needsBarrier = true) {
7636 needsBarrier_ = needsBarrier;
7637 }
7638
7639#ifdef JS_JITSPEW1
7640 void printOpcode(GenericPrinter& out) const override;
7641#endif
7642
7643 ALLOW_CLONE(MStoreFixedSlot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreFixedSlot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7644};
7645
7646class MGetPropertyCache : public MBinaryInstruction,
7647 public MixPolicy<BoxExceptPolicy<0, MIRType::Object>,
7648 CacheIdPolicy<1>>::Data {
7649 MGetPropertyCache(MDefinition* obj, MDefinition* id)
7650 : MBinaryInstruction(classOpcode, obj, id) {
7651 setResultType(MIRType::Value);
7652 }
7653
7654 public:
7655 INSTRUCTION_HEADER(GetPropertyCache)
7656 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)...); }
7657 NAMED_OPERANDS((0, value), (1, idval))MDefinition* value() const { return getOperand(0); } MDefinition
* idval() const { return getOperand(1); }
7658};
7659
7660class MGetPropSuperCache
7661 : public MTernaryInstruction,
7662 public MixPolicy<ObjectPolicy<0>, BoxExceptPolicy<1, MIRType::Object>,
7663 CacheIdPolicy<2>>::Data {
7664 MGetPropSuperCache(MDefinition* obj, MDefinition* receiver, MDefinition* id)
7665 : MTernaryInstruction(classOpcode, obj, receiver, id) {
7666 setResultType(MIRType::Value);
7667 setGuard();
7668 }
7669
7670 public:
7671 INSTRUCTION_HEADER(GetPropSuperCache)
7672 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)...); }
7673 NAMED_OPERANDS((0, object), (1, receiver), (2, idval))MDefinition* object() const { return getOperand(0); } MDefinition
* receiver() const { return getOperand(1); } MDefinition* idval
() const { return getOperand(2); }
7674};
7675
7676// Guard the object's proto is |expected|.
7677class MGuardProto : public MBinaryInstruction, public SingleObjectPolicy::Data {
7678 MGuardProto(MDefinition* obj, MDefinition* expected)
7679 : MBinaryInstruction(classOpcode, obj, expected) {
7680 MOZ_ASSERT(expected->isConstant() || expected->isNurseryObject())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(expected->isConstant() || expected->isNurseryObject
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(expected->isConstant() || expected->isNurseryObject
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("expected->isConstant() || expected->isNurseryObject()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7680); AnnotateMozCrashReason("MOZ_ASSERT" "(" "expected->isConstant() || expected->isNurseryObject()"
")"); do { *((volatile int*)__null) = 7680; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7681 setGuard();
7682 setMovable();
7683 setResultType(MIRType::Object);
7684 }
7685
7686 public:
7687 INSTRUCTION_HEADER(GuardProto)
7688 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)...); }
7689 NAMED_OPERANDS((0, object), (1, expected))MDefinition* object() const { return getOperand(0); } MDefinition
* expected() const { return getOperand(1); }
7690
7691 bool congruentTo(const MDefinition* ins) const override {
7692 return congruentIfOperandsEqual(ins);
7693 }
7694
7695 AliasSet getAliasSet() const override {
7696 return AliasSet::Load(AliasSet::ObjectFields);
7697 }
7698 AliasType mightAlias(const MDefinition* def) const override {
7699 // These instructions never modify the [[Prototype]].
7700 if (def->isAddAndStoreSlot() || def->isAllocateAndStoreSlot()) {
7701 return AliasType::NoAlias;
7702 }
7703 return AliasType::MayAlias;
7704 }
7705};
7706
7707// Guard the object has no proto.
7708class MGuardNullProto : public MUnaryInstruction,
7709 public SingleObjectPolicy::Data {
7710 explicit MGuardNullProto(MDefinition* obj)
7711 : MUnaryInstruction(classOpcode, obj) {
7712 setGuard();
7713 setMovable();
7714 setResultType(MIRType::Object);
7715 }
7716
7717 public:
7718 INSTRUCTION_HEADER(GuardNullProto)
7719 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)...); }
7720 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
7721
7722 bool congruentTo(const MDefinition* ins) const override {
7723 return congruentIfOperandsEqual(ins);
7724 }
7725 AliasSet getAliasSet() const override {
7726 return AliasSet::Load(AliasSet::ObjectFields);
7727 }
7728 AliasType mightAlias(const MDefinition* def) const override {
7729 // These instructions never modify the [[Prototype]].
7730 if (def->isAddAndStoreSlot() || def->isAllocateAndStoreSlot()) {
7731 return AliasType::NoAlias;
7732 }
7733 return AliasType::MayAlias;
7734 }
7735};
7736
7737// Guard on a specific Value.
7738class MGuardValue : public MUnaryInstruction, public BoxInputsPolicy::Data {
7739 Value expected_;
7740
7741 MGuardValue(MDefinition* val, const Value& expected)
7742 : MUnaryInstruction(classOpcode, val), expected_(expected) {
7743 setGuard();
7744 setMovable();
7745 setResultType(MIRType::Value);
7746 }
7747
7748 public:
7749 INSTRUCTION_HEADER(GuardValue)
7750 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)...); }
7751 NAMED_OPERANDS((0, value))MDefinition* value() const { return getOperand(0); }
7752
7753 Value expected() const { return expected_; }
7754
7755 bool congruentTo(const MDefinition* ins) const override {
7756 if (!ins->isGuardValue()) {
7757 return false;
7758 }
7759 if (expected() != ins->toGuardValue()->expected()) {
7760 return false;
7761 }
7762 return congruentIfOperandsEqual(ins);
7763 }
7764 MDefinition* foldsTo(TempAllocator& alloc) override;
7765 AliasSet getAliasSet() const override { return AliasSet::None(); }
7766};
7767
7768// Guard on function flags
7769class MGuardFunctionFlags : public MUnaryInstruction,
7770 public SingleObjectPolicy::Data {
7771 // At least one of the expected flags must be set, but not necessarily all
7772 // expected flags.
7773 uint16_t expectedFlags_;
7774
7775 // None of the unexpected flags must be set.
7776 uint16_t unexpectedFlags_;
7777
7778 explicit MGuardFunctionFlags(MDefinition* fun, uint16_t expectedFlags,
7779 uint16_t unexpectedFlags)
7780 : MUnaryInstruction(classOpcode, fun),
7781 expectedFlags_(expectedFlags),
7782 unexpectedFlags_(unexpectedFlags) {
7783 MOZ_ASSERT((expectedFlags & unexpectedFlags) == 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((expectedFlags & unexpectedFlags) == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!((expectedFlags & unexpectedFlags) == 0))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("(expectedFlags & unexpectedFlags) == 0"
" (" "Can't guard inconsistent flags" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(expectedFlags & unexpectedFlags) == 0"
") (" "Can't guard inconsistent flags" ")"); do { *((volatile
int*)__null) = 7784; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
7784 "Can't guard inconsistent flags")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((expectedFlags & unexpectedFlags) == 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!((expectedFlags & unexpectedFlags) == 0))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("(expectedFlags & unexpectedFlags) == 0"
" (" "Can't guard inconsistent flags" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7784); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(expectedFlags & unexpectedFlags) == 0"
") (" "Can't guard inconsistent flags" ")"); do { *((volatile
int*)__null) = 7784; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
7785 MOZ_ASSERT((expectedFlags | unexpectedFlags) != 0,do { static_assert( mozilla::detail::AssertionConditionType<
decltype((expectedFlags | unexpectedFlags) != 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!((expectedFlags | unexpectedFlags) != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("(expectedFlags | unexpectedFlags) != 0"
" (" "Can't guard zero flags" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(expectedFlags | unexpectedFlags) != 0"
") (" "Can't guard zero flags" ")"); do { *((volatile int*)__null
) = 7786; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
7786 "Can't guard zero flags")do { static_assert( mozilla::detail::AssertionConditionType<
decltype((expectedFlags | unexpectedFlags) != 0)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!((expectedFlags | unexpectedFlags) != 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("(expectedFlags | unexpectedFlags) != 0"
" (" "Can't guard zero flags" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7786); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(expectedFlags | unexpectedFlags) != 0"
") (" "Can't guard zero flags" ")"); do { *((volatile int*)__null
) = 7786; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
7787 setGuard();
7788 setMovable();
7789 setResultType(MIRType::Object);
7790 }
7791
7792 public:
7793 INSTRUCTION_HEADER(GuardFunctionFlags)
7794 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)...); }
7795 NAMED_OPERANDS((0, function))MDefinition* function() const { return getOperand(0); }
7796
7797 uint16_t expectedFlags() const { return expectedFlags_; };
7798 uint16_t unexpectedFlags() const { return unexpectedFlags_; };
7799
7800 bool congruentTo(const MDefinition* ins) const override {
7801 if (!ins->isGuardFunctionFlags()) {
7802 return false;
7803 }
7804 if (expectedFlags() != ins->toGuardFunctionFlags()->expectedFlags()) {
7805 return false;
7806 }
7807 if (unexpectedFlags() != ins->toGuardFunctionFlags()->unexpectedFlags()) {
7808 return false;
7809 }
7810 return congruentIfOperandsEqual(ins);
7811 }
7812 AliasSet getAliasSet() const override {
7813 return AliasSet::Load(AliasSet::ObjectFields);
7814 }
7815};
7816
7817// Guard on an object's identity, inclusively or exclusively.
7818class MGuardObjectIdentity : public MBinaryInstruction,
7819 public SingleObjectPolicy::Data {
7820 bool bailOnEquality_;
7821
7822 MGuardObjectIdentity(MDefinition* obj, MDefinition* expected,
7823 bool bailOnEquality)
7824 : MBinaryInstruction(classOpcode, obj, expected),
7825 bailOnEquality_(bailOnEquality) {
7826 setGuard();
7827 setMovable();
7828 setResultType(MIRType::Object);
7829 }
7830
7831 public:
7832 INSTRUCTION_HEADER(GuardObjectIdentity)
7833 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)...); }
7834 NAMED_OPERANDS((0, object), (1, expected))MDefinition* object() const { return getOperand(0); } MDefinition
* expected() const { return getOperand(1); }
7835
7836 bool bailOnEquality() const { return bailOnEquality_; }
7837 MDefinition* foldsTo(TempAllocator& alloc) override;
7838 bool congruentTo(const MDefinition* ins) const override {
7839 if (!ins->isGuardObjectIdentity()) {
7840 return false;
7841 }
7842 if (bailOnEquality() != ins->toGuardObjectIdentity()->bailOnEquality()) {
7843 return false;
7844 }
7845 return congruentIfOperandsEqual(ins);
7846 }
7847 AliasSet getAliasSet() const override { return AliasSet::None(); }
7848};
7849
7850// Guard on a specific JSFunction. Used instead of MGuardObjectIdentity,
7851// so we can store some metadata related to the expected function.
7852class MGuardSpecificFunction : public MBinaryInstruction,
7853 public SingleObjectPolicy::Data {
7854 uint16_t nargs_;
7855 FunctionFlags flags_;
7856
7857 MGuardSpecificFunction(MDefinition* obj, MDefinition* expected,
7858 uint16_t nargs, FunctionFlags flags)
7859 : MBinaryInstruction(classOpcode, obj, expected),
7860 nargs_(nargs),
7861 flags_(flags) {
7862 MOZ_ASSERT(expected->isConstant() || expected->isNurseryObject())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(expected->isConstant() || expected->isNurseryObject
())>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(expected->isConstant() || expected->isNurseryObject
()))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("expected->isConstant() || expected->isNurseryObject()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7862); AnnotateMozCrashReason("MOZ_ASSERT" "(" "expected->isConstant() || expected->isNurseryObject()"
")"); do { *((volatile int*)__null) = 7862; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7863 setGuard();
7864 setMovable();
7865 setResultType(MIRType::Object);
7866 }
7867
7868 public:
7869 INSTRUCTION_HEADER(GuardSpecificFunction)
7870 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)...); }
7871 NAMED_OPERANDS((0, function), (1, expected))MDefinition* function() const { return getOperand(0); } MDefinition
* expected() const { return getOperand(1); }
7872
7873 uint16_t nargs() const { return nargs_; }
7874 FunctionFlags flags() const { return flags_; }
7875
7876 MDefinition* foldsTo(TempAllocator& alloc) override;
7877 bool congruentTo(const MDefinition* ins) const override {
7878 if (!ins->isGuardSpecificFunction()) {
7879 return false;
7880 }
7881
7882 auto* other = ins->toGuardSpecificFunction();
7883 if (nargs() != other->nargs() ||
7884 flags().toRaw() != other->flags().toRaw()) {
7885 return false;
7886 }
7887 return congruentIfOperandsEqual(other);
7888 }
7889 AliasSet getAliasSet() const override { return AliasSet::None(); }
7890};
7891
7892class MGuardSpecificSymbol : public MUnaryInstruction,
7893 public SymbolPolicy<0>::Data {
7894 CompilerGCPointer<JS::Symbol*> expected_;
7895
7896 MGuardSpecificSymbol(MDefinition* symbol, JS::Symbol* expected)
7897 : MUnaryInstruction(classOpcode, symbol), expected_(expected) {
7898 setGuard();
7899 setMovable();
7900 setResultType(MIRType::Symbol);
7901 }
7902
7903 public:
7904 INSTRUCTION_HEADER(GuardSpecificSymbol)
7905 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)...); }
7906 NAMED_OPERANDS((0, symbol))MDefinition* symbol() const { return getOperand(0); }
7907
7908 JS::Symbol* expected() const { return expected_; }
7909
7910 bool congruentTo(const MDefinition* ins) const override {
7911 if (!ins->isGuardSpecificSymbol()) {
7912 return false;
7913 }
7914 if (expected() != ins->toGuardSpecificSymbol()->expected()) {
7915 return false;
7916 }
7917 return congruentIfOperandsEqual(ins);
7918 }
7919 MDefinition* foldsTo(TempAllocator& alloc) override;
7920 AliasSet getAliasSet() const override { return AliasSet::None(); }
7921};
7922
7923class MGuardTagNotEqual
7924 : public MBinaryInstruction,
7925 public MixPolicy<UnboxedInt32Policy<0>, UnboxedInt32Policy<1>>::Data {
7926 MGuardTagNotEqual(MDefinition* left, MDefinition* right)
7927 : MBinaryInstruction(classOpcode, left, right) {
7928 setGuard();
7929 setMovable();
7930 setCommutative();
7931 }
7932
7933 public:
7934 INSTRUCTION_HEADER(GuardTagNotEqual)
7935 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)...); }
7936
7937 AliasSet getAliasSet() const override { return AliasSet::None(); }
7938
7939 bool congruentTo(const MDefinition* ins) const override {
7940 return binaryCongruentTo(ins);
7941 }
7942};
7943
7944// Load from vp[slot] (slots that are not inline in an object).
7945class MLoadDynamicSlot : public MUnaryInstruction, public NoTypePolicy::Data {
7946 uint32_t slot_;
7947 bool usedAsPropertyKey_ = false;
7948
7949 MLoadDynamicSlot(MDefinition* slots, uint32_t slot)
7950 : MUnaryInstruction(classOpcode, slots), slot_(slot) {
7951 setResultType(MIRType::Value);
7952 setMovable();
7953 MOZ_ASSERT(slots->type() == MIRType::Slots)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slots->type() == MIRType::Slots)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slots->type() == MIRType::
Slots))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slots->type() == MIRType::Slots", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7953); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slots->type() == MIRType::Slots"
")"); do { *((volatile int*)__null) = 7953; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7954 }
7955
7956 public:
7957 INSTRUCTION_HEADER(LoadDynamicSlot)
7958 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)...); }
7959 NAMED_OPERANDS((0, slots))MDefinition* slots() const { return getOperand(0); }
7960
7961 uint32_t slot() const { return slot_; }
7962
7963 HashNumber valueHash() const override;
7964 bool congruentTo(const MDefinition* ins) const override {
7965 if (!ins->isLoadDynamicSlot()) {
7966 return false;
7967 }
7968 if (slot() != ins->toLoadDynamicSlot()->slot()) {
7969 return false;
7970 }
7971 return congruentIfOperandsEqual(ins);
7972 }
7973
7974 MDefinition* foldsTo(TempAllocator& alloc) override;
7975
7976 AliasSet getAliasSet() const override {
7977 MOZ_ASSERT(slots()->type() == MIRType::Slots)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slots()->type() == MIRType::Slots)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slots()->type() == MIRType
::Slots))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slots()->type() == MIRType::Slots", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 7977); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slots()->type() == MIRType::Slots"
")"); do { *((volatile int*)__null) = 7977; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
7978 return AliasSet::Load(AliasSet::DynamicSlot);
7979 }
7980 AliasType mightAlias(const MDefinition* store) const override;
7981
7982#ifdef JS_JITSPEW1
7983 void printOpcode(GenericPrinter& out) const override;
7984#endif
7985
7986 void setUsedAsPropertyKey() { usedAsPropertyKey_ = true; }
7987 bool usedAsPropertyKey() const { return usedAsPropertyKey_; }
7988
7989 ALLOW_CLONE(MLoadDynamicSlot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MLoadDynamicSlot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
7990};
7991
7992class MAddAndStoreSlot
7993 : public MBinaryInstruction,
7994 public MixPolicy<SingleObjectPolicy, BoxPolicy<1>>::Data {
7995 public:
7996 enum class Kind {
7997 FixedSlot,
7998 DynamicSlot,
7999 };
8000
8001 private:
8002 Kind kind_;
8003 uint32_t slotOffset_;
8004 CompilerShape shape_;
8005
8006 MAddAndStoreSlot(MDefinition* obj, MDefinition* value, Kind kind,
8007 uint32_t slotOffset, Shape* shape)
8008 : MBinaryInstruction(classOpcode, obj, value),
8009 kind_(kind),
8010 slotOffset_(slotOffset),
8011 shape_(shape) {}
8012
8013 public:
8014 INSTRUCTION_HEADER(AddAndStoreSlot)
8015 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)...); }
8016 NAMED_OPERANDS((0, object), (1, value))MDefinition* object() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
8017
8018 Kind kind() const { return kind_; }
8019 uint32_t slotOffset() const { return slotOffset_; }
8020 Shape* shape() const { return shape_; }
8021
8022 AliasSet getAliasSet() const override {
8023 return AliasSet::Store(AliasSet::ObjectFields |
8024 (kind() == Kind::FixedSlot ? AliasSet::FixedSlot
8025 : AliasSet::DynamicSlot));
8026 }
8027};
8028
8029// Store to vp[slot] (slots that are not inline in an object).
8030class MStoreDynamicSlot : public MBinaryInstruction,
8031 public NoFloatPolicy<1>::Data {
8032 uint32_t slot_;
8033 bool needsBarrier_;
8034
8035 MStoreDynamicSlot(MDefinition* slots, uint32_t slot, MDefinition* value,
8036 bool barrier)
8037 : MBinaryInstruction(classOpcode, slots, value),
8038 slot_(slot),
8039 needsBarrier_(barrier) {
8040 MOZ_ASSERT(slots->type() == MIRType::Slots)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(slots->type() == MIRType::Slots)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(slots->type() == MIRType::
Slots))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("slots->type() == MIRType::Slots", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8040); AnnotateMozCrashReason("MOZ_ASSERT" "(" "slots->type() == MIRType::Slots"
")"); do { *((volatile int*)__null) = 8040; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8041 }
8042
8043 public:
8044 INSTRUCTION_HEADER(StoreDynamicSlot)
8045 NAMED_OPERANDS((0, slots), (1, value))MDefinition* slots() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
8046
8047 static MStoreDynamicSlot* NewUnbarriered(TempAllocator& alloc,
8048 MDefinition* slots, uint32_t slot,
8049 MDefinition* value) {
8050 return new (alloc) MStoreDynamicSlot(slots, slot, value, false);
8051 }
8052 static MStoreDynamicSlot* NewBarriered(TempAllocator& alloc,
8053 MDefinition* slots, uint32_t slot,
8054 MDefinition* value) {
8055 return new (alloc) MStoreDynamicSlot(slots, slot, value, true);
8056 }
8057
8058 uint32_t slot() const { return slot_; }
8059 bool needsBarrier() const { return needsBarrier_; }
8060 AliasSet getAliasSet() const override {
8061 return AliasSet::Store(AliasSet::DynamicSlot);
8062 }
8063
8064#ifdef JS_JITSPEW1
8065 void printOpcode(GenericPrinter& out) const override;
8066#endif
8067
8068 ALLOW_CLONE(MStoreDynamicSlot)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MStoreDynamicSlot
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8069};
8070
8071class MSetPropertyCache : public MTernaryInstruction,
8072 public MixPolicy<SingleObjectPolicy, CacheIdPolicy<1>,
8073 NoFloatPolicy<2>>::Data {
8074 bool strict_ : 1;
8075
8076 MSetPropertyCache(MDefinition* obj, MDefinition* id, MDefinition* value,
8077 bool strict)
8078 : MTernaryInstruction(classOpcode, obj, id, value), strict_(strict) {}
8079
8080 public:
8081 INSTRUCTION_HEADER(SetPropertyCache)
8082 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)...); }
8083 NAMED_OPERANDS((0, object), (1, idval), (2, value))MDefinition* object() const { return getOperand(0); } MDefinition
* idval() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
8084
8085 bool strict() const { return strict_; }
8086};
8087
8088class MMegamorphicSetElement : public MTernaryInstruction,
8089 public MegamorphicSetElementPolicy::Data {
8090 bool strict_;
8091
8092 MMegamorphicSetElement(MDefinition* object, MDefinition* index,
8093 MDefinition* value, bool strict)
8094 : MTernaryInstruction(classOpcode, object, index, value),
8095 strict_(strict) {}
8096
8097 public:
8098 INSTRUCTION_HEADER(MegamorphicSetElement)
8099 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)...); }
8100 NAMED_OPERANDS((0, object), (1, index), (2, value))MDefinition* object() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
8101
8102 bool strict() const { return strict_; }
8103
8104 bool possiblyCalls() const override { return true; }
8105};
8106
8107class MSetDOMProperty : public MBinaryInstruction,
8108 public MixPolicy<ObjectPolicy<0>, BoxPolicy<1>>::Data {
8109 const JSJitSetterOp func_;
8110 Realm* setterRealm_;
8111 DOMObjectKind objectKind_;
8112
8113 MSetDOMProperty(const JSJitSetterOp func, DOMObjectKind objectKind,
8114 Realm* setterRealm, MDefinition* obj, MDefinition* val)
8115 : MBinaryInstruction(classOpcode, obj, val),
8116 func_(func),
8117 setterRealm_(setterRealm),
8118 objectKind_(objectKind) {}
8119
8120 public:
8121 INSTRUCTION_HEADER(SetDOMProperty)
8122 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)...); }
8123 NAMED_OPERANDS((0, object), (1, value))MDefinition* object() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
8124
8125 JSJitSetterOp fun() const { return func_; }
8126 Realm* setterRealm() const { return setterRealm_; }
8127 DOMObjectKind objectKind() const { return objectKind_; }
8128
8129 bool possiblyCalls() const override { return true; }
8130};
8131
8132class MGetDOMPropertyBase : public MVariadicInstruction,
8133 public ObjectPolicy<0>::Data {
8134 const JSJitInfo* info_;
8135
8136 protected:
8137 MGetDOMPropertyBase(Opcode op, const JSJitInfo* jitinfo)
8138 : MVariadicInstruction(op), info_(jitinfo) {
8139 MOZ_ASSERT(jitinfo)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(jitinfo)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(jitinfo))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("jitinfo", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8139); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jitinfo" ")"
); do { *((volatile int*)__null) = 8139; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8140 MOZ_ASSERT(jitinfo->type() == JSJitInfo::Getter)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(jitinfo->type() == JSJitInfo::Getter)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(jitinfo->type() == JSJitInfo::Getter))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("jitinfo->type() == JSJitInfo::Getter"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8140); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jitinfo->type() == JSJitInfo::Getter"
")"); do { *((volatile int*)__null) = 8140; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8141
8142 // We are movable iff the jitinfo says we can be.
8143 if (isDomMovable()) {
8144 MOZ_ASSERT(jitinfo->aliasSet() != JSJitInfo::AliasEverything)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(jitinfo->aliasSet() != JSJitInfo::AliasEverything
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(jitinfo->aliasSet() != JSJitInfo::AliasEverything
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"jitinfo->aliasSet() != JSJitInfo::AliasEverything", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8144); AnnotateMozCrashReason("MOZ_ASSERT" "(" "jitinfo->aliasSet() != JSJitInfo::AliasEverything"
")"); do { *((volatile int*)__null) = 8144; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8145 setMovable();
8146 } else {
8147 // If we're not movable, that means we shouldn't be DCEd either,
8148 // because we might throw an exception when called, and getting rid
8149 // of that is observable.
8150 setGuard();
8151 }
8152
8153 setResultType(MIRType::Value);
8154 }
8155
8156 const JSJitInfo* info() const { return info_; }
8157
8158 [[nodiscard]] bool init(TempAllocator& alloc, MDefinition* obj,
8159 MDefinition* guard, MDefinition* globalGuard) {
8160 MOZ_ASSERT(obj)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(obj)>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(obj))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("obj", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8160); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj" ")"); do
{ *((volatile int*)__null) = 8160; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
8161 // guard can be null.
8162 // globalGuard can be null.
8163 size_t operandCount = 1;
8164 if (guard) {
8165 ++operandCount;
8166 }
8167 if (globalGuard) {
8168 ++operandCount;
8169 }
8170 if (!MVariadicInstruction::init(alloc, operandCount)) {
8171 return false;
8172 }
8173 initOperand(0, obj);
8174
8175 size_t operandIndex = 1;
8176 // Pin the guard, if we have one as an operand if we want to hoist later.
8177 if (guard) {
8178 initOperand(operandIndex++, guard);
8179 }
8180
8181 // And the same for the global guard, if we have one.
8182 if (globalGuard) {
8183 initOperand(operandIndex, globalGuard);
8184 }
8185
8186 return true;
8187 }
8188
8189 public:
8190 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
8191
8192 JSJitGetterOp fun() const { return info_->getter; }
8193 bool isInfallible() const { return info_->isInfallible; }
8194 bool isDomMovable() const { return info_->isMovable; }
8195 JSJitInfo::AliasSet domAliasSet() const { return info_->aliasSet(); }
8196 size_t domMemberSlotIndex() const {
8197 MOZ_ASSERT(info_->isAlwaysInSlot || info_->isLazilyCachedInSlot)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(info_->isAlwaysInSlot || info_->isLazilyCachedInSlot
)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(info_->isAlwaysInSlot || info_->isLazilyCachedInSlot
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"info_->isAlwaysInSlot || info_->isLazilyCachedInSlot",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8197); AnnotateMozCrashReason("MOZ_ASSERT" "(" "info_->isAlwaysInSlot || info_->isLazilyCachedInSlot"
")"); do { *((volatile int*)__null) = 8197; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8198 return info_->slotIndex;
8199 }
8200 bool valueMayBeInSlot() const { return info_->isLazilyCachedInSlot; }
8201
8202 bool baseCongruentTo(const MGetDOMPropertyBase* ins) const {
8203 if (!isDomMovable()) {
8204 return false;
8205 }
8206
8207 // Checking the jitinfo is the same as checking the constant function
8208 if (!(info() == ins->info())) {
8209 return false;
8210 }
8211
8212 return congruentIfOperandsEqual(ins);
8213 }
8214
8215 AliasSet getAliasSet() const override {
8216 JSJitInfo::AliasSet aliasSet = domAliasSet();
8217 if (aliasSet == JSJitInfo::AliasNone) {
8218 return AliasSet::None();
8219 }
8220 if (aliasSet == JSJitInfo::AliasDOMSets) {
8221 return AliasSet::Load(AliasSet::DOMProperty);
8222 }
8223 MOZ_ASSERT(aliasSet == JSJitInfo::AliasEverything)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aliasSet == JSJitInfo::AliasEverything)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(aliasSet == JSJitInfo::AliasEverything))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("aliasSet == JSJitInfo::AliasEverything"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8223); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliasSet == JSJitInfo::AliasEverything"
")"); do { *((volatile int*)__null) = 8223; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8224 return AliasSet::Store(AliasSet::Any);
8225 }
8226};
8227
8228class MGetDOMProperty : public MGetDOMPropertyBase {
8229 Realm* getterRealm_;
8230 DOMObjectKind objectKind_;
8231
8232 MGetDOMProperty(const JSJitInfo* jitinfo, DOMObjectKind objectKind,
8233 Realm* getterRealm)
8234 : MGetDOMPropertyBase(classOpcode, jitinfo),
8235 getterRealm_(getterRealm),
8236 objectKind_(objectKind) {}
8237
8238 public:
8239 INSTRUCTION_HEADER(GetDOMProperty)
8240
8241 static MGetDOMProperty* New(TempAllocator& alloc, const JSJitInfo* info,
8242 DOMObjectKind objectKind, Realm* getterRealm,
8243 MDefinition* obj, MDefinition* guard,
8244 MDefinition* globalGuard) {
8245 auto* res = new (alloc) MGetDOMProperty(info, objectKind, getterRealm);
8246 if (!res || !res->init(alloc, obj, guard, globalGuard)) {
8247 return nullptr;
8248 }
8249 return res;
8250 }
8251
8252 Realm* getterRealm() const { return getterRealm_; }
8253 DOMObjectKind objectKind() const { return objectKind_; }
8254
8255 bool congruentTo(const MDefinition* ins) const override {
8256 if (!ins->isGetDOMProperty()) {
8257 return false;
8258 }
8259
8260 if (ins->toGetDOMProperty()->getterRealm() != getterRealm()) {
8261 return false;
8262 }
8263
8264 return baseCongruentTo(ins->toGetDOMProperty());
8265 }
8266
8267 bool possiblyCalls() const override { return true; }
8268};
8269
8270class MGetDOMMember : public MGetDOMPropertyBase {
8271 explicit MGetDOMMember(const JSJitInfo* jitinfo)
8272 : MGetDOMPropertyBase(classOpcode, jitinfo) {
8273 setResultType(MIRTypeFromValueType(jitinfo->returnType()));
8274 }
8275
8276 public:
8277 INSTRUCTION_HEADER(GetDOMMember)
8278
8279 static MGetDOMMember* New(TempAllocator& alloc, const JSJitInfo* info,
8280 MDefinition* obj, MDefinition* guard,
8281 MDefinition* globalGuard) {
8282 auto* res = new (alloc) MGetDOMMember(info);
8283 if (!res || !res->init(alloc, obj, guard, globalGuard)) {
8284 return nullptr;
8285 }
8286 return res;
8287 }
8288
8289 bool possiblyCalls() const override { return false; }
8290
8291 bool congruentTo(const MDefinition* ins) const override {
8292 if (!ins->isGetDOMMember()) {
8293 return false;
8294 }
8295
8296 return baseCongruentTo(ins->toGetDOMMember());
8297 }
8298};
8299
8300class MLoadDOMExpandoValueGuardGeneration : public MUnaryInstruction,
8301 public SingleObjectPolicy::Data {
8302 JS::ExpandoAndGeneration* expandoAndGeneration_;
8303 uint64_t generation_;
8304
8305 MLoadDOMExpandoValueGuardGeneration(
8306 MDefinition* proxy, JS::ExpandoAndGeneration* expandoAndGeneration,
8307 uint64_t generation)
8308 : MUnaryInstruction(classOpcode, proxy),
8309 expandoAndGeneration_(expandoAndGeneration),
8310 generation_(generation) {
8311 setGuard();
8312 setMovable();
8313 setResultType(MIRType::Value);
8314 }
8315
8316 public:
8317 INSTRUCTION_HEADER(LoadDOMExpandoValueGuardGeneration)
8318 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)...); }
8319 NAMED_OPERANDS((0, proxy))MDefinition* proxy() const { return getOperand(0); }
8320
8321 JS::ExpandoAndGeneration* expandoAndGeneration() const {
8322 return expandoAndGeneration_;
8323 }
8324 uint64_t generation() const { return generation_; }
8325
8326 bool congruentTo(const MDefinition* ins) const override {
8327 if (!ins->isLoadDOMExpandoValueGuardGeneration()) {
8328 return false;
8329 }
8330 const auto* other = ins->toLoadDOMExpandoValueGuardGeneration();
8331 if (expandoAndGeneration() != other->expandoAndGeneration() ||
8332 generation() != other->generation()) {
8333 return false;
8334 }
8335 return congruentIfOperandsEqual(ins);
8336 }
8337 AliasSet getAliasSet() const override {
8338 return AliasSet::Load(AliasSet::DOMProxyExpando);
8339 }
8340};
8341
8342// Inlined assembly for Math.floor(double | float32) -> int32.
8343class MFloor : public MUnaryInstruction, public FloatingPointPolicy<0>::Data {
8344 explicit MFloor(MDefinition* num) : MUnaryInstruction(classOpcode, num) {
8345 setResultType(MIRType::Int32);
8346 specialization_ = MIRType::Double;
8347 setMovable();
8348 }
8349
8350 public:
8351 INSTRUCTION_HEADER(Floor)
8352 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)...); }
8353
8354 AliasSet getAliasSet() const override { return AliasSet::None(); }
8355 bool isFloat32Commutative() const override { return true; }
8356 void trySpecializeFloat32(TempAllocator& alloc) override;
8357#ifdef DEBUG1
8358 bool isConsistentFloat32Use(MUse* use) const override { return true; }
8359#endif
8360 bool congruentTo(const MDefinition* ins) const override {
8361 return congruentIfOperandsEqual(ins);
8362 }
8363 void computeRange(TempAllocator& alloc) override;
8364 [[nodiscard]] bool writeRecoverData(
8365 CompactBufferWriter& writer) const override;
8366 bool canRecoverOnBailout() const override { return true; }
8367
8368 ALLOW_CLONE(MFloor)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MFloor
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8369};
8370
8371// Inlined assembly version for Math.ceil(double | float32) -> int32.
8372class MCeil : public MUnaryInstruction, public FloatingPointPolicy<0>::Data {
8373 explicit MCeil(MDefinition* num) : MUnaryInstruction(classOpcode, num) {
8374 setResultType(MIRType::Int32);
8375 specialization_ = MIRType::Double;
8376 setMovable();
8377 }
8378
8379 public:
8380 INSTRUCTION_HEADER(Ceil)
8381 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)...); }
8382
8383 AliasSet getAliasSet() const override { return AliasSet::None(); }
8384 bool isFloat32Commutative() const override { return true; }
8385 void trySpecializeFloat32(TempAllocator& alloc) override;
8386#ifdef DEBUG1
8387 bool isConsistentFloat32Use(MUse* use) const override { return true; }
8388#endif
8389 bool congruentTo(const MDefinition* ins) const override {
8390 return congruentIfOperandsEqual(ins);
8391 }
8392 void computeRange(TempAllocator& alloc) override;
8393 [[nodiscard]] bool writeRecoverData(
8394 CompactBufferWriter& writer) const override;
8395 bool canRecoverOnBailout() const override { return true; }
8396
8397 ALLOW_CLONE(MCeil)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MCeil
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8398};
8399
8400// Inlined version of Math.round(double | float32) -> int32.
8401class MRound : public MUnaryInstruction, public FloatingPointPolicy<0>::Data {
8402 explicit MRound(MDefinition* num) : MUnaryInstruction(classOpcode, num) {
8403 setResultType(MIRType::Int32);
8404 specialization_ = MIRType::Double;
8405 setMovable();
8406 }
8407
8408 public:
8409 INSTRUCTION_HEADER(Round)
8410 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)...); }
8411
8412 AliasSet getAliasSet() const override { return AliasSet::None(); }
8413
8414 bool isFloat32Commutative() const override { return true; }
8415 void trySpecializeFloat32(TempAllocator& alloc) override;
8416#ifdef DEBUG1
8417 bool isConsistentFloat32Use(MUse* use) const override { return true; }
8418#endif
8419 bool congruentTo(const MDefinition* ins) const override {
8420 return congruentIfOperandsEqual(ins);
8421 }
8422
8423 [[nodiscard]] bool writeRecoverData(
8424 CompactBufferWriter& writer) const override;
8425 bool canRecoverOnBailout() const override { return true; }
8426
8427 ALLOW_CLONE(MRound)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MRound
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8428};
8429
8430// Inlined version of Math.trunc(double | float32) -> int32.
8431class MTrunc : public MUnaryInstruction, public FloatingPointPolicy<0>::Data {
8432 explicit MTrunc(MDefinition* num) : MUnaryInstruction(classOpcode, num) {
8433 setResultType(MIRType::Int32);
8434 specialization_ = MIRType::Double;
8435 setMovable();
8436 }
8437
8438 public:
8439 INSTRUCTION_HEADER(Trunc)
8440 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)...); }
8441
8442 AliasSet getAliasSet() const override { return AliasSet::None(); }
8443
8444 bool isFloat32Commutative() const override { return true; }
8445 void trySpecializeFloat32(TempAllocator& alloc) override;
8446#ifdef DEBUG1
8447 bool isConsistentFloat32Use(MUse* use) const override { return true; }
8448#endif
8449 bool congruentTo(const MDefinition* ins) const override {
8450 return congruentIfOperandsEqual(ins);
8451 }
8452
8453 [[nodiscard]] bool writeRecoverData(
8454 CompactBufferWriter& writer) const override;
8455 bool canRecoverOnBailout() const override { return true; }
8456
8457 ALLOW_CLONE(MTrunc)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MTrunc
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8458};
8459
8460// NearbyInt rounds the floating-point input to the nearest integer, according
8461// to the RoundingMode.
8462class MNearbyInt : public MUnaryInstruction,
8463 public FloatingPointPolicy<0>::Data {
8464 RoundingMode roundingMode_;
8465
8466 explicit MNearbyInt(MDefinition* num, MIRType resultType,
8467 RoundingMode roundingMode)
8468 : MUnaryInstruction(classOpcode, num), roundingMode_(roundingMode) {
8469 MOZ_ASSERT(HasAssemblerSupport(roundingMode))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(HasAssemblerSupport(roundingMode))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(HasAssemblerSupport(roundingMode
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("HasAssemblerSupport(roundingMode)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "HasAssemblerSupport(roundingMode)"
")"); do { *((volatile int*)__null) = 8469; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8470
8471 MOZ_ASSERT(IsFloatingPointType(resultType))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsFloatingPointType(resultType))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsFloatingPointType(resultType
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsFloatingPointType(resultType)", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8471); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsFloatingPointType(resultType)"
")"); do { *((volatile int*)__null) = 8471; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8472 setResultType(resultType);
8473 specialization_ = resultType;
8474
8475 setMovable();
8476 }
8477
8478 public:
8479 INSTRUCTION_HEADER(NearbyInt)
8480 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)...); }
8481
8482 static bool HasAssemblerSupport(RoundingMode mode) {
8483 return Assembler::HasRoundInstruction(mode);
8484 }
8485
8486 RoundingMode roundingMode() const { return roundingMode_; }
8487
8488 AliasSet getAliasSet() const override { return AliasSet::None(); }
8489
8490 bool isFloat32Commutative() const override { return true; }
8491 void trySpecializeFloat32(TempAllocator& alloc) override;
8492#ifdef DEBUG1
8493 bool isConsistentFloat32Use(MUse* use) const override { return true; }
8494#endif
8495
8496 bool congruentTo(const MDefinition* ins) const override {
8497 return congruentIfOperandsEqual(ins) &&
8498 ins->toNearbyInt()->roundingMode() == roundingMode_;
8499 }
8500
8501#ifdef JS_JITSPEW1
8502 void printOpcode(GenericPrinter& out) const override;
8503#endif
8504
8505 [[nodiscard]] bool writeRecoverData(
8506 CompactBufferWriter& writer) const override;
8507
8508 bool canRecoverOnBailout() const override {
8509 switch (roundingMode_) {
8510 case RoundingMode::Up:
8511 case RoundingMode::Down:
8512 case RoundingMode::TowardsZero:
8513 return true;
8514 default:
8515 return false;
8516 }
8517 }
8518
8519 ALLOW_CLONE(MNearbyInt)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MNearbyInt
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8520};
8521
8522class MGetIteratorCache : public MUnaryInstruction,
8523 public BoxExceptPolicy<0, MIRType::Object>::Data {
8524 explicit MGetIteratorCache(MDefinition* val)
8525 : MUnaryInstruction(classOpcode, val) {
8526 setResultType(MIRType::Object);
8527 }
8528
8529 public:
8530 INSTRUCTION_HEADER(GetIteratorCache)
8531 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)...); }
8532 NAMED_OPERANDS((0, value))MDefinition* value() const { return getOperand(0); }
8533};
8534
8535// Implementation for 'in' operator using instruction cache
8536class MInCache : public MBinaryInstruction,
8537 public MixPolicy<CacheIdPolicy<0>, ObjectPolicy<1>>::Data {
8538 MInCache(MDefinition* key, MDefinition* obj)
8539 : MBinaryInstruction(classOpcode, key, obj) {
8540 setResultType(MIRType::Boolean);
8541 }
8542
8543 public:
8544 INSTRUCTION_HEADER(InCache)
8545 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)...); }
8546 NAMED_OPERANDS((0, key), (1, object))MDefinition* key() const { return getOperand(0); } MDefinition
* object() const { return getOperand(1); }
8547};
8548
8549// Test whether the index is in the array bounds or a hole.
8550class MInArray : public MTernaryInstruction, public NoTypePolicy::Data {
8551 bool needsNegativeIntCheck_ = true;
8552
8553 MInArray(MDefinition* elements, MDefinition* index, MDefinition* initLength)
8554 : MTernaryInstruction(classOpcode, elements, index, initLength) {
8555 setResultType(MIRType::Boolean);
8556 setMovable();
8557
8558 // Set the guard flag to make sure we bail when we see a negative index.
8559 // We can clear this flag (and needsNegativeIntCheck_) in
8560 // collectRangeInfoPreTrunc.
8561 setGuard();
8562
8563 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8563); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 8563; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8564 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8564); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 8564; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8565 MOZ_ASSERT(initLength->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(initLength->type() == MIRType::Int32)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(initLength->type() == MIRType::Int32))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("initLength->type() == MIRType::Int32"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8565); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initLength->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 8565; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8566 }
8567
8568 public:
8569 INSTRUCTION_HEADER(InArray)
8570 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)...); }
8571 NAMED_OPERANDS((0, elements), (1, index), (2, initLength))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* initLength
() const { return getOperand(2); }
8572
8573 bool needsNegativeIntCheck() const { return needsNegativeIntCheck_; }
8574 void collectRangeInfoPreTrunc() override;
8575 AliasSet getAliasSet() const override {
8576 return AliasSet::Load(AliasSet::Element);
8577 }
8578 bool congruentTo(const MDefinition* ins) const override {
8579 if (!ins->isInArray()) {
8580 return false;
8581 }
8582 const MInArray* other = ins->toInArray();
8583 if (needsNegativeIntCheck() != other->needsNegativeIntCheck()) {
8584 return false;
8585 }
8586 return congruentIfOperandsEqual(other);
8587 }
8588};
8589
8590// Bail when the element is a hole.
8591class MGuardElementNotHole : public MBinaryInstruction,
8592 public NoTypePolicy::Data {
8593 MGuardElementNotHole(MDefinition* elements, MDefinition* index)
8594 : MBinaryInstruction(classOpcode, elements, index) {
8595 setMovable();
8596 setGuard();
8597 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 8597; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8598 MOZ_ASSERT(index->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
Int32))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8598); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 8598; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8599 }
8600
8601 public:
8602 INSTRUCTION_HEADER(GuardElementNotHole)
8603 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)...); }
8604 NAMED_OPERANDS((0, elements), (1, index))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); }
8605
8606 AliasSet getAliasSet() const override {
8607 return AliasSet::Load(AliasSet::Element);
8608 }
8609 bool congruentTo(const MDefinition* ins) const override {
8610 return congruentIfOperandsEqual(ins);
8611 }
8612};
8613
8614class MCheckPrivateFieldCache
8615 : public MBinaryInstruction,
8616 public MixPolicy<BoxExceptPolicy<0, MIRType::Object>,
8617 CacheIdPolicy<1>>::Data {
8618 MCheckPrivateFieldCache(MDefinition* obj, MDefinition* id)
8619 : MBinaryInstruction(classOpcode, obj, id) {
8620 setResultType(MIRType::Boolean);
8621 }
8622
8623 public:
8624 INSTRUCTION_HEADER(CheckPrivateFieldCache)
8625 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)...); }
8626 NAMED_OPERANDS((0, value), (1, idval))MDefinition* value() const { return getOperand(0); } MDefinition
* idval() const { return getOperand(1); }
8627};
8628
8629class MHasOwnCache : public MBinaryInstruction,
8630 public MixPolicy<BoxExceptPolicy<0, MIRType::Object>,
8631 CacheIdPolicy<1>>::Data {
8632 MHasOwnCache(MDefinition* obj, MDefinition* id)
8633 : MBinaryInstruction(classOpcode, obj, id) {
8634 setResultType(MIRType::Boolean);
8635 }
8636
8637 public:
8638 INSTRUCTION_HEADER(HasOwnCache)
8639 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)...); }
8640 NAMED_OPERANDS((0, value), (1, idval))MDefinition* value() const { return getOperand(0); } MDefinition
* idval() const { return getOperand(1); }
8641};
8642
8643// Implementation for instanceof operator with specific rhs.
8644class MInstanceOf : public MBinaryInstruction,
8645 public MixPolicy<BoxExceptPolicy<0, MIRType::Object>,
8646 ObjectPolicy<1>>::Data {
8647 MInstanceOf(MDefinition* obj, MDefinition* proto)
8648 : MBinaryInstruction(classOpcode, obj, proto) {
8649 setResultType(MIRType::Boolean);
8650 }
8651
8652 public:
8653 INSTRUCTION_HEADER(InstanceOf)
8654 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)...); }
8655};
8656
8657// Given a value being written to another object, update the generational store
8658// buffer if the value is in the nursery and object is in the tenured heap.
8659class MPostWriteBarrier : public MBinaryInstruction,
8660 public ObjectPolicy<0>::Data {
8661 MPostWriteBarrier(MDefinition* obj, MDefinition* value)
8662 : MBinaryInstruction(classOpcode, obj, value) {
8663 setGuard();
8664 }
8665
8666 public:
8667 INSTRUCTION_HEADER(PostWriteBarrier)
8668 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)...); }
8669 NAMED_OPERANDS((0, object), (1, value))MDefinition* object() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
8670
8671 AliasSet getAliasSet() const override { return AliasSet::None(); }
8672
8673#ifdef DEBUG1
8674 bool isConsistentFloat32Use(MUse* use) const override {
8675 // During lowering, values that neither have object nor value MIR type
8676 // are ignored, thus Float32 can show up at this point without any issue.
8677 return use == getUseFor(1);
8678 }
8679#endif
8680
8681 ALLOW_CLONE(MPostWriteBarrier)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MPostWriteBarrier
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8682};
8683
8684// Given a value being written to another object's elements at the specified
8685// index, update the generational store buffer if the value is in the nursery
8686// and object is in the tenured heap.
8687class MPostWriteElementBarrier
8688 : public MTernaryInstruction,
8689 public MixPolicy<ObjectPolicy<0>, UnboxedInt32Policy<2>>::Data {
8690 MPostWriteElementBarrier(MDefinition* obj, MDefinition* value,
8691 MDefinition* index)
8692 : MTernaryInstruction(classOpcode, obj, value, index) {
8693 setGuard();
8694 }
8695
8696 public:
8697 INSTRUCTION_HEADER(PostWriteElementBarrier)
8698 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)...); }
8699 NAMED_OPERANDS((0, object), (1, value), (2, index))MDefinition* object() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); } MDefinition* index(
) const { return getOperand(2); }
8700
8701 AliasSet getAliasSet() const override { return AliasSet::None(); }
8702
8703#ifdef DEBUG1
8704 bool isConsistentFloat32Use(MUse* use) const override {
8705 // During lowering, values that neither have object nor value MIR type
8706 // are ignored, thus Float32 can show up at this point without any issue.
8707 return use == getUseFor(1);
8708 }
8709#endif
8710
8711 ALLOW_CLONE(MPostWriteElementBarrier)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MPostWriteElementBarrier
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
8712};
8713
8714class MNewCallObject : public MUnaryInstruction,
8715 public SingleObjectPolicy::Data {
8716 public:
8717 INSTRUCTION_HEADER(NewCallObject)
8718 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)...); }
8719
8720 explicit MNewCallObject(MConstant* templateObj)
8721 : MUnaryInstruction(classOpcode, templateObj) {
8722 setResultType(MIRType::Object);
8723 }
8724
8725 CallObject* templateObject() const {
8726 return &getOperand(0)->toConstant()->toObject().as<CallObject>();
8727 }
8728 AliasSet getAliasSet() const override { return AliasSet::None(); }
8729
8730 [[nodiscard]] bool writeRecoverData(
8731 CompactBufferWriter& writer) const override;
8732 bool canRecoverOnBailout() const override { return true; }
8733};
8734
8735class MNewStringObject : public MUnaryInstruction,
8736 public ConvertToStringPolicy<0>::Data {
8737 CompilerObject templateObj_;
8738
8739 MNewStringObject(MDefinition* input, JSObject* templateObj)
8740 : MUnaryInstruction(classOpcode, input), templateObj_(templateObj) {
8741 setResultType(MIRType::Object);
8742 }
8743
8744 public:
8745 INSTRUCTION_HEADER(NewStringObject)
8746 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)...); }
8747
8748 StringObject* templateObj() const;
8749};
8750
8751// This is an alias for MLoadFixedSlot.
8752class MEnclosingEnvironment : public MLoadFixedSlot {
8753 explicit MEnclosingEnvironment(MDefinition* obj)
8754 : MLoadFixedSlot(obj, EnvironmentObject::enclosingEnvironmentSlot()) {
8755 setResultType(MIRType::Object);
8756 }
8757
8758 public:
8759 static MEnclosingEnvironment* New(TempAllocator& alloc, MDefinition* obj) {
8760 return new (alloc) MEnclosingEnvironment(obj);
8761 }
8762
8763 AliasSet getAliasSet() const override {
8764 // EnvironmentObject reserved slots are immutable.
8765 return AliasSet::None();
8766 }
8767};
8768
8769// This is an element of a spaghetti stack which is used to represent the memory
8770// context which has to be restored in case of a bailout.
8771struct MStoreToRecover : public TempObject,
8772 public InlineSpaghettiStackNode<MStoreToRecover> {
8773 MDefinition* operand;
8774
8775 explicit MStoreToRecover(MDefinition* operand) : operand(operand) {}
8776};
8777
8778using MStoresToRecoverList = InlineSpaghettiStack<MStoreToRecover>;
8779
8780// A resume point contains the information needed to reconstruct the Baseline
8781// Interpreter state from a position in Warp JIT code. A resume point is a
8782// mapping of stack slots to MDefinitions.
8783//
8784// We capture stack state at critical points:
8785// * (1) At the beginning of every basic block.
8786// * (2) After every effectful operation.
8787//
8788// As long as these two properties are maintained, instructions can be moved,
8789// hoisted, or, eliminated without problems, and ops without side effects do not
8790// need to worry about capturing state at precisely the right point in time.
8791//
8792// Effectful instructions, of course, need to capture state after completion,
8793// where the interpreter will not attempt to repeat the operation. For this,
8794// ResumeAfter must be used. The state is attached directly to the effectful
8795// instruction to ensure that no intermediate instructions could be injected
8796// in between by a future analysis pass.
8797//
8798// During LIR construction, if an instruction can bail back to the interpreter,
8799// we create an LSnapshot, which uses the last known resume point to request
8800// register/stack assignments for every live value.
8801class MResumePoint final : public MNode
8802#ifdef DEBUG1
8803 ,
8804 public InlineForwardListNode<MResumePoint>
8805#endif
8806{
8807 private:
8808 friend class MBasicBlock;
8809 friend void AssertBasicGraphCoherency(MIRGraph& graph, bool force);
8810
8811 // List of stack slots needed to reconstruct the BaselineFrame.
8812 FixedList<MUse> operands_;
8813
8814 // List of stores needed to reconstruct the content of objects which are
8815 // emulated by EmulateStateOf variants.
8816 MStoresToRecoverList stores_;
8817
8818 jsbytecode* pc_;
8819 MInstruction* instruction_;
8820 ResumeMode mode_;
8821 bool isDiscarded_ = false;
8822
8823 MResumePoint(MBasicBlock* block, jsbytecode* pc, ResumeMode mode);
8824 void inherit(MBasicBlock* state);
8825
8826 // Calling isDefinition or isResumePoint on MResumePoint is unnecessary.
8827 bool isDefinition() const = delete;
8828 bool isResumePoint() const = delete;
8829
8830 void setBlock(MBasicBlock* block) {
8831 setBlockAndKind(block, Kind::ResumePoint);
8832 }
8833
8834 protected:
8835 // Initializes operands_ to an empty array of a fixed length.
8836 // The array may then be filled in by inherit().
8837 [[nodiscard]] bool init(TempAllocator& alloc);
8838
8839 void clearOperand(size_t index) {
8840 // FixedList doesn't initialize its elements, so do an unchecked init.
8841 operands_[index].initUncheckedWithoutProducer(this);
8842 }
8843
8844 MUse* getUseFor(size_t index) override { return &operands_[index]; }
8845 const MUse* getUseFor(size_t index) const override {
8846 return &operands_[index];
8847 }
8848
8849 public:
8850 static MResumePoint* New(TempAllocator& alloc, MBasicBlock* block,
8851 jsbytecode* pc, ResumeMode mode);
8852
8853 MBasicBlock* block() const { return resumePointBlock(); }
8854
8855 size_t numAllocatedOperands() const { return operands_.length(); }
8856 uint32_t stackDepth() const { return numAllocatedOperands(); }
8857 size_t numOperands() const override { return numAllocatedOperands(); }
8858 size_t indexOf(const MUse* u) const final {
8859 MOZ_ASSERT(u >= &operands_[0])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u >= &operands_[0])>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(u >= &operands_[0])))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("u >= &operands_[0]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8859); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u >= &operands_[0]"
")"); do { *((volatile int*)__null) = 8859; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8860 MOZ_ASSERT(u <= &operands_[numOperands() - 1])do { static_assert( mozilla::detail::AssertionConditionType<
decltype(u <= &operands_[numOperands() - 1])>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(u <= &operands_[numOperands() - 1]))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("u <= &operands_[numOperands() - 1]"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8860); AnnotateMozCrashReason("MOZ_ASSERT" "(" "u <= &operands_[numOperands() - 1]"
")"); do { *((volatile int*)__null) = 8860; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8861 return u - &operands_[0];
8862 }
8863 void initOperand(size_t index, MDefinition* operand) {
8864 // FixedList doesn't initialize its elements, so do an unchecked init.
8865 operands_[index].initUnchecked(operand, this);
8866 }
8867 void replaceOperand(size_t index, MDefinition* operand) final {
8868 operands_[index].replaceProducer(operand);
8869 }
8870
8871 bool isObservableOperand(MUse* u) const;
8872 bool isObservableOperand(size_t index) const;
8873 bool isRecoverableOperand(MUse* u) const;
8874
8875 MDefinition* getOperand(size_t index) const override {
8876 return operands_[index].producer();
8877 }
8878 jsbytecode* pc() const { return pc_; }
8879 MResumePoint* caller() const;
8880 uint32_t frameCount() const {
8881 uint32_t count = 1;
8882 for (MResumePoint* it = caller(); it; it = it->caller()) {
8883 count++;
8884 }
8885 return count;
8886 }
8887 MInstruction* instruction() { return instruction_; }
8888 void setInstruction(MInstruction* ins) {
8889 MOZ_ASSERT(!instruction_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!instruction_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!instruction_))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!instruction_",
"/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8889); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!instruction_"
")"); do { *((volatile int*)__null) = 8889; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8890 instruction_ = ins;
8891 }
8892 void resetInstruction() {
8893 MOZ_ASSERT(instruction_)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(instruction_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(instruction_))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("instruction_", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "instruction_"
")"); do { *((volatile int*)__null) = 8893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8894 instruction_ = nullptr;
8895 }
8896 ResumeMode mode() const { return mode_; }
8897
8898 void releaseUses() {
8899 for (size_t i = 0, e = numOperands(); i < e; i++) {
8900 if (operands_[i].hasProducer()) {
8901 operands_[i].releaseProducer();
8902 }
8903 }
8904 }
8905
8906 [[nodiscard]] bool writeRecoverData(
8907 CompactBufferWriter& writer) const override;
8908
8909 // Register a store instruction on the current resume point. This
8910 // instruction would be recovered when we are bailing out. The |cache|
8911 // argument can be any resume point, it is used to share memory if we are
8912 // doing the same modification.
8913 void addStore(TempAllocator& alloc, MDefinition* store,
8914 const MResumePoint* cache = nullptr);
8915
8916 MStoresToRecoverList::iterator storesBegin() const { return stores_.begin(); }
8917 MStoresToRecoverList::iterator storesEnd() const { return stores_.end(); }
8918 bool storesEmpty() const { return stores_.empty(); }
8919
8920 void setDiscarded() { isDiscarded_ = true; }
8921 bool isDiscarded() const { return isDiscarded_; }
8922
8923#ifdef JS_JITSPEW1
8924 virtual void dump(GenericPrinter& out) const override;
8925 virtual void dump() const override;
8926#endif
8927};
8928
8929class MIsCallable : public MUnaryInstruction,
8930 public BoxExceptPolicy<0, MIRType::Object>::Data {
8931 explicit MIsCallable(MDefinition* object)
8932 : MUnaryInstruction(classOpcode, object) {
8933 setResultType(MIRType::Boolean);
8934 setMovable();
8935 }
8936
8937 public:
8938 INSTRUCTION_HEADER(IsCallable)
8939 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)...); }
8940 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
8941
8942 bool congruentTo(const MDefinition* ins) const override {
8943 return congruentIfOperandsEqual(ins);
8944 }
8945
8946 MDefinition* foldsTo(TempAllocator& alloc) override;
8947 AliasSet getAliasSet() const override { return AliasSet::None(); }
8948};
8949
8950class MHasClass : public MUnaryInstruction, public SingleObjectPolicy::Data {
8951 const JSClass* class_;
8952
8953 MHasClass(MDefinition* object, const JSClass* clasp)
8954 : MUnaryInstruction(classOpcode, object), class_(clasp) {
8955 MOZ_ASSERT(object->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(object->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(object->type() == MIRType
::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("object->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8955); AnnotateMozCrashReason("MOZ_ASSERT" "(" "object->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 8955; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8956 setResultType(MIRType::Boolean);
8957 setMovable();
8958 }
8959
8960 public:
8961 INSTRUCTION_HEADER(HasClass)
8962 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)...); }
8963 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
8964
8965 const JSClass* getClass() const { return class_; }
8966
8967 MDefinition* foldsTo(TempAllocator& alloc) override;
8968 AliasSet getAliasSet() const override { return AliasSet::None(); }
8969 bool congruentTo(const MDefinition* ins) const override {
8970 if (!ins->isHasClass()) {
8971 return false;
8972 }
8973 if (getClass() != ins->toHasClass()->getClass()) {
8974 return false;
8975 }
8976 return congruentIfOperandsEqual(ins);
8977 }
8978};
8979
8980class MGuardToClass : public MUnaryInstruction,
8981 public SingleObjectPolicy::Data {
8982 const JSClass* class_;
8983
8984 MGuardToClass(MDefinition* object, const JSClass* clasp)
8985 : MUnaryInstruction(classOpcode, object), class_(clasp) {
8986 MOZ_ASSERT(object->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(object->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(object->type() == MIRType
::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("object->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8986); AnnotateMozCrashReason("MOZ_ASSERT" "(" "object->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 8986; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
8987 MOZ_ASSERT(!clasp->isJSFunction(), "Use MGuardToFunction instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!clasp->isJSFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!clasp->isJSFunction())))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("!clasp->isJSFunction()"
" (" "Use MGuardToFunction instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 8987); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!clasp->isJSFunction()"
") (" "Use MGuardToFunction instead" ")"); do { *((volatile int
*)__null) = 8987; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
8988 setResultType(MIRType::Object);
8989 setMovable();
8990
8991 // We will bail out if the class type is incorrect, so we need to ensure we
8992 // don't eliminate this instruction
8993 setGuard();
8994 }
8995
8996 public:
8997 INSTRUCTION_HEADER(GuardToClass)
8998 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)...); }
8999 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
9000
9001 const JSClass* getClass() const { return class_; }
9002 bool isArgumentsObjectClass() const {
9003 return class_ == &MappedArgumentsObject::class_ ||
9004 class_ == &UnmappedArgumentsObject::class_;
9005 }
9006
9007 MDefinition* foldsTo(TempAllocator& alloc) override;
9008 AliasSet getAliasSet() const override { return AliasSet::None(); }
9009 bool congruentTo(const MDefinition* ins) const override {
9010 if (!ins->isGuardToClass()) {
9011 return false;
9012 }
9013 if (getClass() != ins->toGuardToClass()->getClass()) {
9014 return false;
9015 }
9016 return congruentIfOperandsEqual(ins);
9017 }
9018};
9019
9020class MGuardToEitherClass : public MUnaryInstruction,
9021 public SingleObjectPolicy::Data {
9022 const JSClass* class1_;
9023 const JSClass* class2_;
9024
9025 MGuardToEitherClass(MDefinition* object, const JSClass* clasp1,
9026 const JSClass* clasp2)
9027 : MUnaryInstruction(classOpcode, object),
9028 class1_(clasp1),
9029 class2_(clasp2) {
9030 MOZ_ASSERT(object->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(object->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(object->type() == MIRType
::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("object->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9030); AnnotateMozCrashReason("MOZ_ASSERT" "(" "object->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 9030; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9031 MOZ_ASSERT(clasp1 != clasp2, "Use MGuardToClass instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(clasp1 != clasp2)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(clasp1 != clasp2))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("clasp1 != clasp2"
" (" "Use MGuardToClass instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "clasp1 != clasp2"
") (" "Use MGuardToClass instead" ")"); do { *((volatile int
*)__null) = 9031; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9032 MOZ_ASSERT(!clasp1->isJSFunction(), "Use MGuardToFunction instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!clasp1->isJSFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!clasp1->isJSFunction()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!clasp1->isJSFunction()"
" (" "Use MGuardToFunction instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9032); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!clasp1->isJSFunction()"
") (" "Use MGuardToFunction instead" ")"); do { *((volatile int
*)__null) = 9032; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9033 MOZ_ASSERT(!clasp2->isJSFunction(), "Use MGuardToFunction instead")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!clasp2->isJSFunction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!clasp2->isJSFunction()))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!clasp2->isJSFunction()"
" (" "Use MGuardToFunction instead" ")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9033); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!clasp2->isJSFunction()"
") (" "Use MGuardToFunction instead" ")"); do { *((volatile int
*)__null) = 9033; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
9034 setResultType(MIRType::Object);
9035 setMovable();
9036
9037 // We will bail out if the class type is incorrect, so we need to ensure we
9038 // don't eliminate this instruction
9039 setGuard();
9040 }
9041
9042 public:
9043 INSTRUCTION_HEADER(GuardToEitherClass)
9044 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)...); }
9045 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
9046
9047 const JSClass* getClass1() const { return class1_; }
9048 const JSClass* getClass2() const { return class2_; }
9049
9050 MDefinition* foldsTo(TempAllocator& alloc) override;
9051 AliasSet getAliasSet() const override { return AliasSet::None(); }
9052 bool congruentTo(const MDefinition* ins) const override {
9053 if (!ins->isGuardToEitherClass()) {
9054 return false;
9055 }
9056 const auto* other = ins->toGuardToEitherClass();
9057 if (getClass1() != other->getClass1() &&
9058 getClass1() != other->getClass2()) {
9059 return false;
9060 }
9061 if (getClass2() != other->getClass1() &&
9062 getClass2() != other->getClass2()) {
9063 return false;
9064 }
9065 return congruentIfOperandsEqual(ins);
9066 }
9067};
9068
9069class MGuardToFunction : public MUnaryInstruction,
9070 public SingleObjectPolicy::Data {
9071 explicit MGuardToFunction(MDefinition* object)
9072 : MUnaryInstruction(classOpcode, object) {
9073 MOZ_ASSERT(object->type() == MIRType::Object)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(object->type() == MIRType::Object)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(object->type() == MIRType
::Object))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("object->type() == MIRType::Object", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9073); AnnotateMozCrashReason("MOZ_ASSERT" "(" "object->type() == MIRType::Object"
")"); do { *((volatile int*)__null) = 9073; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9074 setResultType(MIRType::Object);
9075 setMovable();
9076
9077 // We will bail out if the class type is incorrect, so we need to ensure we
9078 // don't eliminate this instruction
9079 setGuard();
9080 }
9081
9082 public:
9083 INSTRUCTION_HEADER(GuardToFunction)
9084 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)...); }
9085 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
9086
9087 MDefinition* foldsTo(TempAllocator& alloc) override;
9088 AliasSet getAliasSet() const override { return AliasSet::None(); }
9089 bool congruentTo(const MDefinition* ins) const override {
9090 if (!ins->isGuardToFunction()) {
9091 return false;
9092 }
9093 return congruentIfOperandsEqual(ins);
9094 }
9095};
9096
9097// Note: we might call a proxy trap, so this instruction is effectful.
9098class MIsArray : public MUnaryInstruction,
9099 public BoxExceptPolicy<0, MIRType::Object>::Data {
9100 explicit MIsArray(MDefinition* value)
9101 : MUnaryInstruction(classOpcode, value) {
9102 setResultType(MIRType::Boolean);
9103 }
9104
9105 public:
9106 INSTRUCTION_HEADER(IsArray)
9107 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)...); }
9108 NAMED_OPERANDS((0, value))MDefinition* value() const { return getOperand(0); }
9109
9110 MDefinition* foldsTo(TempAllocator& alloc) override;
9111};
9112
9113class MIsTypedArray : public MUnaryInstruction,
9114 public SingleObjectPolicy::Data {
9115 bool possiblyWrapped_;
9116
9117 explicit MIsTypedArray(MDefinition* value, bool possiblyWrapped)
9118 : MUnaryInstruction(classOpcode, value),
9119 possiblyWrapped_(possiblyWrapped) {
9120 setResultType(MIRType::Boolean);
9121
9122 if (possiblyWrapped) {
9123 // Proxy checks may throw, so we're neither removable nor movable.
9124 setGuard();
9125 } else {
9126 setMovable();
9127 }
9128 }
9129
9130 public:
9131 INSTRUCTION_HEADER(IsTypedArray)
9132 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)...); }
9133 NAMED_OPERANDS((0, value))MDefinition* value() const { return getOperand(0); }
9134
9135 bool isPossiblyWrapped() const { return possiblyWrapped_; }
9136 AliasSet getAliasSet() const override {
9137 if (isPossiblyWrapped()) {
9138 return AliasSet::Store(AliasSet::Any);
9139 }
9140 return AliasSet::None();
9141 }
9142};
9143
9144// Allocate the generator object for a frame.
9145class MGenerator : public MTernaryInstruction,
9146 public MixPolicy<ObjectPolicy<0>, ObjectPolicy<1>>::Data {
9147 explicit MGenerator(MDefinition* callee, MDefinition* environmentChain,
9148 MDefinition* argsObject)
9149 : MTernaryInstruction(classOpcode, callee, environmentChain, argsObject) {
9150 setResultType(MIRType::Object);
9151 };
9152
9153 public:
9154 INSTRUCTION_HEADER(Generator)
9155 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)...); }
9156 NAMED_OPERANDS((0, callee), (1, environmentChain), (2, argsObject))MDefinition* callee() const { return getOperand(0); } MDefinition
* environmentChain() const { return getOperand(1); } MDefinition
* argsObject() const { return getOperand(2); }
9157};
9158
9159class MMaybeExtractAwaitValue : public MBinaryInstruction,
9160 public BoxPolicy<0>::Data {
9161 explicit MMaybeExtractAwaitValue(MDefinition* value, MDefinition* canSkip)
9162 : MBinaryInstruction(classOpcode, value, canSkip) {
9163 setResultType(MIRType::Value);
9164 }
9165
9166 public:
9167 INSTRUCTION_HEADER(MaybeExtractAwaitValue)
9168 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)...); }
9169 NAMED_OPERANDS((0, value), (1, canSkip))MDefinition* value() const { return getOperand(0); } MDefinition
* canSkip() const { return getOperand(1); }
9170};
9171
9172class MAtomicIsLockFree : public MUnaryInstruction,
9173 public ConvertToInt32Policy<0>::Data {
9174 explicit MAtomicIsLockFree(MDefinition* value)
9175 : MUnaryInstruction(classOpcode, value) {
9176 setResultType(MIRType::Boolean);
9177 setMovable();
9178 }
9179
9180 public:
9181 INSTRUCTION_HEADER(AtomicIsLockFree)
9182 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)...); }
9183
9184 MDefinition* foldsTo(TempAllocator& alloc) override;
9185
9186 AliasSet getAliasSet() const override { return AliasSet::None(); }
9187
9188 bool congruentTo(const MDefinition* ins) const override {
9189 return congruentIfOperandsEqual(ins);
9190 }
9191
9192 [[nodiscard]] bool writeRecoverData(
9193 CompactBufferWriter& writer) const override;
9194 bool canRecoverOnBailout() const override { return true; }
9195
9196 ALLOW_CLONE(MAtomicIsLockFree)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MAtomicIsLockFree
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
9197};
9198
9199class MCompareExchangeTypedArrayElement
9200 : public MQuaternaryInstruction,
9201 public MixPolicy<TruncateToInt32OrToBigIntPolicy<2>,
9202 TruncateToInt32OrToBigIntPolicy<3>>::Data {
9203 Scalar::Type arrayType_;
9204
9205 explicit MCompareExchangeTypedArrayElement(MDefinition* elements,
9206 MDefinition* index,
9207 Scalar::Type arrayType,
9208 MDefinition* oldval,
9209 MDefinition* newval)
9210 : MQuaternaryInstruction(classOpcode, elements, index, oldval, newval),
9211 arrayType_(arrayType) {
9212 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9212); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 9212; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9213 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9213); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 9213; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9214 setGuard(); // Not removable
9215 }
9216
9217 public:
9218 INSTRUCTION_HEADER(CompareExchangeTypedArrayElement)
9219 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)...); }
9220 NAMED_OPERANDS((0, elements), (1, index), (2, oldval), (3, newval))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* oldval
() const { return getOperand(2); } MDefinition* newval() const
{ return getOperand(3); }
9221
9222 bool isByteArray() const {
9223 return (arrayType_ == Scalar::Int8 || arrayType_ == Scalar::Uint8);
9224 }
9225 Scalar::Type arrayType() const { return arrayType_; }
9226 AliasSet getAliasSet() const override {
9227 return AliasSet::Store(AliasSet::UnboxedElement);
9228 }
9229};
9230
9231class MAtomicExchangeTypedArrayElement
9232 : public MTernaryInstruction,
9233 public TruncateToInt32OrToBigIntPolicy<2>::Data {
9234 Scalar::Type arrayType_;
9235
9236 MAtomicExchangeTypedArrayElement(MDefinition* elements, MDefinition* index,
9237 MDefinition* value, Scalar::Type arrayType)
9238 : MTernaryInstruction(classOpcode, elements, index, value),
9239 arrayType_(arrayType) {
9240 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9240); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 9240; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9241 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 9241; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9242 MOZ_ASSERT(arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(arrayType <= Scalar::Uint32 || Scalar::isBigIntType
(arrayType))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(arrayType <= Scalar::Uint32 ||
Scalar::isBigIntType(arrayType)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9242); AnnotateMozCrashReason("MOZ_ASSERT" "(" "arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType)"
")"); do { *((volatile int*)__null) = 9242; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9243 setGuard(); // Not removable
9244 }
9245
9246 public:
9247 INSTRUCTION_HEADER(AtomicExchangeTypedArrayElement)
9248 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)...); }
9249 NAMED_OPERANDS((0, elements), (1, index), (2, value))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
9250
9251 bool isByteArray() const {
9252 return (arrayType_ == Scalar::Int8 || arrayType_ == Scalar::Uint8);
9253 }
9254 Scalar::Type arrayType() const { return arrayType_; }
9255 AliasSet getAliasSet() const override {
9256 return AliasSet::Store(AliasSet::UnboxedElement);
9257 }
9258};
9259
9260class MAtomicTypedArrayElementBinop
9261 : public MTernaryInstruction,
9262 public TruncateToInt32OrToBigIntPolicy<2>::Data {
9263 private:
9264 AtomicOp op_;
9265 Scalar::Type arrayType_;
9266 bool forEffect_;
9267
9268 explicit MAtomicTypedArrayElementBinop(AtomicOp op, MDefinition* elements,
9269 MDefinition* index,
9270 Scalar::Type arrayType,
9271 MDefinition* value, bool forEffect)
9272 : MTernaryInstruction(classOpcode, elements, index, value),
9273 op_(op),
9274 arrayType_(arrayType),
9275 forEffect_(forEffect) {
9276 MOZ_ASSERT(elements->type() == MIRType::Elements)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(elements->type() == MIRType::Elements)>::isValid
, "invalid assertion condition"); if ((__builtin_expect(!!(!(
!!(elements->type() == MIRType::Elements))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("elements->type() == MIRType::Elements"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9276); AnnotateMozCrashReason("MOZ_ASSERT" "(" "elements->type() == MIRType::Elements"
")"); do { *((volatile int*)__null) = 9276; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9277 MOZ_ASSERT(index->type() == MIRType::IntPtr)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(index->type() == MIRType::IntPtr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(index->type() == MIRType::
IntPtr))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("index->type() == MIRType::IntPtr", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9277); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == MIRType::IntPtr"
")"); do { *((volatile int*)__null) = 9277; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9278 MOZ_ASSERT(arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(arrayType <= Scalar::Uint32 || Scalar::isBigIntType
(arrayType))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(arrayType <= Scalar::Uint32 ||
Scalar::isBigIntType(arrayType)))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType)"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9278); AnnotateMozCrashReason("MOZ_ASSERT" "(" "arrayType <= Scalar::Uint32 || Scalar::isBigIntType(arrayType)"
")"); do { *((volatile int*)__null) = 9278; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9279 setGuard(); // Not removable
9280 }
9281
9282 public:
9283 INSTRUCTION_HEADER(AtomicTypedArrayElementBinop)
9284 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)...); }
9285 NAMED_OPERANDS((0, elements), (1, index), (2, value))MDefinition* elements() const { return getOperand(0); } MDefinition
* index() const { return getOperand(1); } MDefinition* value(
) const { return getOperand(2); }
9286
9287 bool isByteArray() const {
9288 return (arrayType_ == Scalar::Int8 || arrayType_ == Scalar::Uint8);
9289 }
9290 AtomicOp operation() const { return op_; }
9291 Scalar::Type arrayType() const { return arrayType_; }
9292 bool isForEffect() const { return forEffect_; }
9293 AliasSet getAliasSet() const override {
9294 return AliasSet::Store(AliasSet::UnboxedElement);
9295 }
9296};
9297
9298class MDebugger : public MNullaryInstruction {
9299 MDebugger() : MNullaryInstruction(classOpcode) {
9300 setBailoutKind(BailoutKind::Debugger);
9301 }
9302
9303 public:
9304 INSTRUCTION_HEADER(Debugger)
9305 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)...); }
9306};
9307
9308// Used to load the prototype of an object known to have
9309// a static prototype.
9310class MObjectStaticProto : public MUnaryInstruction,
9311 public SingleObjectPolicy::Data {
9312 explicit MObjectStaticProto(MDefinition* object)
9313 : MUnaryInstruction(classOpcode, object) {
9314 setResultType(MIRType::Object);
9315 setMovable();
9316 }
9317
9318 public:
9319 INSTRUCTION_HEADER(ObjectStaticProto)
9320 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)...); }
9321 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
9322
9323 bool congruentTo(const MDefinition* ins) const override {
9324 return congruentIfOperandsEqual(ins);
9325 }
9326
9327 AliasSet getAliasSet() const override {
9328 return AliasSet::Load(AliasSet::ObjectFields);
9329 }
9330 AliasType mightAlias(const MDefinition* def) const override {
9331 // These instructions never modify the [[Prototype]].
9332 if (def->isAddAndStoreSlot() || def->isAllocateAndStoreSlot() ||
9333 def->isStoreElementHole() || def->isArrayPush()) {
9334 return AliasType::NoAlias;
9335 }
9336 return AliasType::MayAlias;
9337 }
9338};
9339
9340class MConstantProto : public MUnaryInstruction,
9341 public SingleObjectPolicy::Data {
9342 // NOTE: we're not going to actually use the underlying receiver object for
9343 // anything. This is just here for giving extra information to MGuardShape
9344 // to MGuardShape::mightAlias. Accordingly, we don't take it as an operand,
9345 // but instead just keep a pointer to it. This means we need to ensure it's
9346 // not discarded before we try to access it. If this is discarded, we
9347 // basically just become an MConstant for the object's proto, which is fine.
9348 const MDefinition* receiverObject_;
9349
9350 explicit MConstantProto(MDefinition* protoObject,
9351 const MDefinition* receiverObject)
9352 : MUnaryInstruction(classOpcode, protoObject),
9353 receiverObject_(receiverObject) {
9354 MOZ_ASSERT(protoObject->isConstant())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(protoObject->isConstant())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(protoObject->isConstant()
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"protoObject->isConstant()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 9354); AnnotateMozCrashReason("MOZ_ASSERT" "(" "protoObject->isConstant()"
")"); do { *((volatile int*)__null) = 9354; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9355 setResultType(MIRType::Object);
9356 setMovable();
9357 }
9358
9359 ALLOW_CLONE(MConstantProto)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MConstantProto
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
9360
9361 public:
9362 INSTRUCTION_HEADER(ConstantProto)
9363 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)...); }
9364 NAMED_OPERANDS((0, protoObject))MDefinition* protoObject() const { return getOperand(0); }
9365
9366 HashNumber valueHash() const override;
9367
9368 bool congruentTo(const MDefinition* ins) const override {
9369 if (this == ins) {
9370 return true;
9371 }
9372 const MDefinition* receiverObject = getReceiverObject();
9373 return congruentIfOperandsEqual(ins) && receiverObject &&
9374 receiverObject == ins->toConstantProto()->getReceiverObject();
9375 }
9376
9377 AliasSet getAliasSet() const override { return AliasSet::None(); }
9378
9379 const MDefinition* getReceiverObject() const {
9380 if (receiverObject_->isDiscarded()) {
9381 return nullptr;
9382 }
9383 return receiverObject_;
9384 }
9385};
9386
9387class MObjectToIterator : public MUnaryInstruction,
9388 public ObjectPolicy<0>::Data {
9389 NativeIteratorListHead* enumeratorsAddr_;
9390 bool wantsIndices_ = false;
9391
9392 explicit MObjectToIterator(MDefinition* object,
9393 NativeIteratorListHead* enumeratorsAddr)
9394 : MUnaryInstruction(classOpcode, object),
9395 enumeratorsAddr_(enumeratorsAddr) {
9396 setResultType(MIRType::Object);
9397 }
9398
9399 public:
9400 NativeIteratorListHead* enumeratorsAddr() const { return enumeratorsAddr_; }
9401 INSTRUCTION_HEADER(ObjectToIterator)
9402 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)...); }
9403 NAMED_OPERANDS((0, object))MDefinition* object() const { return getOperand(0); }
9404
9405 bool wantsIndices() const { return wantsIndices_; }
9406 void setWantsIndices(bool value) { wantsIndices_ = value; }
9407};
9408
9409class MPostIntPtrConversion : public MUnaryInstruction,
9410 public NoTypePolicy::Data {
9411 explicit MPostIntPtrConversion(MDefinition* input)
9412 : MUnaryInstruction(classOpcode, input) {
9413 // Passes through the input.
9414 setResultType(input->type());
9415
9416 // Note: Must be non-movable so we can attach a resume point.
9417 }
9418
9419 public:
9420 INSTRUCTION_HEADER(PostIntPtrConversion)
9421 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)...); }
9422
9423 AliasSet getAliasSet() const override { return AliasSet::None(); }
9424};
9425
9426// Flips the input's sign bit, independently of the rest of the number's
9427// payload. Note this is different from multiplying by minus-one, which has
9428// side-effects for e.g. NaNs.
9429class MWasmNeg : public MUnaryInstruction, public NoTypePolicy::Data {
9430 MWasmNeg(MDefinition* op, MIRType type) : MUnaryInstruction(classOpcode, op) {
9431 setResultType(type);
9432 setMovable();
9433 }
9434
9435 public:
9436 INSTRUCTION_HEADER(WasmNeg)
9437 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)...); }
9438};
9439
9440// Machine-level bitwise AND/OR/XOR, avoiding all JS-level complexity embodied
9441// in MBinaryBitwiseInstruction.
9442class MWasmBinaryBitwise : public MBinaryInstruction,
9443 public NoTypePolicy::Data {
9444 public:
9445 enum class SubOpcode { And, Or, Xor };
9446
9447 protected:
9448 MWasmBinaryBitwise(MDefinition* left, MDefinition* right, MIRType type,
9449 SubOpcode subOpcode)
9450 : MBinaryInstruction(classOpcode, left, right), subOpcode_(subOpcode) {
9451 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.h"
, 9451); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32 || type == MIRType::Int64"
")"); do { *((volatile int*)__null) = 9451; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9452 setResultType(type);
9453 setMovable();
9454 setCommutative();
9455 }
9456
9457 public:
9458 INSTRUCTION_HEADER(WasmBinaryBitwise)
9459 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)...); }
9460
9461 SubOpcode subOpcode() const { return subOpcode_; }
9462 MDefinition* foldsTo(TempAllocator& alloc) override;
9463
9464 bool congruentTo(const MDefinition* ins) const override {
9465 return ins->isWasmBinaryBitwise() &&
9466 ins->toWasmBinaryBitwise()->subOpcode() == subOpcode() &&
9467 binaryCongruentTo(ins);
9468 }
9469
9470 AliasSet getAliasSet() const override { return AliasSet::None(); }
9471
9472#ifdef JS_JITSPEW1
9473 void getExtras(ExtrasCollector* extras) override {
9474 const char* what = "!!unknown!!";
Value stored to 'what' during its initialization is never read
9475 switch (subOpcode()) {
9476 case SubOpcode::And:
9477 what = "And";
9478 break;
9479 case SubOpcode::Or:
9480 what = "Or";
9481 break;
9482 case SubOpcode::Xor:
9483 what = "Xor";
9484 break;
9485 }
9486 extras->add(what);
9487 }
9488#endif
9489
9490 private:
9491 SubOpcode subOpcode_;
9492
9493 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; }
9494};
9495
9496class MWasmLoadInstance : public MUnaryInstruction, public NoTypePolicy::Data {
9497 uint32_t offset_;
9498 AliasSet aliases_;
9499
9500 explicit MWasmLoadInstance(MDefinition* instance, uint32_t offset,
9501 MIRType type, AliasSet aliases)
9502 : MUnaryInstruction(classOpcode, instance),
9503 offset_(offset),
9504 aliases_(aliases) {
9505 // Different instance data have different alias classes and only those
9506 // classes are allowed.
9507 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9508 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9509 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9510 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9511 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9512 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.h"
, 9512); 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) = 9512; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9513
9514 // The only types supported at the moment.
9515 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.h"
, 9516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 9516; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9516 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.h"
, 9516); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 9516; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9517
9518 setMovable();
9519 setResultType(type);
9520 }
9521
9522 public:
9523 INSTRUCTION_HEADER(WasmLoadInstance)
9524 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)...); }
9525 NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); }
9526
9527 uint32_t offset() const { return offset_; }
9528
9529 bool congruentTo(const MDefinition* ins) const override {
9530 return op() == ins->op() &&
9531 offset() == ins->toWasmLoadInstance()->offset() &&
9532 type() == ins->type();
9533 }
9534
9535 HashNumber valueHash() const override {
9536 return addU32ToHash(HashNumber(op()), offset());
9537 }
9538
9539 AliasSet getAliasSet() const override { return aliases_; }
9540};
9541
9542class MWasmStoreInstance : public MBinaryInstruction,
9543 public NoTypePolicy::Data {
9544 uint32_t offset_;
9545 AliasSet aliases_;
9546
9547 explicit MWasmStoreInstance(MDefinition* instance, MDefinition* value,
9548 uint32_t offset, MIRType type, AliasSet aliases)
9549 : MBinaryInstruction(classOpcode, instance, value),
9550 offset_(offset),
9551 aliases_(aliases) {
9552 // Different instance data have different alias classes and only those
9553 // classes are allowed.
9554 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.h"
, 9555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()"
")"); do { *((volatile int*)__null) = 9555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9555 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.h"
, 9555); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases_.flags() == AliasSet::Store(AliasSet::WasmPendingException).flags()"
")"); do { *((volatile int*)__null) = 9555; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9556
9557 // The only types supported at the moment.
9558 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.h"
, 9559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 9559; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9559 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.h"
, 9559); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Pointer || type == MIRType::Int32 || type == MIRType::Int64 || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 9559; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9560 }
9561
9562 public:
9563 INSTRUCTION_HEADER(WasmStoreInstance)
9564 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)...); }
9565 NAMED_OPERANDS((0, instance), (1, value))MDefinition* instance() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
9566
9567 uint32_t offset() const { return offset_; }
9568
9569 AliasSet getAliasSet() const override { return aliases_; }
9570};
9571
9572class MWasmHeapReg : public MNullaryInstruction {
9573 AliasSet aliases_;
9574
9575 explicit MWasmHeapReg(AliasSet aliases)
9576 : MNullaryInstruction(classOpcode), aliases_(aliases) {
9577 setMovable();
9578 setResultType(MIRType::Pointer);
9579 }
9580
9581 public:
9582 INSTRUCTION_HEADER(WasmHeapReg)
9583 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)...); }
9584
9585 bool congruentTo(const MDefinition* ins) const override {
9586 return ins->isWasmHeapReg();
9587 }
9588
9589 AliasSet getAliasSet() const override { return aliases_; }
9590};
9591
9592// For memory32, bounds check nodes are of type Int32 on 32-bit systems for both
9593// wasm and asm.js code, as well as on 64-bit systems for asm.js code and for
9594// wasm code that is known to have a bounds check limit that fits into 32 bits.
9595// They are of type Int64 only on 64-bit systems for wasm code with 4GB heaps.
9596// There is no way for nodes of both types to be present in the same function.
9597// Should this change, then BCE must be updated to take type into account.
9598//
9599// For memory64, bounds check nodes are always of type Int64.
9600
9601class MWasmBoundsCheck : public MBinaryInstruction, public NoTypePolicy::Data {
9602 public:
9603 enum Target {
9604 // Linear memory at index zero, which is the only memory allowed so far.
9605 Memory0,
9606 // Everything else. Currently comprises tables, and arrays in the GC
9607 // proposal.
9608 Unknown
9609 };
9610
9611 private:
9612 wasm::BytecodeOffset bytecodeOffset_;
9613 Target target_;
9614
9615 explicit MWasmBoundsCheck(MDefinition* index, MDefinition* boundsCheckLimit,
9616 wasm::BytecodeOffset bytecodeOffset, Target target)
9617 : MBinaryInstruction(classOpcode, index, boundsCheckLimit),
9618 bytecodeOffset_(bytecodeOffset),
9619 target_(target) {
9620 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.h"
, 9620); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index->type() == boundsCheckLimit->type()"
")"); do { *((volatile int*)__null) = 9620; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9621
9622 // Bounds check is effectful: it throws for OOB.
9623 setGuard();
9624
9625 if (JitOptions.spectreIndexMasking) {
9626 setResultType(index->type());
9627 }
9628 }
9629
9630 public:
9631 INSTRUCTION_HEADER(WasmBoundsCheck)
9632 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)...); }
9633 NAMED_OPERANDS((0, index), (1, boundsCheckLimit))MDefinition* index() const { return getOperand(0); } MDefinition
* boundsCheckLimit() const { return getOperand(1); }
9634
9635 AliasSet getAliasSet() const override { return AliasSet::None(); }
9636
9637 bool isMemory0() const { return target_ == MWasmBoundsCheck::Memory0; }
9638
9639 bool isRedundant() const { return !isGuard(); }
9640
9641 void setRedundant() { setNotGuard(); }
9642
9643 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
9644};
9645
9646class MWasmAddOffset : public MUnaryInstruction, public NoTypePolicy::Data {
9647 uint64_t offset_;
9648 wasm::BytecodeOffset bytecodeOffset_;
9649
9650 MWasmAddOffset(MDefinition* base, uint64_t offset,
9651 wasm::BytecodeOffset bytecodeOffset)
9652 : MUnaryInstruction(classOpcode, base),
9653 offset_(offset),
9654 bytecodeOffset_(bytecodeOffset) {
9655 setGuard();
9656 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.h"
, 9657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Int32 || base->type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 9657; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
9657 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.h"
, 9657); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Int32 || base->type() == MIRType::Int64"
")"); do { *((volatile int*)__null) = 9657; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9658 setResultType(base->type());
9659 }
9660
9661 public:
9662 INSTRUCTION_HEADER(WasmAddOffset)
9663 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)...); }
9664 NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); }
9665
9666 MDefinition* foldsTo(TempAllocator& alloc) override;
9667
9668 AliasSet getAliasSet() const override { return AliasSet::None(); }
9669
9670 uint64_t offset() const { return offset_; }
9671 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
9672};
9673
9674class MWasmAlignmentCheck : public MUnaryInstruction,
9675 public NoTypePolicy::Data {
9676 uint32_t byteSize_;
9677 wasm::BytecodeOffset bytecodeOffset_;
9678
9679 explicit MWasmAlignmentCheck(MDefinition* index, uint32_t byteSize,
9680 wasm::BytecodeOffset bytecodeOffset)
9681 : MUnaryInstruction(classOpcode, index),
9682 byteSize_(byteSize),
9683 bytecodeOffset_(bytecodeOffset) {
9684 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.h"
, 9684); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mozilla::IsPowerOfTwo(byteSize)"
")"); do { *((volatile int*)__null) = 9684; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9685 // Alignment check is effectful: it throws for unaligned.
9686 setGuard();
9687 }
9688
9689 public:
9690 INSTRUCTION_HEADER(WasmAlignmentCheck)
9691 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)...); }
9692 NAMED_OPERANDS((0, index))MDefinition* index() const { return getOperand(0); }
9693
9694 bool congruentTo(const MDefinition* ins) const override;
9695
9696 AliasSet getAliasSet() const override { return AliasSet::None(); }
9697
9698 uint32_t byteSize() const { return byteSize_; }
9699
9700 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
9701};
9702
9703class MWasmLoad
9704 : public MVariadicInstruction, // memoryBase is nullptr on some platforms
9705 public NoTypePolicy::Data {
9706 wasm::MemoryAccessDesc access_;
9707
9708 explicit MWasmLoad(const wasm::MemoryAccessDesc& access, MIRType resultType)
9709 : MVariadicInstruction(classOpcode), access_(access) {
9710 setGuard();
9711 setResultType(resultType);
9712 }
9713
9714 public:
9715 INSTRUCTION_HEADER(WasmLoad)
9716 NAMED_OPERANDS((0, base), (1, memoryBase))MDefinition* base() const { return getOperand(0); } MDefinition
* memoryBase() const { return getOperand(1); }
;
9717
9718 static MWasmLoad* New(TempAllocator& alloc, MDefinition* memoryBase,
9719 MDefinition* base, const wasm::MemoryAccessDesc& access,
9720 MIRType resultType) {
9721 MWasmLoad* load = new (alloc) MWasmLoad(access, resultType);
9722 if (!load->init(alloc, 1 + !!memoryBase)) {
9723 return nullptr;
9724 }
9725
9726 load->initOperand(0, base);
9727 if (memoryBase) {
9728 load->initOperand(1, memoryBase);
9729 }
9730
9731 return load;
9732 }
9733
9734 const wasm::MemoryAccessDesc& access() const { return access_; }
9735
9736 AliasSet getAliasSet() const override {
9737 // When a barrier is needed, make the instruction effectful by giving
9738 // it a "store" effect.
9739 if (access_.isAtomic()) {
9740 return AliasSet::Store(AliasSet::WasmHeap);
9741 }
9742 return AliasSet::Load(AliasSet::WasmHeap);
9743 }
9744
9745 bool hasMemoryBase() const { return numOperands() > 1; }
9746
9747#ifdef JS_JITSPEW1
9748 void getExtras(ExtrasCollector* extras) override {
9749 char buf[64];
9750 SprintfLiteral(buf, "(offs=%lld)", (long long int)access().offset64());
9751 extras->add(buf);
9752 }
9753#endif
9754};
9755
9756class MWasmStore : public MVariadicInstruction, public NoTypePolicy::Data {
9757 wasm::MemoryAccessDesc access_;
9758
9759 explicit MWasmStore(const wasm::MemoryAccessDesc& access)
9760 : MVariadicInstruction(classOpcode), access_(access) {
9761 setGuard();
9762 }
9763
9764 public:
9765 INSTRUCTION_HEADER(WasmStore)
9766 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); }
9767
9768 static MWasmStore* New(TempAllocator& alloc, MDefinition* memoryBase,
9769 MDefinition* base,
9770 const wasm::MemoryAccessDesc& access,
9771 MDefinition* value) {
9772 MWasmStore* store = new (alloc) MWasmStore(access);
9773 if (!store->init(alloc, 2 + !!memoryBase)) {
9774 return nullptr;
9775 }
9776
9777 store->initOperand(0, base);
9778 store->initOperand(1, value);
9779 if (memoryBase) {
9780 store->initOperand(2, memoryBase);
9781 }
9782
9783 return store;
9784 }
9785
9786 const wasm::MemoryAccessDesc& access() const { return access_; }
9787
9788 AliasSet getAliasSet() const override {
9789 return AliasSet::Store(AliasSet::WasmHeap);
9790 }
9791
9792 bool hasMemoryBase() const { return numOperands() > 2; }
9793
9794#ifdef JS_JITSPEW1
9795 void getExtras(ExtrasCollector* extras) override {
9796 char buf[64];
9797 SprintfLiteral(buf, "(offs=%lld)", (long long int)access().offset64());
9798 extras->add(buf);
9799 }
9800#endif
9801};
9802
9803class MAsmJSMemoryAccess {
9804 Scalar::Type accessType_;
9805 bool needsBoundsCheck_;
9806
9807 public:
9808 explicit MAsmJSMemoryAccess(Scalar::Type accessType)
9809 : accessType_(accessType), needsBoundsCheck_(true) {
9810 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.h"
, 9810); AnnotateMozCrashReason("MOZ_ASSERT" "(" "accessType != Scalar::Uint8Clamped"
")"); do { *((volatile int*)__null) = 9810; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9811 }
9812
9813 Scalar::Type accessType() const { return accessType_; }
9814 unsigned byteSize() const { return TypedArrayElemSize(accessType()); }
9815 bool needsBoundsCheck() const { return needsBoundsCheck_; }
9816
9817 wasm::MemoryAccessDesc access() const {
9818 return wasm::MemoryAccessDesc(0, accessType_, Scalar::byteSize(accessType_),
9819 0, wasm::BytecodeOffset(), false);
9820 }
9821
9822 void removeBoundsCheck() { needsBoundsCheck_ = false; }
9823};
9824
9825class MAsmJSLoadHeap
9826 : public MVariadicInstruction, // 1 plus optional memoryBase and
9827 // boundsCheckLimit
9828 public MAsmJSMemoryAccess,
9829 public NoTypePolicy::Data {
9830 uint32_t memoryBaseIndex_;
9831
9832 explicit MAsmJSLoadHeap(uint32_t memoryBaseIndex, Scalar::Type accessType)
9833 : MVariadicInstruction(classOpcode),
9834 MAsmJSMemoryAccess(accessType),
9835 memoryBaseIndex_(memoryBaseIndex) {
9836 setResultType(ScalarTypeToMIRType(accessType));
9837 }
9838
9839 public:
9840 INSTRUCTION_HEADER(AsmJSLoadHeap)
9841 NAMED_OPERANDS((0, base), (1, boundsCheckLimit))MDefinition* base() const { return getOperand(0); } MDefinition
* boundsCheckLimit() const { return getOperand(1); }
9842
9843 static MAsmJSLoadHeap* New(TempAllocator& alloc, MDefinition* memoryBase,
9844 MDefinition* base, MDefinition* boundsCheckLimit,
9845 Scalar::Type accessType) {
9846 uint32_t nextIndex = 2;
9847 uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U);
9848
9849 MAsmJSLoadHeap* load =
9850 new (alloc) MAsmJSLoadHeap(memoryBaseIndex, accessType);
9851 if (!load->init(alloc, nextIndex)) {
9852 return nullptr;
9853 }
9854
9855 load->initOperand(0, base);
9856 load->initOperand(1, boundsCheckLimit);
9857 if (memoryBase) {
9858 load->initOperand(memoryBaseIndex, memoryBase);
9859 }
9860
9861 return load;
9862 }
9863
9864 bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); }
9865 MDefinition* memoryBase() const {
9866 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.h"
, 9866); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()"
")"); do { *((volatile int*)__null) = 9866; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9867 return getOperand(memoryBaseIndex_);
9868 }
9869
9870 bool congruentTo(const MDefinition* ins) const override;
9871 AliasSet getAliasSet() const override {
9872 return AliasSet::Load(AliasSet::WasmHeap);
9873 }
9874 AliasType mightAlias(const MDefinition* def) const override;
9875};
9876
9877class MAsmJSStoreHeap
9878 : public MVariadicInstruction, // 2 plus optional memoryBase and
9879 // boundsCheckLimit
9880 public MAsmJSMemoryAccess,
9881 public NoTypePolicy::Data {
9882 uint32_t memoryBaseIndex_;
9883
9884 explicit MAsmJSStoreHeap(uint32_t memoryBaseIndex, Scalar::Type accessType)
9885 : MVariadicInstruction(classOpcode),
9886 MAsmJSMemoryAccess(accessType),
9887 memoryBaseIndex_(memoryBaseIndex) {}
9888
9889 public:
9890 INSTRUCTION_HEADER(AsmJSStoreHeap)
9891 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); }
9892
9893 static MAsmJSStoreHeap* New(TempAllocator& alloc, MDefinition* memoryBase,
9894 MDefinition* base, MDefinition* boundsCheckLimit,
9895 Scalar::Type accessType, MDefinition* v) {
9896 uint32_t nextIndex = 3;
9897 uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U);
9898
9899 MAsmJSStoreHeap* store =
9900 new (alloc) MAsmJSStoreHeap(memoryBaseIndex, accessType);
9901 if (!store->init(alloc, nextIndex)) {
9902 return nullptr;
9903 }
9904
9905 store->initOperand(0, base);
9906 store->initOperand(1, v);
9907 store->initOperand(2, boundsCheckLimit);
9908 if (memoryBase) {
9909 store->initOperand(memoryBaseIndex, memoryBase);
9910 }
9911
9912 return store;
9913 }
9914
9915 bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); }
9916 MDefinition* memoryBase() const {
9917 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.h"
, 9917); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()"
")"); do { *((volatile int*)__null) = 9917; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
9918 return getOperand(memoryBaseIndex_);
9919 }
9920
9921 AliasSet getAliasSet() const override {
9922 return AliasSet::Store(AliasSet::WasmHeap);
9923 }
9924};
9925
9926class MWasmCompareExchangeHeap : public MVariadicInstruction,
9927 public NoTypePolicy::Data {
9928 wasm::MemoryAccessDesc access_;
9929 wasm::BytecodeOffset bytecodeOffset_;
9930
9931 explicit MWasmCompareExchangeHeap(const wasm::MemoryAccessDesc& access,
9932 wasm::BytecodeOffset bytecodeOffset)
9933 : MVariadicInstruction(classOpcode),
9934 access_(access),
9935 bytecodeOffset_(bytecodeOffset) {
9936 setGuard(); // Not removable
9937 setResultType(ScalarTypeToMIRType(access.type()));
9938 }
9939
9940 public:
9941 INSTRUCTION_HEADER(WasmCompareExchangeHeap)
9942 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); }
9943 (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); }
9944
9945 static MWasmCompareExchangeHeap* New(TempAllocator& alloc,
9946 wasm::BytecodeOffset bytecodeOffset,
9947 MDefinition* memoryBase,
9948 MDefinition* base,
9949 const wasm::MemoryAccessDesc& access,
9950 MDefinition* oldv, MDefinition* newv,
9951 MDefinition* instance) {
9952 MWasmCompareExchangeHeap* cas =
9953 new (alloc) MWasmCompareExchangeHeap(access, bytecodeOffset);
9954 if (!cas->init(alloc, 4 + !!memoryBase)) {
9955 return nullptr;
9956 }
9957 cas->initOperand(0, base);
9958 cas->initOperand(1, oldv);
9959 cas->initOperand(2, newv);
9960 cas->initOperand(3, instance);
9961 if (memoryBase) {
9962 cas->initOperand(4, memoryBase);
9963 }
9964 return cas;
9965 }
9966
9967 const wasm::MemoryAccessDesc& access() const { return access_; }
9968 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
9969
9970 AliasSet getAliasSet() const override {
9971 return AliasSet::Store(AliasSet::WasmHeap);
9972 }
9973
9974 bool hasMemoryBase() const { return numOperands() > 4; }
9975};
9976
9977class MWasmAtomicExchangeHeap : public MVariadicInstruction,
9978 public NoTypePolicy::Data {
9979 wasm::MemoryAccessDesc access_;
9980 wasm::BytecodeOffset bytecodeOffset_;
9981
9982 explicit MWasmAtomicExchangeHeap(const wasm::MemoryAccessDesc& access,
9983 wasm::BytecodeOffset bytecodeOffset)
9984 : MVariadicInstruction(classOpcode),
9985 access_(access),
9986 bytecodeOffset_(bytecodeOffset) {
9987 setGuard(); // Not removable
9988 setResultType(ScalarTypeToMIRType(access.type()));
9989 }
9990
9991 public:
9992 INSTRUCTION_HEADER(WasmAtomicExchangeHeap)
9993 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); }
9994
9995 static MWasmAtomicExchangeHeap* New(TempAllocator& alloc,
9996 wasm::BytecodeOffset bytecodeOffset,
9997 MDefinition* memoryBase,
9998 MDefinition* base,
9999 const wasm::MemoryAccessDesc& access,
10000 MDefinition* value,
10001 MDefinition* instance) {
10002 MWasmAtomicExchangeHeap* xchg =
10003 new (alloc) MWasmAtomicExchangeHeap(access, bytecodeOffset);
10004 if (!xchg->init(alloc, 3 + !!memoryBase)) {
10005 return nullptr;
10006 }
10007
10008 xchg->initOperand(0, base);
10009 xchg->initOperand(1, value);
10010 xchg->initOperand(2, instance);
10011 if (memoryBase) {
10012 xchg->initOperand(3, memoryBase);
10013 }
10014
10015 return xchg;
10016 }
10017
10018 const wasm::MemoryAccessDesc& access() const { return access_; }
10019 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
10020
10021 AliasSet getAliasSet() const override {
10022 return AliasSet::Store(AliasSet::WasmHeap);
10023 }
10024
10025 bool hasMemoryBase() const { return numOperands() > 3; }
10026};
10027
10028class MWasmAtomicBinopHeap : public MVariadicInstruction,
10029 public NoTypePolicy::Data {
10030 AtomicOp op_;
10031 wasm::MemoryAccessDesc access_;
10032 wasm::BytecodeOffset bytecodeOffset_;
10033
10034 explicit MWasmAtomicBinopHeap(AtomicOp op,
10035 const wasm::MemoryAccessDesc& access,
10036 wasm::BytecodeOffset bytecodeOffset)
10037 : MVariadicInstruction(classOpcode),
10038 op_(op),
10039 access_(access),
10040 bytecodeOffset_(bytecodeOffset) {
10041 setGuard(); // Not removable
10042 setResultType(ScalarTypeToMIRType(access.type()));
10043 }
10044
10045 public:
10046 INSTRUCTION_HEADER(WasmAtomicBinopHeap)
10047 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); }
10048
10049 static MWasmAtomicBinopHeap* New(TempAllocator& alloc,
10050 wasm::BytecodeOffset bytecodeOffset,
10051 AtomicOp op, MDefinition* memoryBase,
10052 MDefinition* base,
10053 const wasm::MemoryAccessDesc& access,
10054 MDefinition* v, MDefinition* instance) {
10055 MWasmAtomicBinopHeap* binop =
10056 new (alloc) MWasmAtomicBinopHeap(op, access, bytecodeOffset);
10057 if (!binop->init(alloc, 3 + !!memoryBase)) {
10058 return nullptr;
10059 }
10060
10061 binop->initOperand(0, base);
10062 binop->initOperand(1, v);
10063 binop->initOperand(2, instance);
10064 if (memoryBase) {
10065 binop->initOperand(3, memoryBase);
10066 }
10067
10068 return binop;
10069 }
10070
10071 AtomicOp operation() const { return op_; }
10072 const wasm::MemoryAccessDesc& access() const { return access_; }
10073 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
10074
10075 AliasSet getAliasSet() const override {
10076 return AliasSet::Store(AliasSet::WasmHeap);
10077 }
10078
10079 bool hasMemoryBase() const { return numOperands() > 3; }
10080};
10081
10082class MWasmLoadInstanceDataField : public MUnaryInstruction,
10083 public NoTypePolicy::Data {
10084 MWasmLoadInstanceDataField(MIRType type, unsigned instanceDataOffset,
10085 bool isConstant, MDefinition* instance)
10086 : MUnaryInstruction(classOpcode, instance),
10087 instanceDataOffset_(instanceDataOffset),
10088 isConstant_(isConstant) {
10089 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.h"
, 10090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 10090; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10090 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.h"
, 10090); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsNumberType(type) || type == MIRType::Simd128 || type == MIRType::Pointer || type == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 10090; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10091 setResultType(type);
10092 setMovable();
10093 }
10094
10095 unsigned instanceDataOffset_;
10096 bool isConstant_;
10097
10098 public:
10099 INSTRUCTION_HEADER(WasmLoadInstanceDataField)
10100 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)...); }
10101 NAMED_OPERANDS((0, instance))MDefinition* instance() const { return getOperand(0); }
10102
10103 unsigned instanceDataOffset() const { return instanceDataOffset_; }
10104
10105 HashNumber valueHash() const override;
10106 bool congruentTo(const MDefinition* ins) const override;
10107 MDefinition* foldsTo(TempAllocator& alloc) override;
10108
10109 AliasSet getAliasSet() const override {
10110 return isConstant_ ? AliasSet::None()
10111 : AliasSet::Load(AliasSet::WasmInstanceData);
10112 }
10113
10114 AliasType mightAlias(const MDefinition* def) const override;
10115
10116#ifdef JS_JITSPEW1
10117 void getExtras(ExtrasCollector* extras) override {
10118 char buf[96];
10119 SprintfLiteral(buf, "(offs=%lld, isConst=%s)",
10120 (long long int)instanceDataOffset_,
10121 isConstant_ ? "true" : "false");
10122 extras->add(buf);
10123 }
10124#endif
10125};
10126
10127class MWasmLoadGlobalCell : public MUnaryInstruction,
10128 public NoTypePolicy::Data {
10129 MWasmLoadGlobalCell(MIRType type, MDefinition* cellPtr)
10130 : MUnaryInstruction(classOpcode, cellPtr) {
10131 setResultType(type);
10132 setMovable();
10133 }
10134
10135 public:
10136 INSTRUCTION_HEADER(WasmLoadGlobalCell)
10137 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)...); }
10138 NAMED_OPERANDS((0, cellPtr))MDefinition* cellPtr() const { return getOperand(0); }
10139
10140 // The default valueHash is good enough, because there are no non-operand
10141 // fields.
10142 bool congruentTo(const MDefinition* ins) const override;
10143
10144 AliasSet getAliasSet() const override {
10145 return AliasSet::Load(AliasSet::WasmGlobalCell);
10146 }
10147
10148 AliasType mightAlias(const MDefinition* def) const override;
10149};
10150
10151class MWasmLoadTableElement : public MBinaryInstruction,
10152 public NoTypePolicy::Data {
10153 MWasmLoadTableElement(MDefinition* elements, MDefinition* index)
10154 : MBinaryInstruction(classOpcode, elements, index) {
10155 setResultType(MIRType::WasmAnyRef);
10156 setMovable();
10157 }
10158
10159 public:
10160 INSTRUCTION_HEADER(WasmLoadTableElement)
10161 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)...); }
10162 NAMED_OPERANDS((0, elements))MDefinition* elements() const { return getOperand(0); }
10163 NAMED_OPERANDS((1, index))MDefinition* index() const { return getOperand(1); }
10164
10165 AliasSet getAliasSet() const override {
10166 return AliasSet::Load(AliasSet::WasmTableElement);
10167 }
10168};
10169
10170class MWasmStoreInstanceDataField : public MBinaryInstruction,
10171 public NoTypePolicy::Data {
10172 MWasmStoreInstanceDataField(unsigned instanceDataOffset, MDefinition* value,
10173 MDefinition* instance)
10174 : MBinaryInstruction(classOpcode, value, instance),
10175 instanceDataOffset_(instanceDataOffset) {}
10176
10177 unsigned instanceDataOffset_;
10178
10179 public:
10180 INSTRUCTION_HEADER(WasmStoreInstanceDataField)
10181 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)...); }
10182 NAMED_OPERANDS((0, value), (1, instance))MDefinition* value() const { return getOperand(0); } MDefinition
* instance() const { return getOperand(1); }
10183
10184 unsigned instanceDataOffset() const { return instanceDataOffset_; }
10185
10186 AliasSet getAliasSet() const override {
10187 return AliasSet::Store(AliasSet::WasmInstanceData);
10188 }
10189};
10190
10191class MWasmStoreGlobalCell : public MBinaryInstruction,
10192 public NoTypePolicy::Data {
10193 MWasmStoreGlobalCell(MDefinition* value, MDefinition* cellPtr)
10194 : MBinaryInstruction(classOpcode, value, cellPtr) {}
10195
10196 public:
10197 INSTRUCTION_HEADER(WasmStoreGlobalCell)
10198 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)...); }
10199 NAMED_OPERANDS((0, value), (1, cellPtr))MDefinition* value() const { return getOperand(0); } MDefinition
* cellPtr() const { return getOperand(1); }
10200
10201 AliasSet getAliasSet() const override {
10202 return AliasSet::Store(AliasSet::WasmGlobalCell);
10203 }
10204};
10205
10206class MWasmStoreStackResult : public MBinaryInstruction,
10207 public NoTypePolicy::Data {
10208 MWasmStoreStackResult(MDefinition* stackResultArea, uint32_t offset,
10209 MDefinition* value)
10210 : MBinaryInstruction(classOpcode, stackResultArea, value),
10211 offset_(offset) {}
10212
10213 uint32_t offset_;
10214
10215 public:
10216 INSTRUCTION_HEADER(WasmStoreStackResult)
10217 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)...); }
10218 NAMED_OPERANDS((0, stackResultArea), (1, value))MDefinition* stackResultArea() const { return getOperand(0); }
MDefinition* value() const { return getOperand(1); }
10219
10220 uint32_t offset() const { return offset_; }
10221
10222 AliasSet getAliasSet() const override {
10223 return AliasSet::Store(AliasSet::WasmStackResult);
10224 }
10225};
10226
10227// Represents a known-good derived pointer into an object or memory region (in
10228// the most general sense) that will not move while the derived pointer is live.
10229// The `offset` *must* be a valid offset into the object represented by `base`;
10230// hence overflow in the address calculation will never be an issue. `offset`
10231// must be representable as a 31-bit unsigned integer.
10232//
10233// DO NOT use this with a base value of any JS-heap-resident object type.
10234// Such a value would need to be adjusted during GC, yet we have no mechanism
10235// to do that. See bug 1810090.
10236
10237class MWasmDerivedPointer : public MUnaryInstruction,
10238 public NoTypePolicy::Data {
10239 MWasmDerivedPointer(MDefinition* base, size_t offset)
10240 : MUnaryInstruction(classOpcode, base), offset_(uint32_t(offset)) {
10241 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.h"
, 10241); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)"
")"); do { *((volatile int*)__null) = 10241; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10242 // Do not change this to allow `base` to be a GC-heap allocated type.
10243 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.h"
, 10244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()"
")"); do { *((volatile int*)__null) = 10244; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10244 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.h"
, 10244); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer || base->type() == TargetWordMIRType()"
")"); do { *((volatile int*)__null) = 10244; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10245 setResultType(MIRType::Pointer);
10246 setMovable();
10247 }
10248
10249 uint32_t offset_;
10250
10251 public:
10252 INSTRUCTION_HEADER(WasmDerivedPointer)
10253 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)...); }
10254 NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); }
10255
10256 uint32_t offset() const { return offset_; }
10257
10258 AliasSet getAliasSet() const override { return AliasSet::None(); }
10259
10260 bool congruentTo(const MDefinition* ins) const override {
10261 return congruentIfOperandsEqual(ins) &&
10262 ins->toWasmDerivedPointer()->offset() == offset();
10263 }
10264
10265#ifdef JS_JITSPEW1
10266 void getExtras(ExtrasCollector* extras) override {
10267 char buf[64];
10268 SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_);
10269 extras->add(buf);
10270 }
10271#endif
10272
10273 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; }
10274};
10275
10276// As with MWasmDerivedPointer, DO NOT use this with a base value of any
10277// JS-heap-resident object type.
10278class MWasmDerivedIndexPointer : public MBinaryInstruction,
10279 public NoTypePolicy::Data {
10280 MWasmDerivedIndexPointer(MDefinition* base, MDefinition* index, Scale scale)
10281 : MBinaryInstruction(classOpcode, base, index), scale_(scale) {
10282 // Do not change this to allow `base` to be a GC-heap allocated type.
10283 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.h"
, 10283); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::Pointer"
")"); do { *((volatile int*)__null) = 10283; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10284 setResultType(MIRType::Pointer);
10285 setMovable();
10286 }
10287
10288 Scale scale_;
10289
10290 public:
10291 INSTRUCTION_HEADER(WasmDerivedIndexPointer)
10292 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)...); }
10293 NAMED_OPERANDS((0, base))MDefinition* base() const { return getOperand(0); }
10294 NAMED_OPERANDS((1, index))MDefinition* index() const { return getOperand(1); }
10295
10296 Scale scale() const { return scale_; }
10297
10298 AliasSet getAliasSet() const override { return AliasSet::None(); }
10299
10300 bool congruentTo(const MDefinition* ins) const override {
10301 return congruentIfOperandsEqual(ins) &&
10302 ins->toWasmDerivedIndexPointer()->scale() == scale();
10303 }
10304
10305 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; }
10306};
10307
10308// Whether to perform a pre-write barrier for a wasm store reference.
10309enum class WasmPreBarrierKind : uint8_t { None, Normal };
10310
10311// Stores a reference to an address. This performs a pre-barrier on the address,
10312// but not a post-barrier. A post-barrier must be performed separately, if it's
10313// required. The accessed location is `valueBase + valueOffset`. The latter
10314// must be be representable as a 31-bit unsigned integer.
10315
10316class MWasmStoreRef : public MAryInstruction<3>, public NoTypePolicy::Data {
10317 uint32_t offset_;
10318 AliasSet::Flag aliasSet_;
10319 WasmPreBarrierKind preBarrierKind_;
10320
10321 MWasmStoreRef(MDefinition* instance, MDefinition* valueBase,
10322 size_t valueOffset, MDefinition* value, AliasSet::Flag aliasSet,
10323 WasmPreBarrierKind preBarrierKind)
10324 : MAryInstruction<3>(classOpcode),
10325 offset_(uint32_t(valueOffset)),
10326 aliasSet_(aliasSet),
10327 preBarrierKind_(preBarrierKind) {
10328 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.h"
, 10328); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueOffset <= (2147483647)"
")"); do { *((volatile int*)__null) = 10328; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10329 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.h"
, 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults"
")"); do { *((volatile int*)__null) = 10330; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
10330 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.h"
, 10330); AnnotateMozCrashReason("MOZ_ASSERT" "(" "valueBase->type() == MIRType::Pointer || valueBase->type() == MIRType::StackResults"
")"); do { *((volatile int*)__null) = 10330; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10331 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.h"
, 10331); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 10331; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10332 initOperand(0, instance);
10333 initOperand(1, valueBase);
10334 initOperand(2, value);
10335 }
10336
10337 public:
10338 INSTRUCTION_HEADER(WasmStoreRef)
10339 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)...); }
10340 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); }
10341
10342 uint32_t offset() const { return offset_; }
10343 AliasSet getAliasSet() const override { return AliasSet::Store(aliasSet_); }
10344 WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }
10345
10346#ifdef JS_JITSPEW1
10347 void getExtras(ExtrasCollector* extras) override {
10348 char buf[64];
10349 SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_);
10350 extras->add(buf);
10351 }
10352#endif
10353};
10354
10355// Given a value being written to another object, update the generational store
10356// buffer if the value is in the nursery and object is in the tenured heap.
10357class MWasmPostWriteBarrierImmediate : public MQuaternaryInstruction,
10358 public NoTypePolicy::Data {
10359 uint32_t valueOffset_;
10360
10361 MWasmPostWriteBarrierImmediate(MDefinition* instance, MDefinition* object,
10362 MDefinition* valueBase, uint32_t valueOffset,
10363 MDefinition* value)
10364 : MQuaternaryInstruction(classOpcode, instance, object, valueBase, value),
10365 valueOffset_(valueOffset) {
10366 setGuard();
10367 }
10368
10369 public:
10370 INSTRUCTION_HEADER(WasmPostWriteBarrierImmediate)
10371 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)...); }
10372 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); }
10373
10374 AliasSet getAliasSet() const override { return AliasSet::None(); }
10375 uint32_t valueOffset() const { return valueOffset_; }
10376
10377 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; }
10378};
10379
10380// Given a value being written to another object, update the generational store
10381// buffer if the value is in the nursery and object is in the tenured heap.
10382class MWasmPostWriteBarrierIndex : public MAryInstruction<5>,
10383 public NoTypePolicy::Data {
10384 uint32_t elemSize_;
10385
10386 MWasmPostWriteBarrierIndex(MDefinition* instance, MDefinition* object,
10387 MDefinition* valueBase, MDefinition* index,
10388 uint32_t scale, MDefinition* value)
10389 : MAryInstruction<5>(classOpcode), elemSize_(scale) {
10390 initOperand(0, instance);
10391 initOperand(1, object);
10392 initOperand(2, valueBase);
10393 initOperand(3, index);
10394 initOperand(4, value);
10395 setGuard();
10396 }
10397
10398 public:
10399 INSTRUCTION_HEADER(WasmPostWriteBarrierIndex)
10400 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)...); }
10401 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); }
10402 (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); }
10403
10404 AliasSet getAliasSet() const override { return AliasSet::None(); }
10405 uint32_t elemSize() const { return elemSize_; }
10406
10407 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; }
10408};
10409
10410class MWasmParameter : public MNullaryInstruction {
10411 ABIArg abi_;
10412
10413 MWasmParameter(ABIArg abi, MIRType mirType)
10414 : MNullaryInstruction(classOpcode), abi_(abi) {
10415 setResultType(mirType);
10416 }
10417
10418 public:
10419 INSTRUCTION_HEADER(WasmParameter)
10420 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)...); }
10421
10422 ABIArg abi() const { return abi_; }
10423};
10424
10425class MWasmReturn : public MAryControlInstruction<2, 0>,
10426 public NoTypePolicy::Data {
10427 MWasmReturn(MDefinition* ins, MDefinition* instance)
10428 : MAryControlInstruction(classOpcode) {
10429 initOperand(0, ins);
10430 initOperand(1, instance);
10431 }
10432
10433 public:
10434 INSTRUCTION_HEADER(WasmReturn)
10435 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)...); }
10436
10437 AliasSet getAliasSet() const override { return AliasSet::None(); }
10438};
10439
10440class MWasmReturnVoid : public MAryControlInstruction<1, 0>,
10441 public NoTypePolicy::Data {
10442 explicit MWasmReturnVoid(MDefinition* instance)
10443 : MAryControlInstruction(classOpcode) {
10444 initOperand(0, instance);
10445 }
10446
10447 public:
10448 INSTRUCTION_HEADER(WasmReturnVoid)
10449 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)...); }
10450
10451 AliasSet getAliasSet() const override { return AliasSet::None(); }
10452};
10453
10454class MWasmStackArg : public MUnaryInstruction, public NoTypePolicy::Data {
10455 MWasmStackArg(uint32_t spOffset, MDefinition* ins)
10456 : MUnaryInstruction(classOpcode, ins), spOffset_(spOffset) {}
10457
10458 uint32_t spOffset_;
10459
10460 public:
10461 INSTRUCTION_HEADER(WasmStackArg)
10462 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)...); }
10463 NAMED_OPERANDS((0, arg))MDefinition* arg() const { return getOperand(0); }
10464
10465 uint32_t spOffset() const { return spOffset_; }
10466 void incrementOffset(uint32_t inc) { spOffset_ += inc; }
10467};
10468
10469template <typename Location>
10470class MWasmResultBase : public MNullaryInstruction {
10471 Location loc_;
10472
10473 protected:
10474 MWasmResultBase(Opcode op, MIRType type, Location loc)
10475 : MNullaryInstruction(op), loc_(loc) {
10476 setResultType(type);
10477 setCallResultCapture();
10478 }
10479
10480 public:
10481 Location loc() { return loc_; }
10482};
10483
10484class MWasmRegisterResult : public MWasmResultBase<Register> {
10485 MWasmRegisterResult(MIRType type, Register reg)
10486 : MWasmResultBase(classOpcode, type, reg) {}
10487
10488 public:
10489 INSTRUCTION_HEADER(WasmRegisterResult)
10490 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)...); }
10491};
10492
10493class MWasmFloatRegisterResult : public MWasmResultBase<FloatRegister> {
10494 MWasmFloatRegisterResult(MIRType type, FloatRegister reg)
10495 : MWasmResultBase(classOpcode, type, reg) {}
10496
10497 public:
10498 INSTRUCTION_HEADER(WasmFloatRegisterResult)
10499 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)...); }
10500};
10501
10502class MWasmRegister64Result : public MWasmResultBase<Register64> {
10503 explicit MWasmRegister64Result(Register64 reg)
10504 : MWasmResultBase(classOpcode, MIRType::Int64, reg) {}
10505
10506 public:
10507 INSTRUCTION_HEADER(WasmRegister64Result)
10508 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)...); }
10509};
10510
10511class MWasmStackResultArea : public MNullaryInstruction {
10512 public:
10513 class StackResult {
10514 // Offset in bytes from lowest address of stack result area.
10515 uint32_t offset_;
10516 MIRType type_;
10517
10518 public:
10519 StackResult() : type_(MIRType::Undefined) {}
10520 StackResult(uint32_t offset, MIRType type) : offset_(offset), type_(type) {}
10521
10522 bool initialized() const { return type_ != MIRType::Undefined; }
10523 uint32_t offset() const {
10524 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.h"
, 10524); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initialized()"
")"); do { *((volatile int*)__null) = 10524; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10525 return offset_;
10526 }
10527 MIRType type() const {
10528 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.h"
, 10528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "initialized()"
")"); do { *((volatile int*)__null) = 10528; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10529 return type_;
10530 }
10531 uint32_t endOffset() const {
10532 return offset() + wasm::MIRTypeToABIResultSize(type());
10533 }
10534 };
10535
10536 private:
10537 FixedList<StackResult> results_;
10538 uint32_t base_;
10539
10540 explicit MWasmStackResultArea()
10541 : MNullaryInstruction(classOpcode), base_(UINT32_MAX(4294967295U)) {
10542 setResultType(MIRType::StackResults);
10543 }
10544
10545 void assertInitialized() const {
10546 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.h"
, 10546); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_.length() != 0"
")"); do { *((volatile int*)__null) = 10546; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10547#ifdef DEBUG1
10548 for (size_t i = 0; i < results_.length(); i++) {
10549 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.h"
, 10549); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_[i].initialized()"
")"); do { *((volatile int*)__null) = 10549; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10550 }
10551#endif
10552 }
10553
10554 bool baseInitialized() const { return base_ != UINT32_MAX(4294967295U); }
10555
10556 public:
10557 INSTRUCTION_HEADER(WasmStackResultArea)
10558 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)...); }
10559
10560 [[nodiscard]] bool init(TempAllocator& alloc, size_t stackResultCount) {
10561 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.h"
, 10561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_.length() == 0"
")"); do { *((volatile int*)__null) = 10561; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10562 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.h"
, 10562); AnnotateMozCrashReason("MOZ_ASSERT" "(" "stackResultCount > 0"
")"); do { *((volatile int*)__null) = 10562; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10563 if (!results_.init(alloc, stackResultCount)) {
10564 return false;
10565 }
10566 for (size_t n = 0; n < stackResultCount; n++) {
10567 results_[n] = StackResult();
10568 }
10569 return true;
10570 }
10571
10572 size_t resultCount() const { return results_.length(); }
10573 const StackResult& result(size_t n) const {
10574 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.h"
, 10574); AnnotateMozCrashReason("MOZ_ASSERT" "(" "results_[n].initialized()"
")"); do { *((volatile int*)__null) = 10574; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10575 return results_[n];
10576 }
10577 void initResult(size_t n, const StackResult& loc) {
10578 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.h"
, 10578); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!results_[n].initialized()"
")"); do { *((volatile int*)__null) = 10578; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10579 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.h"
, 10579); AnnotateMozCrashReason("MOZ_ASSERT" "(" "(n == 0) == (loc.offset() == 0)"
")"); do { *((volatile int*)__null) = 10579; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10580 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.h"
, 10580); AnnotateMozCrashReason("MOZ_ASSERT" "(" "loc.offset() >= result(n - 1).endOffset()"
")"); do { *((volatile int*)__null) = 10580; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
10581 results_[n] = loc;
10582 }
10583
10584 uint32_t byteSize() const {
10585 assertInitialized();
10586 return result(resultCount() - 1).endOffset();
10587 }
10588
10589 // Stack index indicating base of stack area.
10590 uint32_t base() const {
10591 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.h"
, 10591); AnnotateMozCrashReason("MOZ_ASSERT" "(" "baseInitialized()"
")"); do { *((volatile int*)__null) = 10591; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10592 return base_;
10593 }
10594 void setBase(uint32_t base) {
10595 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.h"
, 10595); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!baseInitialized()"
")"); do { *((volatile int*)__null) = 10595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10596 base_ = base;
10597 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.h"
, 10597); AnnotateMozCrashReason("MOZ_ASSERT" "(" "baseInitialized()"
")"); do { *((volatile int*)__null) = 10597; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10598 }
10599};
10600
10601class MWasmStackResult : public MUnaryInstruction, public NoTypePolicy::Data {
10602 uint32_t resultIdx_;
10603
10604 MWasmStackResult(MWasmStackResultArea* resultArea, size_t idx)
10605 : MUnaryInstruction(classOpcode, resultArea), resultIdx_(idx) {
10606 setResultType(result().type());
10607 setCallResultCapture();
10608 }
10609
10610 public:
10611 INSTRUCTION_HEADER(WasmStackResult)
10612 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)...); }
10613 NAMED_OPERANDS((0, resultArea))MDefinition* resultArea() const { return getOperand(0); }
10614
10615 const MWasmStackResultArea::StackResult& result() const {
10616 return resultArea()->toWasmStackResultArea()->result(resultIdx_);
10617 }
10618};
10619
10620// Arguments for constructing a catchable wasm call inside of a try block.
10621struct MWasmCallTryDesc {
10622 bool inTry;
10623 uint32_t relativeTryDepth;
10624 size_t tryNoteIndex;
10625 MBasicBlock* fallthroughBlock;
10626 MBasicBlock* prePadBlock;
10627
10628 MWasmCallTryDesc()
10629 : inTry(false),
10630 relativeTryDepth(0),
10631 tryNoteIndex(0),
10632 fallthroughBlock(nullptr),
10633 prePadBlock(nullptr) {}
10634};
10635
10636// Mixin class for wasm calls that may or may not be catchable.
10637class MWasmCallBase {
10638 public:
10639 struct Arg {
10640 AnyRegister reg;
10641 MDefinition* def;
10642 Arg(AnyRegister reg, MDefinition* def) : reg(reg), def(def) {}
10643 };
10644 typedef Vector<Arg, 8, SystemAllocPolicy> Args;
10645
10646 protected:
10647 wasm::CallSiteDesc desc_;
10648 wasm::CalleeDesc callee_;
10649 wasm::FailureMode builtinMethodFailureMode_;
10650 FixedList<AnyRegister> argRegs_;
10651 uint32_t stackArgAreaSizeUnaligned_;
10652 ABIArg instanceArg_;
10653 bool inTry_;
10654 size_t tryNoteIndex_;
10655
10656 MWasmCallBase(const wasm::CallSiteDesc& desc, const wasm::CalleeDesc& callee,
10657 uint32_t stackArgAreaSizeUnaligned, bool inTry,
10658 size_t tryNoteIndex)
10659 : desc_(desc),
10660 callee_(callee),
10661 builtinMethodFailureMode_(wasm::FailureMode::Infallible),
10662 stackArgAreaSizeUnaligned_(stackArgAreaSizeUnaligned),
10663 inTry_(inTry),
10664 tryNoteIndex_(tryNoteIndex) {}
10665
10666 template <class MVariadicT>
10667 [[nodiscard]] bool initWithArgs(TempAllocator& alloc, MVariadicT* ins,
10668 const Args& args,
10669 MDefinition* tableIndexOrRef) {
10670 if (!argRegs_.init(alloc, args.length())) {
10671 return false;
10672 }
10673 for (size_t i = 0; i < argRegs_.length(); i++) {
10674 argRegs_[i] = args[i].reg;
10675 }
10676
10677 if (!ins->init(alloc, argRegs_.length() + (tableIndexOrRef ? 1 : 0))) {
10678 return false;
10679 }
10680 // FixedList doesn't initialize its elements, so do an unchecked init.
10681 for (size_t i = 0; i < argRegs_.length(); i++) {
10682 ins->initOperand(i, args[i].def);
10683 }
10684 if (tableIndexOrRef) {
10685 ins->initOperand(argRegs_.length(), tableIndexOrRef);
10686 }
10687 return true;
10688 }
10689
10690 public:
10691 static bool IsWasmCall(MDefinition* def) {
10692 return def->isWasmCallCatchable() || def->isWasmCallUncatchable() ||
10693 def->isWasmReturnCall();
10694 }
10695
10696 size_t numArgs() const { return argRegs_.length(); }
10697 AnyRegister registerForArg(size_t index) const {
10698 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.h"
, 10698); AnnotateMozCrashReason("MOZ_ASSERT" "(" "index < numArgs()"
")"); do { *((volatile int*)__null) = 10698; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10699 return argRegs_[index];
10700 }
10701 const wasm::CallSiteDesc& desc() const { return desc_; }
10702 const wasm::CalleeDesc& callee() const { return callee_; }
10703 wasm::FailureMode builtinMethodFailureMode() const {
10704 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.h"
, 10704); AnnotateMozCrashReason("MOZ_ASSERT" "(" "callee_.which() == wasm::CalleeDesc::BuiltinInstanceMethod"
")"); do { *((volatile int*)__null) = 10704; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10705 return builtinMethodFailureMode_;
10706 }
10707 uint32_t stackArgAreaSizeUnaligned() const {
10708 return stackArgAreaSizeUnaligned_;
10709 }
10710
10711 const ABIArg& instanceArg() const { return instanceArg_; }
10712
10713 bool inTry() const { return inTry_; }
10714 size_t tryNoteIndex() const { return tryNoteIndex_; }
10715
10716 static AliasSet wasmCallAliasSet() {
10717 // This is ok because:
10718 // - numElements is immutable
10719 // - the GC will rewrite any array data pointers on move
10720 AliasSet exclude = AliasSet(AliasSet::WasmArrayNumElements) |
10721 AliasSet(AliasSet::WasmArrayDataPointer);
10722 return AliasSet::Store(AliasSet::Any) & ~exclude;
10723 }
10724};
10725
10726// A wasm call that is catchable. This instruction is a control instruction,
10727// and terminates the block it is on. A normal return will proceed in a the
10728// fallthrough block. An exceptional return will unwind into the landing pad
10729// block for this call. The landing pad block must begin with an
10730// MWasmCallLandingPrePad.
10731class MWasmCallCatchable final : public MVariadicControlInstruction<2>,
10732 public MWasmCallBase,
10733 public NoTypePolicy::Data {
10734 MWasmCallCatchable(const wasm::CallSiteDesc& desc,
10735 const wasm::CalleeDesc& callee,
10736 uint32_t stackArgAreaSizeUnaligned, size_t tryNoteIndex)
10737 : MVariadicControlInstruction(classOpcode),
10738 MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, true,
10739 tryNoteIndex) {}
10740
10741 public:
10742 INSTRUCTION_HEADER(WasmCallCatchable)
10743
10744 static MWasmCallCatchable* New(TempAllocator& alloc,
10745 const wasm::CallSiteDesc& desc,
10746 const wasm::CalleeDesc& callee,
10747 const Args& args,
10748 uint32_t stackArgAreaSizeUnaligned,
10749 const MWasmCallTryDesc& tryDesc,
10750 MDefinition* tableIndexOrRef = nullptr);
10751
10752 static MWasmCallCatchable* NewBuiltinInstanceMethodCall(
10753 TempAllocator& alloc, const wasm::CallSiteDesc& desc,
10754 const wasm::SymbolicAddress builtin, wasm::FailureMode failureMode,
10755 const ABIArg& instanceArg, const Args& args,
10756 uint32_t stackArgAreaSizeUnaligned, const MWasmCallTryDesc& tryDesc);
10757
10758 bool possiblyCalls() const override { return true; }
10759 AliasSet getAliasSet() const override { return wasmCallAliasSet(); }
10760
10761 static const size_t FallthroughBranchIndex = 0;
10762 static const size_t PrePadBranchIndex = 1;
10763};
10764
10765// A wasm call that is not catchable. This instruction is not a control
10766// instruction, and therefore is not a block terminator.
10767class MWasmCallUncatchable final : public MVariadicInstruction,
10768 public MWasmCallBase,
10769 public NoTypePolicy::Data {
10770 MWasmCallUncatchable(const wasm::CallSiteDesc& desc,
10771 const wasm::CalleeDesc& callee,
10772 uint32_t stackArgAreaSizeUnaligned)
10773 : MVariadicInstruction(classOpcode),
10774 MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, false, 0) {}
10775
10776 public:
10777 INSTRUCTION_HEADER(WasmCallUncatchable)
10778
10779 static MWasmCallUncatchable* New(TempAllocator& alloc,
10780 const wasm::CallSiteDesc& desc,
10781 const wasm::CalleeDesc& callee,
10782 const Args& args,
10783 uint32_t stackArgAreaSizeUnaligned,
10784 MDefinition* tableIndexOrRef = nullptr);
10785
10786 static MWasmCallUncatchable* NewBuiltinInstanceMethodCall(
10787 TempAllocator& alloc, const wasm::CallSiteDesc& desc,
10788 const wasm::SymbolicAddress builtin, wasm::FailureMode failureMode,
10789 const ABIArg& instanceArg, const Args& args,
10790 uint32_t stackArgAreaSizeUnaligned);
10791
10792 bool possiblyCalls() const override { return true; }
10793 AliasSet getAliasSet() const override { return wasmCallAliasSet(); }
10794};
10795
10796class MWasmReturnCall final : public MVariadicControlInstruction<0>,
10797 public MWasmCallBase,
10798 public NoTypePolicy::Data {
10799 MWasmReturnCall(const wasm::CallSiteDesc& desc,
10800 const wasm::CalleeDesc& callee,
10801 uint32_t stackArgAreaSizeUnaligned)
10802 : MVariadicControlInstruction(classOpcode),
10803 MWasmCallBase(desc, callee, stackArgAreaSizeUnaligned, false, 0) {}
10804
10805 public:
10806 INSTRUCTION_HEADER(WasmReturnCall)
10807
10808 static MWasmReturnCall* New(TempAllocator& alloc,
10809 const wasm::CallSiteDesc& desc,
10810 const wasm::CalleeDesc& callee, const Args& args,
10811 uint32_t stackArgAreaSizeUnaligned,
10812 MDefinition* tableIndexOrRef = nullptr);
10813
10814 bool possiblyCalls() const override { return true; }
10815};
10816
10817// A marker instruction for a block which is the landing pad for a catchable
10818// wasm call. This instruction does not emit any code, only filling in
10819// metadata. This instruction must be the first instruction added to the
10820// landing pad block.
10821class MWasmCallLandingPrePad : public MNullaryInstruction {
10822 // The block of the call that may unwind to this landing pad.
10823 MBasicBlock* callBlock_;
10824 // The index of the try note to initialize a landing pad for.
10825 size_t tryNoteIndex_;
10826
10827 explicit MWasmCallLandingPrePad(MBasicBlock* callBlock, size_t tryNoteIndex)
10828 : MNullaryInstruction(classOpcode),
10829 callBlock_(callBlock),
10830 tryNoteIndex_(tryNoteIndex) {
10831 setGuard();
10832 }
10833
10834 public:
10835 INSTRUCTION_HEADER(WasmCallLandingPrePad)
10836 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)...); }
10837
10838 AliasSet getAliasSet() const override { return AliasSet::None(); }
10839
10840 size_t tryNoteIndex() { return tryNoteIndex_; }
10841 MBasicBlock* callBlock() { return callBlock_; }
10842};
10843
10844class MWasmSelect : public MTernaryInstruction, public NoTypePolicy::Data {
10845 MWasmSelect(MDefinition* trueExpr, MDefinition* falseExpr,
10846 MDefinition* condExpr)
10847 : MTernaryInstruction(classOpcode, trueExpr, falseExpr, condExpr) {
10848 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.h"
, 10848); AnnotateMozCrashReason("MOZ_ASSERT" "(" "condExpr->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 10848; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10849 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.h"
, 10849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "trueExpr->type() == falseExpr->type()"
")"); do { *((volatile int*)__null) = 10849; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10850 setResultType(trueExpr->type());
10851 setMovable();
10852 }
10853
10854 public:
10855 INSTRUCTION_HEADER(WasmSelect)
10856 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)...); }
10857 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); }
10858
10859 AliasSet getAliasSet() const override { return AliasSet::None(); }
10860
10861 bool congruentTo(const MDefinition* ins) const override {
10862 return congruentIfOperandsEqual(ins);
10863 }
10864
10865 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; }
10866};
10867
10868class MWasmReinterpret : public MUnaryInstruction, public NoTypePolicy::Data {
10869 MWasmReinterpret(MDefinition* val, MIRType toType)
10870 : MUnaryInstruction(classOpcode, val) {
10871 switch (val->type()) {
10872 case MIRType::Int32:
10873 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.h"
, 10873); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Float32"
")"); do { *((volatile int*)__null) = 10873; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10874 break;
10875 case MIRType::Float32:
10876 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.h"
, 10876); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Int32"
")"); do { *((volatile int*)__null) = 10876; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10877 break;
10878 case MIRType::Double:
10879 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.h"
, 10879); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Int64"
")"); do { *((volatile int*)__null) = 10879; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10880 break;
10881 case MIRType::Int64:
10882 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.h"
, 10882); AnnotateMozCrashReason("MOZ_ASSERT" "(" "toType == MIRType::Double"
")"); do { *((volatile int*)__null) = 10882; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
10883 break;
10884 default:
10885 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.h"
, 10885); AnnotateMozCrashReason("MOZ_CRASH(" "unexpected reinterpret conversion"
")"); do { *((volatile int*)__null) = 10885; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
10886 }
10887 setMovable();
10888 setResultType(toType);
10889 }
10890
10891 public:
10892 INSTRUCTION_HEADER(WasmReinterpret)
10893 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)...); }
10894
10895 AliasSet getAliasSet() const override { return AliasSet::None(); }
10896 bool congruentTo(const MDefinition* ins) const override {
10897 // No need to check type() here, because congruentIfOperandsEqual will
10898 // check it.
10899 return congruentIfOperandsEqual(ins);
10900 }
10901
10902 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; }
10903};
10904
10905class MRotate : public MBinaryInstruction, public NoTypePolicy::Data {
10906 bool isLeftRotate_;
10907
10908 MRotate(MDefinition* input, MDefinition* count, MIRType type,
10909 bool isLeftRotate)
10910 : MBinaryInstruction(classOpcode, input, count),
10911 isLeftRotate_(isLeftRotate) {
10912 setMovable();
10913 setResultType(type);
10914 // Prevent reordering. Although there's no problem eliding call result
10915 // definitions, there's also no need, as they cause no codegen.
10916 setGuard();
10917 }
10918
10919 public:
10920 INSTRUCTION_HEADER(Rotate)
10921 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)...); }
10922 NAMED_OPERANDS((0, input), (1, count))MDefinition* input() const { return getOperand(0); } MDefinition
* count() const { return getOperand(1); }
10923
10924 AliasSet getAliasSet() const override { return AliasSet::None(); }
10925 bool congruentTo(const MDefinition* ins) const override {
10926 return congruentIfOperandsEqual(ins) &&
10927 ins->toRotate()->isLeftRotate() == isLeftRotate_;
10928 }
10929
10930 bool isLeftRotate() const { return isLeftRotate_; }
10931
10932 ALLOW_CLONE(MRotate)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MRotate
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
10933};
10934
10935// Wasm SIMD.
10936//
10937// See comment in WasmIonCompile.cpp for a justification for these nodes.
10938
10939// (v128, v128, v128) -> v128 effect-free operation.
10940class MWasmTernarySimd128 : public MTernaryInstruction,
10941 public NoTypePolicy::Data {
10942 wasm::SimdOp simdOp_;
10943
10944 MWasmTernarySimd128(MDefinition* v0, MDefinition* v1, MDefinition* v2,
10945 wasm::SimdOp simdOp)
10946 : MTernaryInstruction(classOpcode, v0, v1, v2), simdOp_(simdOp) {
10947 setMovable();
10948 setResultType(MIRType::Simd128);
10949 }
10950
10951 public:
10952 INSTRUCTION_HEADER(WasmTernarySimd128)
10953 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)...); }
10954 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); }
10955
10956 AliasSet getAliasSet() const override { return AliasSet::None(); }
10957 bool congruentTo(const MDefinition* ins) const override {
10958 return congruentIfOperandsEqual(ins) &&
10959 simdOp() == ins->toWasmTernarySimd128()->simdOp();
10960 }
10961#ifdef ENABLE_WASM_SIMD1
10962 MDefinition* foldsTo(TempAllocator& alloc) override;
10963
10964 // If the control mask of a bitselect allows the operation to be specialized
10965 // as a shuffle and it is profitable to specialize it on this platform, return
10966 // true and the appropriate shuffle mask.
10967 bool specializeBitselectConstantMaskAsShuffle(int8_t shuffle[16]);
10968 // Checks if more relaxed version of lane select can be used. It returns true
10969 // if a bit mask input expected to be all 0s or 1s for entire 8-bit lanes,
10970 // false otherwise.
10971 bool canRelaxBitselect();
10972#endif
10973
10974 wasm::SimdOp simdOp() const { return simdOp_; }
10975
10976 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; }
10977};
10978
10979// (v128, v128) -> v128 effect-free operations.
10980class MWasmBinarySimd128 : public MBinaryInstruction,
10981 public NoTypePolicy::Data {
10982 wasm::SimdOp simdOp_;
10983
10984 MWasmBinarySimd128(MDefinition* lhs, MDefinition* rhs, bool commutative,
10985 wasm::SimdOp simdOp)
10986 : MBinaryInstruction(classOpcode, lhs, rhs), simdOp_(simdOp) {
10987 setMovable();
10988 setResultType(MIRType::Simd128);
10989 if (commutative) {
10990 setCommutative();
10991 }
10992 }
10993
10994 public:
10995 INSTRUCTION_HEADER(WasmBinarySimd128)
10996 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)...); }
10997
10998 AliasSet getAliasSet() const override { return AliasSet::None(); }
10999 bool congruentTo(const MDefinition* ins) const override {
11000 return congruentIfOperandsEqual(ins) &&
11001 ins->toWasmBinarySimd128()->simdOp() == simdOp_;
11002 }
11003#ifdef ENABLE_WASM_SIMD1
11004 MDefinition* foldsTo(TempAllocator& alloc) override;
11005
11006 // Checks if pmaddubsw operation is supported.
11007 bool canPmaddubsw();
11008#endif
11009
11010 wasm::SimdOp simdOp() const { return simdOp_; }
11011
11012 // Platform-dependent specialization.
11013 bool specializeForConstantRhs();
11014
11015 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; }
11016};
11017
11018// (v128, const) -> v128 effect-free operations.
11019class MWasmBinarySimd128WithConstant : public MUnaryInstruction,
11020 public NoTypePolicy::Data {
11021 SimdConstant rhs_;
11022 wasm::SimdOp simdOp_;
11023
11024 MWasmBinarySimd128WithConstant(MDefinition* lhs, const SimdConstant& rhs,
11025 wasm::SimdOp simdOp)
11026 : MUnaryInstruction(classOpcode, lhs), rhs_(rhs), simdOp_(simdOp) {
11027 setMovable();
11028 setResultType(MIRType::Simd128);
11029 }
11030
11031 public:
11032 INSTRUCTION_HEADER(WasmBinarySimd128WithConstant)
11033 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)...); }
11034
11035 AliasSet getAliasSet() const override { return AliasSet::None(); }
11036 bool congruentTo(const MDefinition* ins) const override {
11037 return congruentIfOperandsEqual(ins) &&
11038 ins->toWasmBinarySimd128WithConstant()->simdOp() == simdOp_ &&
11039 rhs_.bitwiseEqual(ins->toWasmBinarySimd128WithConstant()->rhs());
11040 }
11041
11042 wasm::SimdOp simdOp() const { return simdOp_; }
11043 MDefinition* lhs() const { return input(); }
11044 const SimdConstant& rhs() const { return rhs_; }
11045
11046 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; }
11047};
11048
11049// (v128, scalar, imm) -> v128 effect-free operations.
11050class MWasmReplaceLaneSimd128 : public MBinaryInstruction,
11051 public NoTypePolicy::Data {
11052 uint32_t laneIndex_;
11053 wasm::SimdOp simdOp_;
11054
11055 MWasmReplaceLaneSimd128(MDefinition* lhs, MDefinition* rhs,
11056 uint32_t laneIndex, wasm::SimdOp simdOp)
11057 : MBinaryInstruction(classOpcode, lhs, rhs),
11058 laneIndex_(laneIndex),
11059 simdOp_(simdOp) {
11060 setMovable();
11061 setResultType(MIRType::Simd128);
11062 }
11063
11064 public:
11065 INSTRUCTION_HEADER(WasmReplaceLaneSimd128)
11066 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)...); }
11067
11068 AliasSet getAliasSet() const override { return AliasSet::None(); }
11069 bool congruentTo(const MDefinition* ins) const override {
11070 return congruentIfOperandsEqual(ins) &&
11071 ins->toWasmReplaceLaneSimd128()->simdOp() == simdOp_ &&
11072 ins->toWasmReplaceLaneSimd128()->laneIndex() == laneIndex_;
11073 }
11074
11075 uint32_t laneIndex() const { return laneIndex_; }
11076 wasm::SimdOp simdOp() const { return simdOp_; }
11077
11078 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; }
11079};
11080
11081// (scalar) -> v128 effect-free operations.
11082class MWasmScalarToSimd128 : public MUnaryInstruction,
11083 public NoTypePolicy::Data {
11084 wasm::SimdOp simdOp_;
11085
11086 MWasmScalarToSimd128(MDefinition* src, wasm::SimdOp simdOp)
11087 : MUnaryInstruction(classOpcode, src), simdOp_(simdOp) {
11088 setMovable();
11089 setResultType(MIRType::Simd128);
11090 }
11091
11092 public:
11093 INSTRUCTION_HEADER(WasmScalarToSimd128)
11094 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)...); }
11095
11096 AliasSet getAliasSet() const override { return AliasSet::None(); }
11097 bool congruentTo(const MDefinition* ins) const override {
11098 return congruentIfOperandsEqual(ins) &&
11099 ins->toWasmScalarToSimd128()->simdOp() == simdOp_;
11100 }
11101#ifdef ENABLE_WASM_SIMD1
11102 MDefinition* foldsTo(TempAllocator& alloc) override;
11103#endif
11104
11105 wasm::SimdOp simdOp() const { return simdOp_; }
11106
11107 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; }
11108};
11109
11110// (v128, imm) -> scalar effect-free operations.
11111class MWasmReduceSimd128 : public MUnaryInstruction, public NoTypePolicy::Data {
11112 wasm::SimdOp simdOp_;
11113 uint32_t imm_;
11114
11115 MWasmReduceSimd128(MDefinition* src, wasm::SimdOp simdOp, MIRType outType,
11116 uint32_t imm)
11117 : MUnaryInstruction(classOpcode, src), simdOp_(simdOp), imm_(imm) {
11118 setMovable();
11119 setResultType(outType);
11120 }
11121
11122 public:
11123 INSTRUCTION_HEADER(WasmReduceSimd128)
11124 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)...); }
11125
11126 AliasSet getAliasSet() const override { return AliasSet::None(); }
11127 bool congruentTo(const MDefinition* ins) const override {
11128 return congruentIfOperandsEqual(ins) &&
11129 ins->toWasmReduceSimd128()->simdOp() == simdOp_ &&
11130 ins->toWasmReduceSimd128()->imm() == imm_;
11131 }
11132#ifdef ENABLE_WASM_SIMD1
11133 MDefinition* foldsTo(TempAllocator& alloc) override;
11134#endif
11135
11136 uint32_t imm() const { return imm_; }
11137 wasm::SimdOp simdOp() const { return simdOp_; }
11138
11139 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; }
11140};
11141
11142class MWasmLoadLaneSimd128
11143 : public MVariadicInstruction, // memoryBase is nullptr on some platforms
11144 public NoTypePolicy::Data {
11145 wasm::MemoryAccessDesc access_;
11146 uint32_t laneSize_;
11147 uint32_t laneIndex_;
11148 uint32_t memoryBaseIndex_;
11149
11150 MWasmLoadLaneSimd128(const wasm::MemoryAccessDesc& access, uint32_t laneSize,
11151 uint32_t laneIndex, uint32_t memoryBaseIndex)
11152 : MVariadicInstruction(classOpcode),
11153 access_(access),
11154 laneSize_(laneSize),
11155 laneIndex_(laneIndex),
11156 memoryBaseIndex_(memoryBaseIndex) {
11157 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.h"
, 11157); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!access_.isAtomic()"
")"); do { *((volatile int*)__null) = 11157; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11158 setGuard();
11159 setResultType(MIRType::Simd128);
11160 }
11161
11162 public:
11163 INSTRUCTION_HEADER(WasmLoadLaneSimd128)
11164 NAMED_OPERANDS((0, base), (1, value))MDefinition* base() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
;
11165
11166 static MWasmLoadLaneSimd128* New(TempAllocator& alloc,
11167 MDefinition* memoryBase, MDefinition* base,
11168 const wasm::MemoryAccessDesc& access,
11169 uint32_t laneSize, uint32_t laneIndex,
11170 MDefinition* value) {
11171 uint32_t nextIndex = 2;
11172 uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U);
11173
11174 MWasmLoadLaneSimd128* load = new (alloc)
11175 MWasmLoadLaneSimd128(access, laneSize, laneIndex, memoryBaseIndex);
11176 if (!load->init(alloc, nextIndex)) {
11177 return nullptr;
11178 }
11179
11180 load->initOperand(0, base);
11181 load->initOperand(1, value);
11182 if (memoryBase) {
11183 load->initOperand(memoryBaseIndex, memoryBase);
11184 }
11185
11186 return load;
11187 }
11188
11189 const wasm::MemoryAccessDesc& access() const { return access_; }
11190 uint32_t laneSize() const { return laneSize_; }
11191 uint32_t laneIndex() const { return laneIndex_; }
11192 bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); }
11193 MDefinition* memoryBase() const {
11194 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.h"
, 11194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()"
")"); do { *((volatile int*)__null) = 11194; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11195 return getOperand(memoryBaseIndex_);
11196 }
11197
11198 AliasSet getAliasSet() const override {
11199 return AliasSet::Load(AliasSet::WasmHeap);
11200 }
11201};
11202
11203class MWasmStoreLaneSimd128 : public MVariadicInstruction,
11204 public NoTypePolicy::Data {
11205 wasm::MemoryAccessDesc access_;
11206 uint32_t laneSize_;
11207 uint32_t laneIndex_;
11208 uint32_t memoryBaseIndex_;
11209
11210 explicit MWasmStoreLaneSimd128(const wasm::MemoryAccessDesc& access,
11211 uint32_t laneSize, uint32_t laneIndex,
11212 uint32_t memoryBaseIndex)
11213 : MVariadicInstruction(classOpcode),
11214 access_(access),
11215 laneSize_(laneSize),
11216 laneIndex_(laneIndex),
11217 memoryBaseIndex_(memoryBaseIndex) {
11218 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.h"
, 11218); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!access_.isAtomic()"
")"); do { *((volatile int*)__null) = 11218; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11219 setGuard();
11220 setResultType(MIRType::Simd128);
11221 }
11222
11223 public:
11224 INSTRUCTION_HEADER(WasmStoreLaneSimd128)
11225 NAMED_OPERANDS((0, base), (1, value))MDefinition* base() const { return getOperand(0); } MDefinition
* value() const { return getOperand(1); }
11226
11227 static MWasmStoreLaneSimd128* New(TempAllocator& alloc,
11228 MDefinition* memoryBase, MDefinition* base,
11229 const wasm::MemoryAccessDesc& access,
11230 uint32_t laneSize, uint32_t laneIndex,
11231 MDefinition* value) {
11232 uint32_t nextIndex = 2;
11233 uint32_t memoryBaseIndex = memoryBase ? nextIndex++ : UINT32_MAX(4294967295U);
11234
11235 MWasmStoreLaneSimd128* store = new (alloc)
11236 MWasmStoreLaneSimd128(access, laneSize, laneIndex, memoryBaseIndex);
11237 if (!store->init(alloc, nextIndex)) {
11238 return nullptr;
11239 }
11240
11241 store->initOperand(0, base);
11242 store->initOperand(1, value);
11243 if (memoryBase) {
11244 store->initOperand(memoryBaseIndex, memoryBase);
11245 }
11246
11247 return store;
11248 }
11249
11250 const wasm::MemoryAccessDesc& access() const { return access_; }
11251 uint32_t laneSize() const { return laneSize_; }
11252 uint32_t laneIndex() const { return laneIndex_; }
11253 bool hasMemoryBase() const { return memoryBaseIndex_ != UINT32_MAX(4294967295U); }
11254 MDefinition* memoryBase() const {
11255 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.h"
, 11255); AnnotateMozCrashReason("MOZ_ASSERT" "(" "hasMemoryBase()"
")"); do { *((volatile int*)__null) = 11255; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11256 return getOperand(memoryBaseIndex_);
11257 }
11258
11259 AliasSet getAliasSet() const override {
11260 return AliasSet::Store(AliasSet::WasmHeap);
11261 }
11262};
11263
11264// End Wasm SIMD
11265
11266// Used by MIR building to represent the bytecode result of an operation for
11267// which an MBail was generated, to balance the basic block's MDefinition stack.
11268class MUnreachableResult : public MNullaryInstruction {
11269 explicit MUnreachableResult(MIRType type) : MNullaryInstruction(classOpcode) {
11270 MOZ_ASSERT(type != MIRType::None)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(type != MIRType::None)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(type != MIRType::None))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("type != MIRType::None"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11270); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type != MIRType::None"
")"); do { *((volatile int*)__null) = 11270; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11271 setResultType(type);
11272 }
11273
11274 public:
11275 INSTRUCTION_HEADER(UnreachableResult)
11276 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)...); }
11277
11278 bool congruentTo(const MDefinition* ins) const override {
11279 return congruentIfOperandsEqual(ins);
11280 }
11281 AliasSet getAliasSet() const override { return AliasSet::None(); }
11282};
11283
11284class MIonToWasmCall final : public MVariadicInstruction,
11285 public NoTypePolicy::Data {
11286 CompilerGCPointer<WasmInstanceObject*> instanceObj_;
11287 const wasm::FuncExport& funcExport_;
11288
11289 MIonToWasmCall(WasmInstanceObject* instanceObj, MIRType resultType,
11290 const wasm::FuncExport& funcExport)
11291 : MVariadicInstruction(classOpcode),
11292 instanceObj_(instanceObj),
11293 funcExport_(funcExport) {
11294 setResultType(resultType);
11295 }
11296
11297 public:
11298 INSTRUCTION_HEADER(IonToWasmCall);
11299
11300 static MIonToWasmCall* New(TempAllocator& alloc,
11301 WasmInstanceObject* instanceObj,
11302 const wasm::FuncExport& funcExport);
11303
11304 void initArg(size_t i, MDefinition* arg) { initOperand(i, arg); }
11305
11306 WasmInstanceObject* instanceObject() const { return instanceObj_; }
11307 wasm::Instance* instance() const { return &instanceObj_->instance(); }
11308 const wasm::FuncExport& funcExport() const { return funcExport_; }
11309 bool possiblyCalls() const override { return true; }
11310#ifdef DEBUG1
11311 bool isConsistentFloat32Use(MUse* use) const override;
11312#endif
11313};
11314
11315// For accesses to wasm object fields, we need to be able to describe 8- and
11316// 16-bit accesses. But MIRType can't represent those. Hence these two
11317// supplemental enums, used for reading and writing fields respectively.
11318
11319// Indicates how to widen an 8- or 16-bit value (when it is read from memory).
11320enum class MWideningOp : uint8_t { None, FromU16, FromS16, FromU8, FromS8 };
11321
11322#ifdef JS_JITSPEW1
11323static inline const char* StringFromMWideningOp(MWideningOp op) {
11324 switch (op) {
11325 case MWideningOp::None:
11326 return "None";
11327 case MWideningOp::FromU16:
11328 return "FromU16";
11329 case MWideningOp::FromS16:
11330 return "FromS16";
11331 case MWideningOp::FromU8:
11332 return "FromU8";
11333 case MWideningOp::FromS8:
11334 return "FromS8";
11335 default:
11336 break;
11337 }
11338 MOZ_CRASH("Unknown MWideningOp")do { do { } while (false); MOZ_ReportCrash("" "Unknown MWideningOp"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11338); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown MWideningOp"
")"); do { *((volatile int*)__null) = 11338; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
11339}
11340#endif
11341
11342// Indicates how to narrow a 32-bit value (when it is written to memory). The
11343// operation is a simple truncate.
11344enum class MNarrowingOp : uint8_t { None, To16, To8 };
11345
11346#ifdef JS_JITSPEW1
11347static inline const char* StringFromMNarrowingOp(MNarrowingOp op) {
11348 switch (op) {
11349 case MNarrowingOp::None:
11350 return "None";
11351 case MNarrowingOp::To16:
11352 return "To16";
11353 case MNarrowingOp::To8:
11354 return "To8";
11355 default:
11356 break;
11357 }
11358 MOZ_CRASH("Unknown MNarrowingOp")do { do { } while (false); MOZ_ReportCrash("" "Unknown MNarrowingOp"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11358); AnnotateMozCrashReason("MOZ_CRASH(" "Unknown MNarrowingOp"
")"); do { *((volatile int*)__null) = 11358; __attribute__((
nomerge)) ::abort(); } while (false); } while (false)
;
11359}
11360#endif
11361
11362// Provide information about potential trap at the instruction machine code,
11363// e.g. null pointer dereference.
11364struct TrapSiteInfo {
11365 wasm::BytecodeOffset offset;
11366 explicit TrapSiteInfo(wasm::BytecodeOffset offset_) : offset(offset_) {}
11367};
11368
11369typedef mozilla::Maybe<TrapSiteInfo> MaybeTrapSiteInfo;
11370
11371// Load an object field stored at a fixed offset from a base pointer. This
11372// field may be any value type, including references. No barriers are
11373// performed. The offset must be representable as a 31-bit unsigned integer.
11374class MWasmLoadField : public MUnaryInstruction, public NoTypePolicy::Data {
11375 uint32_t offset_;
11376 MWideningOp wideningOp_;
11377 AliasSet aliases_;
11378 MaybeTrapSiteInfo maybeTrap_;
11379
11380 MWasmLoadField(MDefinition* obj, uint32_t offset, MIRType type,
11381 MWideningOp wideningOp, AliasSet aliases,
11382 MaybeTrapSiteInfo maybeTrap = mozilla::Nothing())
11383 : MUnaryInstruction(classOpcode, obj),
11384 offset_(uint32_t(offset)),
11385 wideningOp_(wideningOp),
11386 aliases_(aliases),
11387 maybeTrap_(maybeTrap) {
11388 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.h"
, 11388); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)"
")"); do { *((volatile int*)__null) = 11388; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11389 // "if you want to widen the value when it is loaded, the destination type
11390 // must be Int32".
11391 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.h"
, 11391); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11391; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11392 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11393 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11394 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11395 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11396 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11397 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11398 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11399 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.h"
, 11399); 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) = 11399; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11400 setResultType(type);
11401 if (maybeTrap_) {
11402 setGuard();
11403 }
11404 }
11405
11406 public:
11407 INSTRUCTION_HEADER(WasmLoadField)
11408 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)...); }
11409 NAMED_OPERANDS((0, obj))MDefinition* obj() const { return getOperand(0); }
11410
11411 uint32_t offset() const { return offset_; }
11412 MWideningOp wideningOp() const { return wideningOp_; }
11413 AliasSet getAliasSet() const override { return aliases_; }
11414 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11415
11416 bool congruentTo(const MDefinition* ins) const override {
11417 // In the limited case where this insn is used to read
11418 // WasmStructObject::outlineData_ (the field itself, not what it points
11419 // at), we allow commoning up to happen. This is OK because
11420 // WasmStructObject::outlineData_ is readonly for the life of the
11421 // WasmStructObject.
11422 if (!ins->isWasmLoadField()) {
11423 return false;
11424 }
11425 const MWasmLoadField* other = ins->toWasmLoadField();
11426 return ins->isWasmLoadField() && congruentIfOperandsEqual(ins) &&
11427 offset() == other->offset() && wideningOp() == other->wideningOp() &&
11428 getAliasSet().flags() == other->getAliasSet().flags();
11429 }
11430
11431#ifdef JS_JITSPEW1
11432 void getExtras(ExtrasCollector* extras) override {
11433 char buf[96];
11434 SprintfLiteral(buf, "(offs=%lld, wideningOp=%s)", (long long int)offset_,
11435 StringFromMWideningOp(wideningOp_));
11436 extras->add(buf);
11437 }
11438#endif
11439};
11440
11441// Loads a value from a location, denoted as a fixed offset from a base
11442// pointer, which (it is assumed) is within a wasm object. This field may be
11443// any value type, including references. No barriers are performed.
11444//
11445// This instruction takes a pointer to a second object `ka`, which it is
11446// necessary to keep alive. It is expected that `ka` holds a reference to
11447// `obj`, but this is not enforced and no code is generated to access `ka`.
11448// This instruction extends the lifetime of `ka` so that it, and hence `obj`,
11449// cannot be collected while `obj` is live. This is necessary if `obj` does
11450// not point to a GC-managed object. `offset` must be representable as a
11451// 31-bit unsigned integer.
11452class MWasmLoadFieldKA : public MBinaryInstruction, public NoTypePolicy::Data {
11453 uint32_t offset_;
11454 MWideningOp wideningOp_;
11455 AliasSet aliases_;
11456 MaybeTrapSiteInfo maybeTrap_;
11457
11458 MWasmLoadFieldKA(MDefinition* ka, MDefinition* obj, size_t offset,
11459 MIRType type, MWideningOp wideningOp, AliasSet aliases,
11460 MaybeTrapSiteInfo maybeTrap = mozilla::Nothing())
11461 : MBinaryInstruction(classOpcode, ka, obj),
11462 offset_(uint32_t(offset)),
11463 wideningOp_(wideningOp),
11464 aliases_(aliases),
11465 maybeTrap_(maybeTrap) {
11466 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.h"
, 11466); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)"
")"); do { *((volatile int*)__null) = 11466; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11467 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.h"
, 11467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "type == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11467; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11468 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11469 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11470 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11471 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11472 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11473 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11474 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11475 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.h"
, 11475); 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) = 11475; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11476 setResultType(type);
11477 if (maybeTrap_) {
11478 setGuard();
11479 }
11480 }
11481
11482 public:
11483 INSTRUCTION_HEADER(WasmLoadFieldKA)
11484 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)...); }
11485 NAMED_OPERANDS((0, ka), (1, obj))MDefinition* ka() const { return getOperand(0); } MDefinition
* obj() const { return getOperand(1); }
11486
11487 uint32_t offset() const { return offset_; }
11488 MWideningOp wideningOp() const { return wideningOp_; }
11489 AliasSet getAliasSet() const override { return aliases_; }
11490 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11491
11492#ifdef JS_JITSPEW1
11493 void getExtras(ExtrasCollector* extras) override {
11494 char buf[96];
11495 SprintfLiteral(buf, "(offs=%lld, wideningOp=%s)", (long long int)offset_,
11496 StringFromMWideningOp(wideningOp_));
11497 extras->add(buf);
11498 }
11499#endif
11500};
11501
11502// Loads a value from base pointer, given an index and element size. This field
11503// may be any value type, including references. No barriers are performed.
11504//
11505// The element size is implicitly defined by MIRType and MWideningOp. For
11506// example, MIRType::Float32 indicates an element size of 32 bits, and
11507// MIRType::Int32 and MWideningOp::FromU16 together indicate an element size of
11508// 16 bits.
11509//
11510// This instruction takes a second object `ka` that must be kept alive, as
11511// described for MWasmLoadFieldKA above.
11512class MWasmLoadElementKA : public MTernaryInstruction,
11513 public NoTypePolicy::Data {
11514 MWideningOp wideningOp_;
11515 Scale scale_;
11516 AliasSet aliases_;
11517 MaybeTrapSiteInfo maybeTrap_;
11518
11519 MWasmLoadElementKA(MDefinition* ka, MDefinition* base, MDefinition* index,
11520 MIRType type, MWideningOp wideningOp, Scale scale,
11521 AliasSet aliases,
11522 MaybeTrapSiteInfo maybeTrap = mozilla::Nothing())
11523 : MTernaryInstruction(classOpcode, ka, base, index),
11524 wideningOp_(wideningOp),
11525 scale_(scale),
11526 aliases_(aliases),
11527 maybeTrap_(maybeTrap) {
11528 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.h"
, 11528); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11528; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11529 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.h"
, 11531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11531; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11530 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.h"
, 11531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11531; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11531 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.h"
, 11531); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Load(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Load(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11531; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11532 setResultType(type);
11533 if (maybeTrap_) {
11534 setGuard();
11535 }
11536 }
11537
11538 public:
11539 INSTRUCTION_HEADER(WasmLoadElementKA)
11540 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)...); }
11541 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); }
11542
11543 MWideningOp wideningOp() const { return wideningOp_; }
11544 Scale scale() const { return scale_; }
11545 AliasSet getAliasSet() const override { return aliases_; }
11546 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11547
11548#ifdef JS_JITSPEW1
11549 void getExtras(ExtrasCollector* extras) override {
11550 char buf[96];
11551 SprintfLiteral(buf, "(wideningOp=%s, scale=%s)",
11552 StringFromMWideningOp(wideningOp_), StringFromScale(scale_));
11553 extras->add(buf);
11554 }
11555#endif
11556};
11557
11558// Stores a non-reference value to anlocation, denoted as a fixed offset from
11559// a base pointer, which (it is assumed) is within a wasm object. This field
11560// may be any value type, _excluding_ references. References _must_ use the
11561// 'Ref' variant of this instruction. The offset must be representable as a
11562// 31-bit unsigned integer.
11563//
11564// This instruction takes a second object `ka` that must be kept alive, as
11565// described for MWasmLoadFieldKA above.
11566class MWasmStoreFieldKA : public MTernaryInstruction,
11567 public NoTypePolicy::Data {
11568 uint32_t offset_;
11569 MNarrowingOp narrowingOp_;
11570 AliasSet aliases_;
11571 MaybeTrapSiteInfo maybeTrap_;
11572
11573 MWasmStoreFieldKA(MDefinition* ka, MDefinition* obj, size_t offset,
11574 MDefinition* value, MNarrowingOp narrowingOp,
11575 AliasSet aliases,
11576 MaybeTrapSiteInfo maybeTrap = mozilla::Nothing())
11577 : MTernaryInstruction(classOpcode, ka, obj, value),
11578 offset_(uint32_t(offset)),
11579 narrowingOp_(narrowingOp),
11580 aliases_(aliases),
11581 maybeTrap_(maybeTrap) {
11582 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.h"
, 11582); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)"
")"); do { *((volatile int*)__null) = 11582; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11583 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.h"
, 11583); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 11583; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11584 // "if you want to narrow the value when it is stored, the source type
11585 // must be Int32".
11586 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.h"
, 11587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11587; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
11587 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.h"
, 11587); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11587; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11588 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11589 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11590 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11591 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11592 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11593 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11594 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11595 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.h"
, 11595); 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) = 11595; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11596 if (maybeTrap_) {
11597 setGuard();
11598 }
11599 }
11600
11601 public:
11602 INSTRUCTION_HEADER(WasmStoreFieldKA)
11603 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)...); }
11604 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); }
11605
11606 uint32_t offset() const { return offset_; }
11607 MNarrowingOp narrowingOp() const { return narrowingOp_; }
11608 AliasSet getAliasSet() const override { return aliases_; }
11609 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11610
11611#ifdef JS_JITSPEW1
11612 void getExtras(ExtrasCollector* extras) override {
11613 char buf[96];
11614 SprintfLiteral(buf, "(offs=%lld, narrowingOp=%s)", (long long int)offset_,
11615 StringFromMNarrowingOp(narrowingOp_));
11616 extras->add(buf);
11617 }
11618#endif
11619};
11620
11621// Stores a reference value to a location, denoted as a fixed offset from a
11622// base pointer, which (it is assumed) is within a wasm object. This
11623// instruction emits a pre-barrier. A post barrier _must_ be performed
11624// separately. The offset must be representable as a 31-bit unsigned integer.
11625//
11626// This instruction takes a second object `ka` that must be kept alive, as
11627// described for MWasmLoadFieldKA above.
11628class MWasmStoreFieldRefKA : public MAryInstruction<4>,
11629 public NoTypePolicy::Data {
11630 uint32_t offset_;
11631 AliasSet aliases_;
11632 MaybeTrapSiteInfo maybeTrap_;
11633 WasmPreBarrierKind preBarrierKind_;
11634
11635 MWasmStoreFieldRefKA(MDefinition* instance, MDefinition* ka, MDefinition* obj,
11636 size_t offset, MDefinition* value, AliasSet aliases,
11637 MaybeTrapSiteInfo maybeTrap,
11638 WasmPreBarrierKind preBarrierKind)
11639 : MAryInstruction<4>(classOpcode),
11640 offset_(uint32_t(offset)),
11641 aliases_(aliases),
11642 maybeTrap_(maybeTrap),
11643 preBarrierKind_(preBarrierKind) {
11644 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.h"
, 11647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11647; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11645 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.h"
, 11647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11647; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11646 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.h"
, 11647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11647; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11647 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.h"
, 11647); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == TargetWordMIRType() || obj->type() == MIRType::Pointer || obj->type() == MIRType::WasmAnyRef || obj->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11647; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11648 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.h"
, 11648); AnnotateMozCrashReason("MOZ_ASSERT" "(" "offset <= (2147483647)"
")"); do { *((volatile int*)__null) = 11648; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11649 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.h"
, 11649); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 11649; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11650 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11651 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11652 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11653 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11654 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11655 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11656 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11657 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.h"
, 11657); 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) = 11657; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11658 initOperand(0, instance);
11659 initOperand(1, ka);
11660 initOperand(2, obj);
11661 initOperand(3, value);
11662 if (maybeTrap_) {
11663 setGuard();
11664 }
11665 }
11666
11667 public:
11668 INSTRUCTION_HEADER(WasmStoreFieldRefKA)
11669 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)...); }
11670 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); }
11671
11672 uint32_t offset() const { return offset_; }
11673 AliasSet getAliasSet() const override { return aliases_; }
11674 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11675 WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }
11676
11677#ifdef JS_JITSPEW1
11678 void getExtras(ExtrasCollector* extras) override {
11679 char buf[64];
11680 SprintfLiteral(buf, "(offs=%lld)", (long long int)offset_);
11681 extras->add(buf);
11682 }
11683#endif
11684};
11685
11686// Stores a non-reference value to a base pointer, given an index and element
11687// size. This field may be any value type, excluding references. References MUST
11688// use the 'Ref' variant of this instruction.
11689//
11690// The element size is implicitly defined by MIRType and MNarrowingOp. For
11691// example, MIRType::Float32 indicates an element size of 32 bits, and
11692// MIRType::Int32 and MNarrowingOp::To16 together indicate an element size of 16
11693// bits.
11694//
11695// This instruction takes a second object `ka` that must be kept alive, as
11696// described for MWasmLoadFieldKA above.
11697class MWasmStoreElementKA : public MQuaternaryInstruction,
11698 public NoTypePolicy::Data {
11699 MNarrowingOp narrowingOp_;
11700 Scale scale_;
11701 AliasSet aliases_;
11702 MaybeTrapSiteInfo maybeTrap_;
11703
11704 MWasmStoreElementKA(MDefinition* ka, MDefinition* base, MDefinition* index,
11705 MDefinition* value, MNarrowingOp narrowingOp, Scale scale,
11706 AliasSet aliases,
11707 MaybeTrapSiteInfo maybeTrap = mozilla::Nothing())
11708 : MQuaternaryInstruction(classOpcode, ka, base, index, value),
11709 narrowingOp_(narrowingOp),
11710 scale_(scale),
11711 aliases_(aliases),
11712 maybeTrap_(maybeTrap) {
11713 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.h"
, 11713); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11713; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11714 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.h"
, 11714); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() != MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 11714; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11715 // "if you want to narrow the value when it is stored, the source type
11716 // must be Int32".
11717 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.h"
, 11718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11718; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
11718 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.h"
, 11718); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11718; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false); } } while
(false)
;
11719 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.h"
, 11721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11721; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11720 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.h"
, 11721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11721; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11721 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.h"
, 11721); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11721; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11722 if (maybeTrap_) {
11723 setGuard();
11724 }
11725 }
11726
11727 public:
11728 INSTRUCTION_HEADER(WasmStoreElementKA)
11729 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)...); }
11730 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); }
11731
11732 MNarrowingOp narrowingOp() const { return narrowingOp_; }
11733 Scale scale() const { return scale_; }
11734 AliasSet getAliasSet() const override { return aliases_; }
11735 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11736
11737#ifdef JS_JITSPEW1
11738 void getExtras(ExtrasCollector* extras) override {
11739 char buf[96];
11740 SprintfLiteral(buf, "(narrowingOp=%s, scale=%s)",
11741 StringFromMNarrowingOp(narrowingOp_),
11742 StringFromScale(scale_));
11743 extras->add(buf);
11744 }
11745#endif
11746};
11747
11748// Stores a reference value to a base pointer, given an index and element size.
11749// This instruction emits a pre-barrier. A post barrier MUST be performed
11750// separately.
11751//
11752// The element size is implicitly defined by MIRType and MNarrowingOp, as
11753// described for MWasmStoreElementKA above.
11754//
11755// This instruction takes a second object `ka` that must be kept alive, as
11756// described for MWasmLoadFieldKA above.
11757class MWasmStoreElementRefKA : public MAryInstruction<5>,
11758 public NoTypePolicy::Data {
11759 AliasSet aliases_;
11760 MaybeTrapSiteInfo maybeTrap_;
11761 WasmPreBarrierKind preBarrierKind_;
11762
11763 MWasmStoreElementRefKA(MDefinition* instance, MDefinition* ka,
11764 MDefinition* base, MDefinition* index,
11765 MDefinition* value, AliasSet aliases,
11766 MaybeTrapSiteInfo maybeTrap,
11767 WasmPreBarrierKind preBarrierKind)
11768 : MAryInstruction<5>(classOpcode),
11769 aliases_(aliases),
11770 maybeTrap_(maybeTrap),
11771 preBarrierKind_(preBarrierKind) {
11772 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.h"
, 11772); AnnotateMozCrashReason("MOZ_ASSERT" "(" "base->type() == MIRType::WasmArrayData"
")"); do { *((volatile int*)__null) = 11772; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11773 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.h"
, 11773); AnnotateMozCrashReason("MOZ_ASSERT" "(" "value->type() == MIRType::WasmAnyRef"
")"); do { *((volatile int*)__null) = 11773; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11774 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.h"
, 11776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11776; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11775 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.h"
, 11776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11776; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
11776 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.h"
, 11776); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aliases.flags() == AliasSet::Store(AliasSet::WasmArrayDataArea).flags() || aliases.flags() == AliasSet::Store(AliasSet::Any).flags()"
")"); do { *((volatile int*)__null) = 11776; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11777 initOperand(0, instance);
11778 initOperand(1, ka);
11779 initOperand(2, base);
11780 initOperand(3, index);
11781 initOperand(4, value);
11782 if (maybeTrap_) {
11783 setGuard();
11784 }
11785 }
11786
11787 public:
11788 INSTRUCTION_HEADER(WasmStoreElementRefKA)
11789 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)...); }
11790 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); }
11791
11792 AliasSet getAliasSet() const override { return aliases_; }
11793 MaybeTrapSiteInfo maybeTrap() const { return maybeTrap_; }
11794 WasmPreBarrierKind preBarrierKind() const { return preBarrierKind_; }
11795};
11796
11797class MWasmRefIsSubtypeOfAbstract : public MUnaryInstruction,
11798 public NoTypePolicy::Data {
11799 wasm::RefType sourceType_;
11800 wasm::RefType destType_;
11801
11802 MWasmRefIsSubtypeOfAbstract(MDefinition* ref, wasm::RefType sourceType,
11803 wasm::RefType destType)
11804 : MUnaryInstruction(classOpcode, ref),
11805 sourceType_(sourceType),
11806 destType_(destType) {
11807 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.h"
, 11807); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!destType.isTypeRef()"
")"); do { *((volatile int*)__null) = 11807; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11808 setResultType(MIRType::Int32);
11809 setMovable();
11810 }
11811
11812 public:
11813 INSTRUCTION_HEADER(WasmRefIsSubtypeOfAbstract)
11814 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)...); }
11815 NAMED_OPERANDS((0, ref))MDefinition* ref() const { return getOperand(0); }
11816
11817 wasm::RefType sourceType() const { return sourceType_; };
11818 wasm::RefType destType() const { return destType_; };
11819
11820 bool congruentTo(const MDefinition* ins) const override {
11821 return congruentIfOperandsEqual(ins) &&
11822 sourceType() == ins->toWasmRefIsSubtypeOfAbstract()->sourceType() &&
11823 destType() == ins->toWasmRefIsSubtypeOfAbstract()->destType();
11824 }
11825
11826 HashNumber valueHash() const override {
11827 HashNumber hn = MUnaryInstruction::valueHash();
11828 hn = addU64ToHash(hn, sourceType().packed().bits());
11829 hn = addU64ToHash(hn, destType().packed().bits());
11830 return hn;
11831 }
11832
11833 MDefinition* foldsTo(TempAllocator& alloc) override;
11834};
11835
11836// Tests if the wasm ref `ref` is a subtype of `superSTV`.
11837// The actual super type definition must be known at compile time, so that the
11838// subtyping depth of super type depth can be used.
11839class MWasmRefIsSubtypeOfConcrete : public MBinaryInstruction,
11840 public NoTypePolicy::Data {
11841 wasm::RefType sourceType_;
11842 wasm::RefType destType_;
11843
11844 MWasmRefIsSubtypeOfConcrete(MDefinition* ref, MDefinition* superSTV,
11845 wasm::RefType sourceType, wasm::RefType destType)
11846 : MBinaryInstruction(classOpcode, ref, superSTV),
11847 sourceType_(sourceType),
11848 destType_(destType) {
11849 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.h"
, 11849); AnnotateMozCrashReason("MOZ_ASSERT" "(" "destType.isTypeRef()"
")"); do { *((volatile int*)__null) = 11849; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11850 setResultType(MIRType::Int32);
11851 setMovable();
11852 }
11853
11854 public:
11855 INSTRUCTION_HEADER(WasmRefIsSubtypeOfConcrete)
11856 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)...); }
11857 NAMED_OPERANDS((0, ref), (1, superSTV))MDefinition* ref() const { return getOperand(0); } MDefinition
* superSTV() const { return getOperand(1); }
11858
11859 wasm::RefType sourceType() const { return sourceType_; };
11860 wasm::RefType destType() const { return destType_; };
11861
11862 bool congruentTo(const MDefinition* ins) const override {
11863 return congruentIfOperandsEqual(ins) &&
11864 sourceType() == ins->toWasmRefIsSubtypeOfConcrete()->sourceType() &&
11865 destType() == ins->toWasmRefIsSubtypeOfConcrete()->destType();
11866 }
11867
11868 HashNumber valueHash() const override {
11869 HashNumber hn = MBinaryInstruction::valueHash();
11870 hn = addU64ToHash(hn, sourceType().packed().bits());
11871 hn = addU64ToHash(hn, destType().packed().bits());
11872 return hn;
11873 }
11874
11875 MDefinition* foldsTo(TempAllocator& alloc) override;
11876};
11877
11878class MWasmNewStructObject : public MBinaryInstruction,
11879 public NoTypePolicy::Data {
11880 private:
11881 bool isOutline_;
11882 bool zeroFields_;
11883 gc::AllocKind allocKind_;
11884
11885 MWasmNewStructObject(MDefinition* instance, MDefinition* typeDefData,
11886 bool isOutline, bool zeroFields, gc::AllocKind allocKind)
11887 : MBinaryInstruction(classOpcode, instance, typeDefData),
11888 isOutline_(isOutline),
11889 zeroFields_(zeroFields),
11890 allocKind_(allocKind) {
11891 setResultType(MIRType::WasmAnyRef);
11892 }
11893
11894 public:
11895 INSTRUCTION_HEADER(WasmNewStructObject)
11896 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)...); }
11897 NAMED_OPERANDS((0, instance), (1, typeDefData))MDefinition* instance() const { return getOperand(0); } MDefinition
* typeDefData() const { return getOperand(1); }
11898
11899 AliasSet getAliasSet() const override {
11900 if (js::SupportDifferentialTesting()) {
11901 // Consider allocations effectful for differential testing.
11902 return MDefinition::getAliasSet();
11903 }
11904 return AliasSet::None();
11905 }
11906 bool isOutline() const { return isOutline_; }
11907 bool zeroFields() const { return zeroFields_; }
11908 gc::AllocKind allocKind() const { return allocKind_; }
11909};
11910
11911class MWasmNewArrayObject : public MTernaryInstruction,
11912 public NoTypePolicy::Data {
11913 private:
11914 uint32_t elemSize_;
11915 bool zeroFields_;
11916 wasm::BytecodeOffset bytecodeOffset_;
11917
11918 MWasmNewArrayObject(MDefinition* instance, MDefinition* numElements,
11919 MDefinition* typeDefData, uint32_t elemSize,
11920 bool zeroFields, wasm::BytecodeOffset bytecodeOffset)
11921 : MTernaryInstruction(classOpcode, instance, numElements, typeDefData),
11922 elemSize_(elemSize),
11923 zeroFields_(zeroFields),
11924 bytecodeOffset_(bytecodeOffset) {
11925 setResultType(MIRType::WasmAnyRef);
11926 }
11927
11928 public:
11929 INSTRUCTION_HEADER(WasmNewArrayObject)
11930 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)...); }
11931 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); }
11932
11933 AliasSet getAliasSet() const override {
11934 if (js::SupportDifferentialTesting()) {
11935 // Consider allocations effectful for differential testing.
11936 return MDefinition::getAliasSet();
11937 }
11938 return AliasSet::None();
11939 }
11940 uint32_t elemSize() const { return elemSize_; }
11941 bool zeroFields() const { return zeroFields_; }
11942 wasm::BytecodeOffset bytecodeOffset() const { return bytecodeOffset_; }
11943};
11944
11945#ifdef FUZZING_JS_FUZZILLI
11946class MFuzzilliHash : public MUnaryInstruction, public NoTypePolicy::Data {
11947 explicit MFuzzilliHash(MDefinition* obj)
11948 : MUnaryInstruction(classOpcode, obj) {
11949 setResultType(MIRType::Int32);
11950 setMovable();
11951 }
11952
11953 public:
11954 INSTRUCTION_HEADER(FuzzilliHash);
11955 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)...); }
11956 ALLOW_CLONE(MFuzzilliHash)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MFuzzilliHash
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
11957
11958# ifdef DEBUG1
11959 bool isConsistentFloat32Use(MUse* use) const override { return true; }
11960# endif
11961
11962 AliasSet getAliasSet() const override {
11963 MDefinition* obj = getOperand(0);
11964 if (obj->type() == MIRType::Object || obj->type() == MIRType::Value) {
11965 return AliasSet::Load(AliasSet::ObjectFields | AliasSet::FixedSlot |
11966 AliasSet::DynamicSlot | AliasSet::Element |
11967 AliasSet::UnboxedElement);
11968 }
11969 return AliasSet::None();
11970 }
11971};
11972
11973class MFuzzilliHashStore : public MUnaryInstruction, public NoTypePolicy::Data {
11974 explicit MFuzzilliHashStore(MDefinition* obj)
11975 : MUnaryInstruction(classOpcode, obj) {
11976 MOZ_ASSERT(obj->type() == MIRType::Int32)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(obj->type() == MIRType::Int32)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(obj->type() == MIRType::Int32
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"obj->type() == MIRType::Int32", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11976); AnnotateMozCrashReason("MOZ_ASSERT" "(" "obj->type() == MIRType::Int32"
")"); do { *((volatile int*)__null) = 11976; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
11977
11978 setResultType(MIRType::None);
11979 }
11980
11981 public:
11982 INSTRUCTION_HEADER(FuzzilliHashStore);
11983 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)...); }
11984 ALLOW_CLONE(MFuzzilliHashStore)bool canClone() const override { return true; } MInstruction*
clone(TempAllocator& alloc, const MDefinitionVector&
inputs) const override { MInstruction* res = new (alloc) MFuzzilliHashStore
(*this); for (size_t i = 0; i < numOperands(); i++) res->
replaceOperand(i, inputs[i]); return res; }
11985
11986 // this is a store and hence effectful, however no other load can
11987 // alias with the store
11988 AliasSet getAliasSet() const override {
11989 return AliasSet::Store(AliasSet::FuzzilliHash);
11990 }
11991};
11992#endif
11993
11994#undef INSTRUCTION_HEADER
11995
11996void MUse::init(MDefinition* producer, MNode* consumer) {
11997 MOZ_ASSERT(!consumer_, "Initializing MUse that already has a consumer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!consumer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!consumer_))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!consumer_" " (" "Initializing MUse that already has a consumer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11997); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!consumer_"
") (" "Initializing MUse that already has a consumer" ")"); do
{ *((volatile int*)__null) = 11997; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11998 MOZ_ASSERT(!producer_, "Initializing MUse that already has a producer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!producer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!producer_))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("!producer_" " (" "Initializing MUse that already has a producer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 11998); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!producer_"
") (" "Initializing MUse that already has a producer" ")"); do
{ *((volatile int*)__null) = 11998; __attribute__((nomerge))
::abort(); } while (false); } } while (false)
;
11999 initUnchecked(producer, consumer);
12000}
12001
12002void MUse::initUnchecked(MDefinition* producer, MNode* consumer) {
12003 MOZ_ASSERT(consumer, "Initializing to null consumer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("consumer" " (" "Initializing to null consumer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12003); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer" ") ("
"Initializing to null consumer" ")"); do { *((volatile int*)
__null) = 12003; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12004 consumer_ = consumer;
12005 producer_ = producer;
12006 producer_->addUseUnchecked(this);
12007}
12008
12009void MUse::initUncheckedWithoutProducer(MNode* consumer) {
12010 MOZ_ASSERT(consumer, "Initializing to null consumer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("consumer" " (" "Initializing to null consumer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12010); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer" ") ("
"Initializing to null consumer" ")"); do { *((volatile int*)
__null) = 12010; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
12011 consumer_ = consumer;
12012 producer_ = nullptr;
12013}
12014
12015void MUse::replaceProducer(MDefinition* producer) {
12016 MOZ_ASSERT(consumer_, "Resetting MUse without a consumer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("consumer_" " (" "Resetting MUse without a consumer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12016); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer_"
") (" "Resetting MUse without a consumer" ")"); do { *((volatile
int*)__null) = 12016; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12017 producer_->removeUse(this);
12018 producer_ = producer;
12019 producer_->addUse(this);
12020}
12021
12022void MUse::releaseProducer() {
12023 MOZ_ASSERT(consumer_, "Clearing MUse without a consumer")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(consumer_)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(consumer_))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("consumer_" " (" "Clearing MUse without a consumer"
")", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12023); AnnotateMozCrashReason("MOZ_ASSERT" "(" "consumer_"
") (" "Clearing MUse without a consumer" ")"); do { *((volatile
int*)__null) = 12023; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
12024 producer_->removeUse(this);
12025 producer_ = nullptr;
12026}
12027
12028// Implement cast functions now that the compiler can see the inheritance.
12029
12030MDefinition* MNode::toDefinition() {
12031 MOZ_ASSERT(isDefinition())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isDefinition())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isDefinition()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isDefinition()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12031); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isDefinition()"
")"); do { *((volatile int*)__null) = 12031; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12032 return (MDefinition*)this;
12033}
12034
12035MResumePoint* MNode::toResumePoint() {
12036 MOZ_ASSERT(isResumePoint())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isResumePoint())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isResumePoint()))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("isResumePoint()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12036); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isResumePoint()"
")"); do { *((volatile int*)__null) = 12036; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12037 return (MResumePoint*)this;
12038}
12039
12040MInstruction* MDefinition::toInstruction() {
12041 MOZ_ASSERT(!isPhi())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isPhi())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isPhi()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isPhi()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isPhi()" ")"
); do { *((volatile int*)__null) = 12041; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12042 return (MInstruction*)this;
12043}
12044
12045const MInstruction* MDefinition::toInstruction() const {
12046 MOZ_ASSERT(!isPhi())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isPhi())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isPhi()))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("!isPhi()", "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12046); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isPhi()" ")"
); do { *((volatile int*)__null) = 12046; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
12047 return (const MInstruction*)this;
12048}
12049
12050MControlInstruction* MDefinition::toControlInstruction() {
12051 MOZ_ASSERT(isControlInstruction())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isControlInstruction())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isControlInstruction()))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("isControlInstruction()"
, "/var/lib/jenkins/workspace/firefox-scan-build/js/src/jit/MIR.h"
, 12051); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isControlInstruction()"
")"); do { *((volatile int*)__null) = 12051; __attribute__((
nomerge)) ::abort(); } while (false); } } while (false)
;
12052 return (MControlInstruction*)this;
12053}
12054
12055MConstant* MDefinition::maybeConstantValue() {
12056 MDefinition* op = this;
12057 if (op->isBox()) {
12058 op = op->toBox()->input();
12059 }
12060 if (op->isConstant()) {
12061 return op->toConstant();
12062 }
12063 return nullptr;
12064}
12065
12066#ifdef ENABLE_WASM_SIMD1
12067MWasmShuffleSimd128* BuildWasmShuffleSimd128(TempAllocator& alloc,
12068 const int8_t* control,
12069 MDefinition* lhs,
12070 MDefinition* rhs);
12071#endif // ENABLE_WASM_SIMD
12072
12073} // namespace jit
12074} // namespace js
12075
12076#endif /* jit_MIR_h */