js/src/jit/MIROps.yaml
author Emilio Cobos Álvarez <emilio@crisal.io>
Tue, 28 Mar 2023 08:20:09 +0000
changeset 658112 702d4a62e5d03a2b36b3a17645718208a30ddb08
parent 657578 17d9f529b72a4e5d7491bd101d3b99e12e092c03
permissions -rw-r--r--
Bug 1824304 - Fix PiP window type hint after bug 1823350. r=stransky Differential Revision: https://phabricator.services.mozilla.com/D173677

# 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

- 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
# 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: 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
  result_type: String
  movable: true
  congruent_to: if_operands_equal
  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: 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: 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 also supports out-of-bounds access.
- name: CharCodeAtMaybeOutOfBounds
  operands:
    string: String
    index: Int32
  result_type: Value
  movable: true
  congruent_to: if_operands_equal
  # Strings are immutable, so there is no implicit dependency.
  alias_set: none

# Like CharCodeAtMaybeOutOfBounds, this operation also supports out-of-bounds access.
- name: CharAtMaybeOutOfBounds
  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: 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: StringIndexOf
  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: 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 value is null
- name: WasmTrapIfNull
  operands:
    value: RefOrNull
  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

- 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
  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
  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: 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::InitialHeap
  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::InitialHeap
  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::InitialHeap
  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.

- 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: 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: 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: 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: 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

- 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: 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.
- 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

- 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: WasmNeg
  gen_boilerplate: false

- name: WasmBinaryBitwise
  gen_boilerplate: false

- name: WasmLoadInstance
  gen_boilerplate: false

- name: WasmStoreInstance
  gen_boilerplate: false

- name: WasmHeapBase
  gen_boilerplate: false

- name: WasmBoundsCheck
  gen_boilerplate: false

- 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: WasmLoadGlobalVar
  gen_boilerplate: false

- name: WasmLoadGlobalCell
  gen_boilerplate: false

- name: WasmLoadTableElement
  gen_boilerplate: false

- name: WasmStoreGlobalVar
  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: WasmPostWriteBarrier
  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: WasmSelect
  gen_boilerplate: false

- name: WasmReinterpret
  gen_boilerplate: false

- name: Rotate
  gen_boilerplate: false

- 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: WasmStoreFieldKA
  gen_boilerplate: false

- name: WasmStoreFieldRefKA
  gen_boilerplate: false

- name: WasmGcObjectIsSubtypeOf
  gen_boilerplate: false

#ifdef FUZZING_JS_FUZZILLI
- name: FuzzilliHash
  gen_boilerplate: false

- name: FuzzilliHashStore
  gen_boilerplate: false
#endif