BOOLEAN_TO_JSVAL
DOUBLE_TO_JSVAL
INT_FITS_IN_JSVAL
INT_TO_JSVAL
JS::Add*Root
JS::AutoIdArray
JS::AutoSaveExceptionState
JS::AutoValueArray
JS::AutoVectorRooter
JS::BooleanValue
JS::Call
JS::CallArgs
JS::CloneFunctionObject
JS::Compile
JS::CompileFunction
JS::CompileOffThread
JS::CompileOptions
JS::Construct
JS::CreateError
JS::CurrentGlobalOrNull
JS::DeflateStringToUTF8Buffer
JS::DoubleNaNValue
JS::DoubleValue
JS::Evaluate
JS::FalseValue
JS::Float32Value
JS::GetDeflatedUTF8StringLength
JS::GetFirstArgumentAsTypeHint
JS::GetSelfHostedFunction
JS::Handle
JS::HandleValueArray
JS::IdentifyStandardInstance
JS::Int32Value
JS::IsCallable
JS::MutableHandle
JS::NewFunctionFromSpec
JS::NullHandleValue
JS::NullValue
JS::NumberValue
JS::ObjectOrNullValue
JS::ObjectValue
JS::OrdinaryToPrimitive
JS::PersistentRooted
JS::PropertySpecNameEqualsId
JS::PropertySpecNameIsSymbol
JS::PropertySpecNameToPermanentId
JS::ProtoKeyToId
JS::Remove*Root
JS::Rooted
JS::SetLargeAllocationFailureCallback
JS::SetOutOfMemoryCallback
JS::SourceBufferHolder
JS::StringValue
JS::SymbolValue
JS::ToBoolean
JS::ToInt32
JS::ToInt64
JS::ToNumber
JS::ToPrimitive
JS::ToString
JS::ToUint16
JS::ToUint32
JS::ToUint64
JS::TrueHandleValue
JS::TrueValue
JS::UndefinedHandleValue
JS::UndefinedValue
JS::Value
JSAutoByteString
JSAutoCompartment
JSBool
JSCheckAccessOp
JSClass
JSClass.call
JSClass.flags
JSConstDoubleSpec
JSConvertOp
JSDeletePropertyOp
JSEnumerateOp
JSErrorFormatString
JSErrorReport
JSExceptionState
JSExnType
JSExtendedClass
JSExtendedClass.outerObject
JSExtendedClass.wrappedObject
JSFUN_BOUND_METHOD
JSFUN_GLOBAL_PARENT
JSFastNative
JSFinalizeOp
JSFreeOp
JSFunction
JSFunctionSpec
JSGetObjectOps
JSHasInstanceOp
JSID_EMPTY
JSID_IS_EMPTY
JSID_IS_GCTHING
JSID_IS_INT
JSID_IS_STRING
JSID_IS_SYMBOL
JSID_IS_VOID
JSID_IS_ZERO
JSID_VOID
JSIdArray
JSIteratorOp
JSMarkOp
JSNative
JSNewEnumerateOp
JSNewResolveOp
JSObject
JSObjectOp
JSObjectOps.defaultValue
JSObjectOps.defineProperty
JSObjectOps.destroyObjectMap
JSObjectOps.dropProperty
JSObjectOps.enumerate
JSObjectOps.getAttributes
JSObjectOps.getProperty
JSObjectOps.getRequiredSlot
JSObjectOps.lookupProperty
JSObjectOps.newObjectMap
JSObjectOps.setProto
JSObjectPrincipalsFinder
JSPRINCIPALS_HOLD
JSPrincipals
JSPrincipalsTranscoder
JSProperty
JSPropertyDescriptor
JSPropertyOp
JSPropertySpec
JSProtoKey
JSReserveSlotsOp
JSResolveOp
JSRuntime
JSSecurityCallbacks.contentSecurityPolicyAllows
JSString
JSStringFinalizer
JSTraceOp
JSType
JSVAL_IS_BOOLEAN
JSVAL_IS_DOUBLE
JSVAL_IS_GCTHING
JSVAL_IS_INT
JSVAL_IS_NULL
JSVAL_IS_NUMBER
JSVAL_IS_OBJECT
JSVAL_IS_PRIMITIVE
JSVAL_IS_STRING
JSVAL_IS_VOID
JSVAL_LOCK
JSVAL_NULL
JSVAL_ONE
JSVAL_TO_BOOLEAN
JSVAL_TO_DOUBLE
JSVAL_TO_GCTHING
JSVAL_TO_INT
JSVAL_TO_OBJECT
JSVAL_TO_STRING
JSVAL_TRUE
JSVAL_UNLOCK
JSVAL_VOID
JSVAL_ZERO
JSVersion
JSXDRObjectOp
JS_ASSERT_STRING_IS_FLAT
JS_Add*Root
JS_AddArgumentFormatter
JS_AddExternalStringFinalizer
JS_AddFinalizeCallback
JS_AliasElement
JS_AliasProperty
JS_AlreadyHasOwnProperty
JS_BeginRequest
JS_BindCallable
JS_BufferIsCompilableUnit
JS_CStringsAreUTF8
JS_CallFunction
JS_CheckAccess
JS_CheckForInterrupt
JS_ClearContextThread
JS_ClearDateCaches
JS_ClearNewbornRoots
JS_ClearNonGlobalObject
JS_ClearPendingException
JS_ClearRegExpStatics
JS_ClearScope
JS_CloneFunctionObject
JS_CompareStrings
JS_CompileFileHandleForPrincipals
JS_CompileFileHandleForPrincipalsVersion
JS_CompileFunction
JS_CompileFunctionForPrincipals
JS_CompileScript
JS_CompileScriptForPrincipals
JS_CompileUCFunctionForPrincipalsVersion
JS_CompileUTF8File
JS_CompileUTF8FileHandle
JS_ConcatStrings
JS_ConstructObject
JS_ContextIterator
JS_ConvertArguments
JS_ConvertArgumentsVA
JS_ConvertValue
JS_DecompileFunction
JS_DecompileFunctionBody
JS_DecompileScript
JS_DecompileScriptObject
JS_DeepFreezeObject
JS_DefaultValue
JS_DefineConstDoubles
JS_DefineElement
JS_DefineFunction
JS_DefineFunctions
JS_DefineObject
JS_DefineOwnProperty
JS_DefineProperties
JS_DefineProperty
JS_DefinePropertyWithTinyId
JS_DeleteElement
JS_DeleteElement2
JS_DeleteProperty
JS_DeleteProperty2
JS_DestroyContext
JS_DestroyIdArray
JS_DestroyRuntime
JS_DestroyScript
JS_DoubleIsInt32
JS_DoubleToInt32
JS_DropExceptionState
JS_DumpHeap
JS_DumpNamedRoots
JS_EncodeCharacters
JS_EncodeString
JS_EncodeStringToBuffer
JS_EnterCompartment
JS_EnterCrossCompartmentCall
JS_EnterLocalRootScope
JS_Enumerate
JS_EnumerateDiagnosticMemoryRegions
JS_EnumerateResolvedStandardClasses
JS_EnumerateStandardClasses
JS_ErrorFromException
JS_EvaluateScript
JS_EvaluateScriptForPrincipals
JS_ExecuteRegExp
JS_ExecuteScript
JS_ExecuteScriptPart
JS_ExecuteScriptVersion
JS_FORGET_STRING_FLATNESS
JS_FS
JS_FileEscapedString
JS_Finish
JS_FlattenString
JS_FlushCaches
JS_ForgetLocalRoot
JS_ForwardGetPropertyTo
JS_FreezeObject
JS_GC
JS_GET_CLASS
JS_GetArrayLength
JS_GetArrayPrototype
JS_GetClass
JS_GetClassObject
JS_GetClassPrototype
JS_GetCompartmentPrivate
JS_GetConstructor
JS_GetContextPrivate
JS_GetContextThread
JS_GetDefaultFreeOp
JS_GetElement
JS_GetEmptyString
JS_GetEmptyStringValue
JS_GetErrorPrototype
JS_GetExternalStringClosure
JS_GetExternalStringFinalizer
JS_GetFlatStringChars
JS_GetFunctionArity
JS_GetFunctionCallback
JS_GetFunctionFlags
JS_GetFunctionId
JS_GetFunctionName
JS_GetFunctionObject
JS_GetFunctionPrototype
JS_GetFunctionScript
JS_GetGCParameter
JS_GetGlobalForCompartmentOrNull
JS_GetGlobalForObject
JS_GetGlobalForObject3
JS_GetGlobalForScopeChain
JS_GetGlobalObject
JS_GetImplementationVersion
JS_GetInstancePrivate
JS_GetInternedStringChars
JS_GetLatin1FlatStringChars
JS_GetLatin1InternedStringChars
JS_GetLatin1StringCharsAndLength
JS_GetLocaleCallbacks
JS_GetNaNValue
JS_GetObjectPrototype
JS_GetObjectRuntime
JS_GetOptions
JS_GetOwnPropertyDescriptor
JS_GetParent
JS_GetParentRuntime
JS_GetPendingException
JS_GetPositiveInfinityValue
JS_GetPrivate
JS_GetProperty
JS_GetPropertyAttributes
JS_GetPropertyAttrsGetterAndSetter
JS_GetPropertyDefault
JS_GetPropertyDescriptor
JS_GetPrototype
JS_GetRegExpFlags
JS_GetRegExpSource
JS_GetReservedSlot
JS_GetRuntime
JS_GetRuntimePrivate
JS_GetScopeChain
JS_GetSecurityCallbacks
JS_GetStringBytes
JS_GetStringCharAt
JS_GetStringChars
JS_GetStringCharsAndLength
JS_GetStringEncodingLength
JS_GetStringLength
JS_GetTwoByteExternalStringChars
JS_GetTypeName
JS_GetVersion
JS_HasArrayLength
JS_HasElement
JS_HasInstance
JS_HasOwnProperty
JS_HasProperty
JS_IdArrayGet
JS_IdArrayLength
JS_IdToProtoKey
JS_IdToValue
JS_Init
JS_InitCTypesClass
JS_InitClass
JS_InitStandardClasses
JS_InstanceOf
JS_InternJSString
JS_InternString
JS_IsArrayObject
JS_IsAssigning
JS_IsBuiltinEvalFunction
JS_IsBuiltinFunctionConstructor
JS_IsConstructing
JS_IsConstructing_PossiblyWithGivenThisObject
JS_IsConstructor
JS_IsExceptionPending
JS_IsExtensible
JS_IsExternalString
JS_IsGlobalObject
JS_IsIdentifier
JS_IsNative
JS_IsNativeFunction
JS_IsRunning
JS_IsStopIteration
JS_IterateCompartments
JS_LeaveCompartment
JS_LeaveCrossCompartmentCall
JS_LeaveLocalRootScope
JS_LeaveLocalRootScopeWithResult
JS_LinkConstructorAndPrototype
JS_Lock
JS_LockGCThing
JS_LookupElement
JS_LookupProperty
JS_LooselyEqual
JS_MakeStringImmutable
JS_MapGCRoots
JS_MaybeGC
JS_New
JS_NewArrayObject
JS_NewCompartmentAndGlobalObject
JS_NewContext
JS_NewDateObject
JS_NewDateObjectMsec
JS_NewDependentString
JS_NewDouble
JS_NewDoubleValue
JS_NewExternalString
JS_NewFunction
JS_NewGlobalObject
JS_NewNumberValue
JS_NewObject
JS_NewObjectForConstructor
JS_NewPlainObject
JS_NewPropertyIterator
JS_NewRegExpObject
JS_NewRuntime
JS_NewScriptObject
JS_NewStringCopyN
JS_NewStringCopyZ
JS_NewUCString
JS_NextProperty
JS_Now
JS_NumberValue
JS_ObjectIsDate
JS_ObjectIsFunction
JS_ObjectIsRegExp
JS_PSGS
JS_ParseJSON
JS_PopArguments
JS_PreventExtensions
JS_PropertyStub
JS_PushArguments
JS_PutEscapedString
JS_Remove*Root
JS_RemoveExternalStringFinalizer
JS_RemoveRootRT
JS_ReportError
JS_ReportErrorNumber
JS_ReportOutOfMemory
JS_ReportPendingException
JS_ResolveStandardClass
JS_RestoreExceptionState
JS_SET_TRACING_DETAILS
JS_SameValue
JS_SaveExceptionState
JS_SaveFrameChain
JS_ScheduleGC
JS_SealObject
JS_SetAllNonReservedSlotsToUndefined
JS_SetArrayLength
JS_SetBranchCallback
JS_SetCallReturnValue2
JS_SetCheckObjectAccessCallback
JS_SetCompartmentNameCallback
JS_SetContextCallback
JS_SetDefaultLocale
JS_SetDestroyCompartmentCallback
JS_SetElement
JS_SetErrorReporter
JS_SetExtraGCRoots
JS_SetFunctionCallback
JS_SetGCCallback
JS_SetGCParametersBasedOnAvailableMemory
JS_SetGCZeal
JS_SetGlobalObject
JS_SetICUMemoryFunctions
JS_SetInterruptCallback
JS_SetNativeStackQuota
JS_SetObjectPrincipalsFinder
JS_SetOperationCallback
JS_SetOptions
JS_SetParent
JS_SetPendingException
JS_SetPrincipalsTranscoder
JS_SetPrivate
JS_SetProperty
JS_SetPropertyAttributes
JS_SetPrototype
JS_SetRegExpInput
JS_SetScriptStackQuota
JS_SetThreadStackLimit
JS_SetVersion
JS_SetVersionForCompartment
JS_ShutDown
JS_StrictlyEqual
JS_StringEqualsAscii
JS_StringHasBeenInterned
JS_StringHasLatin1Chars
JS_StringIsFlat
JS_StringToVersion
JS_SuspendRequest
JS_THREADSAFE
JS_ThrowStopIteration
JS_ToggleOptions
JS_TracerInit
JS_TypeOfValue
JS_Unlock
JS_ValueToBoolean
JS_ValueToECMAInt32
JS_ValueToFunction
JS_ValueToId
JS_ValueToInt32
JS_ValueToNumber
JS_ValueToObject
JS_ValueToSource
JS_ValueToString
JS_VersionToString
JS_YieldRequest
JS_freeop
JS_malloc
JS_updateMallocCounter
OBJECT_TO_JSVAL
PRIVATE_TO_JSVAL
Property attributes
STRING_TO_JSVAL
Stored value
jschar
jsdouble
jsid
jsint
This document is automatically generated from Opcodes.h by make_opcode_doc.py.
Undefined
undefined
Push undefined
.
Null
null
Push null
.
False
, True
true/false
Push a boolean constant.
Int32
(int32_t val)
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
.
Zero
0
Push the number 0
.
One
1
Push the number 1
.
Int8
(int8_t val)
val
Push the int8_t
immediate operand as an Int32Value
.
Uint16
(uint16_t val)
val
Push the uint16_t
immediate operand as an Int32Value
.
Uint24
(uint24_t val)
val
Push the uint24_t
immediate operand as an Int32Value
.
Double
(double val)
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
).
BigInt
(uint32_t bigIntIndex)
bigint
Push the BigInt constant script->getBigInt(bigIntIndex)
.
String
(uint32_t atomIndex)
string
Push the string constant script->getAtom(atomIndex)
.
Symbol
(uint8_t symbol (the JS::SymbolCode of the symbol to use))
symbol
Push a well-known symbol.
symbol
must be in range for JS::SymbolCode
.
Void
val
⇒ undefined
Pop the top value on the stack, discard it, and push undefined
.
Implements: The void
operator, step 3.
Typeof
, TypeofExpr
val
⇒ (typeof val)
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.
Pos
val
⇒ (+val)
+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.)
Neg
val
⇒ (-val)
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.
BitNot
val
⇒ (~val)
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.
Not
val
⇒ (!val)
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.
BitOr
, BitXor
, BitAnd
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.
Eq
, Ne
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.
StrictEq
, StrictNe
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.
Lt
, Gt
, Le
, Ge
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.
Instanceof
value, target
⇒ (value instanceof target)
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.
In
id, obj
⇒ (id in obj)
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.
Lsh
, Rsh
, Ursh
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.
Add
lval, rval
⇒ (lval + rval)
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.
Sub
lval, rval
⇒ (lval - rval)
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.
Inc
, Dec
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.
Mul
, Div
, Mod
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.
Pow
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.
ToPropertyKey
propertyNameValue
⇒ propertyKey
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.
ToNumeric
, ToString
val
⇒ ToNumeric(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.
GlobalThis
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
.
NewTarget
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.
DynamicImport
moduleId
⇒ promise
Dynamic import of the module specified by the string value on the top of the stack.
Implements: Import Calls.
ImportMeta
import.meta
Push the import.meta
object.
This must be used only in module code.
NewInit
obj
Create and push a new object with no properties.
NewObject
, NewObjectWithGroup
(uint32_t baseobjIndex)
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::NewObjectWithGroup
, the new object has the same group as the
template object.
Object
(uint32_t objectIndex)
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.
ObjWithProto
proto
⇒ obj
Create and push a new ordinary object with the provided [[Prototype]].
This is used to create the .prototype
object for derived classes.
InitProp
(uint32_t nameIndex)
obj, val
⇒ obj
Define a data property on an object.
obj
must be an object.
Implements: CreateDataPropertyOrThrow as used in PropertyDefinitionEvaluation of regular and shorthand PropertyDefinitions.
InitHiddenProp
(uint32_t nameIndex)
obj, val
⇒ obj
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.
InitLockedProp
(uint32_t nameIndex)
obj, val
⇒ obj
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.
InitElem
, InitHiddenElem
obj, id, val
⇒ obj
Define a data property on obj
with property key id
and value val
.
obj
must be an object.
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.
InitPropGetter
, InitHiddenPropGetter
(uint32_t nameIndex)
obj, getter
⇒ obj
Define an accessor property on obj
with the given getter
.
nameIndex
gives the property name.
obj
must be an object and getter
must be a function.
JSOp::InitHiddenPropGetter
is the same but defines a non-enumerable
property, for getters in classes.
InitElemGetter
, InitHiddenElemGetter
obj, id, getter
⇒ obj
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() {}
.
obj
must be an object and getter
must be a function.
JSOp::InitHiddenElemGetter
is the same but defines a non-enumerable
property, for getters in classes.
InitPropSetter
, InitHiddenPropSetter
(uint32_t nameIndex)
obj, setter
⇒ obj
Define an accessor property on obj
with the given setter
.
This is used to implement ordinary setters like set foo(v) {}
.
obj
must be an object and setter
must be a function.
JSOp::InitHiddenPropSetter
is the same but defines a non-enumerable
property, for setters in classes.
InitElemSetter
, InitHiddenElemSetter
obj, id, setter
⇒ obj
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::InitHiddenElemSetter
is the same but defines a non-enumerable
property, for setters in classes.
GetProp
, CallProp
(uint32_t nameIndex)
obj
⇒ obj[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.
GetElem
, CallElem
obj, key
⇒ obj[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.
Length
(uint32_t nameIndex)
obj
⇒ obj.length
Push the value of obj.length
.
nameIndex
must be the index of the atom "length"
. This then behaves
exactly like JSOp::GetProp
.
SetProp
(uint32_t nameIndex)
obj, val
⇒ val
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.
StrictSetProp
(uint32_t nameIndex)
obj, val
⇒ val
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.
SetElem
obj, key, val
⇒ val
Non-strict assignment to a property, obj[key] = val
.
Implements: PutValue step 6 for non-strict code.
StrictSetElem
obj, key, val
⇒ val
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.
DelProp
(uint32_t nameIndex)
obj
⇒ succeeded
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.
StrictDelProp
(uint32_t nameIndex)
obj
⇒ succeeded
Like JSOp::DelProp
, but for strict mode code. Push true
on success,
else throw a TypeError.
DelElem
obj, key
⇒ succeeded
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.
StrictDelElem
obj, key
⇒ succeeded
Like JSOp::DelElem, but for strict mode code. Push
true` on success,
else throw a TypeError.
HasOwn
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).
SuperBase
callee
⇒ superBase
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.
GetPropSuper
(uint32_t nameIndex)
receiver, obj
⇒ super.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.
GetElemSuper
receiver, key, obj
⇒ super[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)
.
SetPropSuper
(uint32_t nameIndex)
receiver, obj, val
⇒ val
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.
StrictSetPropSuper
(uint32_t nameIndex)
receiver, obj, val
⇒ val
Like JSOp::SetPropSuper
, but for strict mode code.
SetElemSuper
receiver, key, obj, val
⇒ val
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.
StrictSetElemSuper
receiver, key, obj, val
⇒ val
Like JSOp::SetElemSuper
, but for strict mode code.
Iter
val
⇒ iter
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.
MoreIter
iter
⇒ iter, 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
.
IsNoIter
val
⇒ val, done
Test whether the value on top of the stack is
MagicValue(JS_NO_ITER_VALUE)
and push the boolean result.
IterNext
val
⇒ val
No-op instruction to hint to IonBuilder that the value on top of the stack is the string key in a for-in loop.
EndIter
iter, iterval
⇒Exit a for-in loop, closing the iterator.
iter
must be a PropertyIteratorObject
pushed by JSOp::Iter
.
CheckIsObj
(CheckIsObjectKind kind)
result
⇒ result
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.
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.
CheckObjCoercible
val
⇒ val
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.
ToAsyncIter
iter, next
⇒ asynciter
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.
MutateProto
obj, protoVal
⇒ obj
Set the prototype of obj
.
obj
must be an object.
Implements: B.3.1 proto Property Names in Object Initializers, step 7.a.
NewArray
(uint32_t length)
array
Create and push a new Array object with the given length
,
preallocating enough memory to hold that many elements.
InitElemArray
(uint32_t index)
array, val
⇒ array
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::InitElemArray
.
Implements: ArrayAccumulation, the third algorithm, step 4, in the common case where nextIndex is known.
InitElemInc
array, index, val
⇒ array, (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::InitElemArray
and JSOp::InitElemInc
.
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]
, InitElemArray 0
is used to put
a
into the array, but InitElemInc
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.
Hole
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::InitElemArray
or
JSOp::InitElemInc
.
NewArrayCopyOnWrite
(uint32_t objectIndex)
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.
RegExp
(uint32_t regexpIndex)
regexp
Clone and push a new RegExp object.
Implements: Evaluation for RegularExpressionLiteral.
Lambda
(uint32_t funcIndex)
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.
LambdaArrow
(uint32_t funcIndex)
newTarget
⇒ arrowFn
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.
SetFunName
(FunctionPrefixKind prefixKind)
fun, name
⇒ fun
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.
InitHomeObject
fun, homeObject
⇒ fun
Initialize the home object for functions with super bindings.
fun
must be a method, getter, or setter, so that it has a
[[HomeObject]] slot. homeObject
must be a plain object or (for static
methods) a constructor.
CheckClassHeritage
baseClass
⇒ baseClass
Throw a TypeError if baseClass
isn't either null
or a constructor.
Implements: ClassDefinitionEvaluation step 6.f.
FunWithProto
(uint32_t funcIndex)
proto
⇒ obj
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.
ClassConstructor
(uint32_t nameIndex, uint32_t sourceStart, uint32_t sourceEnd)
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, used for toString()
. They must
be valid offsets into the source buffer, measured in code units, such
that scriptSource->substring(cx, start, end)
is valid.
DerivedConstructor
(uint32_t nameIndex, uint32_t sourceStart, uint32_t sourceEnd)
proto
⇒ constructor
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.
sourceStart
and sourceEnd
follow the same rules as for
JSOp::ClassConstructor
.
FunctionProto
%FunctionPrototype%
Pushes the current global's FunctionPrototype.
kind
must be in range for JSProtoKey
(and must not be
JSProto_LIMIT
).
Call
, CallIter
, FunApply
, FunCall
, CallIgnoresRv
(uint16_t argc)
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::CallIgnoresRv
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.
SpreadCall
callee, this, args
⇒ rval
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::InitElemArray
.
OptimizeSpreadCall
arr
⇒ arr, 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
.
Eval
(uint16_t argc)
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 instructions 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.
The instruction immediately following any JSOp::*Eval
instruction must
be JSOp::Lineno
.
Implements: Function Call Evaluation, steps 5-7 and 9, when the syntactic critera for direct eval in step 6 are all met.
SpreadEval
callee, this, args
⇒ rval
Spread-call variant of JSOp::Eval
.
See JSOp::SpreadCall
for restrictions on args
.
StrictEval
(uint16_t argc)
evalFn, this, args[0], ..., args[argc-1]
⇒ rval
Like JSOp::Eval
, but for strict mode code.
StrictSpreadEval
callee, this, args
⇒ rval
Spread-call variant of JSOp::StrictEval
.
See JSOp::SpreadCall
for restrictions on args
.
ImplicitThis
(uint32_t nameIndex)
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.
GImplicitThis
(uint32_t nameIndex)
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.
CallSiteObj
(uint32_t objectIndex)
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.
IsConstructing
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.
New
, SuperCall
(uint16_t argc)
callee, isConstructing, args[0], ..., args[argc-1], newTarget
⇒ rval
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::IsConstructing
.
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.
SpreadNew
, SpreadSuperCall
callee, isConstructing, args, newTarget
⇒ rval
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::IsConstructing
.
See JSOp::SpreadCall
for restrictions on args
.
JSOp::SpreadSuperCall
behaves exactly like JSOp::SpreadNew
, but is
used for SuperCall expressions.
SuperFun
callee
⇒ superFun
Push the prototype of callee
in preparation for calling super()
.
callee
must be a derived class constructor.
Implements: GetSuperConstructor, steps 4-7.
CheckThisReinit
thisval
⇒ thisval
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.
Generator
gen
Create and push a generator object for the current frame.
This instruction must appear only in scripts for generators, async functions, and async generators. There must not already be a generator object for the current frame (that is, this instruction must execute at most once per generator or async call).
InitialYield
(uint24_t resumeIndex)
gen
⇒ rval, gen, resumeKind
Suspend the current generator and return to the caller.
When a generator is called, its script starts running, like any other JS
function, because FunctionDeclarationInstantation and other
generator object setup are implemented mostly in bytecode. However,
the FunctionBody of the generator is not supposed to start running
until the first .next()
call, so after setup the script suspends
itself: the "initial yield".
Later, when resuming execution, rval
, gen
and resumeKind
will
receive the values passed in by JSOp::Resume
. resumeKind
is the
GeneratorResumeKind
stored as an Int32 value.
This instruction must appear only in scripts for generators and async
generators. gen
must be the generator object for the current frame. It
must not have been previously suspended. The resume point indicated by
resumeIndex
must be the next instruction in the script, which must be
AfterYield
.
Implements: GeneratorStart, steps 4-7.
AfterYield
(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.
The preceding instruction in the script must be Yield
, InitialYield
,
or Await
.
FinalYieldRval
gen
⇒Suspend and close the current generator, async function, or async generator.
gen
must be the generator object for the current frame.
If the current function is a non-async generator, then the value in the
frame's return value slot is returned to the caller. It should be an
object of the form {value: returnValue, done: true}
.
If the current function is an async function or async generator, the frame's return value slot must contain the current frame's result promise, which must already be resolved or rejected.
Yield
(uint24_t resumeIndex)
rval1, gen
⇒ rval2, gen, resumeKind
Suspend execution of the current generator or async generator, returning
rval1
.
For non-async generators, rval1
should be an object of the form
{value: valueToYield, done: true}
. For async generators, rval1
should be the value to yield, and the caller is responsible for creating
the iterator result object (under js::AsyncGeneratorYield
).
This instruction must appear only in scripts for generators and async
generators. gen
must be the generator object for the current stack
frame. The resume point indicated by resumeIndex
must be the next
instruction in the script, which must be AfterYield
.
When resuming execution, rval2
, gen
and resumeKind
receive the
values passed in by JSOp::Resume
.
Implements: GeneratorYield and AsyncGeneratorYield.
IsGenClosing
val
⇒ val, res
Pushes a boolean indicating whether the top of the stack is
MagicValue(JS_GENERATOR_CLOSING)
.
AsyncAwait
value, gen
⇒ promise
Arrange for this async function to resume asynchronously when value
becomes resolved.
This is the last thing an async function does before suspending for an
await
expression. It coerces the awaited value
to a promise and
effectively calls .then()
on it, passing handler functions that will
resume this async function call later. See js::AsyncFunctionAwait
.
This instruction must appear only in non-generator async function
scripts. gen
must be the internal generator object for the current
frame. After this instruction, the script should suspend itself with
Await
(rather than exiting any other way).
The result promise
is the async function's result promise,
gen->as<AsyncFunctionGeneratorObject>().promise()
.
Implements: Await, steps 2-9.
AsyncResolve
(AsyncFunctionResolveKind fulfillOrReject)
valueOrReason, gen
⇒ promise
Resolve or reject the current async function's result promise with 'valueOrReason'.
This instruction must appear only in non-generator async function
scripts. gen
must be the internal generator object for the current
frame. This instruction must run at most once per async function call,
as resolving/rejecting an already resolved/rejected promise is not
permitted.
The result promise
is the async function's result promise,
gen->as<AsyncFunctionGeneratorObject>().promise()
.
Implements: AsyncFunctionStart, step 4.d.i. and 4.e.i.
Await
(uint24_t resumeIndex)
promise, gen
⇒ resolved, gen, resumeKind
Suspend the current frame for an await
expression.
This instruction must appear only in scripts for async functions and
async generators. gen
must be the internal generator object for the
current frame.
This returns promise
to the caller. Later, when this async call is
resumed, resolved
, gen
and resumeKind
receive the values passed in
by JSOp::Resume
, and execution continues at the next instruction,
which must be AfterYield
.
This instruction is used in two subtly different ways.
In async functions:
... # valueToAwait
GetAliasedVar ".generator" # valueToAwait gen
AsyncAwait # resultPromise
GetAliasedVar ".generator" # resultPromise gen
Await # resolved gen resumeKind
AfterYield
AsyncAwait
arranges for this frame to be resumed later and pushes
its result promise. Await
then suspends the frame and removes it
from the stack, returning the result promise to the caller. (If this
async call hasn't awaited before, the caller may be user code.
Otherwise, the caller is self-hosted code using resumeGenerator
.)
In async generators:
... # valueToAwait
GetAliasedVar ".generator" # valueToAwait gen
Await # resolved gen resumeKind
AfterYield
AsyncAwait
is not used, so (1) the value returned to the caller by
Await
is valueToAwait
, not resultPromise
; and (2) the caller
is responsible for doing the async-generator equivalent of
AsyncAwait
(namely, js::AsyncGeneratorAwait
, called from
js::AsyncGeneratorResume
after js::CallSelfHostedFunction
returns).
Implements: Await, steps 10-12.
TrySkipAwait
value
⇒ value_or_resolved, can_skip
Decide whether awaiting 'value' can be skipped.
This is part of an optimization for await
expressions. Programs very
often await values that aren't promises, or promises that are already
resolved. We can then sometimes skip suspending the current frame and
returning to the microtask loop. If the circumstances permit the
optimization, TrySkipAwait
replaces value
with the result of the
await
expression (unwrapping the resolved promise, if any) and pushes
true
. Otherwise, it leaves value
unchanged and pushes 'false'.
ResumeKind
(GeneratorResumeKind resumeKind (encoded as uint8_t))
resumeKind
Pushes one of the GeneratorResumeKind values as Int32Value.
CheckResumeKind
rval, gen, resumeKind
⇒ rval
Handle Throw and Return resumption.
gen
must be the generator object for the current frame. resumeKind
must be a GeneratorResumeKind
stored as an Int32
value. If it is
Next
, continue to the next instruction. If resumeKind
is Throw
or
Return
, these completions are handled by throwing an exception. See
GeneratorThrowOrReturn
.
Resume
gen, val, resumeKind
⇒ rval
Resume execution of a generator, async function, or async generator.
This behaves something like a call instruction. It pushes a stack frame
(the one saved when gen
was suspended, rather than a fresh one) and
runs instructions in it. Once gen
returns or yields, its return value
is pushed to this frame's stack and execution continues in this script.
This instruction is emitted only for the resumeGenerator
self-hosting
intrinsic. It is used in the implementation of
%GeneratorPrototype%.next
, .throw
, and .return
.
gen
must be a suspended generator object. resumeKind
must be in
range for GeneratorResumeKind
.
JumpTarget
(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.
LoopHead
(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.
Goto
(int32_t offset)
Jump to a 32-bit offset from the current bytecode.
See "Jump instructions" above for details.
IfEq
(int32_t forwardOffset)
cond
⇒If ToBoolean(cond
) is false, jumps to a 32-bit offset from the current
instruction.
IfNe
(int32_t offset)
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.
And
(int32_t forwardOffset)
cond
⇒ cond
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.
Or
(int32_t forwardOffset)
cond
⇒ cond
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.
Coalesce
(int32_t forwardOffset)
val
⇒ val
Short-circuiting for nullish coalescing.
If val
is not null or undefined, jump to a 32-bit offset from the
current instruction.
Case
(int32_t forwardOffset)
val, cond
⇒ val (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 JSOp::Pop
inside the switch
body would
complicate fallthrough.
Default
(int32_t forwardOffset)
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.
TableSwitch
(int32_t defaultOffset, int32_t low, int32_t high, uint24_t firstResumeIndex)
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()
.
Return
rval
⇒Return rval
.
This must not be used in derived class constructors. Instead use
JSOp::SetRval
, JSOp::CheckReturn
, and JSOp::RetRval
.
GetRval
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.
SetRval
rval
⇒Store rval
in the current stack frame's returnValue
slot.
This instruction must not be used in a toplevel script compiled with the
noScriptRval
option.
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.
CheckReturn
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.
Throw
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.
ThrowMsg
(ThrowMsgKind 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.
ThrowSetConst
(uint32_t nameIndex)
Throws a runtime TypeError for invalid assignment to a const
binding.
Try
(int32_t jumpAtEndOffset)
No-op instruction that marks the top of the bytecode for a TryStatement.
The jumpAtEndOffset
operand must be 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()
.
TryDestructuring
No-op instruction used by the exception unwinder to determine the correct environment to unwind to when performing IteratorClose due to destructuring.
This instruction must appear immediately before each
JSTRY_DESTRUCTURING
span in a script's try notes.
Exception
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.
ResumeIndex
(uint24_t resumeIndex)
resumeIndex
Push resumeIndex
.
This value must be used only by JSOp::Gosub
, JSOp::Finally
, and JSOp::Retsub
.
Gosub
(int32_t forwardOffset)
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.
Finally
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
.
Retsub
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
.
Uninitialized
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::InitLexical
.
InitLexical
(uint24_t localno)
v
⇒ v
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.)
InitGLexical
(uint32_t nameIndex)
val
⇒ val
Initialize a global lexical binding.
The binding must already have been created by DefLet
or DefConst
and
must be uninitialized.
Like JSOp::InitLexical
but for global lexicals. Unlike InitLexical
this can't be used to mark a binding as uninitialized.
InitAliasedLexical
(uint8_t hops, uint24_t slot)
v
⇒ v
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
.
CheckLexical
(uint24_t localno)
v
⇒ v
Throw a ReferenceError if the value on top of the stack is uninitialized.
Typically used after JSOp::GetLocal
with the same localno
.
Implements: GetBindingValue step 3 and SetMutableBinding step 4 for declarative Environment Records.
CheckAliasedLexical
(uint8_t hops, uint24_t slot)
v
⇒ v
Like JSOp::CheckLexical
but for aliased bindings.
Typically used after JSOp::GetAliasedVar
with the same hops/slot.
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.
CheckThis
this
⇒ this
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.
BindGName
(uint32_t nameIndex)
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.
BindName
(uint32_t nameIndex)
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.
GetName
(uint32_t nameIndex)
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.
GetGName
(uint32_t nameIndex)
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.
NonSyntacticVariablesObject
s 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.
GetArg
(uint16_t argno)
arguments[argno]
Push the value of an argument that is stored in the stack frame
or in an ArgumentsObject
.
GetLocal
(uint24_t localno)
val
Push the value of an optimized local variable.
If the variable is an uninitialized lexical, push
MagicValue(JS_UNINIITALIZED_LEXICAL)
.
GetAliasedVar
(uint8_t hops, uint24_t slot)
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
EnvironmentObject
s.
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.
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.
GetImport
(uint32_t nameIndex)
val
Get the value of a module import by name and pushes it onto the stack.
GetBoundName
(uint32_t nameIndex)
env
⇒ v
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
or JSOp::BindVar
.
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.
GetIntrinsic
(uint32_t nameIndex)
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.
Callee
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).
EnvCallee
(uint8_t numHops)
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. The environment chain element indicated by numHops
must be a CallObject.
SetName
(uint32_t nameIndex)
env, val
⇒ val
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
or JSOp::BindVar
.
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.
StrictSetName
(uint32_t nameIndex)
env, val
⇒ val
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.
SetGName
(uint32_t nameIndex)
env, val
⇒ val
Like JSOp::SetName
, but for assigning to globals. env
must be an
environment pushed by JSOp::BindGName
.
StrictSetGName
(uint32_t nameIndex)
env, val
⇒ val
Like JSOp::StrictSetGName
, but for assigning to globals. env
must be
an environment pushed by JSOp::BindGName
.
SetArg
(uint16_t argno)
val
⇒ val
Assign val
to an argument binding that's stored in the stack frame or
in an ArgumentsObject
.
SetLocal
(uint24_t localno)
v
⇒ v
Assign to an optimized local binding.
SetAliasedVar
(uint8_t hops, uint24_t slot)
val
⇒ val
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.
SetIntrinsic
(uint32_t nameIndex)
val
⇒ val
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 var
s, but it has many function
s.)
PushLexicalEnv
(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.
The following rules for JSOp::{Push,Pop}LexicalEnv
also apply to
JSOp::PushVarEnv
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.
PopLexicalEnv
Pop a lexical environment from the environment chain.
See JSOp::PushLexicalEnv
for the fine print.
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 either this instruction (if the scope is optimized) or
JSOp::PopLexicalEnv
(if not).
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.
The current environment must be a LexicalEnvironmentObject.
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.
The current environment must be a LexicalEnvironmentObject.
PushVarEnv
(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.
There is no corresponding JSOp::PopVarEnv
operation, because a
VarEnvironmentObject
is never popped from the environment chain.
Implements: Places in the spec where the VariableEnvironment is set:
The bit in PerformEval where, in strict direct eval, the new eval scope is taken as varEnv and becomes "runningContext's VariableEnvironment".
The weird scoping rules for functions with default parameter expressions, as specified in FunctionDeclarationInstantiation step 28 ("NOTE: A separate Environment Record is needed...").
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.
EnterWith
(uint32_t staticWithIndex)
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.
LeaveWith
Pop a WithEnvironmentObject
from the environment chain.
See JSOp::PushLexicalEnv
for the fine print.
Implements: Evaluation of with
statements, step 8.
BindVar
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.
DefVar
(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. This is checked by the
JSOp::CheckGlobalOrEvalDecl
bytecode instruction that must appear
before JSOp::Def{Var,Let,Const,Fun}
.)
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.
DefFun
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.
DefLet
(uint32_t nameIndex)
Create a new uninitialized 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.
DefConst
(uint32_t nameIndex)
Like DefLet
, but create an uninitialized constant binding.
CheckGlobalOrEvalDecl
Check for conflicting bindings before JSOp::Def{Var,Let,Const,Fun}
in
global or sloppy eval scripts.
Implements: GlobalDeclarationInstantiation steps 5, 6, 10 and 12, and EvalDeclarationInstantiation steps 5 and 8.
DelName
(uint32_t nameIndex)
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.
Arguments
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.
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
.
Rest
rest
Create and push the rest parameter array for current function call.
This must appear only in a script for a function that has a rest parameter.
FunctionThis
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.
In non-strict functions, this
is always an object. Undefined/null
this
is converted into the global this
value. Other primitive values
are boxed. See js::BoxNonStrictThis
.
Pop
v
⇒Pop the top value from the stack and discard it.
PopN
(uint16_t n)
v[n-1], ..., v[1], v[0]
⇒Pop the top n
values from the stack. n
must be <= the current stack
depth.
Dup
v
⇒ v, v
Push a copy of the top value on the stack.
Dup2
v1, v2
⇒ v1, v2, v1, v2
Duplicate the top two values on the stack.
DupAt
(uint24_t n)
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.
Swap
v1, v2
⇒ v2, v1
Swap the top two values on the stack.
Pick
(uint8_t n)
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.
Unpick
(uint8_t n)
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 n
th element of the stack.
n
must not be 0.
Nop
Do nothing. This is used when we need distinct bytecode locations for various mechanisms.
Lineno
(uint32_t lineno)
No-op instruction emitted immediately after JSOp::*Eval
so that direct
eval does not have to do slow pc-to-line mapping.
The lineno
operand should agree with this script's source notes about
the line number of the preceding *Eval
instruction.
NopDestructuring
No-op instruction to hint that the top stack value is uninteresting.
This affects only debug output and some error messages.
In array destructuring, we emit bytecode that is roughly equivalent to
result.done ? undefined : result.value
.
NopDestructuring
is emitted after the undefined
, so that the
expression decompiler and disassembler know to casually ignore the
possibility of undefined
, and render the result of the conditional
expression simply as "result.value
".
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.
DebugCheckSelfHosted
checkVal
⇒ checkVal
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.
InstrumentationActive
val
Push a boolean indicating if instrumentation is active.
InstrumentationCallback
val
Push the instrumentation callback for the current realm.
InstrumentationScriptId
val
Push the current script's instrumentation ID.
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.