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_; }