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