Source code

Revision control

Copy as Markdown

Other Tools

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# [SMDOC] MIR Opcodes
# =======================
# This file defines all MIR opcodes. It is parsed by GenerateMIRFiles.py
# at build time to create MIROpsGenerated.h. Each opcode consists of a
# name and a set of attributes that are described below. A few of the
# attributes below allow setting the value to "custom", meaning the
# method will be declared for the MIR op, but will need to be implemented
# in C++ (typically done in MIR.cpp). Unless marked as required, attributes
# are optional.
#
# name [required]
# ====
# Opcode name.
# Possible values:
# - opcode string: used as the name for MIR opcode.
#
# gen_boilerplate
# ===============
# Used to decide to generate MIR boilerplate.
# - true (default): auto generate boilerplate for this MIR opcode
# - false: do not generate boilerplate for this MIR opcode
#
# operands
# ========
# A list of operands for the MIR op class constructor. Each operand is a
# MIR node. The operand kind is specified from the one of the kinds from
# the MIRType enum in IonTypes.h. The specified types for the
# operands will decide the type policy for the instruction.
#
# The naming of operands is how the NAMED_OPERANDS macro will define
# its operands.
#
# For example:
# object: Object
# id: Value
# value: Object
#
# Will result in an instruction having the type policy of:
# MixPolicy<ObjectPolicy<0>, BoxPolicy<1>, ObjectPolicy<2>>
# and a named operands definition that looks like the following:
# NAMED_OPERANDS((0, object), (1, idValue), (2, value))
#
# - attribute not specified (default): no code generated
# - operand list: MIRTypes (See MIRType in jit/IonTypes.h)
#
# arguments
# =========
# A list of non-MIR node arguments to the MIR op class constructor
# that are passed along with the operands. The arguments require
# both a name and a full type signature for each item in the list.
#
# For example:
# templateObject: JSObject*
# initialHeap: gc::Heap
#
# For each argument a private variable declaration will be autogenerated
# in the MIR op class, as well as simple accessor for that variable. If
# the type of the variable is a GC pointer it will by automatically
# wrapped by CompilerGCPointer. The above arguments list will result in
# the following declarations and accessors:
#
# CompilerGCPointer<JSObject*> templateObject_;
# gc::Heap initialHeap_;
#
# JSObject* templateObject() const { return templateObject_; }
# gc::Heap initialHeap() const { return initialHeap_; }
#
# - attribute not specified (default): no code generated
# - operand list: argument names and their full type signature
#
# type_policy
# ============
# If this attribute is present, then the type policy for that opcode will be
# NoTypePolicy. This is used for opcode that should have no type policy.
# - attribute not specified (default): no code generated, type policy
# is based off of operands
# - none: defines the type policy as opcode's NoTypePolicy
#
# result_type
# ===========
# Defines the result type of the MIR opcode.
# - attribute not specified (default): no code is generated
# - MIRType string: Will add a call to setResultType to the opcode constructor.
# This will set the MIR opcodes result type to whatever the
# specified MIRType is (See MIRType in jit/IonTypes.h).
#
# guard
# =====
# Set if the opcode is a guard instruction and is used for checks in optimizations
# such as range analysis and value numbering.
# - attribute not specified (default): no code generated
# - true: adds setGuard to opcode constructor
#
# movable
# =======
# Defines the movable MIR flag for movable instructions. This is used for knowing
# whether we can hoist an instruction.
# - attribute not specified (default): no code generated
# - true: adds setMovable call in opcode constructor
#
# folds_to
# ========
# The foldsTo method is used for determining if an instruction can be folded into
# simpler instruction or for constant folding, depending on its operands.
# - attribute not specified (default): no code generated, no constants to fold
# - custom: custom C++ implementation
#
# congruent_to
# ============
# Used by ValueNumbering to determine if two values are congruent.
# - attribute not specified (default): no code generated, congruentTo(foo) returns
# false
# - if_operands_equal: congruentTo(foo) will return congruentIfOperandsEqual(foo)
# - custom: custom C++ implementation
#
# alias_set
# =========
# Defines the getAliasSet function for a MIR op. The alias set is used for alias
# analysis. The default alias set is Any.
# - attribute not specified (default): no code generated, alias set is Any
# - none: this is the most common case, this is will set the alias set to None.
# - custom: custom C++ implementation in MIR.cpp
#
# possibly_calls
# ==============
# Defines if a opcode can possibly call.
# - attribute not specified (default): no code generated, opcode does not call
# - true: possiblyCalls returns true
# - custom: custom C++ implementation
#
# compute_range
# =============
# Computes and sets the range value for a MIR node, which is then used in range
# analysis.
# - attribute not specified (default): no code generated, range is not set for node
# - custom: custom C++ implementation in RangeAnalysis.cpp
#
# can_recover
# ===========
# Indicates whether this instruction can be recovered on bailout.
# Possible values:
# - attribute not specified (default): no code generated, canRecoverOnBailout
# returns false
# - true: canRecoverOnBailout returns true
# - custom: canRecoverOnBailout has a custom C++ implementation
# If the value is either 'true' or 'custom', writeRecoverData has a custom C++
# implementation.
#
# clone
# =====
# Allows cloning for that MIR op.
# - attribute not specified (default): no code generated
# - true: allows cloning
#
# can_consume_float32
# ===================
# Indicates whether this instruction's operands can have MIRType::Float32.
# Possible values:
# - attribute not specified (default): no code generated
# - true: canConsumeFloat32 returns true
#
# TODO(no-TI): try to remove this instruction.
- name: Start
# Instruction marking on entrypoint for on-stack replacement.
# OSR may occur at loop headers (at JSOp::LoopHead).
# There is at most one MOsrEntry per MIRGraph.
- name: OsrEntry
result_type: Pointer
- name: Nop
alias_set: none
clone: true
- name: LimitedTruncate
gen_boilerplate: false
- name: Constant
gen_boilerplate: false
- name: WasmNullConstant
gen_boilerplate: false
- name: WasmFloatConstant
gen_boilerplate: false
- name: Parameter
gen_boilerplate: false
- name: Callee
result_type: Object
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: IsConstructing
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: TableSwitch
gen_boilerplate: false
- name: Goto
gen_boilerplate: false
- name: Test
gen_boilerplate: false
- name: Return
gen_boilerplate: false
- name: Throw
operands:
value: Value
alias_set: custom
possibly_calls: true
- name: ThrowWithStack
operands:
value: Value
stack: Value
alias_set: custom
possibly_calls: true
- name: NewArray
gen_boilerplate: false
- name: NewArrayDynamicLength
operands:
length: Int32
arguments:
templateObject: JSObject*
initialHeap: gc::Heap
result_type: Object
# Need to throw if length is negative.
guard: true
# Throws if length is negative.
alias_set: custom
- name: NewTypedArray
gen_boilerplate: false
- name: NewTypedArrayDynamicLength
operands:
length: Int32
arguments:
templateObject: JSObject*
initialHeap: gc::Heap
result_type: Object
guard: true
# Throws if length is negative.
alias_set: custom
# Create a new TypedArray from an Array (or Array-like object) or a TypedArray.
- name: NewTypedArrayFromArray
operands:
array: Object
arguments:
templateObject: JSObject*
initialHeap: gc::Heap
result_type: Object
guard: true
possibly_calls: true
# Create a new TypedArray from an ArrayBuffer (or SharedArrayBuffer).
- name: NewTypedArrayFromArrayBuffer
operands:
arrayBuffer: Object
byteOffset: Value
length: Value
arguments:
templateObject: JSObject*
initialHeap: gc::Heap
result_type: Object
guard: true
possibly_calls: true
- name: NewObject
gen_boilerplate: false
- name: NewPlainObject
gen_boilerplate: false
- name: NewArrayObject
gen_boilerplate: false
- name: NewIterator
gen_boilerplate: false
- name: ObjectState
gen_boilerplate: false
- name: ArrayState
gen_boilerplate: false
- name: BindFunction
gen_boilerplate: false
- name: NewBoundFunction
arguments:
templateObj: JSObject*
result_type: Object
alias_set: none
- name: BoundFunctionNumArgs
operands:
object: Object
result_type: Int32
movable: true
congruent_to: if_operands_equal
# A bound function's state is immutable, so there is no
# implicit dependency.
alias_set: none
- name: GuardBoundFunctionIsConstructor
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
# The is-constructor flag is immutable for a bound function.
alias_set: none
# Setting __proto__ in an object literal.
- name: MutateProto
operands:
object: Object
value: Value
result_type: None
possibly_calls: true
- name: InitPropGetterSetter
operands:
object: Object
value: Object
arguments:
name: PropertyName*
- name: InitElemGetterSetter
operands:
object: Object
id: Value
value: Object
- name: Call
gen_boilerplate: false
- name: CallClassHook
gen_boilerplate: false
- name: ApplyArgs
gen_boilerplate: false
- name: ApplyArgsObj
gen_boilerplate: false
- name: ApplyArray
gen_boilerplate: false
- name: ConstructArgs
gen_boilerplate: false
- name: ConstructArray
gen_boilerplate: false
- name: Bail
gen_boilerplate: false
- name: Unreachable
gen_boilerplate: false
# This op serves as a way to force the encoding of a snapshot, even if there
# is no resume point using it. This is useful to run MAssertRecoveredOnBailout
# assertions.
- name: EncodeSnapshot
guard: true
- name: AssertRecoveredOnBailout
gen_boilerplate: false
- name: AssertFloat32
gen_boilerplate: false
- name: Compare
gen_boilerplate: false
- name: SameValueDouble
operands:
left: Double
right: Double
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
clone: true
- name: SameValue
operands:
left: Value
right: Value
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
clone: true
- name: Box
gen_boilerplate: false
- name: Unbox
gen_boilerplate: false
- name: AssertRange
gen_boilerplate: false
- name: AssertClass
gen_boilerplate: false
- name: AssertShape
gen_boilerplate: false
# Caller-side allocation of |this| for |new|:
# Constructs |this| when possible, else MagicValue(JS_IS_CONSTRUCTING).
- name: CreateThis
operands:
callee: Object
newTarget: Object
result_type: Value
# Performs a property read from |newTarget| iff |newTarget| is a JSFunction
# with an own |.prototype| property.
alias_set: custom
possibly_calls: true
- name: CreateArgumentsObject
gen_boilerplate: false
- name: CreateInlinedArgumentsObject
gen_boilerplate: false
- name: GetInlinedArgument
gen_boilerplate: false
- name: GetInlinedArgumentHole
gen_boilerplate: false
- name: GetArgumentsObjectArg
operands:
argsObject: Object
arguments:
argno: size_t
result_type: Value
congruent_to: custom
alias_set: custom
- name: SetArgumentsObjectArg
operands:
argsObject: Object
value: Value
arguments:
argno: size_t
alias_set: custom
# Load |arguments[index]| from a mapped or unmapped arguments object. Bails out
# when any elements were overridden or deleted. Also bails out if the index is
# out of bounds.
- name: LoadArgumentsObjectArg
operands:
argsObject: Object
index: Int32
result_type: Value
guard: true
congruent_to: if_operands_equal
alias_set: custom
# Load |arguments[index]| from a mapped or unmapped arguments object. Bails out
# when any elements were overridden or deleted. Returns undefined if the index is
# out of bounds.
- name: LoadArgumentsObjectArgHole
operands:
argsObject: Object
index: Int32
result_type: Value
guard: true
congruent_to: if_operands_equal
alias_set: custom
- name: InArgumentsObjectArg
operands:
argsObject: Object
index: Int32
result_type: Boolean
guard: true
congruent_to: if_operands_equal
alias_set: custom
# Load |arguments.length|. Bails out if the length has been overriden.
- name: ArgumentsObjectLength
operands:
argsObject: Object
result_type: Int32
guard: true
movable: true
congruent_to: if_operands_equal
# Even though the "length" property is lazily resolved, it acts similar to
# a normal property load, so we can treat this operation like any other
# property read.
alias_set: custom
# Create an array from an arguments object.
- name: ArrayFromArgumentsObject
operands:
argsObject: Object
arguments:
shape: Shape*
result_type: Object
possibly_calls: true
# Guard that the given flags are not set on the arguments object.
- name: GuardArgumentsObjectFlags
operands:
argsObject: Object
arguments:
flags: uint32_t
result_type: Object
movable: true
guard: true
congruent_to: custom
# The flags are packed with the length in a fixed private slot.
alias_set: custom
- name: LoadScriptedProxyHandler
operands:
object: Object
result_type: Object
guard: true
congruent_to: if_operands_equal
alias_set: none
#ifdef JS_PUNBOX64
- name: CheckScriptedProxyGetResult
operands:
target: Value
id: Value
value: Value
guard: true
alias_set: custom
#endif
- name: IdToStringOrSymbol
operands:
idVal: Value
result_type: Value
congruent_to: if_operands_equal
alias_set: none
folds_to: custom
# Given a MIRType::Value A and a MIRType::Object B:
# If the Value may be safely unboxed to an Object, return Object(A).
# Otherwise, return B.
# Used to implement return behavior for inlined constructors.
- name: ReturnFromCtor
operands:
value: Value
object: Object
result_type: Object
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
- name: ToDouble
gen_boilerplate: false
- name: ToFloat32
gen_boilerplate: false
# Converts a uint32 to a double (coming from wasm).
- name: WasmUnsignedToDouble
operands:
def: Int32
type_policy: none
result_type: Double
movable: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
- name: WasmUnsignedToFloat32
gen_boilerplate: false
- name: WrapInt64ToInt32
gen_boilerplate: false
- name: ExtendInt32ToInt64
gen_boilerplate: false
- name: WasmBuiltinTruncateToInt64
gen_boilerplate: false
- name: WasmTruncateToInt64
gen_boilerplate: false
- name: WasmTruncateToInt32
gen_boilerplate: false
- name: WasmAnyRefFromJSValue
operands:
def: Value
result_type: WasmAnyRef
congruent_to: if_operands_equal
alias_set: none
- name: WasmAnyRefFromJSObject
operands:
def: Object
type_policy: none
result_type: WasmAnyRef
congruent_to: if_operands_equal
alias_set: none
- name: WasmAnyRefFromJSString
operands:
def: String
type_policy: none
result_type: WasmAnyRef
congruent_to: if_operands_equal
alias_set: none
- name: WasmNewI31Ref
operands:
input: Int32
type_policy: none
result_type: WasmAnyRef
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: WasmI31RefGet
operands:
input: WasmAnyRef
arguments:
wideningOp: wasm::FieldWideningOp
type_policy: none
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: Int32ToIntPtr
gen_boilerplate: false
- name: NonNegativeIntPtrToInt32
gen_boilerplate: false
- name: IntPtrToDouble
gen_boilerplate: false
- name: AdjustDataViewLength
gen_boilerplate: false
- name: Int64ToFloatingPoint
gen_boilerplate: false
- name: BuiltinInt64ToFloatingPoint
gen_boilerplate: false
- name: ToNumberInt32
gen_boilerplate: false
- name: BooleanToInt32
operands:
input: Boolean
result_type: Int32
movable: true
compute_range: custom
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
- name: TruncateToInt32
gen_boilerplate: false
- name: WasmBuiltinTruncateToInt32
gen_boilerplate: false
- name: ToBigInt
gen_boilerplate: false
- name: ToInt64
gen_boilerplate: false
- name: TruncateBigIntToInt64
gen_boilerplate: false
- name: Int64ToBigInt
gen_boilerplate: false
- name: ToString
gen_boilerplate: false
- name: BitNot
gen_boilerplate: false
- name: TypeOf
gen_boilerplate: false
- name: TypeOfName
operands:
input: Int32
result_type: String
movable: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
can_recover: true
- name: TypeOfIs
gen_boilerplate: false
- name: ToAsyncIter
operands:
iterator: Object
nextMethod: Value
result_type: Object
- name: ToPropertyKeyCache
operands:
input: Value
result_type: Value
- name: BitAnd
gen_boilerplate: false
- name: BitOr
gen_boilerplate: false
- name: BitXor
gen_boilerplate: false
- name: Lsh
gen_boilerplate: false
- name: Rsh
gen_boilerplate: false
- name: Ursh
gen_boilerplate: false
- name: SignExtendInt32
gen_boilerplate: false
- name: SignExtendInt64
gen_boilerplate: false
- name: MinMax
gen_boilerplate: false
- name: MinMaxArray
gen_boilerplate: false
- name: Abs
gen_boilerplate: false
- name: Clz
gen_boilerplate: false
- name: Ctz
gen_boilerplate: false
- name: Popcnt
gen_boilerplate: false
- name: Sqrt
gen_boilerplate: false
- name: CopySign
gen_boilerplate: false
# Inline implementation of atan2 (arctangent of y/x).
- name: Atan2
operands:
y: Double
x: Double
result_type: Double
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
can_recover: true
clone: true
- name: Hypot
gen_boilerplate: false
- name: Pow
gen_boilerplate: false
- name: PowHalf
gen_boilerplate: false
- name: Random
result_type: Double
alias_set: custom
possibly_calls: true
compute_range: custom
can_recover: custom
clone: true
- name: Sign
gen_boilerplate: false
- name: MathFunction
gen_boilerplate: false
- name: Add
gen_boilerplate: false
- name: Sub
gen_boilerplate: false
- name: Mul
gen_boilerplate: false
- name: Div
gen_boilerplate: false
- name: WasmBuiltinDivI64
gen_boilerplate: false
- name: Mod
gen_boilerplate: false
- name: WasmBuiltinModD
gen_boilerplate: false
- name: WasmBuiltinModI64
gen_boilerplate: false
- name: BigIntAdd
gen_boilerplate: false
- name: BigIntSub
gen_boilerplate: false
- name: BigIntMul
gen_boilerplate: false
- name: BigIntDiv
gen_boilerplate: false
- name: BigIntMod
gen_boilerplate: false
- name: BigIntPow
gen_boilerplate: false
- name: BigIntBitAnd
gen_boilerplate: false
- name: BigIntBitOr
gen_boilerplate: false
- name: BigIntBitXor
gen_boilerplate: false
- name: BigIntLsh
gen_boilerplate: false
- name: BigIntRsh
gen_boilerplate: false
- name: BigIntIncrement
gen_boilerplate: false
- name: BigIntDecrement
gen_boilerplate: false
- name: BigIntNegate
gen_boilerplate: false
- name: BigIntBitNot
gen_boilerplate: false
- name: Int32ToStringWithBase
operands:
input: Int32
base: Int32
arguments:
lowerCase: bool
result_type: String
movable: true
congruent_to: custom
alias_set: none
- name: NumberParseInt
operands:
string: String
radix: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: DoubleParseInt
operands:
number: Double
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: Concat
gen_boilerplate: false
- name: LinearizeString
operands:
string: String
result_type: String
movable: true
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
- name: LinearizeForCharAccess
operands:
string: String
index: Int32
result_type: String
movable: true
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
- name: LinearizeForCodePointAccess
operands:
string: String
index: Int32
result_type: String
movable: true
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
- name: ToRelativeStringIndex
operands:
index: Int32
length: Int32
result_type: Int32
movable: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
- name: CharCodeAt
operands:
string: String
index: Int32
result_type: Int32
movable: true
folds_to: custom
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
compute_range: custom
can_recover: true
clone: true
# Similar to CharCodeAt, but returns a negative value on out-of-bounds access.
- name: CharCodeAtOrNegative
operands:
string: String
index: Int32
result_type: Int32
movable: true
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
- name: CodePointAt
operands:
string: String
index: Int32
result_type: Int32
movable: true
folds_to: custom
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
compute_range: custom
clone: true
# Similar to CodePointAt, but returns a negative value on out-of-bounds access.
- name: CodePointAtOrNegative
operands:
string: String
index: Int32
result_type: Int32
movable: true
congruent_to: if_operands_equal
# Strings are immutable, so there is no implicit dependency.
alias_set: none
# Return the input if non-negative, otherwise return NaN.
- name: NegativeToNaN
operands:
input: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
# Return the input if non-negative, otherwise return undefined.
- name: NegativeToUndefined
operands:
input: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: FromCharCode
operands:
code: Int32
result_type: String
movable: true
congruent_to: if_operands_equal
alias_set: none
can_recover: true
clone: true
# Similar to FromCharCode, but returns the empty string if the input is negative.
- name: FromCharCodeEmptyIfNegative
operands:
code: Int32
result_type: String
movable: true
congruent_to: if_operands_equal
alias_set: none
can_recover: true
clone: true
# Similar to FromCharCode, but returns the |undefined| if the input is negative.
- name: FromCharCodeUndefinedIfNegative
operands:
code: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: FromCodePoint
operands:
codePoint: Int32
result_type: String
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
clone: true
- name: StringIncludes
operands:
string: String
searchString: String
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: StringIndexOf
operands:
string: String
searchString: String
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: StringLastIndexOf
operands:
string: String
searchString: String
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: StringStartsWith
operands:
string: String
searchString: String
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: StringEndsWith
operands:
string: String
searchString: String
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: StringConvertCase
gen_boilerplate: false
- name: CharCodeConvertCase
gen_boilerplate: false
- name: StringTrimStartIndex
operands:
string: String
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: StringTrimEndIndex
operands:
string: String
start: Int32
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: StringSplit
operands:
string: String
separator: String
result_type: Object
possibly_calls: true
# Although this instruction returns a new array, we don't have to mark
# it as store instruction, see also MNewArray.
alias_set: none
can_recover: true
- name: BoxNonStrictThis
operands:
def: Value
arguments:
globalThis: JSObject*
result_type: Object
folds_to: custom
possibly_calls: true
# This instruction can allocate a new object for wrapped primitives, but
# has no effect on existing objects.
alias_set: none
- name: ImplicitThis
operands:
envChain: Object
arguments:
name: PropertyName*
result_type: Value
possibly_calls: true
- name: Phi
gen_boilerplate: false
- name: Beta
gen_boilerplate: false
- name: NaNToZero
gen_boilerplate: false
- name: OsrValue
gen_boilerplate: false
- name: OsrEnvironmentChain
gen_boilerplate: false
- name: OsrArgumentsObject
gen_boilerplate: false
- name: OsrReturnValue
gen_boilerplate: false
- name: BinaryCache
gen_boilerplate: false
- name: UnaryCache
operands:
input: Value
result_type: Value
# Checks whether we need to fire the interrupt handler.
- name: CheckOverRecursed
guard: true
alias_set: none
# Check whether we need to fire the interrupt handler.
- name: InterruptCheck
guard: true
alias_set: none
- name: WasmInterruptCheck
gen_boilerplate: false
- name: WasmTrap
gen_boilerplate: false
# Trap if the given ref is null
- name: WasmTrapIfNull
operands:
ref: WasmAnyRef
arguments:
trap: wasm::Trap
bytecodeOffset: wasm::BytecodeOffset
guard: true
type_policy: none
result_type: None
- name: LexicalCheck
gen_boilerplate: false
# Unconditionally throw an uninitialized let error.
- name: ThrowRuntimeLexicalError
arguments:
errorNumber: unsigned
result_type: None
guard: true
alias_set: custom
- name: ThrowMsg
gen_boilerplate: false
# In the prologues of global and eval scripts, check for redeclarations and
# initialize bindings.
- name: GlobalDeclInstantiation
guard: true
- name: RegExp
arguments:
source: RegExpObject*
hasShared: bool
result_type: Object
possibly_calls: true
alias_set: none
- name: RegExpMatcher
operands:
regexp: Object
string: String
lastIndex: Int32
result_type: Value
possibly_calls: true
can_recover: true
# Note: this instruction writes to cx->regExpSearcherLastLimit.
# See also MRegExpSearcherLastLimit.
- name: RegExpSearcher
operands:
regexp: Object
string: String
lastIndex: Int32
result_type: Int32
possibly_calls: true
can_recover: false
# This instruction loads cx->regExpSearcherLastLimit. We don't have a
# specialized alias set for this so just use the default alias set similar to
# the MRegExpSearcher instruction that precedes it.
- name: RegExpSearcherLastLimit
operands:
result_type: Int32
- name: RegExpExecMatch
operands:
regexp: Object
string: String
result_type: Value
possibly_calls: true
can_recover: false
- name: RegExpExecTest
operands:
regexp: Object
string: String
result_type: Boolean
possibly_calls: true
can_recover: false
- name: RegExpHasCaptureGroups
operands:
regexp: Object
input: String
result_type: Boolean
possibly_calls: true
- name: RegExpPrototypeOptimizable
operands:
object: Object
result_type: Boolean
alias_set: none
- name: RegExpInstanceOptimizable
operands:
object: Object
proto: Object
result_type: Boolean
alias_set: none
- name: GetFirstDollarIndex
gen_boilerplate: false
- name: StringReplace
gen_boilerplate: false
- name: Substr
operands:
string: String
begin: Int32
length: Int32
result_type: String
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
can_recover: true
- name: ModuleMetadata
arguments:
module: JSObject*
result_type: Object
- name: DynamicImport
operands:
specifier: Value
options: Value
result_type: Object
- name: Lambda
gen_boilerplate: false
- name: FunctionWithProto
gen_boilerplate: false
- name: SetFunName
operands:
fun: Object
name: Value
arguments:
prefixKind: uint8_t
result_type: None
possibly_calls: true
# Returns obj->slots.
- name: Slots
operands:
object: Object
result_type: Slots
movable: true
congruent_to: if_operands_equal
alias_set: custom
might_alias: custom
clone: true
# Returns obj->elements.
- name: Elements
operands:
object: Object
result_type: Elements
movable: true
congruent_to: if_operands_equal
alias_set: custom
clone: true
# Load the initialized length from an elements header.
- name: InitializedLength
operands:
elements: Elements
type_policy: none
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: custom
compute_range: custom
clone: true
- name: SetInitializedLength
operands:
elements: Elements
index: Int32
type_policy: none
alias_set: custom
clone: true
# Load the array length from an elements header.
- name: ArrayLength
operands:
elements: Elements
type_policy: none
result_type: Int32
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: custom
compute_range: custom
clone: true
# Store to the length in an elements header. Note the input is an *index*, one
# less than the desired length.
- name: SetArrayLength
operands:
elements: Elements
index: Int32
type_policy: none
alias_set: custom
# Load the function length. Bails for functions with lazy scripts or a
# resolved "length" property.
- name: FunctionLength
operands:
function: Object
result_type: Int32
guard: true
congruent_to: if_operands_equal
# Even though the "length" property is lazily resolved, it acts similar to
# a normal property load, so we can treat this operation like any other
# property read.
alias_set: custom
# Load the function name. Bails for bound functions when the bound function
# name prefix isn't present or functions with a resolved "name" property.
- name: FunctionName
operands:
function: Object
result_type: String
guard: true
congruent_to: if_operands_equal
# Even though the "name" property is lazily resolved, it acts similar to
# a normal property load, so we can treat this operation like any other
# property read.
alias_set: custom
- name: GetNextEntryForIterator
gen_boilerplate: false
# Read the byte length of an array buffer as IntPtr.
- name: ArrayBufferByteLength
operands:
object: Object
result_type: IntPtr
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Read the length of an array buffer view.
- name: ArrayBufferViewLength
operands:
object: Object
result_type: IntPtr
movable: true
congruent_to: if_operands_equal
alias_set: custom
compute_range: custom
- name: ArrayBufferViewByteOffset
operands:
object: Object
result_type: IntPtr
movable: true
congruent_to: if_operands_equal
alias_set: custom
compute_range: custom
# Read the length of an array buffer view.
- name: ArrayBufferViewElements
operands:
object: Object
result_type: Elements
movable: true
congruent_to: if_operands_equal
alias_set: custom
clone: true
# Implements the TypedArrayByteOffset intrinsic for resizable typed arrays,
# which calls TypedArrayObject::byteOffsetMaybeOutOfBounds().
- name: ResizableTypedArrayByteOffsetMaybeOutOfBounds
operands:
object: Object
result_type: IntPtr
movable: true
congruent_to: if_operands_equal
alias_set: custom
compute_range: custom
# Read the length of a resizable typed array.
- name: ResizableTypedArrayLength
operands:
object: Object
arguments:
requiresMemoryBarrier: MemoryBarrierRequirement
result_type: IntPtr
# Not removable or movable when a barrier is needed.
guard: true
movable: false
congruent_to: custom
alias_set: custom
compute_range: custom
# Read the byteLength of a resizable dataview.
- name: ResizableDataViewByteLength
operands:
object: Object
arguments:
requiresMemoryBarrier: MemoryBarrierRequirement
result_type: IntPtr
# Not removable or movable when a barrier is needed.
guard: true
movable: false
congruent_to: custom
alias_set: custom
compute_range: custom
# Read the byte length of a growable shared array buffer as IntPtr.
- name: GrowableSharedArrayBufferByteLength
operands:
object: Object
result_type: IntPtr
guard: true
movable: false
alias_set: custom
# Return the element size of a typed array.
- name: TypedArrayElementSize
operands:
object: Object
result_type: Int32
movable: true
congruent_to: if_operands_equal
# Class is immutable. See also MHasClass.
alias_set: none
compute_range: custom
# Guard an ArrayBufferView has an attached ArrayBuffer.
- name: GuardHasAttachedArrayBuffer
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Guard a resizable typed array is in-bounds.
- name: GuardResizableArrayBufferViewInBounds
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Guard a resizable typed array is in-bounds or detached.
- name: GuardResizableArrayBufferViewInBoundsOrDetached
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GuardNumberToIntPtrIndex
gen_boilerplate: false
- name: KeepAliveObject
operands:
object: Object
result_type: None
guard: true
- name: DebugEnterGCUnsafeRegion
result_type: None
guard: true
alias_set: none
- name: DebugLeaveGCUnsafeRegion
result_type: None
guard: true
alias_set: none
- name: Not
gen_boilerplate: false
- name: BoundsCheck
gen_boilerplate: false
- name: BoundsCheckLower
gen_boilerplate: false
- name: SpectreMaskIndex
gen_boilerplate: false
- name: LoadElement
gen_boilerplate: false
- name: LoadElementAndUnbox
gen_boilerplate: false
- name: LoadElementHole
gen_boilerplate: false
- name: StoreElement
gen_boilerplate: false
- name: StoreHoleValueElement
gen_boilerplate: false
- name: StoreElementHole
gen_boilerplate: false
- name: ArrayPopShift
gen_boilerplate: false
# Array.prototype.push on a dense array. Returns the new array length.
- name: ArrayPush
operands:
object: Object
value: Value
result_type: Int32
alias_set: custom
compute_range: custom
clone: true
# Array.prototype.slice on a dense array.
- name: ArraySlice
operands:
object: Object
begin: Int32
end: Int32
arguments:
templateObj: JSObject*
initialHeap: gc::Heap
result_type: Object
possibly_calls: true
# Array.prototype.slice on an arguments object.
- name: ArgumentsSlice
operands:
object: Object
begin: Int32
end: Int32
arguments:
templateObj: JSObject*
initialHeap: gc::Heap
result_type: Object
possibly_calls: true
# Array.prototype.slice on an arguments object.
- name: FrameArgumentsSlice
operands:
begin: Int32
count: Int32
arguments:
templateObj: JSObject*
initialHeap: gc::Heap
result_type: Object
alias_set: none
possibly_calls: true
# Array.prototype.slice on an inlined arguments object.
- name: InlineArgumentsSlice
gen_boilerplate: false
- name: NormalizeSliceTerm
operands:
value: Int32
length: Int32
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
folds_to: custom
# MArrayJoin doesn't override |getAliasSet()|, because Array.prototype.join
# might coerce the elements of the Array to strings. This coercion might
# cause the evaluation of JavaScript code.
- name: ArrayJoin
operands:
array: Object
sep: String
result_type: String
possibly_calls: true
folds_to: custom
# MArrayJoin doesn't override |getAliasSet()|, because Array.prototype.join
# might coerce the elements of the Array to strings. This coercion might
# cause the evaluation of JavaScript code.
# Object.prototype.keys. Used to elide it when possible.
- name: ObjectKeys
operands:
object: Object
result_type: Object
# We can recover Object.keys on bailout as long as the object is not escaped
# or that the object is not mutated by any aliased calls in-between the
# instruction and the recovered location, as the recovered keys array might be
# different.
can_recover: custom
# Used to fold Object.keys(obj).length into a single operation.
#
# This should not be used with a Proxy, as proxies can have a user-defined
# `ownKeys` function which can have arbitrary outputs.
#
# This MIR node is created by folding an MObjectKeys with an MArrayLength, as
# part of MArrayLength::foldsTo.
- name: ObjectKeysLength
operands:
object: Object
result_type: Int32
movable: false
congruent_to: if_operands_equal
alias_set: custom
clone: true
- name: LoadUnboxedScalar
gen_boilerplate: false
- name: LoadDataViewElement
gen_boilerplate: false
- name: LoadTypedArrayElementHole
gen_boilerplate: false
- name: StoreUnboxedScalar
gen_boilerplate: false
- name: StoreDataViewElement
gen_boilerplate: false
- name: StoreTypedArrayElementHole
gen_boilerplate: false
- name: EffectiveAddress
gen_boilerplate: false
- name: ClampToUint8
gen_boilerplate: false
- name: LoadFixedSlot
gen_boilerplate: false
- name: LoadFixedSlotAndUnbox
gen_boilerplate: false
- name: LoadDynamicSlotAndUnbox
gen_boilerplate: false
- name: StoreFixedSlot
gen_boilerplate: false
- name: GetPropertyCache
gen_boilerplate: false
- name: HomeObjectSuperBase
operands:
homeObject: Object
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GetPropSuperCache
gen_boilerplate: false
- name: BindNameCache
operands:
envChain: Object
result_type: Object
- name: CallBindVar
operands:
environmentChain: Object
result_type: Object
movable: true
congruent_to: custom
alias_set: none
- name: GuardShape
operands:
object: Object
arguments:
shape: Shape*
result_type: Object
guard: true
movable: true
congruent_to: custom
alias_set: custom
might_alias: custom
- name: GuardFuse
arguments:
fuseIndex: RealmFuses::FuseIndex
result_type: None
guard: true
movable: true
congruent_to: custom
alias_set: custom
- name: GuardMultipleShapes
operands:
object: Object
shapeList: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GuardProto
gen_boilerplate: false
- name: GuardNullProto
gen_boilerplate: false
# Guard the object is a native object.
- name: GuardIsNativeObject
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardGlobalGeneration
arguments:
expected: uint32_t
generationAddr: const void*
result_type: None
guard: true
movable: true
alias_set: custom
congruent_to: custom
- name: GuardIsProxy
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardIsNotDOMProxy
operands:
proxy: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardIsNotProxy
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: ProxyGet
operands:
proxy: Object
arguments:
id: jsid
result_type: Value
possibly_calls: true
- name: ProxyGetByValue
operands:
proxy: Object
idVal: Value
result_type: Value
possibly_calls: true
- name: ProxyHasProp
operands:
proxy: Object
idVal: Value
arguments:
hasOwn: bool
result_type: Boolean
possibly_calls: true
- name: ProxySet
operands:
proxy: Object
rhs: Value
arguments:
id: jsid
strict: bool
possibly_calls: true
- name: ProxySetByValue
operands:
proxy: Object
idVal: Value
rhs: Value
arguments:
strict: bool
possibly_calls: true
- name: CallSetArrayLength
operands:
obj: Object
rhs: Value
arguments:
strict: bool
possibly_calls: true
- name: MegamorphicLoadSlot
operands:
object: Object
arguments:
name: PropertyKey
result_type: Value
# Bails when non-native or accessor properties are encountered, so we can't
# DCE this instruction.
guard: true
possibly_calls: true
congruent_to: custom
alias_set: custom
- name: MegamorphicLoadSlotByValue
operands:
object: Object
idVal: Value
result_type: Value
# Bails when non-native or accessor properties are encountered, so we can't
# DCE this instruction.
guard: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: custom
possibly_calls: true
- name: MegamorphicStoreSlot
operands:
object: Object
rhs: Value
arguments:
name: PropertyKey
strict: bool
possibly_calls: true
- name: MegamorphicHasProp
operands:
object: Object
idVal: Value
arguments:
hasOwn: bool
result_type: Boolean
# Bails when non-native or accessor properties are encountered, so we can't
# DCE this instruction.
guard: true
congruent_to: custom
alias_set: custom
possibly_calls: true
- name: SmallObjectVariableKeyHasProp
operands:
idStr: String
arguments:
shape: Shape*
congruent_to: custom
result_type: Boolean
alias_set: custom
- name: GuardIsNotArrayBufferMaybeShared
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardIsTypedArray
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardIsFixedLengthTypedArray
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardIsResizableTypedArray
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: GuardHasProxyHandler
operands:
object: Object
arguments:
handler: const void*
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
# Loads a specific JSObject* that was originally nursery-allocated.
# See also WarpObjectField.
- name: NurseryObject
arguments:
# Index in the Vector of objects stored in the WarpSnapshot.
nurseryIndex: uint32_t
result_type: Object
movable: true
congruent_to: custom
alias_set: none
- name: GuardValue
gen_boilerplate: false
- name: GuardNullOrUndefined
operands:
value: Value
result_type: Value
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardIsNotObject
operands:
value: Value
result_type: Value
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardFunctionFlags
gen_boilerplate: false
- name: GuardFunctionIsNonBuiltinCtor
operands:
function: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GuardFunctionKind
operands:
function: Object
arguments:
expected: FunctionFlags::FunctionKind
bailOnEquality: bool
result_type: Object
guard: true
movable: true
congruent_to: custom
alias_set: custom
- name: GuardFunctionScript
operands:
function: Object
arguments:
expected: BaseScript*
nargs: uint16_t
flags: FunctionFlags
result_type: Object
guard: true
movable: true
folds_to: custom
congruent_to: custom
# A JSFunction's BaseScript pointer is immutable. Relazification of
# self-hosted functions is an exception to this, but we don't use this
# guard for self-hosted functions.
alias_set: custom
- name: GuardObjectIdentity
gen_boilerplate: false
- name: GuardSpecificFunction
gen_boilerplate: false
- name: GuardSpecificAtom
operands:
str: String
arguments:
atom: JSAtom*
result_type: String
guard: true
movable: true
congruent_to: custom
folds_to: custom
alias_set: none
- name: GuardSpecificSymbol
gen_boilerplate: false
- name: GuardSpecificInt32
operands:
num: Int32
arguments:
expected: int32_t
result_type: Int32
guard: true
movable: true
folds_to: custom
alias_set: none
- name: GuardStringToIndex
operands:
string: String
result_type: Int32
# Mark as guard because this instruction must not be eliminated. For
# example, if the string is not an index the operation could change from a
# typed array load to a getter call.
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardStringToInt32
operands:
string: String
result_type: Int32
# Mark as guard to prevent the issue described in MGuardStringToIndex's
# constructor.
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardStringToDouble
operands:
string: String
result_type: Double
# Mark as guard to prevent the issue described in MGuardStringToIndex's
# constructor.
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardNoDenseElements
operands:
object: Object
result_type: Object
guard: true
movable: true
alias_set: custom
- name: GuardTagNotEqual
gen_boilerplate: false
- name: LoadDynamicSlot
gen_boilerplate: false
# Inline call to access a function's environment (scope chain).
- name: FunctionEnvironment
operands:
function: Object
result_type: Object
movable: true
folds_to: custom
# A function's environment is fixed.
alias_set: none
# Allocate a new BlockLexicalEnvironmentObject.
- name: NewLexicalEnvironmentObject
operands:
templateObj: Object
result_type: Object
alias_set: none
# Allocate a new ClassBodyEnvironmentObject.
- name: NewClassBodyEnvironmentObject
operands:
templateObj: Object
result_type: Object
alias_set: none
- name: NewVarEnvironmentObject
operands:
templateObj: Object
result_type: Object
alias_set: none
- name: HomeObject
operands:
function: Object
result_type: Object
movable: true
# A function's [[HomeObject]] is fixed.
alias_set: none
- name: AddAndStoreSlot
gen_boilerplate: false
- name: AllocateAndStoreSlot
operands:
object: Object
value: Value
arguments:
slotOffset: uint32_t
shape: Shape*
numNewSlots: uint32_t
possibly_calls: true
alias_set: custom
- name: AddSlotAndCallAddPropHook
operands:
object: Object
value: Value
arguments:
shape: Shape*
possibly_calls: true
- name: StoreDynamicSlot
gen_boilerplate: false
- name: GetNameCache
operands:
envObj: Object
result_type: Value
- name: CallGetIntrinsicValue
arguments:
name: PropertyName*
result_type: Value
possibly_calls: true
- name: DeleteProperty
operands:
value: Value
arguments:
name: PropertyName*
strict: bool
result_type: Boolean
- name: DeleteElement
operands:
value: Value
index: Value
arguments:
strict: bool
result_type: Boolean
- name: SetPropertyCache
gen_boilerplate: false
- name: MegamorphicSetElement
gen_boilerplate: false
- name: SetDOMProperty
gen_boilerplate: false
- name: GetDOMProperty
gen_boilerplate: false
- name: GetDOMMember
gen_boilerplate: false
- name: ObjectToIterator
gen_boilerplate: false
- name: ValueToIterator
operands:
value: Value
result_type: Object
- name: IteratorHasIndices
operands:
object: Object
iterator: Object
result_type: Boolean
alias_set: custom
- name: LoadSlotByIteratorIndex
operands:
object: Object
iterator: Object # TODO: add MIRType::NativeIterator?
result_type: Value
alias_set: custom
- name: StoreSlotByIteratorIndex
operands:
object: Object
iterator: Object
value: Value
alias_set: custom
# Load the private value expando from a DOM proxy. The target is stored in the
# proxy object's private slot.
# This is either an UndefinedValue (no expando), ObjectValue (the expando
# object), or PrivateValue(ExpandoAndGeneration*).
- name: LoadDOMExpandoValue
operands:
proxy: Object
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: LoadDOMExpandoValueGuardGeneration
gen_boilerplate: false
- name: LoadDOMExpandoValueIgnoreGeneration
operands:
proxy: Object
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Takes an expando Value as input, then guards it's either UndefinedValue or
# an object with the expected shape.
- name: GuardDOMExpandoMissingOrGuardShape
operands:
expando: Value
arguments:
shape: Shape*
result_type: Value
guard: true
movable: true
congruent_to: custom
alias_set: custom
- name: StringLength
operands:
string: String
result_type: Int32
movable: true
folds_to: custom
congruent_to: if_operands_equal
# The string |length| property is immutable, so there is no
# implicit dependency.
alias_set: none
compute_range: custom
can_recover: true
clone: true
- name: Floor
gen_boilerplate: false
- name: Ceil
gen_boilerplate: false
- name: Round
gen_boilerplate: false
- name: Trunc
gen_boilerplate: false
- name: NearbyInt
gen_boilerplate: false
- name: GetIteratorCache
gen_boilerplate: false
- name: OptimizeSpreadCallCache
operands:
value: Value
result_type: Value
- name: IteratorMore
operands:
iterator: Object
result_type: Value
- name: IsNoIter
operands:
def: Object
result_type: Boolean
type_policy: none
movable : true
alias_set: none
- name: IteratorEnd
operands:
iterator: Object
- name: CloseIterCache
operands:
iter: Object
arguments:
completionKind: uint8_t
possibly_calls: true
- name: OptimizeGetIteratorCache
operands:
value: Value
result_type: Boolean
- name: InCache
gen_boilerplate: false
- name: InArray
gen_boilerplate: false
- name: GuardElementNotHole
gen_boilerplate: false
- name: NewPrivateName
arguments:
name: JSAtom*
result_type: Symbol
possibly_calls: true
- name: CheckPrivateFieldCache
gen_boilerplate: false
- name: HasOwnCache
gen_boilerplate: false
- name: InstanceOf
gen_boilerplate: false
# Implementation for instanceof operator with unknown rhs.
- name: InstanceOfCache
operands:
obj: Value
proto: Object
result_type: Boolean
- name: ArgumentsLength
result_type: Int32
movable: true
congruent_to: if_operands_equal
# Arguments |length| cannot be mutated by Ion Code.
alias_set: none
compute_range: custom
can_recover: true
# This MIR instruction is used to get an argument from the actual arguments.
- name: GetFrameArgument
operands:
index: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
# This instruction is never aliased, because ops like JSOp::SetArg don't
# write to the argument frames. We create an arguments object in that case.
alias_set: none
# This MIR instruction is used to get an argument from the actual arguments.
# Returns undefined if |index| is larger-or-equals to |length|. Bails out if
# |index| is negative.
- name: GetFrameArgumentHole
operands:
index: Int32
length: Int32
result_type: Value
guard: true
movable: true
congruent_to: if_operands_equal
# This instruction is never aliased, because ops like JSOp::SetArg don't
# write to the argument frames. We create an arguments object in that case.
alias_set: none
- name: NewTarget
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: Rest
operands:
numActuals: Int32
arguments:
numFormals: unsigned
shape: Shape*
result_type: Object
possibly_calls: true
alias_set: none
can_recover: true
- name: PostWriteBarrier
gen_boilerplate: false
- name: PostWriteElementBarrier
gen_boilerplate: false
- name: AssertCanElidePostWriteBarrier
operands:
object: Object
value: Value
result_type: None
guard: true
alias_set: none
- name: NewNamedLambdaObject
arguments:
templateObj: NamedLambdaObject*
result_type: Object
alias_set: none
- name: NewCallObject
gen_boilerplate: false
- name: NewStringObject
gen_boilerplate: false
- name: IsCallable
gen_boilerplate: false
- name: IsConstructor
operands:
object: Object
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: IsCrossRealmArrayConstructor
operands:
object: Object
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: IsObject
operands:
object: Value
result_type: Boolean
movable: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
- name: IsNullOrUndefined
operands:
value: Value
result_type: Boolean
movable: true
folds_to: custom
congruent_to: if_operands_equal
alias_set: none
type_policy: none
can_consume_float32: true
- name: HasClass
gen_boilerplate: false
- name: GuardToClass
gen_boilerplate: false
- name: GuardToEitherClass
gen_boilerplate: false
- name: GuardToFunction
gen_boilerplate: false
- name: IsArray
gen_boilerplate: false
- name: IsTypedArray
gen_boilerplate: false
- name: ObjectClassToString
operands:
object: Object
result_type: String
guard: true
movable: true
congruent_to: if_operands_equal
possibly_calls: true
# Tests @@toStringTag is neither present on this object nor on any object
# of the prototype chain.
alias_set: custom
- name: CheckReturn
operands:
returnValue: Value
thisValue: Value
result_type: Value
guard: true
folds_to: custom
alias_set: custom
- name: CheckThis
operands:
thisValue: Value
result_type: Value
guard: true
folds_to: custom
alias_set: custom
- name: AsyncResolve
operands:
generator: Object
value: Value
result_type: Object
- name: AsyncReject
operands:
generator: Object
reason: Value
stack: Value
result_type: Object
# Returns from this function to the previous caller; this looks like a regular
# Unary instruction and is used to lie to the MIR generator about suspending
# ops like Yield/Await, which are emitted like returns, but MIR-Build like
# regular instructions.
- name: GeneratorReturn
operands:
input: Value
guard: true
alias_set: none
- name: AsyncAwait
operands:
value: Value
generator: Object
result_type: Object
- name: CheckThisReinit
operands:
thisValue: Value
result_type: Value
guard: true
folds_to: custom
alias_set: custom
- name: Generator
gen_boilerplate: false
- name: CanSkipAwait
operands:
value: Value
result_type: Boolean
- name: MaybeExtractAwaitValue
gen_boilerplate: false
- name: IncrementWarmUpCounter
arguments:
script: JSScript*
alias_set: none
- name: AtomicIsLockFree
gen_boilerplate: false
- name: CompareExchangeTypedArrayElement
gen_boilerplate: false
- name: AtomicExchangeTypedArrayElement
gen_boilerplate: false
- name: AtomicTypedArrayElementBinop
gen_boilerplate: false
- name: Debugger
gen_boilerplate: false
- name: CheckIsObj
operands:
value: Value
arguments:
checkKind: uint8_t
result_type: Object
guard: true
folds_to: custom
alias_set: custom
- name: CheckObjCoercible
operands:
checkValue: Value
result_type: Value
guard: true
folds_to: custom
# Throws on null or undefined.
alias_set: custom
- name: CheckClassHeritage
operands:
heritage: Value
result_type: Value
guard: true
- name: DebugCheckSelfHosted
operands:
checkValue: Value
result_type: Value
guard: true
- name: IsPackedArray
operands:
object: Object
result_type: Boolean
movable: true
alias_set: custom
- name: GuardArrayIsPacked
operands:
array: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GetPrototypeOf
operands:
target: Object
result_type: Value
# May throw if target is a proxy.
guard: true
- name: ObjectWithProto
operands:
prototype: Value
result_type: Object
# May throw if prototype is neither an object nor null.
guard: true
possibly_calls: true
- name: ObjectStaticProto
gen_boilerplate: false
# This is basically just a limited case of Constant, for objects which are
# the prototype of another object and will be used for a GuardShape. It
# includes a reference to the receiver object so we can eliminate redundant
# shape guards.
- name: ConstantProto
gen_boilerplate: false
- name: BuiltinObject
arguments:
builtinObjectKind: BuiltinObjectKind
result_type: Object
possibly_calls: true
- name: SuperFunction
operands:
callee: Object
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: InitHomeObject
operands:
function: Object
homeObject: Value
result_type: Object
alias_set: custom
# Return true if the object is definitely a TypedArray constructor, but not
# necessarily from the currently active realm. Return false if the object is
# not a TypedArray constructor or if it's a wrapper.
- name: IsTypedArrayConstructor
operands:
object: Object
result_type: Boolean
alias_set: none
# Load the JSValueTag on all platforms except ARM64. See the comments in
# MacroAssembler-arm64.h for the |cmpTag(Register, ImmTag)| method for why
# ARM64 doesn't use the raw JSValueTag, but instead a modified tag value. That
# modified tag value can't be directly compared against JSValueTag constants.
- name: LoadValueTag
operands:
value: Value
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
# Load the target object from a proxy wrapper. The target is stored in the
# proxy object's private slot. This operation is fallible if the proxy can
# be revoked.
- name: LoadWrapperTarget
operands:
object: Object
arguments:
fallible: bool
result_type: Object
movable: true
congruent_to: custom
# Can't use |AliasSet::None| because the target changes on navigation.
# TODO: Investigate using a narrower or a custom alias set.
alias_set: custom
# Guard the accessor shape is present on the object or its prototype chain.
- name: GuardHasGetterSetter
operands:
object: Object
arguments:
propId: jsid
getterSetter: GetterSetter*
result_type: Object
guard: true
movable: true
possibly_calls: true
congruent_to: custom
alias_set: custom
- name: GuardIsExtensible
operands:
object: Object
result_type: Object
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: GuardInt32IsNonNegative
operands:
index: Int32
result_type: Int32
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: GuardInt32Range
operands:
input: Int32
arguments:
minimum: int32_t
maximum: int32_t
result_type: Int32
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
# Guard the input index is either greater than the dense initialized length of
# an object, or a hole element.
- name: GuardIndexIsNotDenseElement
operands:
object: Object
index: Int32
result_type: Int32
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Guard an array object's length can be updated successfully when adding an
# element at the input index.
- name: GuardIndexIsValidUpdateOrAdd
operands:
object: Object
index: Int32
result_type: Int32
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: custom
# Add or update a sparse element of an ArrayObject or PlainObject. It's allowed
# for the sparse element to be already present on the object. It may also be an
# accessor property, so this instruction is always marked as effectful.
- name: CallAddOrUpdateSparseElement
operands:
object: Object
index: Int32
value: Value
arguments:
strict: bool
possibly_calls: true
# Get a sparse element from an ArrayObject or PlainObject, possibly by calling
# an accessor property.
- name: CallGetSparseElement
operands:
object: Object
index: Int32
result_type: Value
possibly_calls: true
- name: CallNativeGetElement
operands:
object: Object
index: Int32
result_type: Value
possibly_calls: true
- name: CallNativeGetElementSuper
operands:
object: Object
index: Int32
receiver: Value
result_type: Value
possibly_calls: true
# Test if a native object has an own element (sparse or dense) at an index.
- name: CallObjectHasSparseElement
operands:
object: Object
index: Int32
result_type: Boolean
guard: true
congruent_to: if_operands_equal
possibly_calls: true
alias_set: custom
- name: BigIntAsIntN
operands:
bits: Int32
input: BigInt
result_type: BigInt
movable: true
congruent_to: if_operands_equal
possibly_calls: true
alias_set: none
can_recover: true
clone: true
- name: BigIntAsUintN
operands:
bits: Int32
input: BigInt
result_type: BigInt
movable: true
congruent_to: if_operands_equal
possibly_calls: true
alias_set: none
can_recover: true
clone: true
- name: GuardNonGCThing
operands:
input: Value
result_type: Value
guard: true
movable: true
congruent_to: if_operands_equal
folds_to: custom
alias_set: none
- name: ToHashableNonGCThing
operands:
input: Value
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: ToHashableString
operands:
input: String
result_type: String
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: ToHashableValue
operands:
input: Value
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: none
possibly_calls: true
- name: HashNonGCThing
operands:
input: Value
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: HashString
operands:
input: String
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: HashSymbol
operands:
input: Symbol
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: HashBigInt
operands:
input: BigInt
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: none
- name: HashObject
operands:
set: Object
input: Value
result_type: Int32
# In contrast to the previous hash operations, we can't move this
# instruction, because the hashcode is computed from the object's address,
# which can change when the object is moved by the GC.
movable: false
alias_set: none
- name: HashValue
operands:
set: Object
input: Value
result_type: Int32
movable: false
alias_set: none
- name: SetObjectHasNonBigInt
operands:
set: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: SetObjectHasBigInt
operands:
set: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: SetObjectHasValue
operands:
set: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: SetObjectHasValueVMCall
operands:
set: Object
value: Value
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
possibly_calls: true
- name: SetObjectSize
operands:
set: Object
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectHasNonBigInt
operands:
map: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectHasBigInt
operands:
map: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectHasValue
operands:
map: Object
value: Value
hash: Int32
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectHasValueVMCall
operands:
map: Object
value: Value
result_type: Boolean
movable: true
congruent_to: if_operands_equal
alias_set: custom
possibly_calls: true
- name: MapObjectGetNonBigInt
operands:
map: Object
value: Value
hash: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectGetBigInt
operands:
map: Object
value: Value
hash: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectGetValue
operands:
map: Object
value: Value
hash: Int32
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: MapObjectGetValueVMCall
operands:
map: Object
value: Value
result_type: Value
movable: true
congruent_to: if_operands_equal
alias_set: custom
possibly_calls: true
- name: MapObjectSize
operands:
map: Object
result_type: Int32
movable: true
congruent_to: if_operands_equal
alias_set: custom
- name: PostIntPtrConversion
gen_boilerplate: false
- name: WasmNeg
gen_boilerplate: false
- name: WasmBinaryBitwise
gen_boilerplate: false
- name: WasmLoadInstance
gen_boilerplate: false
- name: WasmStoreInstance
gen_boilerplate: false
- name: WasmHeapReg
gen_boilerplate: false
- name: WasmBoundsCheck
gen_boilerplate: false
- name: WasmBoundsCheckRange32
operands:
index: Int32
length: Int32
limit: Int32
arguments:
bytecodeOffset: wasm::BytecodeOffset
result_type: Int32
congruent_to: if_operands_equal
type_policy: none
- name: WasmExtendU32Index
operands:
input: Int32
result_type: Int64
movable: true
congruent_to: if_operands_equal
folds_to: custom
type_policy: none
alias_set: none
- name: WasmWrapU32Index
operands:
input: Int64
result_type: Int32
movable: true
congruent_to: if_operands_equal
folds_to: custom
type_policy: none
alias_set: none
- name: WasmAddOffset
gen_boilerplate: false
- name: WasmAlignmentCheck
gen_boilerplate: false
- name: WasmLoad
gen_boilerplate: false
- name: WasmStore
gen_boilerplate: false
- name: AsmJSLoadHeap
gen_boilerplate: false
- name: AsmJSStoreHeap
gen_boilerplate: false
- name: WasmFence
guard: true
alias_set: none
clone: true
- name: WasmCompareExchangeHeap
gen_boilerplate: false
- name: WasmAtomicExchangeHeap
gen_boilerplate: false
- name: WasmAtomicBinopHeap
gen_boilerplate: false
- name: WasmLoadInstanceDataField
gen_boilerplate: false
- name: WasmLoadGlobalCell
gen_boilerplate: false
- name: WasmLoadTableElement
gen_boilerplate: false
- name: WasmStoreInstanceDataField
gen_boilerplate: false
- name: WasmStoreGlobalCell
gen_boilerplate: false
- name: WasmStoreStackResult
gen_boilerplate: false
- name: WasmDerivedPointer
gen_boilerplate: false
- name: WasmDerivedIndexPointer
gen_boilerplate: false
- name: WasmStoreRef
gen_boilerplate: false
- name: WasmPostWriteBarrierImmediate
gen_boilerplate: false
- name: WasmPostWriteBarrierIndex
gen_boilerplate: false
- name: WasmParameter
gen_boilerplate: false
- name: WasmReturn
gen_boilerplate: false
- name: WasmReturnVoid
gen_boilerplate: false
- name: WasmStackArg
gen_boilerplate: false
- name: WasmRegisterResult
gen_boilerplate: false
- name: WasmFloatRegisterResult
gen_boilerplate: false
- name: WasmRegister64Result
gen_boilerplate: false
- name: WasmStackResultArea
gen_boilerplate: false
- name: WasmStackResult
gen_boilerplate: false
- name: WasmCallCatchable
gen_boilerplate: false
- name: WasmCallUncatchable
gen_boilerplate: false
- name: WasmCallLandingPrePad
gen_boilerplate: false
- name: WasmReturnCall
gen_boilerplate: false
- name: WasmSelect
gen_boilerplate: false
- name: WasmReinterpret
gen_boilerplate: false
- name: Rotate
gen_boilerplate: false
- name: WasmStackSwitchToMain
operands:
suspender: Object
fn: Object
data: WasmAnyRef
type_policy: none
- name: WasmStackSwitchToSuspendable
operands:
suspender: Object
fn: Object
data: WasmAnyRef
type_policy: none
- name: WasmStackContinueOnSuspendable
operands:
suspender: Object
type_policy: none
- name: WasmBinarySimd128
gen_boilerplate: false
- name: WasmBinarySimd128WithConstant
gen_boilerplate: false
# (v128, i32) -> v128 effect-free shift operations.
- name: WasmShiftSimd128
operands:
lhs: Simd128
rhs: Int32
arguments:
simdOp: wasm::SimdOp
type_policy: none
result_type: Simd128
movable: true
congruent_to: custom
alias_set: none
clone: true
# (v128, v128, mask) -> v128 effect-free operation.
- name: WasmShuffleSimd128
operands:
lhs: Simd128
rhs: Simd128
arguments:
shuffle: SimdShuffle
type_policy: none
result_type: Simd128
movable: true
congruent_to: custom
alias_set: none
clone: true
- name: WasmReplaceLaneSimd128
gen_boilerplate: false
- name: WasmUnarySimd128
operands:
src: Simd128
arguments:
simdOp: wasm::SimdOp
type_policy: none
result_type: Simd128
movable: true
congruent_to: custom
alias_set: none
clone: true
- name: WasmTernarySimd128
gen_boilerplate: false
- name: WasmScalarToSimd128
gen_boilerplate: false
- name: WasmReduceSimd128
gen_boilerplate: false
- name: WasmLoadLaneSimd128
gen_boilerplate: false
- name: WasmStoreLaneSimd128
gen_boilerplate: false
- name: UnreachableResult
gen_boilerplate: false
- name: IonToWasmCall
gen_boilerplate: false
- name: WasmLoadField
gen_boilerplate: false
- name: WasmLoadFieldKA
gen_boilerplate: false
- name: WasmLoadElementKA
gen_boilerplate: false
- name: WasmStoreFieldKA
gen_boilerplate: false
- name: WasmStoreFieldRefKA
gen_boilerplate: false
- name: WasmStoreElementKA
gen_boilerplate: false
- name: WasmStoreElementRefKA
gen_boilerplate: false
- name: WasmRefIsSubtypeOfConcrete
gen_boilerplate: false
- name: WasmRefIsSubtypeOfAbstract
gen_boilerplate: false
- name: WasmNewStructObject
gen_boilerplate: false
- name: WasmNewArrayObject
gen_boilerplate: false
#ifdef FUZZING_JS_FUZZILLI
- name: FuzzilliHash
gen_boilerplate: false
- name: FuzzilliHashStore
gen_boilerplate: false
#endif