Source code

Revision control

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::InitialHeap
#
# 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::InitialHeap initialHeap_;
#
# JSObject* templateObject() const { return templateObject_; }
# gc::InitialHeap 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
# if 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
#
# 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:
ins: Value
alias_set: custom
possibly_calls: true
- name: NewArray
gen_boilerplate: false
- name: NewArrayDynamicLength
operands:
length: Int32
arguments:
templateObject: JSObject*
initialHeap: gc::InitialHeap
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::InitialHeap
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::InitialHeap
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::InitialHeap
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
# 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: 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
# if 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
# if 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
# 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
# Store a JS Value that can't be represented as an AnyRef pointer into an
# object that holds the value (opaquely) as such a pointer.
- name: WasmBoxValue
operands:
def: Value
result_type: RefOrNull
congruent_to: if_operands_equal
alias_set: none
- name: WasmAnyRefFromJSObject
operands:
def: Object
type_policy: none
result_type: RefOrNull
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: ToIntegerInt32
gen_boilerplate: false
- 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: Concat
gen_boilerplate: false
- 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
- name: FromCharCode
operands:
code: Int32
result_type: String
movable: true
congruent_to: if_operands_equal
alias_set: none
can_recover: true
clone: true
- name: FromCodePoint
operands:
codePoint: Int32
result_type: String
guard: true
movable: true
congruent_to: if_operands_equal
alias_set: none
clone: true
- name: StringConvertCase
gen_boilerplate: false
- name: StringSplit
operands:
string: String
separator: String
result_type: Object
possibly_calls: true
congruent_to: if_operands_equal
# 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
# Load an arrow function's |new.target| value.
- name: ArrowNewTarget
operands:
callee: Object
result_type: Value
movable: true
congruent_to: if_operands_equal
# An arrow function's lexical |this| value is immutable.
alias_set: none
- 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
- 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
- name: RegExpSearcher
operands:
regexp: Object
string: String
lastIndex: Int32
result_type: Int32
possibly_calls: true
can_recover: true
- name: RegExpTester
operands:
regexp: Object
string: String
lastIndex: Int32
result_type: Int32
possibly_calls: true
can_recover: 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
congruent_to: if_operands_equal
alias_set: none
- name: ModuleMetadata
arguments:
module: JSObject*
result_type: Object
- name: DynamicImport
operands:
specifier: Value
options: Value
result_type: Object
- name: Lambda
gen_boilerplate: false
- name: LambdaArrow
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
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
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
# By default no, unless built as a recovered instruction.
can_recover: 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
# 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
- name: GuardNumberToIntPtrIndex
gen_boilerplate: false
- name: KeepAliveObject
operands:
object: Object
result_type: None
guard: true
- 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::InitialHeap
result_type: Object
possibly_calls: true
# 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.
- 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
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
- 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: 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: PropertyName*
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
congruent_to: if_operands_equal
alias_set: custom
possibly_calls: true
- name: MegamorphicStoreSlot
operands:
object: Object
rhs: Value
arguments:
name: PropertyName*
congruent_to: custom
alias_set: custom
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: 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
# 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: 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
- name: NewLexicalEnvironmentObject
gen_boilerplate: false
# Allocate a new ClassBodyEnvironmentObject.
- name: NewClassBodyEnvironmentObject
operands:
enclosing: Object
arguments:
scope: ClassBodyScope*
result_type: Object
possibly_calls: true
alias_set: none
# Allocate a new BlockLexicalEnvironmentObject from an existing one.
- name: CopyLexicalEnvironmentObject
operands:
env: Object
arguments:
copySlots: bool
result_type: Object
possibly_calls: true
alias_set: custom
- 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: CallSetElement
gen_boilerplate: false
- name: SetDOMProperty
gen_boilerplate: false
- name: GetDOMProperty
gen_boilerplate: false
- name: GetDOMMember
gen_boilerplate: false
- name: ValueToIterator
operands:
value: Value
result_type: Object
# 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: 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: 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
- name: HasClass
gen_boilerplate: false
- name: GuardToClass
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
valueOrReason: Value
arguments:
resolveKind: AsyncFunctionResolveKind
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: none
- 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: FinishBoundFunctionInit
operands:
bound: Object
target: Object
argCount: Int32
- 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
- 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.
- name: LoadWrapperTarget
operands:
object: Object
result_type: Object
movable: true
congruent_to: if_operands_equal
# 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
# Guard the input index is greater than the dense initialized length of an
# object.
- name: GuardIndexGreaterThanDenseInitLength
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 array object. It's allowed for the
# sparse element to be already present on the array. It may also be an accessor
# property, so this instruction is always marked as effectful.
- name: CallAddOrUpdateSparseElement
operands: