Bytecode Descriptions

Bytecode Listing

This document is automatically generated from Opcodes.h by make_opcode_doc.py.

Constants

JSOP_UNDEFINED
Stack: ⇒ undefined

Push undefined.

JSOP_NULL
Stack: ⇒ null

Push null.

JSOP_FALSE, JSOP_TRUE
Stack: ⇒ true/false

Push a boolean constant.

JSOP_INT32
Operands: (int32_t val)
Stack: ⇒ val

Push the int32_t immediate operand as an Int32Value.

JSOP_ZERO, JSOP_ONE, JSOP_INT8, JSOP_UINT16, and JSOP_UINT24 are all compact encodings for JSOP_INT32.

JSOP_ZERO
Stack: ⇒ 0

Push the number 0.

JSOP_ONE
Stack: ⇒ 1

Push the number 1.

JSOP_INT8
Operands: (int8_t val)
Stack: ⇒ val

Push the int8_t immediate operand as an Int32Value.

JSOP_UINT16
Operands: (uint16_t val)
Stack: ⇒ val

Push the uint16_t immediate operand as an Int32Value.

JSOP_UINT24
Operands: (uint24_t val)
Stack: ⇒ val

Push the uint24_t immediate operand as an Int32Value.

JSOP_DOUBLE
Operands: (double val)
Stack: ⇒ val

Push the 64-bit floating-point immediate operand as a DoubleValue.

If the operand is a NaN, it must be the canonical NaN (see JS::detail::CanonicalizeNaN).

JSOP_BIGINT
Operands: (uint32_t bigIntIndex)
Stack: ⇒ bigint

Push the BigInt constant script->getBigInt(bigIntIndex).

JSOP_STRING
Operands: (uint32_t atomIndex)
Stack: ⇒ string

Push the string constant script->getAtom(atomIndex).

Flags: JOF_ATOM
JSOP_SYMBOL
Operands: (uint8_t symbol (the JS::SymbolCode of the symbol to use))
Stack: ⇒ symbol

Push a well-known symbol.

symbol must be in range for JS::SymbolCode.

Expressions

Unary operators

JSOP_VOID
Stack: valundefined

Pop the top value on the stack, discard it, and push undefined.

Implements: The void operator, step 3.

JSOP_TYPEOF, JSOP_TYPEOFEXPR
Stack: val(typeof val)

The typeof operator.

Infallible. The result is always a string that depends on the type of val.

JSOP_TYPEOF and JSOP_TYPEOFEXPR are the same except that--amazingly--JSOP_TYPEOF affects the behavior of an immediately preceding JSOP_GETNAME or JSOP_GETGNAME instruction! This is how we implement typeof step 2, making typeof nonExistingVariable return "undefined" instead of throwing a ReferenceError.

In a global scope:

  • typeof x compiles to GETGNAME "x"; TYPEOF.
  • typeof (0, x) compiles to GETGNAME "x"; TYPEOFEXPR.

Emitting the same bytecode for these two expressions would be a bug. Per spec, the latter throws a ReferenceError if x doesn't exist.

Flags: JOF_DETECTING, JOF_IC
JSOP_POS
Stack: val(+val)

The unary + operator.

+val doesn't do any actual math. It just calls ToNumber(val).

The conversion can call .toString()/.valueOf() methods and can throw. The result on success is always a Number. (Per spec, unary - supports BigInts, but unary + does not.)

JSOP_NEG
Stack: val(-val)

The unary - operator.

Convert val to a numeric value, then push -val. The conversion can call .toString()/.valueOf() methods and can throw. The result on success is always numeric.

Flags: JOF_IC
JSOP_BITNOT
Stack: val(~val)

The bitwise NOT operator (~).

val is converted to an integer, then bitwise negated. The conversion can call .toString()/.valueOf() methods and can throw. The result on success is always an Int32 or BigInt value.

Flags: JOF_IC
JSOP_NOT
Stack: val(!val)

The logical NOT operator (!).

val is first converted with ToBoolean, then logically negated. The result is always a boolean value. This does not call user-defined methods and can't throw.

Flags: JOF_DETECTING, JOF_IC

Binary operators

JSOP_BITOR, JSOP_BITXOR, JSOP_BITAND
Stack: lval, rval(lval OP rval)

Binary bitwise operations (|, ^, &).

The arguments are converted to integers first. The conversion can call .toString()/.valueOf() methods and can throw. The result on success is always an Int32 or BigInt Value.

Flags: JOF_IC
JSOP_EQ, JSOP_NE
Stack: lval, rval(lval OP rval)

Loose equality operators (== and !=).

Pop two values, compare them, and push the boolean result. The comparison may perform conversions that call .toString()/.valueOf() methods and can throw.

Implements: Abstract Equality Comparison.

Flags: JOF_DETECTING, JOF_IC
JSOP_STRICTEQ, JSOP_STRICTNE
Stack: lval, rval(lval OP rval)

Strict equality operators (=== and !==).

Pop two values, check whether they're equal, and push the boolean result. This does not call user-defined methods and can't throw (except possibly due to OOM while flattening a string).

Implements: Strict Equality Comparison.

Flags: JOF_DETECTING, JOF_IC
JSOP_LT, JSOP_GT, JSOP_LE, JSOP_GE
Stack: lval, rval(lval OP rval)

Relative operators (<, >, <=, >=).

Pop two values, compare them, and push the boolean result. The comparison may perform conversions that call .toString()/.valueOf() methods and can throw.

Implements: Relational Operators: Evaluation.

Flags: JOF_IC
JSOP_INSTANCEOF
Stack: value, target(value instanceof target)

The instanceof operator.

This throws a TypeError if target is not an object. It calls target[Symbol.hasInstance](value) if the method exists. On success, the result is always a boolean value.

Flags: JOF_IC
JSOP_IN
Stack: id, obj(id in obj)

The in operator.

Push true if obj has a property with the key id. Otherwise push false.

This throws a TypeError if obj is not an object. This can fire proxy hooks and can throw. On success, the result is always a boolean value.

Flags: JOF_IC
JSOP_LSH, JSOP_RSH, JSOP_URSH
Stack: lval, rval(lval OP rval)

Bitwise shift operators (<<, >>, >>>).

Pop two values, convert them to integers, perform a bitwise shift, and push the result.

Conversion can call .toString()/.valueOf() methods and can throw. The result on success is always an Int32 or BigInt Value.

Flags: JOF_IC
JSOP_ADD
Stack: lval, rval(lval + rval)

The binary + operator.

Pop two values, convert them to primitive values, add them, and push the result. If both values are numeric, add them; if either is a string, do string concatenation instead.

The conversion can call .toString()/.valueOf() methods and can throw.

Flags: JOF_IC
JSOP_SUB
Stack: lval, rval(lval - rval)

The binary - operator.

Pop two values, convert them to numeric values, subtract the top value from the other one, and push the result.

The conversion can call .toString()/.valueOf() methods and can throw. On success, the result is always numeric.

Flags: JOF_IC
JSOP_INC, JSOP_DEC
Stack: val(val +/- 1)

Add or subtract 1.

val must already be a numeric value, such as the result of JSOP_TONUMERIC.

Implements: The ++ and -- operators, step 3 of each algorithm.

Flags: JOF_IC
JSOP_MUL, JSOP_DIV, JSOP_MOD
Stack: lval, rval(lval OP rval)

The multiplicative operators (*, /, %).

Pop two values, convert them to numeric values, do math, and push the result.

The conversion can call .toString()/.valueOf() methods and can throw. On success, the result is always numeric.

Flags: JOF_IC
JSOP_POW
Stack: lval, rval(lval ** rval)

The exponentiation operator (**).

Pop two values, convert them to numeric values, do exponentiation, and push the result. The top value is the exponent.

The conversion can call .toString()/.valueOf() methods and can throw. This throws a RangeError if both values are BigInts and the exponent is negative.

Flags: JOF_IC

Conversions

JSOP_TOID
Stack: propertyNameValuepropertyKey

Convert a value to a property key.

Implements: ToPropertyKey, except that if the result would be the string representation of some integer in the range 0..2^31, we push the corresponding Int32 value instead. This is because the spec insists that array indices are strings, whereas for us they are integers.

This is used for code like ++obj[index], which must do both a JSOP_GETELEM and a JSOP_SETELEM with the same property key. Both instructions would convert index to a property key for us, but the spec says to convert it only once.

The conversion can call .toString()/.valueOf() methods and can throw.

JSOP_TONUMERIC, JSOP_TOSTRING
Stack: valToNumeric(val)

Convert a value to a numeric value (a Number or BigInt).

Implements: ToNumeric(val).

Note: This is used to implement ++ and --. Surprisingly, it's not possible to get the right behavior using JSOP_ADD and JSOP_SUB alone. For one thing, JSOP_ADD sometimes does string concatenation, while ++ always does numeric addition. More fundamentally, the result of evaluating --x is ToNumeric(old value of x), a value that the sequence GETLOCAL "x"; ONE; SUB; SETLOCAL "x" does not give us.

Other expressions

JSOP_GLOBALTHIS
Stack: ⇒ this

Push the global this value. Not to be confused with the globalThis property on the global.

This must be used only in scopes where this refers to the global this.

JSOP_NEWTARGET
Stack: ⇒ new.target

Push the value of new.target.

The result is a constructor or undefined.

This must be used only in scripts where new.target is allowed: non-arrow function scripts and other scripts that have a non-arrow function script on the scope chain.

Implements: GetNewTarget.

JSOP_DYNAMIC_IMPORT
Stack: moduleIdpromise

Dynamic import of the module specified by the string value on the top of the stack.

Implements: Import Calls.

JSOP_IMPORTMETA
Stack: ⇒ import.meta

Push the import.meta object.

This must be used only in module code.

Objects

Creating objects

JSOP_NEWINIT
Operands: (uint32_t _unused)
Stack: ⇒ obj

Create and push a new object with no properties.

(This opcode has 4 unused bytes so it can be easily turned into JSOP_NEWOBJECT during bytecode generation.)

Flags: JOF_IC
JSOP_NEWOBJECT, JSOP_NEWOBJECT_WITHGROUP
Operands: (uint32_t baseobjIndex)
Stack: ⇒ obj

Create and push a new object of a predetermined shape.

The new object has the shape of the template object script->getObject(baseobjIndex). Subsequent INITPROP instructions must fill in all slots of the new object before it is used in any other way.

For JSOP_NEWOBJECT, the new object has a group based on the allocation site (or a new group if the template's group is a singleton). For JSOP_NEWOBJECT_WITHGROUP, the new object has the same group as the template object.

Flags: JOF_OBJECT, JOF_IC
JSOP_OBJECT
Operands: (uint32_t objectIndex)
Stack: ⇒ obj

Push a preconstructed object.

Going one step further than JSOP_NEWOBJECT, this instruction doesn't just reuse the shape--it actually pushes the preconstructed object script->getObject(objectIndex) right onto the stack. The object must be a singleton PlainObject or ArrayObject.

The spec requires that an ObjectLiteral or ArrayLiteral creates a new object every time it's evaluated, so this instruction must not be used anywhere it might be executed more than once.

There's a shell-only option, newGlobal({cloneSingletons: true}), that makes this instruction do a deep copy of the object. A few tests use it.

Flags: JOF_OBJECT
JSOP_OBJWITHPROTO
Stack: protoobj

Create and push a new ordinary object with the provided [[Prototype]].

This is used to create the .prototype object for derived classes.

Defining properties

JSOP_INITPROP
Operands: (uint32_t nameIndex)
Stack: obj, valobj

Define a data property on an object.

obj must be an object.

Implements: CreateDataPropertyOrThrow as used in PropertyDefinitionEvaluation of regular and shorthand PropertyDefinitions.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPINIT, JOF_DETECTING, JOF_IC
JSOP_INITHIDDENPROP
Operands: (uint32_t nameIndex)
Stack: obj, valobj

Like JSOP_INITPROP, but define a non-enumerable property.

This is used to define class methods.

Implements: PropertyDefinitionEvaluation for methods, steps 3 and 4, when enumerable is false.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPINIT, JOF_DETECTING, JOF_IC
JSOP_INITLOCKEDPROP
Operands: (uint32_t nameIndex)
Stack: obj, valobj

Like JSOP_INITPROP, but define a non-enumerable, non-writable, non-configurable property.

This is used to define the .prototype property on classes.

Implements: MakeConstructor, step 8, when writablePrototype is false.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPINIT, JOF_DETECTING, JOF_IC
JSOP_INITELEM, JSOP_INITHIDDENELEM
Stack: obj, id, valobj

Define a data property on obj with property key id and value val.

Implements: CreateDataPropertyOrThrow. This instruction is used for object literals like {0: val} and {[id]: val}, and methods like *[Symbol.iterator]() {}.

JSOP_INITHIDDENELEM is the same but defines a non-enumerable property, for class methods.

Flags: JOF_ELEM, JOF_PROPINIT, JOF_DETECTING, JOF_IC
JSOP_INITPROP_GETTER, JSOP_INITHIDDENPROP_GETTER
Operands: (uint32_t nameIndex)
Stack: obj, getterobj

Define an accessor property on obj with the given getter. nameIndex gives the property name.

JSOP_INITHIDDENPROP_GETTER is the same but defines a non-enumerable property, for getters in classes.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPINIT, JOF_DETECTING
JSOP_INITELEM_GETTER, JSOP_INITHIDDENELEM_GETTER
Stack: obj, id, getterobj

Define an accessor property on obj with property key id and the given getter.

This is used to implement getters like get [id]() {} or get 0() {}.

JSOP_INITHIDDENELEM_GETTER is the same but defines a non-enumerable property, for getters in classes.

Flags: JOF_ELEM, JOF_PROPINIT, JOF_DETECTING
JSOP_INITPROP_SETTER, JSOP_INITHIDDENPROP_SETTER
Operands: (uint32_t nameIndex)
Stack: obj, setterobj

Define an accessor property on obj with the given setter.

This is used to implement ordinary setters like set foo(v) {}.

JSOP_INITHIDDENPROP_SETTER is the same but defines a non-enumerable property, for setters in classes.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPINIT, JOF_DETECTING
JSOP_INITELEM_SETTER, JSOP_INITHIDDENELEM_SETTER
Stack: obj, id, setterobj

Define an accesssor property on obj with property key id and the given setter.

This is used to implement setters with computed property keys or numeric keys.

JSOP_INITHIDDENELEM_SETTER is the same but defines a non-enumerable property, for setters in classes.

Flags: JOF_ELEM, JOF_PROPINIT, JOF_DETECTING

Accessing properties

JSOP_GETPROP, JSOP_CALLPROP
Operands: (uint32_t nameIndex)
Stack: objobj[name]

Get the value of the property obj.name. This can call getters and proxy traps.

JSOP_CALLPROP is exactly like JSOP_GETPROP but hints to the VM that we're getting a method in order to call it.

Implements: GetV, GetValue step 5.

Flags: JOF_ATOM, JOF_PROP, JOF_TYPESET, JOF_IC
JSOP_GETELEM, JSOP_CALLELEM
Stack: obj, keyobj[key]

Get the value of the property obj[key].

JSOP_CALLELEM is exactly like JSOP_GETELEM but hints to the VM that we're getting a method in order to call it.

Implements: GetV, GetValue step 5.

Flags: JOF_ELEM, JOF_TYPESET, JOF_IC
JSOP_LENGTH
Operands: (uint32_t nameIndex)
Stack: objobj.length

Push the value of obj.length.

nameIndex must be the index of the atom "length". This then behaves exactly like JSOP_GETPROP.

Flags: JOF_ATOM, JOF_PROP, JOF_TYPESET, JOF_IC
JSOP_SETPROP
Operands: (uint32_t nameIndex)
Stack: obj, valval

Non-strict assignment to a property, obj.name = val.

This throws a TypeError if obj is null or undefined. If it's a primitive value, the property is set on ToObject(obj), typically with no effect.

Implements: PutValue step 6 for non-strict code.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSLOPPY, JOF_IC
JSOP_STRICTSETPROP
Operands: (uint32_t nameIndex)
Stack: obj, valval

Like JSOP_SETPROP, but for strict mode code. Throw a TypeError if obj[key] exists but is non-writable, if it's an accessor property with no setter, or if obj is a primitive value.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSTRICT, JOF_IC
JSOP_SETELEM
Stack: obj, key, valval

Non-strict assignment to a property, obj[key] = val.

Implements: PutValue step 6 for non-strict code.

Flags: JOF_ELEM, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSLOPPY, JOF_IC
JSOP_STRICTSETELEM
Stack: obj, key, valval

Like JSOP_SETELEM, but for strict mode code. Throw a TypeError if obj[key] exists but is non-writable, if it's an accessor property with no setter, or if obj is a primitive value.

Flags: JOF_ELEM, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSTRICT, JOF_IC
JSOP_DELPROP
Operands: (uint32_t nameIndex)
Stack: objsucceeded

Delete a property from obj. Push true on success, false if the property existed but could not be deleted. This implements delete obj.name in non-strict code.

Throws if obj is null or undefined. Can call proxy traps.

Implements: delete obj.propname step 5 in non-strict code.

Flags: JOF_ATOM, JOF_PROP, JOF_CHECKSLOPPY
JSOP_STRICTDELPROP
Operands: (uint32_t nameIndex)
Stack: objsucceeded

Like JSOP_DELPROP, but for strict mode code. Push true on success, else throw a TypeError.

Flags: JOF_ATOM, JOF_PROP, JOF_CHECKSTRICT
JSOP_DELELEM
Stack: obj, keysucceeded

Delete the property obj[key] and push true on success, false if the property existed but could not be deleted.

This throws if obj is null or undefined. Can call proxy traps.

Implements: delete obj[key] step 5 in non-strict code.

Flags: JOF_ELEM, JOF_CHECKSLOPPY
JSOP_STRICTDELELEM
Stack: obj, keysucceeded

Like JSOP_DELELEM, but for strict mode code. Pushtrue` on success, else throw a TypeError.

Flags: JOF_ELEM, JOF_CHECKSTRICT
JSOP_HASOWN
Stack: id, obj(obj.hasOwnProperty(id))

Push true if obj has an own property id.

Note that obj is the top value, like JSOP_IN.

This opcode is not used for normal JS. Self-hosted code uses it by calling the intrinsic hasOwn(id, obj). For example, Object.prototype.hasOwnProperty is implemented this way (see js/src/builtin/Object.js).

Flags: JOF_IC

Super

JSOP_SUPERBASE
Stack: calleesuperBase

Push the SuperBase of the method callee. The SuperBase is callee.[[HomeObject]].[[GetPrototypeOf]](), the object where super property lookups should begin.

callee must be a function that has a HomeObject that's an object, typically produced by JSOP_CALLEE or JSOP_ENVCALLEE.

Implements: GetSuperBase, except that instead of the environment, the argument supplies the callee.

JSOP_GETPROP_SUPER
Operands: (uint32_t nameIndex)
Stack: receiver, objsuper.name

Get the value of receiver.name, starting the property search at obj. In spec terms, obj.[[Get]](name, receiver).

Implements: GetValue for references created by super.name. The receiver is this and obj is the SuperBase of the enclosing method.

Flags: JOF_ATOM, JOF_PROP, JOF_TYPESET, JOF_IC
JSOP_GETELEM_SUPER
Stack: receiver, key, objsuper[key]

Get the value of receiver[key], starting the property search at obj. In spec terms, obj.[[Get]](key, receiver).

Implements: GetValue for references created by super[key] (where the receiver is this and obj is the SuperBase of the enclosing method); Reflect.get(obj, key, receiver).

Flags: JOF_ELEM, JOF_TYPESET, JOF_IC
JSOP_SETPROP_SUPER
Operands: (uint32_t nameIndex)
Stack: receiver, obj, valval

Assign val to receiver.name, starting the search for an existing property at obj. In spec terms, obj.[[Set]](name, val, receiver).

Implements: PutValue for references created by super.name in non-strict code. The receiver is this and obj is the SuperBase of the enclosing method.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSLOPPY
JSOP_STRICTSETPROP_SUPER
Operands: (uint32_t nameIndex)
Stack: receiver, obj, valval

Like JSOP_SETPROP_SUPER, but for strict mode code.

Flags: JOF_ATOM, JOF_PROP, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSTRICT
JSOP_SETELEM_SUPER
Stack: receiver, key, obj, valval

Assign val to receiver[key], strating the search for an existing property at obj. In spec terms, obj.[[Set]](key, val, receiver).

Implements: PutValue for references created by super[key] in non-strict code. The receiver is this and obj is the SuperBase of the enclosing method.

Flags: JOF_ELEM, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSLOPPY
JSOP_STRICTSETELEM_SUPER
Stack: receiver, key, obj, valval

Like JSOP_SETELEM_SUPER, but for strict mode code.

Flags: JOF_ELEM, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSTRICT

Enumeration

JSOP_ITER
Stack: valiter

Set up a for-in loop by pushing a PropertyIteratorObject over the enumerable properties of val.

Implements: ForIn/OfHeadEvaluation step 6, EnumerateObjectProperties. (The spec refers to an "Iterator object" with a next method, but notes that it "is never directly accessible" to scripts. The object we use for this has no public methods.)

If val is null or undefined, this pushes an empty iterator.

The iter object pushed by this instruction must not be used or removed from the stack except by JSOP_MOREITER and JSOP_ENDITER, or by error handling.

The script's JSScript::trynotes() must mark the body of the for-in loop, i.e. exactly those instructions that begin executing with iter on the stack, starting with the next instruction (always JSOP_LOOPHEAD). Code must not jump into or out of this region: control can enter only by executing JSOP_ITER and can exit only by executing a JSOP_ENDITER or by exception unwinding. (A JSOP_ENDITER is always emitted at the end of the loop, and extra copies are emitted on "exit slides", where a break, continue, or return statement exits the loop.)

Typically a single try note entry marks the contiguous chunk of bytecode from the instruction after JSOP_ITER to JSOP_ENDITER (inclusive); but if that range contains any instructions on exit slides, after a JSOP_ENDITER, then those must be correctly noted as outside the loop.

Flags: JOF_IC
JSOP_MOREITER
Stack: iteriter, name

Get the next property name for a for-in loop.

iter must be a PropertyIteratorObject produced by JSOP_ITER. This pushes the property name for the next loop iteration, or MagicValue(JS_NO_ITER_VALUE) if there are no more enumerable properties to iterate over. The magic value must be used only by JSOP_ISNOITER and JSOP_ENDITER.

JSOP_ISNOITER
Stack: valval, done

Test whether the value on top of the stack is MagicValue(JS_NO_ITER_VALUE) and push the boolean result.

JSOP_ITERNEXT
Stack: valval

No-op instruction to hint to IonBuilder that the value on top of the stack is the (likely string) key in a for-in loop.

JSOP_ENDITER
Stack: iter, iterval

Exit a for-in loop, closing the iterator.

iter must be a PropertyIteratorObject pushed by JSOP_ITER.

Iteration

JSOP_CHECKISOBJ
Operands: (uint8_t kind)
Stack: resultresult

Check that the top value on the stack is an object, and throw a TypeError if not. kind is used only to generate an appropriate error message. It must be in range for js::CheckIsObjectKind.

Implements: GetIterator step 5, IteratorNext step 3. Both operations call a JS method which scripts can define however they want, so they check afterwards that the method returned an object.

JSOP_CHECKISCALLABLE
Operands: (uint8_t kind)
Stack: objobj

Check that the top value on the stack is callable, and throw a TypeError if not. The operand kind is used only to generate an appropriate error message. It must be in range for js::CheckIsCallableKind.

JSOP_CHECKOBJCOERCIBLE
Stack: valval

Throw a TypeError if val is null or undefined.

Implements: RequireObjectCoercible. But most instructions that require an object will perform this check for us, so of the dozens of calls to RequireObjectCoercible in the spec, we need this instruction only for destructuring assignment and initialization.

JSOP_TOASYNCITER
Stack: iter, nextasynciter

Create and push an async iterator wrapping the sync iterator iter. next should be iter's .next method.

Implements: CreateAsyncToSyncIterator. The spec says this operation takes one argument, but that argument is a Record with two relevant fields, [[Iterator]] and [[NextMethod]].

Used for for await loops.

SetPrototype

JSOP_MUTATEPROTO
Stack: obj, protoValobj

Set the prototype of obj.

obj must be an object.

Implements: B.3.1 proto Property Names in Object Initializers, step 7.a.

Array literals

JSOP_NEWARRAY
Operands: (uint32_t length)
Stack: ⇒ array

Create and push a new Array object with the given length, preallocating enough memory to hold that many elements.

Flags: JOF_IC
JSOP_INITELEM_ARRAY
Operands: (uint32_t index)
Stack: array, valarray

Initialize an array element array[index] with value val.

val may be MagicValue(JS_ELEMENTS_HOLE). If it is, this does nothing.

This never calls setters or proxy traps.

array must be an Array object created by JSOP_NEWARRAY with length > index, and never used except by JSOP_INITELEM_ARRAY.

Implements: ArrayAccumulation, the third algorithm, step 4, in the common case where nextIndex is known.

Flags: JOF_ELEM, JOF_PROPINIT, JOF_DETECTING, JOF_IC
JSOP_INITELEM_INC
Stack: array, index, valarray, (index + 1)

Initialize an array element array[index++] with value val.

val may be MagicValue(JS_ELEMENTS_HOLE). If it is, no element is defined, but the array length and the stack value index are still incremented.

This never calls setters or proxy traps.

array must be an Array object created by JSOP_NEWARRAY and never used except by JSOP_INITELEM_ARRAY and JSOP_INITELEM_INC.

index must be an integer, 0 <= index <= INT32_MAX. If index is INT32_MAX, this throws a RangeError.

This instruction is used when an array literal contains a SpreadElement. In [a, ...b, c], INITELEM_ARRAY 0 is used to put a into the array, but INITELEM_INC is used for the elements of b and for c.

Implements: Several steps in ArrayAccumulation that call CreateDataProperty, set the array length, and/or increment nextIndex.

Flags: JOF_ELEM, JOF_PROPINIT, JOF_IC
JSOP_HOLE
Stack: ⇒ hole

Push MagicValue(JS_ELEMENTS_HOLE), representing an Elision in an array literal (like the missing property 0 in the array [, 1]).

This magic value must be used only by JSOP_INITELEM_ARRAY or JSOP_INITELEM_INC.

JSOP_NEWARRAY_COPYONWRITE
Operands: (uint32_t objectIndex)
Stack: ⇒ array

Create and push a new array that shares the elements of a template object.

script->getObject(objectIndex) must be a copy-on-write array whose elements are all primitive values.

This is an optimization. This single instruction implements an entire array literal, saving run time, code, and memory compared to JSOP_NEWARRAY and a series of JSOP_INITELEM instructions.

Flags: JOF_OBJECT

RegExp literals

JSOP_REGEXP
Operands: (uint32_t regexpIndex)
Stack: ⇒ regexp

Clone and push a new RegExp object.

Implements: Evaluation for RegularExpressionLiteral.

Functions

Creating functions

JSOP_LAMBDA
Operands: (uint32_t funcIndex)
Stack: ⇒ fn

Push a function object.

This clones the function unless it's a singleton; see CanReuseFunctionForClone. The new function inherits the current environment chain.

Used to create most JS functions. Notable exceptions are arrow functions and derived or default class constructors.

The function indicated by funcIndex must be a non-arrow function.

Implements: InstantiateFunctionObject, Evaluation for FunctionExpression, and so on.

Flags: JOF_OBJECT
JSOP_LAMBDA_ARROW
Operands: (uint32_t funcIndex)
Stack: newTargetarrowFn

Push a new arrow function.

newTarget matters only if the arrow function uses the expression new.target. It should be the current value of new.target, so that the arrow function inherits new.target from the enclosing scope. (If new.target is illegal here, the value doesn't matter; use null.)

The function indicated by funcIndex must be an arrow function.

Flags: JOF_OBJECT
JSOP_SETFUNNAME
Operands: (uint8_t prefixKind)
Stack: fun, namefun

Set the name of a function.

fun must be a function object. name must be a string, Int32 value, or symbol (like the result of JSOP_TOID).

Implements: SetFunctionName, used e.g. to name methods with computed property names.

JSOP_INITHOMEOBJECT
Stack: fun, homeObjectfun

Initialize the home object for functions with super bindings.

Creating constructors

JSOP_CHECKCLASSHERITAGE
Stack: baseClassbaseClass

Throw a TypeError if baseClass isn't either null or a constructor.

Implements: ClassDefinitionEvaluation step 6.f.

JSOP_FUNWITHPROTO
Operands: (uint32_t funcIndex)
Stack: protoobj

Like JSOP_LAMBDA, but using proto as the new function's [[Prototype]] (or %FunctionPrototype% if proto is null).

proto must be either a constructor or null. We use JSOP_CHECKCLASSHERITAGE to check.

This is used to create the constructor for a derived class.

Implements: ClassDefinitionEvaluation steps 6.e.ii, 6.g.iii, and 12 for derived classes.

Flags: JOF_OBJECT
JSOP_CLASSCONSTRUCTOR
Operands: (uint32_t nameIndex, uint32_t sourceStart, uint32_t sourceEnd)
Stack: ⇒ constructor

Create and push a default constructor for a base class.

A default constructor behaves like constructor() {}.

Implements: ClassDefinitionEvaluation for ClassTail, steps 10.b. and 12-17.

The sourceStart/sourceEnd offsets are the start/end offsets of the class definition in the source buffer and are used for toString().

Flags: JOF_CLASS_CTOR
JSOP_DERIVEDCONSTRUCTOR
Operands: (uint32_t nameIndex, uint32_t sourceStart, uint32_t sourceEnd)
Stack: protoconstructor

Create and push a default constructor for a derived class.

A default derived-class constructor behaves like constructor(...args) { super(...args); }.

Implements: ClassDefinitionEvaluation for ClassTail, steps 10.a. and 12-17.

The sourceStart/sourceEnd offsets are the start/end offsets of the class definition in the source buffer and are used for toString().

Flags: JOF_CLASS_CTOR
JSOP_BUILTINPROTO
Operands: (uint8_t kind)
Stack: ⇒ %BuiltinPrototype%

Pushes the current global's builtin prototype for a given proto key.

Calls

JSOP_CALL, JSOP_CALLITER, JSOP_FUNAPPLY, JSOP_FUNCALL, JSOP_CALL_IGNORES_RV
Operands: (uint16_t argc)
Stack: callee, this, args[0], ..., args[argc-1]rval

Invoke callee with this and args, and push the return value. Throw a TypeError if callee isn't a function.

JSOP_CALLITER is used for implicit calls to @@iterator methods, to ensure error messages are formatted with JSMSG_NOT_ITERABLE ("x is not iterable") rather than JSMSG_NOT_FUNCTION ("x[Symbol.iterator] is not a function"). The argc operand must be 0 for this variation.

JSOP_FUNAPPLY hints to the VM that this is likely a call to the builtin method Function.prototype.apply, an easy optimization target.

JSOP_FUNCALL similarly hints to the VM that the callee is likely Function.prototype.call.

JSOP_CALL_IGNORES_RV hints to the VM that the return value is ignored. This allows alternate faster implementations to be used that avoid unnecesary allocations.

Implements: EvaluateCall steps 4, 5, and 7.

Flags: JOF_ARGC, JOF_INVOKE, JOF_TYPESET, JOF_IC
JSOP_SPREADCALL
Stack: callee, this, argsrval

Like JSOP_CALL, but the arguments are provided in an array rather than a span of stack slots. Used to implement spread-call syntax: f(...args).

args must be an Array object containing the actual arguments. The array must be packed (dense and free of holes; see IsPackedArray). This can be ensured by creating the array with JSOP_NEWARRAY and populating it using JSOP_INITELEM_ARRAY.

Flags: JOF_INVOKE, JOF_TYPESET, JOF_IC
JSOP_OPTIMIZE_SPREADCALL
Stack: arrarr, optimized

Push true if arr is an array object that can be passed directly as the args argument to JSOP_SPREADCALL.

This instruction and the branch around the iterator loop are emitted only when arr is itself a rest parameter, as in (...arr) => f(...arr), a strong hint that it's a packed Array whose prototype is Array.prototype.

See js::OptimizeSpreadCall.

JSOP_EVAL
Operands: (uint16_t argc)
Stack: callee, this, args[0], ..., args[argc-1]rval

Perform a direct eval in the current environment if callee is the builtin eval function, otherwise follow same behaviour as JSOP_CALL.

All direct evals use one of the JSOP_*EVAL operations here and these opcodes are only used when the syntactic conditions for a direct eval are met. If the builtin eval function is called though other means, it becomes an indirect eval.

Direct eval causes all bindings in enclosing non-global scopes to be marked "aliased". The optimization that puts bindings in stack slots has to prove that the bindings won't need to be captured by closures or accessed using JSOP_{GET,BIND,SET,DEL}NAME instructions. Direct eval makes that analysis impossible.

Implements: Function Call Evaluation, steps 5-7 and 9, when the syntactic critera for direct eval in step 6 are all met.

Flags: JOF_ARGC, JOF_INVOKE, JOF_TYPESET, JOF_CHECKSLOPPY, JOF_IC
JSOP_SPREADEVAL
Stack: callee, this, argsrval

Spread-call variant of JSOP_EVAL.

See JSOP_SPREADCALL for restrictions on args.

Flags: JOF_INVOKE, JOF_TYPESET, JOF_CHECKSLOPPY, JOF_IC
JSOP_STRICTEVAL
Operands: (uint16_t argc)
Stack: evalFn, this, args[0], ..., args[argc-1]rval

Like JSOP_EVAL, but for strict mode code.

Flags: JOF_ARGC, JOF_INVOKE, JOF_TYPESET, JOF_CHECKSTRICT, JOF_IC
JSOP_STRICTSPREADEVAL
Stack: callee, this, argsrval

Spread-call variant of JSOP_STRICTEVAL.

See JSOP_SPREADCALL for restrictions on args.

Flags: JOF_INVOKE, JOF_TYPESET, JOF_CHECKSTRICT, JOF_IC
JSOP_IMPLICITTHIS
Operands: (uint32_t nameIndex)
Stack: ⇒ this

Push the implicit this value for an unqualified function call, like foo(). nameIndex gives the name of the function we're calling.

The result is always undefined except when the name refers to a with binding. For example, in with (date) { getFullYear(); }, the implicit this passed to getFullYear is date, not undefined.

This walks the run-time environment chain looking for the environment record that contains the function. If the function call is not inside a with statement, use JSOP_GIMPLICITTHIS instead. If the function call definitely refers to a local binding, use JSOP_UNDEFINED.

Implements: EvaluateCall step 1.b. But not entirely correctly. See bug 1166408.

Flags: JOF_ATOM
JSOP_GIMPLICITTHIS
Operands: (uint32_t nameIndex)
Stack: ⇒ this

Like JSOP_IMPLICITTHIS, but the name must not be bound in any local environments.

The result is always undefined except when the name refers to a binding in a non-syntactic with environment.

Note: The frontend has to emit JSOP_GIMPLICITTHIS (and not JSOP_UNDEFINED) for global unqualified function calls, even when CompileOptions::nonSyntacticScope == false, because later js::CloneGlobalScript can be called with ScopeKind::NonSyntactic to clone the script into a non-syntactic environment, with the bytecode reused, unchanged.

Flags: JOF_ATOM
JSOP_CALLSITEOBJ
Operands: (uint32_t objectIndex)
Stack: ⇒ callSiteObj

Push the call site object for a tagged template call.

script->getObject(objectIndex) is the call site object; script->getObject(objectIndex + 1) is the raw object.

The first time this instruction runs for a given template, it assembles the final value, defining the .raw property on the call site object and freezing both objects.

Implements: GetTemplateObject, steps 4 and 12-16.

Flags: JOF_OBJECT
JSOP_IS_CONSTRUCTING
Stack: ⇒ JS_IS_CONSTRUCTING

Push MagicValue(JS_IS_CONSTRUCTING).

This magic value is a required argument to the JSOP_NEW and JSOP_SUPERCALL instructions and must not be used any other way.

JSOP_NEW, JSOP_SUPERCALL
Operands: (uint16_t argc)
Stack: callee, isConstructing, args[0], ..., args[argc-1], newTargetrval

Invoke callee as a constructor with args and newTarget, and push the return value. Throw a TypeError if callee isn't a constructor.

isConstructing must be the value pushed by JSOP_IS_CONSTRUCTING.

JSOP_SUPERCALL behaves exactly like JSOP_NEW, but is used for SuperCall expressions, to allow JITs to distinguish them from new expressions.

Implements: EvaluateConstruct steps 7 and 8.

Flags: JOF_ARGC, JOF_INVOKE, JOF_TYPESET, JOF_IC, JOF_IC
JSOP_SPREADNEW, JSOP_SPREADSUPERCALL
Stack: callee, isConstructing, args, newTargetrval

Spread-call variant of JSOP_NEW.

Invokes callee as a constructor with args and newTarget, and pushes the return value onto the stack.

isConstructing must be the value pushed by JSOP_IS_CONSTRUCTING. See JSOP_SPREADCALL for restrictions on args.

JSOP_SPREADSUPERCALL behaves exactly like JSOP_SPREADNEW, but is used for SuperCall expressions.

Flags: JOF_INVOKE, JOF_TYPESET, JOF_IC
JSOP_SUPERFUN
Stack: calleesuperFun

Push the prototype of callee in preparation for calling super(). Throw a TypeError if that value is not a constructor.

callee must be a derived class constructor.

Implements: GetSuperConstructor, steps 4-7.

JSOP_CHECKTHISREINIT
Stack: thisvalthisval

Throw a ReferenceError if thisval is not MagicValue(JS_UNINITIALIZED_LEXICAL). Used in derived class constructors to prohibit calling super more than once.

Implements: BindThisValue, step 3.

Generators and async functions

JSOP_GENERATOR
Stack: ⇒ generator

Initializes generator frame, creates a generator and pushes it on the stack.

JSOP_INITIALYIELD
Operands: (uint24_t resumeIndex)
Stack: genrval, gen, resumeKind

Pops the generator from the top of the stack, suspends it and stops execution.

When resuming execution, JSOP_RESUME pushes the rval, gen and resumeKind values. resumeKind is the GeneratorResumeKind stored as int32.

Flags: JOF_RESUMEINDEX
JSOP_AFTERYIELD
Operands: (uint32_t icIndex)

Bytecode emitted after 'yield' expressions. This is useful for the Debugger and AbstractGeneratorObject::isAfterYieldOrAwait. It's treated as jump target op so that the Baseline Interpreter can efficiently restore the frame's interpreterICEntry when resuming a generator.

Flags: JOF_ICINDEX
JSOP_FINALYIELDRVAL
Stack: gen

Pops the generator and suspends and closes it. Yields the value in the frame's return value slot.

JSOP_YIELD
Operands: (uint24_t resumeIndex)
Stack: rval1, genrval2, gen, resumeKind

Pops the generator and the return value 'rval1', stops execution and returns 'rval1'.

When resuming execution, JSOP_RESUME pushes the rval2, gen and resumeKind values.

Flags: JOF_RESUMEINDEX
JSOP_ISGENCLOSING
Stack: valval, res

Pushes a boolean indicating whether the top of the stack is MagicValue(JS_GENERATOR_CLOSING).

JSOP_ASYNCAWAIT
Stack: value, genpromise

Pops the top two values 'value' and 'gen' from the stack, then starts "awaiting" for 'value' to be resolved, which will then resume the execution of 'gen'. Pushes the async function promise on the stack, so that it'll be returned to the caller on the very first "await".

JSOP_ASYNCRESOLVE
Operands: (uint8_t fulfillOrReject)
Stack: valueOrReason, genpromise

Pops the top two values 'valueOrReason' and 'gen' from the stack, then pushes the promise resolved with 'valueOrReason'. gen must be the internal generator object created in async functions. The pushed promise is the async function's result promise, which is stored in gen.

JSOP_AWAIT
Operands: (uint24_t resumeIndex)
Stack: promise, genresolved, gen, resumeKind

Pops the generator and the return value 'promise', stops execution and returns 'promise'.

When resuming execution, JSOP_RESUME pushes the resolved, gen and resumeKind values. resumeKind is the GeneratorResumeKind stored as int32.

Flags: JOF_RESUMEINDEX
JSOP_TRYSKIPAWAIT
Stack: valuevalue_or_resolved, canskip

Pops the top of stack value as 'value', checks if the await for 'value' can be skipped. If the await operation can be skipped and the resolution value for 'value' can be acquired, pushes the resolution value and 'true' onto the stack. Otherwise, pushes 'value' and 'false' on the stack.

JSOP_RESUMEKIND
Operands: (GeneratorResumeKind resumeKind (encoded as uint8_t))
Stack: ⇒ resumeKind

Pushes one of the GeneratorResumeKind values as Int32Value.

JSOP_CHECK_RESUMEKIND
Stack: rval, gen, resumeKindrval

Pops the generator and resumeKind values. resumeKind is the GeneratorResumeKind stored as int32. If resumeKind is Next, continue execution. If resumeKind is Throw or Return, these completions are handled by throwing an exception. See GeneratorThrowOrReturn.

JSOP_RESUME
Stack: gen, val, resumeKindrval

Pops the generator, argument and resumeKind from the stack, pushes a new generator frame and resumes execution of it. Pushes the return value after the generator yields.

Flags: JOF_INVOKE

Control flow

Jump targets

JSOP_JUMPTARGET
Operands: (uint32_t icIndex)

No-op instruction marking the target of a jump instruction.

This instruction and a few others (see js::BytecodeIsJumpTarget) are jump target instructions. The Baseline Interpreter uses these instructions to sync the frame's interpreterICEntry after a jump. Ion uses them to find block boundaries when translating bytecode to MIR.

Flags: JOF_ICINDEX
JSOP_LOOPHEAD
Operands: (uint32_t icIndex, uint8_t depthHint)

Marks the target of the backwards jump for some loop.

This is a jump target instruction (see JSOP_JUMPTARGET). Additionally, it checks for interrupts and handles JIT tiering.

The depthHint operand is a loop depth hint for Ion. It starts at 1 and deeply nested loops all have the same value.

For the convenience of the JITs, scripts must not start with this instruction. See bug 1602390.

Jumps

JSOP_GOTO
Operands: (int32_t offset)

Jump to a 32-bit offset from the current bytecode.

See "Jump instructions" above for details.

Flags: JOF_JUMP
JSOP_IFEQ
Operands: (int32_t forwardOffset)
Stack: cond

If ToBoolean(cond) is false, jumps to a 32-bit offset from the current instruction.

Flags: JOF_JUMP, JOF_DETECTING, JOF_IC
JSOP_IFNE
Operands: (int32_t offset)
Stack: cond

If ToBoolean(cond) is true, jump to a 32-bit offset from the current instruction.

offset may be positive or negative. This is the instruction used at the end of a do-while loop to jump back to the top.

Flags: JOF_JUMP, JOF_IC
JSOP_AND
Operands: (int32_t forwardOffset)
Stack: condcond

Short-circuit for logical AND.

If ToBoolean(cond) is false, jump to a 32-bit offset from the current instruction. The value remains on the stack.

Flags: JOF_JUMP, JOF_DETECTING, JOF_IC
JSOP_OR
Operands: (int32_t forwardOffset)
Stack: condcond

Short-circuit for logical OR.

If ToBoolean(cond) is true, jump to a 32-bit offset from the current instruction. The value remains on the stack.

Flags: JOF_JUMP, JOF_DETECTING, JOF_IC
JSOP_COALESCE
Operands: (int32_t forwardOffset)
Stack: valval

Short-circuiting for nullish coalescing.

If val is not null or undefined, jump to a 32-bit offset from the current instruction.

Flags: JOF_JUMP, JOF_DETECTING
JSOP_CASE
Operands: (int32_t forwardOffset)
Stack: val, condval (if !cond)

Like JSOP_IFNE ("jump if true"), but if the branch is taken, pop and discard an additional stack value.

This is used to implement switch statements when the JSOP_TABLESWITCH optimization is not possible. The switch statement

switch (expr) {
    case A: stmt1;
    case B: stmt2;
}

compiles to this bytecode:

    # dispatch code - evaluate expr, check it against each `case`,
    # jump to the right place in the body or to the end.
    <expr>
    dup; <A>; stricteq; case L1; jumptarget
    dup; <B>; stricteq; case L2; jumptarget
    default LE

    # body code
L1: jumptarget; <stmt1>
L2: jumptarget; <stmt2>
LE: jumptarget

This opcode is weird: it's the only one whose ndefs varies depending on which way a conditional branch goes. We could implement switch statements using JSOP_IFNE and JSOP_POP, but that would also be awkward--putting the POP inside the switch body would complicate fallthrough.

Flags: JOF_JUMP
JSOP_DEFAULT
Operands: (int32_t forwardOffset)
Stack: lval

Like JSOP_GOTO, but pop and discard an additional stack value.

This appears after all cases for a non-optimized switch statement. If there's a default: label, it jumps to that point in the body; otherwise it jumps to the next statement.

Flags: JOF_JUMP
JSOP_TABLESWITCH
Operands: (int32_t defaultOffset, int32_t low, int32_t high, uint24_t firstResumeIndex)
Stack: i

Optimized switch-statement dispatch, used when all case labels are small integer constants.

If low <= i <= high, jump to the instruction at the offset given by script->resumeOffsets()[firstResumeIndex + i - low], in bytes from the start of the current script's bytecode. Otherwise, jump to the instruction at defaultOffset from the current instruction. All of these offsets must be in range for the current script and must point to JSOP_JUMPTARGET instructions.

The following inequalities must hold: low <= high and firstResumeIndex + high - low < resumeOffsets().size().

Flags: JOF_DETECTING

Return

JSOP_RETURN
Stack: rval

Return rval.

This must not be used in derived class constructors. Instead use JSOP_SETRVAL, JSOP_CHECKRETURN, and JSOP_RETRVAL.

JSOP_GETRVAL
Stack: ⇒ rval

Push the current stack frame's returnValue. If no JSOP_SETRVAL instruction has been executed in this stack frame, this is undefined.

Every stack frame has a returnValue slot, used by top-level scripts, generators, async functions, and derived class constructors. Plain functions usually use JSOP_RETURN instead.

JSOP_SETRVAL
Stack: rval

Store rval in the current stack frame's returnValue slot.

JSOP_RETRVAL

Stop execution and return the current stack frame's returnValue. If no JSOP_SETRVAL instruction has been executed in this stack frame, this is undefined.

Also emitted at end of every script so consumers don't need to worry about running off the end.

If the current script is a derived class constructor, returnValue must be an object. The script can use JSOP_CHECKRETURN to ensure this.

JSOP_CHECKRETURN
Stack: thisval

Check the return value in a derived class constructor.

  • If the current stack frame's returnValue is an object, do nothing.

  • Otherwise, if the returnValue is undefined and thisval is an object, store thisval in the returnValue slot.

  • Otherwise, throw a TypeError.

This is exactly what has to happen when a derived class constructor returns. thisval should be the current value of this, or MagicValue(JS_UNINITIALIZED_LEXICAL) if this is uninitialized.

Implements: The [[Construct]] internal method of JS functions, steps 13 and 15.

Exceptions

JSOP_THROW
Stack: exc

Throw exc. (ノಠ益ಠ)ノ彡┴──┴

This sets the pending exception to exc and jumps to error-handling code. If we're in a try block, error handling adjusts the stack and environment chain and resumes execution at the top of the catch or finally block. Otherwise it starts unwinding the stack.

Implements: ThrowStatement Evaluation, step 3.

This is also used in for-of loops. If the body of the loop throws an exception, we catch it, close the iterator, then use JSOP_THROW to rethrow.

JSOP_THROWMSG
Operands: (uint16_t msgNumber)

Create and throw an Error object.

Sometimes we know at emit time that an operation always throws. For example, delete super.prop; is allowed in methods, but always throws a ReferenceError.

msgNumber must be one of the error codes listed in js/src/js.msg; it determines the .message and [[Prototype]] of the new Error object. The number of arguments in the error message must be 0.

JSOP_THROWSETALIASEDCONST
Operands: (uint8_t hops, uint24_t slot)
Stack: vv

Throw a TypeError for invalid assignment to a const. The environment coordinate is used to get the variable name for the error message.

Flags: JOF_ENVCOORD, JOF_NAME, JOF_DETECTING
JSOP_THROWSETCALLEE
Stack: vv

Throw a TypeError for invalid assignment to the callee binding in a named lambda, which is always a const binding. This is a different bytecode than JSOP_THROWSETCONST because the named lambda callee, if not closed over, does not have a frame slot to look up the name with for the error message.

JSOP_THROWSETCONST
Operands: (uint24_t localno)
Stack: vv

Throws a runtime TypeError for invalid assignment to an optimized const binding. localno is used to get the variable name for the error message.

Flags: JOF_LOCAL, JOF_NAME, JOF_DETECTING
JSOP_TRY
Operands: (int32_t jumpAtEndOffset)

No-op instruction that marks the top of the bytecode for a TryStatement.

The jumpAtEndOffset operand is the offset (relative to the current op) of the JSOP_GOTO at the end of the try-block body. This is used by bytecode analysis and JIT compilation.

Location information for catch/finally blocks is stored in a side table, script->trynotes().

Flags: JOF_CODE_OFFSET
JSOP_TRY_DESTRUCTURING

No-op instruction used by the exception unwinder to determine the correct environment to unwind to when performing IteratorClose due to destructuring.

JSOP_EXCEPTION
Stack: ⇒ exception

Push and clear the pending exception. ┬──┬◡ノ(° -°ノ)

This must be used only in the fixed sequence of instructions following a JSTRY_CATCH span (see "Bytecode Invariants" above), as that's the only way instructions would run with an exception pending.

Used to implement catch-blocks, including the implicit ones generated as part of for-of iteration.

JSOP_RESUMEINDEX
Operands: (uint24_t resumeIndex)
Stack: ⇒ resumeIndex

Push resumeIndex.

This value must be used only by JSOP_GOSUB, JSOP_FINALLY, and JSOP_RETSUB.

Flags: JOF_RESUMEINDEX
JSOP_GOSUB
Operands: (int32_t forwardOffset)
Stack: false, resumeIndex

Jump to the start of a finally block.

JSOP_GOSUB is unusual: if the finally block finishes normally, it will reach the JSOP_RETSUB instruction at the end, and control then "returns" to the JSOP_GOSUB and picks up at the next instruction, like a function call but within a single script and stack frame. (It's named after the thing in BASIC.)

We need this because a try block can terminate in several different ways: control can flow off the end, return, throw an exception, break with or without a label, or continue. Exceptions are handled separately; but all those success paths are written as bytecode, and each one needs to run the finally block before continuing with whatever they were doing. They use JSOP_GOSUB for this. It is thus normal for multiple GOSUB instructions in a script to target the same finally block.

Rules: forwardOffset must be positive and must target a JSOP_JUMPTARGET instruction followed by JSOP_FINALLY. The instruction immediately following JSOP_GOSUB in the script must be a JSOP_JUMPTARGET instruction, and resumeIndex must be the index into script->resumeOffsets() that points to that instruction.

Note: This op doesn't actually push or pop any values. Its use count of 2 is a lie to make the stack depth math work for this very odd control flow instruction.

JSOP_GOSUB is considered to have two "successors": the target of offset, which is the actual next instruction to run; and the instruction immediately following JSOP_GOSUB, even though it won't run until later. We define the successor graph this way in order to support knowing the stack depth at that instruction without first reading the whole finally block.

The stack depth at that instruction is, as it happens, the current stack depth minus 2. So this instruction gets nuses == 2.

Unfortunately there is a price to be paid in horribleness. When JSOP_GOSUB runs, it leaves two values on the stack that the stack depth math doesn't know about. It jumps to the finally block, where JSOP_FINALLY again does nothing to the stack, but with a bogus def count of 2, restoring balance to the accounting. If JSOP_RETSUB is reached, it pops the two values (for real this time) and control resumes at the instruction that follows JSOP_GOSUB in memory.

Flags: JOF_JUMP
JSOP_FINALLY
Stack: ⇒ false, resumeIndex

No-op instruction that marks the start of a finally block. This has a def count of 2, but the values are already on the stack (they're actually left on the stack by JSOP_GOSUB).

These two values must not be used except by JSOP_RETSUB.

JSOP_RETSUB
Stack: throwing, v

Jump back to the next instruction, or rethrow an exception, at the end of a finally block. See JSOP_GOSUB for the explanation.

If throwing is true, throw v. Otherwise, v must be a resume index; jump to the corresponding offset within the script.

The two values popped must be the ones notionally pushed by JSOP_FINALLY.

Variables and scopes

Initialization

JSOP_UNINITIALIZED
Stack: ⇒ uninitialized

Push MagicValue(JS_UNINITIALIZED_LEXICAL), a magic value used to mark a binding as uninitialized.

This magic value must be used only by JSOP_INIT*LEXICAL.

JSOP_INITLEXICAL
Operands: (uint24_t localno)
Stack: vv

Initialize an optimized local lexical binding; or mark it as uninitialized.

This stores the value v in the fixed slot localno in the current stack frame. If v is the magic value produced by JSOP_UNINITIALIZED, this marks the binding as uninitialized. Otherwise this initializes the binding with value v.

Implements: CreateMutableBinding step 3, substep "record that it is uninitialized", and InitializeBinding, for optimized locals. (Note: this is how const bindings are initialized.)

Flags: JOF_LOCAL, JOF_NAME, JOF_DETECTING
JSOP_INITGLEXICAL
Operands: (uint32_t nameIndex)
Stack: valval

Initialize a global lexical binding; or mark it as uninitialized.

Like JSOP_INITLEXICAL but for global lexicals.

Flags: JOF_ATOM, JOF_NAME, JOF_PROPINIT, JOF_GNAME, JOF_IC
JSOP_INITALIASEDLEXICAL
Operands: (uint8_t hops, uint24_t slot)
Stack: vv

Initialize an aliased lexical binding; or mark it as uninitialized.

Like JSOP_INITLEXICAL but for aliased bindings.

Note: There is no even-less-optimized INITNAME instruction because JS doesn't need it. We always know statically which binding we're initializing.

hops is usually 0, but in function f(a=eval("var b;")) { }, the argument a is initialized from inside a nested scope, so hops == 1.

Flags: JOF_ENVCOORD, JOF_NAME, JOF_PROPINIT, JOF_DETECTING
JSOP_CHECKLEXICAL
Operands: (uint24_t localno)

Throw a ReferenceError if the optimized local localno is uninitialized.

localno must be the number of a fixed slot in the current stack frame previously initialized or marked uninitialized using JSOP_INITLEXICAL.

Typically used before JSOP_GETLOCAL or JSOP_SETLOCAL.

Implements: GetBindingValue step 3 and SetMutableBinding step 4 for declarative Environment Records.

Flags: JOF_LOCAL, JOF_NAME
JSOP_CHECKALIASEDLEXICAL
Operands: (uint8_t hops, uint24_t slot)

Like JSOP_CHECKLEXICAL but for aliased bindings.

Note: There are no CHECKNAME or CHECKGNAME instructions because they're unnecessary. JSOP_{GET,SET}{NAME,GNAME} all check for uninitialized lexicals and throw if needed.

Flags: JOF_ENVCOORD, JOF_NAME
JSOP_CHECKTHIS
Stack: thisthis

Throw a ReferenceError if the value on top of the stack is MagicValue(JS_UNINITIALIZED_LEXICAL). Used in derived class constructors to check this (which needs to be initialized before use, by calling super()).

Implements: GetThisBinding step 3.

Looking up bindings

JSOP_BINDGNAME
Operands: (uint32_t nameIndex)
Stack: ⇒ global

Push the global environment onto the stack, unless the script has a non-syntactic global scope. In that case, this acts like JSOP_BINDNAME.

nameIndex is only used when acting like JSOP_BINDNAME.

Flags: JOF_ATOM, JOF_NAME, JOF_GNAME, JOF_IC
JSOP_BINDNAME
Operands: (uint32_t nameIndex)
Stack: ⇒ env

Look up a name on the environment chain and push the environment which contains a binding for that name. If no such binding exists, push the global lexical environment.

Flags: JOF_ATOM, JOF_NAME, JOF_IC

Getting binding values

JSOP_GETNAME
Operands: (uint32_t nameIndex)
Stack: ⇒ val

Find a binding on the environment chain and push its value.

If the binding is an uninitialized lexical, throw a ReferenceError. If no such binding exists, throw a ReferenceError unless the next instruction is JSOP_TYPEOF, in which case push undefined.

Implements: ResolveBinding followed by GetValue (adjusted hackily for typeof).

This is the fallback GET instruction that handles all unoptimized cases. Optimized instructions follow.

Flags: JOF_ATOM, JOF_NAME, JOF_TYPESET, JOF_IC
JSOP_GETGNAME
Operands: (uint32_t nameIndex)
Stack: ⇒ val

Find a global binding and push its value.

This searches the global lexical environment and, failing that, the global object. (Unlike most declarative environments, the global lexical environment can gain more bindings after compilation, possibly shadowing global object properties.)

This is an optimized version of JSOP_GETNAME that skips all local scopes, for use when the name doesn't refer to any local binding. NonSyntacticVariablesObjects break this optimization, so if the current script has a non-syntactic global scope, this acts like JSOP_GETNAME.

Like JSOP_GETNAME, this throws a ReferenceError if no such binding is found (unless the next instruction is JSOP_TYPEOF) or if the binding is an uninitialized lexical.

Flags: JOF_ATOM, JOF_NAME, JOF_TYPESET, JOF_GNAME, JOF_IC
JSOP_GETARG
Operands: (uint16_t argno)
Stack: ⇒ arguments[argno]

Push the value of an argument that is stored in the stack frame or in an ArgumentsObject.

Flags: JOF_QARG, JOF_NAME
JSOP_GETLOCAL
Operands: (uint24_t localno)
Stack: ⇒ val

Push the value of an optimized local variable.

If the variable is an uninitialized lexical, push MagicValue(JS_UNINIITALIZED_LEXICAL).

Flags: JOF_LOCAL, JOF_NAME
JSOP_GETALIASEDVAR
Operands: (uint8_t hops, uint24_t slot)
Stack: ⇒ aliasedVar

Push the value of an aliased binding.

Local bindings that aren't closed over or dynamically accessed are stored in stack slots. Global and with bindings are object properties. All other bindings are called "aliased" and stored in EnvironmentObjects.

Where possible, ALIASED instructions are used to access aliased bindings. (There's no difference in meaning between ALIASEDVAR and ALIASEDLEXICAL.) Each of these instructions has operands hops and slot that encode an EnvironmentCoordinate, directions to the binding from the current environment object.

hops and slot must be valid for the current scope.

ALIASED instructions can't be used when there's a dynamic scope (due to non-strict eval or with) that might shadow the aliased binding.

Flags: JOF_ENVCOORD, JOF_NAME, JOF_TYPESET, JOF_IC
JSOP_GETIMPORT
Operands: (uint32_t nameIndex)
Stack: ⇒ val

Get the value of a module import by name and pushes it onto the stack.

Flags: JOF_ATOM, JOF_NAME, JOF_TYPESET, JOF_IC
JSOP_GETBOUNDNAME
Operands: (uint32_t nameIndex)
Stack: envv

Get the value of a binding from the environment env. If the name is not bound in env, throw a ReferenceError.

env must be an environment currently on the environment chain, pushed by JSOP_BINDNAME.

Note: JSOP_BINDNAME and JSOP_GETBOUNDNAME are the two halves of the JSOP_GETNAME operation: finding and reading a variable. This decomposed version is needed to implement the compound assignment and increment/decrement operators, which get and then set a variable. The spec says the variable lookup is done only once. If we did the lookup twice, there would be observable bugs, thanks to dynamic scoping. We could set the wrong variable or call proxy traps incorrectly.

Implements: GetValue steps 4 and 6.

Flags: JOF_ATOM, JOF_NAME, JOF_TYPESET, JOF_IC
JSOP_GETINTRINSIC
Operands: (uint32_t nameIndex)
Stack: ⇒ intrinsic[name]

Push the value of an intrinsic onto the stack.

Non-standard. Intrinsics are slots in the intrinsics holder object (see GlobalObject::getIntrinsicsHolder), which is used in lieu of global bindings in self-hosting code.

Flags: JOF_ATOM, JOF_NAME, JOF_TYPESET, JOF_IC
JSOP_CALLEE
Stack: ⇒ callee

Pushes the currently executing function onto the stack.

The current script must be a function script.

Used to implement super. This is also used sometimes as a minor optimization when a named function expression refers to itself by name:

f = function fac(n) {  ... fac(n - 1) ... };

This lets us optimize away a lexical environment that contains only the binding for fac, unless it's otherwise observable (via with, eval, or a nested closure).

JSOP_ENVCALLEE
Operands: (uint8_t numHops)
Stack: ⇒ callee

Load the callee stored in a CallObject on the environment chain. The numHops operand is the number of environment objects to skip on the environment chain.

Setting binding values

JSOP_SETNAME
Operands: (uint32_t nameIndex)
Stack: env, valval

Assign val to the binding in env with the name given by nameIndex. Throw a ReferenceError if the binding is an uninitialized lexical. This can call setters and/or proxy traps.

env must be an environment currently on the environment chain, pushed by JSOP_BINDNAME.

This is the fallback SET instruction that handles all unoptimized cases. Optimized instructions follow.

Implements: PutValue steps 5 and 7 for unoptimized bindings.

Note: JSOP_BINDNAME and JSOP_SETNAME are the two halves of simple assignment: finding and setting a variable. They are two separate instructions because, per spec, the "finding" part happens before evaluating the right-hand side of the assignment, and the "setting" part after. Optimized cases don't need a BIND instruction because the "finding" is done statically.

Flags: JOF_ATOM, JOF_NAME, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSLOPPY, JOF_IC
JSOP_STRICTSETNAME
Operands: (uint32_t nameIndex)
Stack: env, valval

Like JSOP_SETNAME, but throw a TypeError if there is no binding for the specified name in env, or if the binding is immutable (a const or read-only property).

Implements: PutValue steps 5 and 7 for strict mode code.

Flags: JOF_ATOM, JOF_NAME, JOF_PROPSET, JOF_DETECTING, JOF_CHECKSTRICT, JOF_IC
JSOP_SETGNAME
Operands: (uint32_t nameIndex)
Stack: env, valval

Like JSOP_SETNAME, but for assigning to globals. env must be an environment pushed by JSOP_BINDGNAME.

Flags: JOF_ATOM, JOF_NAME, JOF_PROPSET, JOF_DETECTING, JOF_GNAME, JOF_CHECKSLOPPY, JOF_IC
JSOP_STRICTSETGNAME
Operands: (uint32_t nameIndex)
Stack: env, valval

Like JSOP_STRICTSETGNAME, but for assigning to globals. env must be an environment pushed by JSOP_BINDGNAME.

Flags: JOF_ATOM, JOF_NAME, JOF_PROPSET, JOF_DETECTING, JOF_GNAME, JOF_CHECKSTRICT, JOF_IC
JSOP_SETARG
Operands: (uint16_t argno)
Stack: valval

Assign val to an argument binding that's stored in the stack frame or in an ArgumentsObject.

Flags: JOF_QARG, JOF_NAME
JSOP_SETLOCAL
Operands: (uint24_t localno)
Stack: vv

Assign to an optimized local binding.

Flags: JOF_LOCAL, JOF_NAME, JOF_DETECTING
JSOP_SETALIASEDVAR
Operands: (uint8_t hops, uint24_t slot)
Stack: valval

Assign to an aliased binding.

Implements: SetMutableBinding for declarative Environment Records, in certain cases where it's known that the binding exists, is mutable, and has been initialized.

Flags: JOF_ENVCOORD, JOF_NAME, JOF_PROPSET, JOF_DETECTING
JSOP_SETINTRINSIC
Operands: (uint32_t nameIndex)
Stack: valval

Assign to an intrinsic.

Nonstandard. Intrinsics are used in lieu of global bindings in self- hosted code. The value is actually stored in the intrinsics holder object, GlobalObject::getIntrinsicsHolder. (Self-hosted code doesn't have many global vars, but it has many functions.)

Flags: JOF_ATOM, JOF_NAME, JOF_DETECTING

Entering and leaving environments

JSOP_PUSHLEXICALENV
Operands: (uint32_t lexicalScopeIndex)

Push a lexical environment onto the environment chain.

The LexicalScope indicated by lexicalScopeIndex determines the shape of the new LexicalEnvironmentObject. All bindings in the new environment are marked as uninitialized.

Implements: Evaluation of Block, steps 1-4.

Fine print for environment chain instructions

The following rules for JSOP_{PUSH,POP}LEXICALENV also apply to JSOP_{PUSH,POP}VARENV and JSOP_{ENTER,LEAVE}WITH.

Each JSOP_POPLEXICALENV instruction matches a particular JSOP_PUSHLEXICALENV instruction in the same script and must have the same scope and stack depth as the instruction immediately after that PUSHLEXICALENV.

JSOP_PUSHLEXICALENV enters a scope that extends to some set of instructions in the script. Code must not jump into or out of this region: control can enter only by executing PUSHLEXICALENV and can exit only by executing a POPLEXICALENV or by exception unwinding. (A JSOP_POPLEXICALENV is always emitted at the end of the block, and extra copies are emitted on "exit slides", where a break, continue, or return statement exits the scope.)

The script's JSScript::scopeNotes() must identify exactly which instructions begin executing in this scope. Typically this means a single entry marking the contiguous chunk of bytecode from the instruction after JSOP_PUSHLEXICALENV to JSOP_POPLEXICALENV (inclusive); but if that range contains any instructions on exit slides, after a JSOP_POPLEXICALENV, then those must be correctly noted as outside the scope.

Flags: JOF_SCOPE
JSOP_POPLEXICALENV

Pop a lexical environment from the environment chain.

See JSOP_PUSHLEXICALENV for the fine print.

JSOP_DEBUGLEAVELEXICALENV

No-op instruction that indicates leaving an optimized lexical scope.

If all bindings in a lexical scope are optimized into stack slots, then the runtime environment objects for that scope are optimized away. No JSOP_{PUSH,POP}LEXICALENV instructions are emitted. However, the debugger still needs to be notified when control exits a scope; that's what this instruction does.

The last instruction in a lexical scope, as indicated by scope notes, must be marked with either this instruction (if the scope is optimized) or JSOP_POPLEXICALENV (if not).

JSOP_RECREATELEXICALENV

Recreate the current block on the environment chain with a fresh block with uninitialized bindings. This implements the behavior of inducing a fresh lexical environment for every iteration of a for-in/of loop whose loop-head has a (captured) lexical declaration.

JSOP_FRESHENLEXICALENV

Replace the current block on the environment chain with a fresh block that copies all the bindings in the block. This implements the behavior of inducing a fresh lexical environment for every iteration of a for(let ...; ...; ...) loop, if any declarations induced by such a loop are captured within the loop.

JSOP_PUSHVARENV
Operands: (uint32_t scopeIndex)

Push a var environment onto the environment chain.

Like JSOP_PUSHLEXICALENV, but pushes a VarEnvironmentObject rather than a LexicalEnvironmentObject. The difference is that non-strict direct eval can add bindings to a var environment; see VarScope in Scope.h.

See JSOP_PUSHLEXICALENV for the fine print.

Implements: Places in the spec where the VariableEnvironment is set:

Note: The spec also pushes a new VariableEnvironment on entry to every function, but the VM takes care of that as part of pushing the stack frame, before the function script starts to run, so JSOP_PUSHVARENV is not needed.

Flags: JOF_SCOPE
JSOP_POPVARENV

Pop a VarEnvironmentObject from the environment chain.

See JSOP_PUSHLEXICALENV for the fine print.

JSOP_ENTERWITH
Operands: (uint32_t staticWithIndex)
Stack: val

Push a WithEnvironmentObject wrapping ToObject(val) to the environment chain.

Implements: Evaluation of with statements, steps 2-6.

Operations that may need to consult a WithEnvironment can't be correctly implemented using optimized instructions like JSOP_GETLOCAL. A script must use the deoptimized JSOP_GETNAME, BINDNAME, SETNAME, and DELNAME instead. Since those instructions don't work correctly with optimized locals and arguments, all bindings in scopes enclosing a with statement are marked as "aliased" and deoptimized too.

See JSOP_PUSHLEXICALENV for the fine print.

Flags: JOF_SCOPE
JSOP_LEAVEWITH

Pop a WithEnvironmentObject from the environment chain.

See JSOP_PUSHLEXICALENV for the fine print.

Implements: Evaluation of with statements, step 8.

Creating and deleting bindings

JSOP_BINDVAR
Stack: ⇒ env

Push the current VariableEnvironment (the environment on the environment chain designated to receive new variables).

Implements: Annex B.3.3.1, changes to FunctionDeclarationInstantiation for block-level functions, step 1.a.ii.3.a, and similar steps in other Annex B.3.3 algorithms, when setting the function's second binding can't be optimized.

JSOP_DEFVAR
Operands: (uint32_t nameIndex)

Create a new binding on the current VariableEnvironment (the environment on the environment chain designated to receive new variables).

JSOP_DEF{VAR,LET,CONST,FUN} instructions must appear in the script before anything else that might add bindings to the environment, and only once per binding. There must be a correct entry for the new binding in script->bodyScope(). (All this ensures that at run time, there is no existing conflicting binding. We check before running the script, in js::CheckGlobalOrEvalDeclarationConflicts.)

Throw a SyntaxError if the current VariableEnvironment is the global environment and a binding with the same name exists on the global lexical environment.

This is used for global scripts and also in some cases for function scripts where use of dynamic scoping inhibits optimization.

Flags: JOF_ATOM
JSOP_DEFFUN
Stack: fun

Create a new binding for the given function on the current scope.

fun must be a function object with an explicit name. The new variable's name is fun->explicitName(), and its value is fun. In global scope, this creates a new property on the global object.

Implements: The body of the loop in GlobalDeclarationInstantiation step 17 ("For each Parse Node f in functionsToInitialize...") and the corresponding loop in EvalDeclarationInstantiation.

JSOP_DEFLET
Operands: (uint32_t nameIndex)

Create a new mutable binding in the global lexical environment. Throw a SyntaxError if a binding with the same name already exists on that environment, or if a var binding with the same name exists on the global.

Flags: JOF_ATOM
JSOP_DEFCONST
Operands: (uint32_t nameIndex)

Create a new constant binding in the global lexical environment.

Throw a SyntaxError if a binding with the same name already exists in that environment, or if a var binding with the same name exists on the global.

Flags: JOF_ATOM
JSOP_DELNAME
Operands: (uint32_t nameIndex)
Stack: ⇒ succeeded

Look up a variable on the environment chain and delete it. Push true on success (if a binding was deleted, or if no such binding existed in the first place), false otherwise (most kinds of bindings can't be deleted).

Implements: delete Identifier, which is a SyntaxError in strict mode code.

Flags: JOF_ATOM, JOF_NAME, JOF_CHECKSLOPPY

Function environment setup

JSOP_ARGUMENTS
Stack: ⇒ arguments

Create and push the arguments object for the current function activation.

When it exists, arguments is stored in an ordinary local variable. JSOP_ARGUMENTS is used in function preludes, to populate that variable before the function body runs, not each time arguments appears in a function.

If a function clearly doesn't use arguments, we optimize it away when emitting bytecode. The function's script won't use JSOP_ARGUMENTS at all.

The current script must be a function script. This instruction must execute at most once per function activation.

Optimized arguments

If script->needsArgsObj() is false, no ArgumentsObject is created. Instead, MagicValue(JS_OPTIMIZED_ARGUMENTS) is pushed.

This optimization imposes no restrictions on bytecode. Rather, js::jit::AnalyzeArgumentsUsage examines the bytecode and enables the optimization only if all uses of arguments are optimizable. Each execution engine must know what the analysis considers optimizable and cope with the magic value when it is used in those ways.

Example 1: arguments[0] is supported; therefore the interpreter's implementation of JSOP_GETELEM checks for optimized arguments (see GetElemOptimizedArguments).

Example 2: f.apply(this, arguments) is supported; therefore our implementation of Function.prototype.apply checks for optimized arguments (see js::fun_apply), and all JSOP_FUNAPPLY implementations must check for cases where f.apply turns out to be any other function (see GuardFunApplyArgumentsOptimization).

It's not documented anywhere exactly which opcodes support JS_OPTIMIZED_ARGUMENTS; see the source of AnalyzeArgumentsUsage.

JSOP_REST
Stack: ⇒ rest

Create and push the rest parameter array for current function call.

This must appear only in function scripts.

Flags: JOF_TYPESET, JOF_IC
JSOP_FUNCTIONTHIS
Stack: ⇒ this

Determines the this value for current function frame and pushes it onto the stack.

In functions, this is stored in a local variable. This instruction is used in the function prologue to get the value to initialize that variable. (This doesn't apply to arrow functions, becauses they don't have a this binding; also, this is optimized away if it's unused.)

Functions that have a this binding have a local variable named ".this", which is initialized using this instruction in the function prologue.

Stack operations

JSOP_POP
Stack: v

Pop the top value from the stack and discard it.

JSOP_POPN
Operands: (uint16_t n)
Stack: v[n-1], ..., v[1], v[0]

Pop the top n values from the stack. n must be <= the current stack depth.

JSOP_DUP
Stack: vv, v

Push a copy of the top value on the stack.

JSOP_DUP2
Stack: v1, v2v1, v2, v1, v2

Duplicate the top two values on the stack.

JSOP_DUPAT
Operands: (uint24_t n)
Stack: v[n], v[n-1], ..., v[1], v[0]v[n], v[n-1], ..., v[1], v[0], v[n]

Push a copy of the nth value from the top of the stack.

n must be less than the current stack depth.

JSOP_SWAP
Stack: v1, v2v2, v1

Swap the top two values on the stack.

JSOP_PICK
Operands: (uint8_t n)
Stack: v[n], v[n-1], ..., v[1], v[0]v[n-1], ..., v[1], v[0], v[n]

Pick the nth element from the stack and move it to the top of the stack.

JSOP_UNPICK
Operands: (uint8_t n)
Stack: v[n], v[n-1], ..., v[1], v[0]v[0], v[n], v[n-1], ..., v[1]

Move the top of the stack value under the nth element of the stack. n must not be 0.

Other

JSOP_NOP

Do nothing. This is used when we need distinct bytecode locations for various mechanisms.

JSOP_LINENO
Operands: (uint32_t lineno)

No-op instruction used to speed up pc-to-line mapping.

JSOP_NOP_DESTRUCTURING

No-op instruction used by the decompiler to produce nicer error messages about destructuring code.

JSOP_FORCEINTERPRETER

No-op instruction only emitted in some self-hosted functions. Not handled by the JITs or Baseline Interpreter so the script always runs in the C++ interpreter.

JSOP_DEBUGCHECKSELFHOSTED
Stack: checkValcheckVal

Examine the top stack value, asserting that it's either a self-hosted function or a self-hosted intrinsic. This does nothing in a non-debug build.

JSOP_INSTRUMENTATION_ACTIVE
Stack: ⇒ val

Push a boolean indicating if instrumentation is active.

JSOP_INSTRUMENTATION_CALLBACK
Stack: ⇒ val

Push the instrumentation callback for the current realm.

JSOP_INSTRUMENTATION_SCRIPT_ID
Stack: ⇒ val

Push the current script's instrumentation ID.

JSOP_DEBUGGER

Break in the debugger, if one is attached. Otherwise this is a no-op.

The Debugger API offers a way to hook into this instruction.

Implements: Evaluation for DebuggerStatement.