From 18824baba89351a5d7e0400b42079cea6b405e68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Juli=C3=A1n=20Espina?= Date: Sat, 29 Oct 2022 06:52:59 +0000 Subject: [PATCH] Generate `Opcode` impl using macro (#2391) This reduces a lot of the repetition from the `Opcode` functions and makes it easier to add a new Op. --- boa_engine/src/vm/mod.rs | 172 +- boa_engine/src/vm/opcode/mod.rs | 2885 ++++++++++++++----------------- 2 files changed, 1296 insertions(+), 1761 deletions(-) diff --git a/boa_engine/src/vm/mod.rs b/boa_engine/src/vm/mod.rs index 66d5c9f448..0276380183 100644 --- a/boa_engine/src/vm/mod.rs +++ b/boa_engine/src/vm/mod.rs @@ -15,9 +15,6 @@ mod call_frame; mod code_block; mod opcode; -#[allow(clippy::wildcard_imports)] -use opcode::*; - pub use {call_frame::CallFrame, code_block::CodeBlock, opcode::Opcode}; pub(crate) use { @@ -126,174 +123,7 @@ impl Context { let _timer = Profiler::global().start_event(opcode.as_instruction_str(), "vm"); - let result = match opcode { - Opcode::Nop => Nop::execute(self)?, - Opcode::Pop => Pop::execute(self)?, - Opcode::PopIfThrown => PopIfThrown::execute(self)?, - Opcode::Dup => Dup::execute(self)?, - Opcode::Swap => Swap::execute(self)?, - Opcode::RotateLeft => RotateLeft::execute(self)?, - Opcode::RotateRight => RotateRight::execute(self)?, - Opcode::PushUndefined => PushUndefined::execute(self)?, - Opcode::PushNull => PushNull::execute(self)?, - Opcode::PushTrue => PushTrue::execute(self)?, - Opcode::PushFalse => PushFalse::execute(self)?, - Opcode::PushZero => PushZero::execute(self)?, - Opcode::PushOne => PushOne::execute(self)?, - Opcode::PushInt8 => PushInt8::execute(self)?, - Opcode::PushInt16 => PushInt16::execute(self)?, - Opcode::PushInt32 => PushInt32::execute(self)?, - Opcode::PushRational => PushRational::execute(self)?, - Opcode::PushNaN => PushNaN::execute(self)?, - Opcode::PushPositiveInfinity => PushPositiveInfinity::execute(self)?, - Opcode::PushNegativeInfinity => PushNegativeInfinity::execute(self)?, - Opcode::PushLiteral => PushLiteral::execute(self)?, - Opcode::PushEmptyObject => PushEmptyObject::execute(self)?, - Opcode::PushClassPrototype => PushClassPrototype::execute(self)?, - Opcode::SetClassPrototype => SetClassPrototype::execute(self)?, - Opcode::SetHomeObject => SetHomeObject::execute(self)?, - Opcode::PushNewArray => PushNewArray::execute(self)?, - Opcode::PushValueToArray => PushValueToArray::execute(self)?, - Opcode::PushElisionToArray => PushElisionToArray::execute(self)?, - Opcode::PushIteratorToArray => PushIteratorToArray::execute(self)?, - Opcode::Add => Add::execute(self)?, - Opcode::Sub => Sub::execute(self)?, - Opcode::Mul => Mul::execute(self)?, - Opcode::Div => Div::execute(self)?, - Opcode::Pow => Pow::execute(self)?, - Opcode::Mod => Mod::execute(self)?, - Opcode::BitAnd => BitAnd::execute(self)?, - Opcode::BitOr => BitOr::execute(self)?, - Opcode::BitXor => BitXor::execute(self)?, - Opcode::ShiftLeft => ShiftLeft::execute(self)?, - Opcode::ShiftRight => ShiftRight::execute(self)?, - Opcode::UnsignedShiftRight => UnsignedShiftRight::execute(self)?, - Opcode::Eq => Eq::execute(self)?, - Opcode::NotEq => NotEq::execute(self)?, - Opcode::StrictEq => StrictEq::execute(self)?, - Opcode::StrictNotEq => StrictNotEq::execute(self)?, - Opcode::GreaterThan => GreaterThan::execute(self)?, - Opcode::GreaterThanOrEq => GreaterThanOrEq::execute(self)?, - Opcode::LessThan => LessThan::execute(self)?, - Opcode::LessThanOrEq => LessThanOrEq::execute(self)?, - Opcode::In => In::execute(self)?, - Opcode::InstanceOf => InstanceOf::execute(self)?, - Opcode::Void => Void::execute(self)?, - Opcode::TypeOf => TypeOf::execute(self)?, - Opcode::Pos => Pos::execute(self)?, - Opcode::Neg => Neg::execute(self)?, - Opcode::Inc => Inc::execute(self)?, - Opcode::IncPost => IncPost::execute(self)?, - Opcode::Dec => Dec::execute(self)?, - Opcode::DecPost => DecPost::execute(self)?, - Opcode::LogicalNot => LogicalNot::execute(self)?, - Opcode::BitNot => BitNot::execute(self)?, - Opcode::DefVar => DefVar::execute(self)?, - Opcode::DefInitVar => DefInitVar::execute(self)?, - Opcode::DefLet => DefLet::execute(self)?, - Opcode::DefInitLet => DefInitLet::execute(self)?, - Opcode::DefInitConst => DefInitConst::execute(self)?, - Opcode::DefInitArg => DefInitArg::execute(self)?, - Opcode::GetName => GetName::execute(self)?, - Opcode::GetNameOrUndefined => GetNameOrUndefined::execute(self)?, - Opcode::SetName => SetName::execute(self)?, - Opcode::Jump => Jump::execute(self)?, - Opcode::JumpIfFalse => JumpIfFalse::execute(self)?, - Opcode::JumpIfNotUndefined => JumpIfNotUndefined::execute(self)?, - Opcode::JumpIfNullOrUndefined => JumpIfNullOrUndefined::execute(self)?, - Opcode::LogicalAnd => LogicalAnd::execute(self)?, - Opcode::LogicalOr => LogicalOr::execute(self)?, - Opcode::Coalesce => Coalesce::execute(self)?, - Opcode::ToBoolean => ToBoolean::execute(self)?, - Opcode::GetPropertyByName => GetPropertyByName::execute(self)?, - Opcode::GetPropertyByValue => GetPropertyByValue::execute(self)?, - Opcode::GetPropertyByValuePush => GetPropertyByValuePush::execute(self)?, - Opcode::SetPropertyByName => SetPropertyByName::execute(self)?, - Opcode::DefineOwnPropertyByName => DefineOwnPropertyByName::execute(self)?, - Opcode::DefineClassMethodByName => DefineClassMethodByName::execute(self)?, - Opcode::SetPropertyByValue => SetPropertyByValue::execute(self)?, - Opcode::DefineOwnPropertyByValue => DefineOwnPropertyByValue::execute(self)?, - Opcode::DefineClassMethodByValue => DefineClassMethodByValue::execute(self)?, - Opcode::SetPropertyGetterByName => SetPropertyGetterByName::execute(self)?, - Opcode::DefineClassGetterByName => DefineClassGetterByName::execute(self)?, - Opcode::SetPropertyGetterByValue => SetPropertyGetterByValue::execute(self)?, - Opcode::DefineClassGetterByValue => DefineClassGetterByValue::execute(self)?, - Opcode::SetPropertySetterByName => SetPropertySetterByName::execute(self)?, - Opcode::DefineClassSetterByName => DefineClassSetterByName::execute(self)?, - Opcode::SetPropertySetterByValue => SetPropertySetterByValue::execute(self)?, - Opcode::DefineClassSetterByValue => DefineClassSetterByValue::execute(self)?, - Opcode::AssignPrivateField => AssignPrivateField::execute(self)?, - Opcode::SetPrivateField => SetPrivateField::execute(self)?, - Opcode::SetPrivateMethod => SetPrivateMethod::execute(self)?, - Opcode::SetPrivateSetter => SetPrivateSetter::execute(self)?, - Opcode::SetPrivateGetter => SetPrivateGetter::execute(self)?, - Opcode::GetPrivateField => GetPrivateField::execute(self)?, - Opcode::PushClassField => PushClassField::execute(self)?, - Opcode::PushClassFieldPrivate => PushClassFieldPrivate::execute(self)?, - Opcode::PushClassPrivateGetter => PushClassPrivateGetter::execute(self)?, - Opcode::PushClassPrivateSetter => PushClassPrivateSetter::execute(self)?, - Opcode::PushClassPrivateMethod => PushClassPrivateMethod::execute(self)?, - Opcode::DeletePropertyByName => DeletePropertyByName::execute(self)?, - Opcode::DeletePropertyByValue => DeletePropertyByValue::execute(self)?, - Opcode::CopyDataProperties => CopyDataProperties::execute(self)?, - Opcode::ToPropertyKey => ToPropertyKey::execute(self)?, - Opcode::Throw => Throw::execute(self)?, - Opcode::TryStart => TryStart::execute(self)?, - Opcode::TryEnd => TryEnd::execute(self)?, - Opcode::CatchEnd => CatchEnd::execute(self)?, - Opcode::CatchStart => CatchStart::execute(self)?, - Opcode::CatchEnd2 => CatchEnd2::execute(self)?, - Opcode::FinallyStart => FinallyStart::execute(self)?, - Opcode::FinallyEnd => FinallyEnd::execute(self)?, - Opcode::FinallySetJump => FinallySetJump::execute(self)?, - Opcode::This => This::execute(self)?, - Opcode::Super => Super::execute(self)?, - Opcode::SuperCall => SuperCall::execute(self)?, - Opcode::SuperCallSpread => SuperCallSpread::execute(self)?, - Opcode::SuperCallDerived => SuperCallDerived::execute(self)?, - Opcode::Case => Case::execute(self)?, - Opcode::Default => Default::execute(self)?, - Opcode::GetArrowFunction => GetArrowFunction::execute(self)?, - Opcode::GetFunction => GetFunction::execute(self)?, - Opcode::GetFunctionAsync => GetFunctionAsync::execute(self)?, - Opcode::GetGenerator => GetGenerator::execute(self)?, - Opcode::GetGeneratorAsync => GetGeneratorAsync::execute(self)?, - Opcode::CallEval => CallEval::execute(self)?, - Opcode::CallEvalSpread => CallEvalSpread::execute(self)?, - Opcode::Call => Call::execute(self)?, - Opcode::CallSpread => CallSpread::execute(self)?, - Opcode::New => New::execute(self)?, - Opcode::NewSpread => NewSpread::execute(self)?, - Opcode::Return => Return::execute(self)?, - Opcode::PushDeclarativeEnvironment => PushDeclarativeEnvironment::execute(self)?, - Opcode::PushFunctionEnvironment => PushFunctionEnvironment::execute(self)?, - Opcode::PopEnvironment => PopEnvironment::execute(self)?, - Opcode::LoopStart => LoopStart::execute(self)?, - Opcode::LoopContinue => LoopContinue::execute(self)?, - Opcode::LoopEnd => LoopEnd::execute(self)?, - Opcode::ForInLoopInitIterator => ForInLoopInitIterator::execute(self)?, - Opcode::InitIterator => InitIterator::execute(self)?, - Opcode::InitIteratorAsync => InitIteratorAsync::execute(self)?, - Opcode::IteratorNext => IteratorNext::execute(self)?, - Opcode::IteratorClose => IteratorClose::execute(self)?, - Opcode::IteratorToArray => IteratorToArray::execute(self)?, - Opcode::ForInLoopNext => ForInLoopNext::execute(self)?, - Opcode::ForAwaitOfLoopIterate => ForAwaitOfLoopIterate::execute(self)?, - Opcode::ForAwaitOfLoopNext => ForAwaitOfLoopNext::execute(self)?, - Opcode::ConcatToString => ConcatToString::execute(self)?, - Opcode::RequireObjectCoercible => RequireObjectCoercible::execute(self)?, - Opcode::ValueNotNullOrUndefined => ValueNotNullOrUndefined::execute(self)?, - Opcode::RestParameterInit => RestParameterInit::execute(self)?, - Opcode::RestParameterPop => RestParameterPop::execute(self)?, - Opcode::PopOnReturnAdd => PopOnReturnAdd::execute(self)?, - Opcode::PopOnReturnSub => PopOnReturnSub::execute(self)?, - Opcode::Yield => Yield::execute(self)?, - Opcode::GeneratorNext => GeneratorNext::execute(self)?, - Opcode::AsyncGeneratorNext => AsyncGeneratorNext::execute(self)?, - Opcode::GeneratorNextDelegate => GeneratorNextDelegate::execute(self)?, - Opcode::Await => Await::execute(self)?, - Opcode::PushNewTarget => PushNewTarget::execute(self)?, - }; + let result = opcode.execute(self)?; Ok(result) } diff --git a/boa_engine/src/vm/opcode/mod.rs b/boa_engine/src/vm/opcode/mod.rs index ecf9aa3e34..ae10eb5f18 100644 --- a/boa_engine/src/vm/opcode/mod.rs +++ b/boa_engine/src/vm/opcode/mod.rs @@ -92,9 +92,66 @@ pub(crate) use unary_ops::*; #[doc(inline)] pub(crate) use value::*; +macro_rules! generate_impl { + ( + $(#[$outer:meta])* + pub enum $Type:ident { + $( + $(#[$inner:ident $($args:tt)*])* + $Variant:ident + ),* + $(,)? + } + ) => { + $(#[$outer])* + pub enum $Type { + $( + $(#[$inner $($args)*])* + $Variant + ),* + } + + impl $Type { + + /// Create opcode from `u8` byte. + /// + /// # Safety + /// + /// Does not check if `u8` type is a valid `Opcode`. + pub unsafe fn from_raw(value: u8) -> Self { + std::mem::transmute(value) + } + + pub fn as_str(self) -> &'static str { + match self { + $( + Self::$Variant => $Variant::NAME + ),* + } + } + + /// Name of the profiler event for this opcode + pub fn as_instruction_str(self) -> &'static str { + match self { + $( + Self::$Variant => $Variant::INSTRUCTION + ),* + } + } + + pub(super) fn execute(self, context: &mut Context) -> JsResult { + match self { + $( + Self::$Variant => $Variant::execute(context) + ),* + } + } + } + }; +} + /// The `Operation` trait implements the execution code along with the -/// identifying Name and Instruction value for an Boa Opcode -/// +/// identifying Name and Instruction value for an Boa Opcode. /// /// This trait should be implemented for a struct that corresponds with /// any arm of the `OpCode` enum. @@ -106,1594 +163,1242 @@ pub(crate) trait Operation { fn execute(context: &mut Context) -> JsResult; } -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -#[repr(u8)] -pub enum Opcode { - /// Pop the top value from the stack. - /// - /// Operands: - /// - /// Stack: value **=>** - Pop, - - /// Pop the top value from the stack if the last try block has thrown a value. - /// - /// Operands: - /// - /// Stack: value **=>** - PopIfThrown, - - /// Push a copy of the top value on the stack. - /// - /// Operands: - /// - /// Stack: value **=>** value, value - Dup, - - /// Swap the top two values on the stack. - /// - /// Operands: - /// - /// Stack: second, first **=>** first, second - Swap, - - /// Rotates the top `n` values of the stack to the left by `1`. - /// - /// Equivalent to calling [`slice::rotate_left`] with argument `1` on the top `n` values of the - /// stack. - /// - /// Operands: n: `u8` - /// - /// Stack: v\[n\], v\[n-1\], ... , v\[1\], v\[0\] **=>** v\[n-1\], ... , v\[1\], v\[0\], v\[n\] - RotateLeft, - - /// Rotates the top `n` values of the stack to the right by `1`. - /// - /// Equivalent to calling [`slice::rotate_right`] with argument `1` on the top `n` values of the - /// stack. - /// - /// Operands: n: `u8` - /// - /// Stack: v\[n\], v\[n-1\], ... , v\[1\], v\[0\] **=>** v\[0\], v\[n\], v\[n-1\], ... , v\[1\] - RotateRight, - - /// Push integer `0` on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `0` - PushZero, - - /// Push integer `1` on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `1` - PushOne, - - /// Push `i8` value on the stack. - /// - /// Operands: value: `i8` - /// - /// Stack: **=>** value - PushInt8, - - /// Push i16 value on the stack. - /// - /// Operands: value: `i16` - /// - /// Stack: **=>** value - PushInt16, - - /// Push i32 value on the stack. - /// - /// Operands: value: `i32` - /// - /// Stack: **=>** value - PushInt32, - - /// Push `f64` value on the stack. - /// - /// Operands: value: `f64` - /// - /// Stack: **=>** value - PushRational, - - /// Push `NaN` integer on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `NaN` - PushNaN, - - /// Push `Infinity` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `Infinity` - PushPositiveInfinity, - - /// Push `-Infinity` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `-Infinity` - PushNegativeInfinity, - - /// Push `null` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `null` - PushNull, - - /// Push `true` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `true` - PushTrue, - - /// Push `false` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `false` - PushFalse, - - /// Push `undefined` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `undefined` - PushUndefined, - - /// Push literal value on the stack. - /// - /// Like strings and bigints. The index operand is used to index into the `literals` - /// array to get the value. - /// - /// Operands: index: `u32` - /// - /// Stack: **=>** (`literals[index]`) - PushLiteral, - - /// Push empty object `{}` value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `{}` - PushEmptyObject, - - /// Get the prototype of a superclass and push it on the stack. - /// - /// Operands: - /// - /// Stack: class, superclass **=>** class, superclass.prototype - PushClassPrototype, - - /// Set the prototype of a class object. - /// - /// Operands: - /// - /// Stack: class, prototype **=>** class.prototype - SetClassPrototype, - - /// Set home object internal slot of a function object. - /// - /// Operands: - /// - /// Stack: home, function **=>** home, function - SetHomeObject, - - /// Push an empty array value on the stack. - /// - /// Operands: - /// - /// Stack: **=>** `[]` - PushNewArray, - - /// Push a value to an array. - /// - /// Operands: - /// - /// Stack: array, value **=>** array - PushValueToArray, - - /// Push an empty element/hole to an array. - /// - /// Operands: - /// - /// Stack: array **=>** array - PushElisionToArray, - - /// Push all iterator values to an array. - /// - /// Operands: - /// - /// Stack: array, iterator, next_method, done **=>** array - PushIteratorToArray, - - /// Binary `+` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs + rhs) - Add, - - /// Binary `-` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs - rhs) - Sub, - - /// Binary `/` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs / rhs) - Div, - - /// Binary `*` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs * rhs) - Mul, - - /// Binary `%` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs % rhs) - Mod, - - /// Binary `**` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs ** rhs) - Pow, - - /// Binary `>>` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs >> rhs) - ShiftRight, - - /// Binary `<<` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs << rhs) - ShiftLeft, - - /// Binary `>>>` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs >>> rhs) - UnsignedShiftRight, - - /// Binary bitwise `|` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs | rhs) - BitOr, - - /// Binary bitwise `&` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs & rhs) - BitAnd, - - /// Binary bitwise `^` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs ^ rhs) - BitXor, - - /// Unary bitwise `~` operator. - /// - /// Operands: - /// - /// Stack: value **=>** ~value - BitNot, - - /// Binary `in` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs `in` rhs) - In, - - /// Binary `==` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs `==` rhs) - Eq, - - /// Binary `===` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs `===` rhs) - StrictEq, - - /// Binary `!=` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs `!=` rhs) - NotEq, - - /// Binary `!==` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs `!==` rhs) - StrictNotEq, - - /// Binary `>` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs > rhs) - GreaterThan, - - /// Binary `>=` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs >= rhs) - GreaterThanOrEq, - - /// Binary `<` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs < rhs) - LessThan, - - /// Binary `<=` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs <= rhs) - LessThanOrEq, - - /// Binary `instanceof` operator. - /// - /// Operands: - /// - /// Stack: lhs, rhs **=>** (lhs instanceof rhs) - InstanceOf, - - /// Binary logical `&&` operator. - /// - /// This is a short-circuit operator, if the `lhs` value is `false`, then it jumps to `exit` address. - /// - /// Operands: exit: `u32` - /// - /// Stack: lhs, rhs **=>** (lhs && rhs) - LogicalAnd, - - /// Binary logical `||` operator. - /// - /// This is a short-circuit operator, if the `lhs` value is `true`, then it jumps to `exit` address. - /// - /// Operands: exit: `u32` - /// - /// Stack: lhs, rhs **=>** (lhs || rhs) - LogicalOr, - - /// Binary `??` operator. - /// - /// This is a short-circuit operator, if the `lhs` value is **not** `null` or `undefined`, - /// then it jumps to `exit` address. - /// - /// Operands: exit: `u32` - /// - /// Stack: lhs, rhs **=>** (lhs ?? rhs) - Coalesce, - - /// Unary `typeof` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (`typeof` value) - TypeOf, - - /// Unary `void` operator. - /// - /// Operands: - /// - /// Stack: value **=>** `undefined` - Void, - - /// Unary logical `!` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (!value) - LogicalNot, - - /// Unary `+` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (+value) - Pos, - - /// Unary `-` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (-value) - Neg, - - /// Unary `++` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (value + 1) - Inc, - - /// Unary postfix `++` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (ToNumeric(value)), (value + 1) - IncPost, - - /// Unary `--` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (value - 1) - Dec, - - /// Unary postfix `--` operator. - /// - /// Operands: - /// - /// Stack: value **=>** (ToNumeric(value)), (value - 1) - DecPost, - - /// Declare and initialize a function argument. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value **=>** - DefInitArg, - - /// Declare `var` type variable. - /// - /// Operands: name_index: `u32` - /// - /// Stack: **=>** - DefVar, - - /// Declare and initialize `var` type variable. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, has_declarative_binding **=>** - DefInitVar, - - /// Declare `let` type variable. - /// - /// Operands: name_index: `u32` - /// - /// Stack: **=>** - DefLet, - - /// Declare and initialize `let` type variable. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value **=>** - DefInitLet, - - /// Declare and initialize `const` type variable. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value **=>** - DefInitConst, - - /// Find a binding on the environment chain and push its value. - /// - /// Operands: name_index: `u32` - /// - /// Stack: **=>** value - GetName, - - /// Find a binding on the environment chain and push its value. If the binding does not exist push undefined. - /// - /// Operands: name_index: `u32` - /// - /// Stack: **=>** value - GetNameOrUndefined, - - /// Find a binding on the environment chain and assign its value. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value **=>** - SetName, - - /// Get a property by name from an object an push it on the stack. - /// - /// Like `object.name` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object **=>** value - GetPropertyByName, - - /// Get a property by value from an object an push it on the stack. - /// - /// Like `object[key]` - /// - /// Operands: - /// - /// Stack: key, object **=>** value - GetPropertyByValue, - - /// Get a property by value from an object an push the key and value on the stack. - /// - /// Like `object[key]` - /// - /// Operands: - /// - /// Stack: key, object **=>** key, value - GetPropertyByValuePush, - - /// Sets a property by name of an object. - /// - /// Like `object.name = value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - SetPropertyByName, - - /// Defines a own property of an object by name. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - DefineOwnPropertyByName, - - /// Defines a class method by name. - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - DefineClassMethodByName, - - /// Sets a property by value of an object. - /// - /// Like `object[key] = value` - /// - /// Operands: - /// - /// Stack: value, key, object **=>** - SetPropertyByValue, - - /// Defines a own property of an object by value. - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - DefineOwnPropertyByValue, - - /// Defines a class method by value. - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - DefineClassMethodByValue, - - /// Sets a getter property by name of an object. - /// - /// Like `get name() value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - SetPropertyGetterByName, - - /// Defines a getter class method by name. - /// - /// Like `get name() value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - DefineClassGetterByName, - - /// Sets a getter property by value of an object. - /// - /// Like `get [key]() value` - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - SetPropertyGetterByValue, - - /// Defines a getter class method by value. - /// - /// Like `get [key]() value` - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - DefineClassGetterByValue, - - /// Sets a setter property by name of an object. - /// - /// Like `set name() value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - SetPropertySetterByName, - - /// Defines a setter class method by name. - /// - /// Like `set name() value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: value, object **=>** - DefineClassSetterByName, - - /// Sets a setter property by value of an object. - /// - /// Like `set [key]() value` - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - SetPropertySetterByValue, - - /// Defines a setter class method by value. - /// - /// Like `set [key]() value` - /// - /// Operands: - /// - /// Stack: object, key, value **=>** - DefineClassSetterByValue, - - /// Assign the value of a private property of an object by it's name. - /// - /// Like `obj.#name = value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object, value **=>** - AssignPrivateField, - - /// Set a private property of a class constructor by it's name. - /// - /// Like `#name = value` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object, value **=>** - SetPrivateField, - - /// Set a private method of a class constructor by it's name. - /// - /// Like `#name() {}` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object, value **=>** - SetPrivateMethod, - - /// Set a private setter property of a class constructor by it's name. - /// - /// Like `set #name() {}` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object, value **=>** - SetPrivateSetter, - - /// Set a private getter property of a class constructor by it's name. - /// - /// Like `get #name() {}` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object, value **=>** - SetPrivateGetter, - - /// Get a private property by name from an object an push it on the stack. - /// - /// Like `object.#name` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object **=>** value - GetPrivateField, - - /// Push a field to a class. - /// - /// Operands: - /// - /// Stack: class, field_name, field_function **=>** - PushClassField, - - /// Push a private field to the class. - /// - /// Operands: name_index: `u32` - /// - /// Stack: class, field_function **=>** - PushClassFieldPrivate, - - /// Push a private getter to the class. - /// - /// Operands: name_index: `u32` - /// - /// Stack: class, getter **=>** - PushClassPrivateGetter, - - /// Push a private setter to the class. - /// - /// Operands: name_index: `u32` - /// - /// Stack: class, setter **=>** - PushClassPrivateSetter, - - /// Push a private method to the class. - /// - /// Operands: name_index: `u32` - /// - /// Stack: class, method **=>** - PushClassPrivateMethod, - - /// Deletes a property by name of an object. - /// - /// Like `delete object.key` - /// - /// Operands: name_index: `u32` - /// - /// Stack: object **=>** - DeletePropertyByName, - - /// Deletes a property by value of an object. - /// - /// Like `delete object[key]` - /// - /// Operands: - /// - /// Stack: key, object **=>** - DeletePropertyByValue, - - /// Copy all properties of one object to another object. - /// - /// Operands: excluded_key_count: `u32`, excluded_key_count_computed: `u32` - /// - /// Stack: excluded_key_computed_0 ... excluded_key_computed_n, source, value, excluded_key_0 ... excluded_key_n **=>** value - CopyDataProperties, - - /// Call ToPropertyKey on the value on the stack. - /// - /// Operands: - /// - /// Stack: value **=>** key - ToPropertyKey, - - /// Unconditional jump to address. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** - Jump, - - /// Conditional jump to address. - /// - /// If the value popped is [`falsy`][falsy] then jump to `address`. - /// - /// Operands: address: `u32` - /// - /// Stack: cond **=>** - /// - /// [falsy]: https://developer.mozilla.org/en-US/docs/Glossary/Falsy - JumpIfFalse, - - /// Conditional jump to address. - /// - /// If the value popped is not undefined jump to `address`. - /// - /// Operands: address: `u32` - /// - /// Stack: value **=>** value - JumpIfNotUndefined, - - /// Conditional jump to address. - /// - /// If the value popped is undefined jump to `address`. - /// - /// Operands: address: `u32` - /// - /// Stack: value **=>** value - JumpIfNullOrUndefined, - - /// Throw exception - /// - /// Operands: - /// - /// Stack: value **=>** - Throw, - - /// Start of a try block. - /// - /// Operands: next_address: `u32`, finally_address: `u32` - /// - /// Stack: **=>** - TryStart, - - /// End of a try block. - /// - /// Operands: - /// - /// Stack: **=>** - TryEnd, - - /// Start of a catch block. - /// - /// Operands: - /// - /// Stack: **=>** - CatchStart, - - /// End of a catch block. - /// - /// Operands: - /// - /// Stack: **=>** - CatchEnd, - - /// End of a catch block. - /// - /// Operands: - /// - /// Stack: **=>** - CatchEnd2, - - /// Start of a finally block. - /// - /// Operands: - /// - /// Stack: **=>** - FinallyStart, - - /// End of a finally block. - /// - /// Operands: - /// - /// Stack: **=>** - FinallyEnd, - - /// Set the address for a finally jump. - /// - /// Operands: - /// - /// Stack: **=>** - FinallySetJump, - - /// Pops value converts it to boolean and pushes it back. - /// - /// Operands: - /// - /// Stack: value **=>** (`ToBoolean(value)`) - ToBoolean, - - /// Pushes `this` value - /// - /// Operands: - /// - /// Stack: **=>** this - This, - - /// Pushes the current `super` value to the stack. - /// - /// Operands: - /// - /// Stack: **=>** super - Super, - - /// Execute the `super()` method. - /// - /// Operands: argument_count: `u32` - /// - /// Stack: argument_1, ... argument_n **=>** - SuperCall, - - /// Execute the `super()` method where the arguments contain spreads. - /// - /// Operands: - /// - /// Stack: arguments_array **=>** - SuperCallSpread, - - /// Execute the `super()` method when no constructor of the class is defined. - /// - /// Operands: - /// - /// Stack: argument_1, ... argument_n **=>** - SuperCallDerived, - - /// Pop the two values of the stack, strict equal compares the two values, - /// if true jumps to address, otherwise push the second pop'ed value. - /// - /// Operands: address: `u32` - /// - /// Stack: value, cond **=>** cond (if `cond !== value`). - Case, - - /// Pops the top of stack and jump to address. - /// - /// Operands: address: `u32` - /// - /// Stack: `value` **=>** - Default, - - /// Get arrow function from the pre-compiled inner functions. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** func - GetArrowFunction, - - /// Get function from the pre-compiled inner functions. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** func - GetFunction, - - /// Get async function from the pre-compiled inner functions. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** func - GetFunctionAsync, - - /// Get generator function from the pre-compiled inner functions. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** func - GetGenerator, - - /// Get async generator function from the pre-compiled inner functions. - /// - /// Operands: address: `u32` - /// - /// Stack: **=>** func - GetGeneratorAsync, - - /// Call a function named "eval". - /// - /// Operands: argument_count: `u32` - /// - /// Stack: this, func, argument_1, ... argument_n **=>** result - CallEval, - - /// Call a function named "eval" where the arguments contain spreads. - /// - /// Operands: - /// - /// Stack: this, func, arguments_array **=>** result - CallEvalSpread, - - /// Call a function. - /// - /// Operands: argument_count: `u32` - /// - /// Stack: this, func, argument_1, ... argument_n **=>** result - Call, - - /// Call a function where the arguments contain spreads. - /// - /// Operands: - /// - /// Stack: this, func, arguments_array **=>** result - CallSpread, - - /// Call construct on a function. - /// - /// Operands: argument_count: `u32` - /// - /// Stack: func, argument_1, ... argument_n **=>** result - New, - - /// Call construct on a function where the arguments contain spreads. - /// - /// Operands: - /// - /// Stack: arguments_array, func **=>** result - NewSpread, - - /// Return from a function. - /// - /// Operands: - /// - /// Stack: **=>** - Return, - - /// Push a declarative environment. - /// - /// Operands: num_bindings: `u32`, compile_environments_index: `u32` - /// - /// Stack: **=>** - PushDeclarativeEnvironment, - - /// Push a function environment. - /// - /// Operands: num_bindings: `u32`, compile_environments_index: `u32` - /// - /// Stack: **=>** - PushFunctionEnvironment, - - /// Pop the current environment. - /// - /// Operands: - /// - /// Stack: **=>** - PopEnvironment, - - /// Push loop start marker. - /// - /// Operands: - /// - /// Stack: **=>** - LoopStart, - - /// Clean up environments when a loop continues. - /// - /// Operands: - /// - /// Stack: **=>** - LoopContinue, - - /// Clean up environments at the end of a loop. - /// - /// Operands: - /// - /// Stack: **=>** - LoopEnd, - - /// Initialize the iterator for a for..in loop or jump to after the loop if object is null or undefined. - /// - /// Operands: address: `u32` - /// - /// Stack: object **=>** iterator, next_method, done - ForInLoopInitIterator, - - /// Initialize an iterator. - /// - /// Operands: - /// - /// Stack: object **=>** iterator, next_method, done - InitIterator, - - /// Initialize an async iterator. - /// - /// Operands: - /// - /// Stack: object **=>** iterator, next_method, done - InitIteratorAsync, - - /// Advance the iterator by one and put the value on the stack. - /// - /// Operands: - /// - /// Stack: iterator, next_method, done **=>** iterator, next_method, done, next_value - IteratorNext, - - /// Close an iterator. - /// - /// Operands: - /// - /// Stack: iterator, next_method, done **=>** - IteratorClose, - - /// Consume the iterator and construct and array with all the values. - /// - /// Operands: - /// - /// Stack: iterator, next_method, done **=>** iterator, next_method, done, array - IteratorToArray, - - /// Move to the next value in a for..in loop or jump to exit of the loop if done. - /// - /// Note: next_result is only pushed if the iterator is not done. - /// - /// Operands: address: `u32` - /// - /// Stack: iterator, next_method, done **=>** iterator, next_method, done, next_result - ForInLoopNext, - - /// Move to the next value in a for await..of loop. - /// - /// Operands: - /// - /// Stack: iterator, next_method, done **=>** iterator, next_method, next_result - ForAwaitOfLoopIterate, - - /// Get the value from a for await..of loop next result. - /// - /// Operands: address: `u32` - /// - /// Stack: next_result **=>** done, value - ForAwaitOfLoopNext, - - /// Concat multiple stack objects into a string. - /// - /// Operands: value_count: `u32` - /// - /// Stack: value_1,...value_n **=>** string - ConcatToString, - - /// Call RequireObjectCoercible on the stack value. - /// - /// Operands: - /// - /// Stack: value **=>** value - RequireObjectCoercible, - - /// Require the stack value to be neither null nor undefined. - /// - /// Operands: - /// - /// Stack: value **=>** value - ValueNotNullOrUndefined, - - /// Initialize the rest parameter value of a function from the remaining arguments. - /// - /// Operands: - /// - /// Stack: `argument_1` .. `argument_n` **=>** `array` - RestParameterInit, - - /// Pop the remaining arguments of a function. - /// - /// Operands: - /// - /// Stack: `argument_1` .. `argument_n` **=>** - RestParameterPop, - - /// Add one to the pop on return count. - /// - /// Operands: - /// - /// Stack: **=>** - PopOnReturnAdd, - - /// Subtract one from the pop on return count. - /// - /// Operands: - /// - /// Stack: **=>** - PopOnReturnSub, - - /// Yield from the current execution. - /// - /// Operands: - /// - /// Stack: value **=>** - Yield, - - /// Resumes the current generator function. - /// - /// Operands: - /// - /// Stack: received **=>** - GeneratorNext, - - /// Resumes the current generator function. - /// - /// Operands: - /// - /// Stack: received **=>** Option, skip_0, skip_1 - AsyncGeneratorNext, - - /// Delegates the current generator function another generator. - /// - /// Operands: done_address: `u32` - /// - /// Stack: iterator, next_method, done, received **=>** iterator, next_method, done - GeneratorNextDelegate, - - /// Stops the current async function and schedules it to resume later. - /// - /// Operands: - /// - /// Stack: promise **=>** - Await, - - /// Push the current new target to the stack. - /// - /// Operands: - /// - /// Stack: **=>** new_target - PushNewTarget, - - /// No-operation instruction, does nothing. - /// - /// Operands: - /// - /// Stack: **=>** - // Safety: Must be last in the list since, we use this for range checking - // in TryFrom impl. - Nop, -} - -impl Opcode { - /// Create opcode from `u8` byte. - /// - /// # Safety - /// - /// Does not check if `u8` type is a valid `Opcode`. - pub unsafe fn from_raw(value: u8) -> Self { - std::mem::transmute(value) - } - - pub fn as_str(self) -> &'static str { - match self { - Self::Pop => Pop::NAME, - Self::PopIfThrown => PopIfThrown::NAME, - Self::Dup => Dup::NAME, - Self::Swap => Swap::NAME, - Self::RotateLeft => RotateLeft::NAME, - Self::RotateRight => RotateRight::NAME, - Self::PushZero => PushZero::NAME, - Self::PushOne => PushOne::NAME, - Self::PushInt8 => PushInt8::NAME, - Self::PushInt16 => PushInt16::NAME, - Self::PushInt32 => PushInt32::NAME, - Self::PushRational => PushRational::NAME, - Self::PushNaN => PushNaN::NAME, - Self::PushPositiveInfinity => PushPositiveInfinity::NAME, - Self::PushNegativeInfinity => PushNegativeInfinity::NAME, - Self::PushNull => PushNull::NAME, - Self::PushTrue => PushTrue::NAME, - Self::PushFalse => PushFalse::NAME, - Self::PushUndefined => PushUndefined::NAME, - Self::PushLiteral => PushLiteral::NAME, - Self::PushEmptyObject => PushEmptyObject::NAME, - Self::PushClassPrototype => PushClassPrototype::NAME, - Self::SetClassPrototype => SetClassPrototype::NAME, - Self::SetHomeObject => SetHomeObject::NAME, - Self::PushNewArray => PushNewArray::NAME, - Self::PushValueToArray => PushValueToArray::NAME, - Self::PushElisionToArray => PushElisionToArray::NAME, - Self::PushIteratorToArray => PushIteratorToArray::NAME, - Self::Add => Add::NAME, - Self::Sub => Sub::NAME, - Self::Div => Div::NAME, - Self::Mul => Mul::NAME, - Self::Mod => Mod::NAME, - Self::Pow => Pow::NAME, - Self::ShiftRight => ShiftRight::NAME, - Self::ShiftLeft => ShiftLeft::NAME, - Self::UnsignedShiftRight => UnsignedShiftRight::NAME, - Self::BitOr => BitOr::NAME, - Self::BitAnd => BitAnd::NAME, - Self::BitXor => BitXor::NAME, - Self::BitNot => BitNot::NAME, - Self::In => In::NAME, - Self::Eq => Eq::NAME, - Self::StrictEq => StrictEq::NAME, - Self::NotEq => NotEq::NAME, - Self::StrictNotEq => StrictNotEq::NAME, - Self::GreaterThan => GreaterThan::NAME, - Self::GreaterThanOrEq => GreaterThanOrEq::NAME, - Self::LessThan => LessThan::NAME, - Self::LessThanOrEq => LessThanOrEq::NAME, - Self::InstanceOf => InstanceOf::NAME, - Self::TypeOf => TypeOf::NAME, - Self::Void => Void::NAME, - Self::LogicalNot => LogicalNot::NAME, - Self::LogicalAnd => LogicalAnd::NAME, - Self::LogicalOr => LogicalOr::NAME, - Self::Coalesce => Coalesce::NAME, - Self::Pos => Pos::NAME, - Self::Neg => Neg::NAME, - Self::Inc => Inc::NAME, - Self::IncPost => IncPost::NAME, - Self::Dec => Dec::NAME, - Self::DecPost => DecPost::NAME, - Self::DefInitArg => DefInitArg::NAME, - Self::DefVar => DefVar::NAME, - Self::DefInitVar => DefInitVar::NAME, - Self::DefLet => DefLet::NAME, - Self::DefInitLet => DefInitLet::NAME, - Self::DefInitConst => DefInitConst::NAME, - Self::GetName => GetName::NAME, - Self::GetNameOrUndefined => GetNameOrUndefined::NAME, - Self::SetName => SetName::NAME, - Self::GetPropertyByName => GetPropertyByName::NAME, - Self::GetPropertyByValue => GetPropertyByValue::NAME, - Self::GetPropertyByValuePush => GetPropertyByValuePush::NAME, - Self::SetPropertyByName => SetPropertyByName::NAME, - Self::DefineOwnPropertyByName => DefineOwnPropertyByName::NAME, - Self::DefineClassMethodByName => DefineClassMethodByName::NAME, - Self::SetPropertyByValue => SetPropertyByValue::NAME, - Self::DefineOwnPropertyByValue => DefineOwnPropertyByValue::NAME, - Self::DefineClassMethodByValue => DefineClassMethodByValue::NAME, - Self::SetPropertyGetterByName => SetPropertyGetterByName::NAME, - Self::DefineClassGetterByName => DefineClassGetterByName::NAME, - Self::SetPropertyGetterByValue => SetPropertyGetterByValue::NAME, - Self::DefineClassGetterByValue => DefineClassGetterByValue::NAME, - Self::SetPropertySetterByName => SetPropertySetterByName::NAME, - Self::DefineClassSetterByName => DefineClassSetterByName::NAME, - Self::SetPropertySetterByValue => SetPropertySetterByValue::NAME, - Self::DefineClassSetterByValue => DefineClassSetterByValue::NAME, - Self::AssignPrivateField => AssignPrivateField::NAME, - Self::SetPrivateField => SetPrivateField::NAME, - Self::SetPrivateMethod => SetPrivateMethod::NAME, - Self::SetPrivateSetter => SetPrivateSetter::NAME, - Self::SetPrivateGetter => SetPrivateGetter::NAME, - Self::GetPrivateField => GetPrivateField::NAME, - Self::PushClassField => PushClassField::NAME, - Self::PushClassFieldPrivate => PushClassFieldPrivate::NAME, - Self::PushClassPrivateGetter => PushClassPrivateGetter::NAME, - Self::PushClassPrivateSetter => PushClassPrivateSetter::NAME, - Self::PushClassPrivateMethod => PushClassPrivateMethod::NAME, - Self::DeletePropertyByName => DeletePropertyByName::NAME, - Self::DeletePropertyByValue => DeletePropertyByValue::NAME, - Self::CopyDataProperties => CopyDataProperties::NAME, - Self::ToPropertyKey => ToPropertyKey::NAME, - Self::Jump => Jump::NAME, - Self::JumpIfFalse => JumpIfFalse::NAME, - Self::JumpIfNotUndefined => JumpIfNotUndefined::NAME, - Self::JumpIfNullOrUndefined => JumpIfNullOrUndefined::NAME, - Self::Throw => Throw::NAME, - Self::TryStart => TryStart::NAME, - Self::TryEnd => TryEnd::NAME, - Self::CatchStart => CatchStart::NAME, - Self::CatchEnd => CatchEnd::NAME, - Self::CatchEnd2 => CatchEnd2::NAME, - Self::FinallyStart => FinallyStart::NAME, - Self::FinallyEnd => FinallyEnd::NAME, - Self::FinallySetJump => FinallySetJump::NAME, - Self::ToBoolean => ToBoolean::NAME, - Self::This => This::NAME, - Self::Super => Super::NAME, - Self::SuperCall => SuperCall::NAME, - Self::SuperCallSpread => SuperCallSpread::NAME, - Self::SuperCallDerived => SuperCallDerived::NAME, - Self::Case => Case::NAME, - Self::Default => Default::NAME, - Self::GetArrowFunction => GetArrowFunction::NAME, - Self::GetFunction => GetFunction::NAME, - Self::GetFunctionAsync => GetFunctionAsync::NAME, - Self::GetGenerator => GetGenerator::NAME, - Self::GetGeneratorAsync => GetGeneratorAsync::NAME, - Self::CallEval => CallEval::NAME, - Self::CallEvalSpread => CallEvalSpread::NAME, - Self::Call => Call::NAME, - Self::CallSpread => CallSpread::NAME, - Self::New => New::NAME, - Self::NewSpread => NewSpread::NAME, - Self::Return => Return::NAME, - Self::PushDeclarativeEnvironment => PushDeclarativeEnvironment::NAME, - Self::PushFunctionEnvironment => PushFunctionEnvironment::NAME, - Self::PopEnvironment => PopEnvironment::NAME, - Self::LoopStart => LoopStart::NAME, - Self::LoopContinue => LoopContinue::NAME, - Self::LoopEnd => LoopEnd::NAME, - Self::ForInLoopInitIterator => ForInLoopInitIterator::NAME, - Self::InitIterator => InitIterator::NAME, - Self::InitIteratorAsync => InitIteratorAsync::NAME, - Self::IteratorNext => IteratorNext::NAME, - Self::IteratorClose => IteratorClose::NAME, - Self::IteratorToArray => IteratorToArray::NAME, - Self::ForInLoopNext => ForInLoopNext::NAME, - Self::ForAwaitOfLoopNext => ForAwaitOfLoopNext::NAME, - Self::ForAwaitOfLoopIterate => ForAwaitOfLoopIterate::NAME, - Self::ConcatToString => ConcatToString::NAME, - Self::RequireObjectCoercible => RequireObjectCoercible::NAME, - Self::ValueNotNullOrUndefined => ValueNotNullOrUndefined::NAME, - Self::RestParameterInit => RestParameterInit::NAME, - Self::RestParameterPop => RestParameterPop::NAME, - Self::PopOnReturnAdd => PopOnReturnAdd::NAME, - Self::PopOnReturnSub => PopOnReturnSub::NAME, - Self::Yield => Yield::NAME, - Self::GeneratorNext => GeneratorNext::NAME, - Self::AsyncGeneratorNext => AsyncGeneratorNext::NAME, - Self::Await => Await::NAME, - Self::PushNewTarget => PushNewTarget::NAME, - Self::GeneratorNextDelegate => GeneratorNextDelegate::NAME, - Self::Nop => Nop::NAME, - } - } - - /// Name of the profiler event for this opcode - pub fn as_instruction_str(self) -> &'static str { - match self { - Self::Pop => Pop::INSTRUCTION, - Self::PopIfThrown => PopIfThrown::INSTRUCTION, - Self::Dup => Dup::INSTRUCTION, - Self::Swap => Swap::INSTRUCTION, - Self::RotateLeft => RotateLeft::INSTRUCTION, - Self::RotateRight => RotateRight::INSTRUCTION, - Self::PushZero => PushZero::INSTRUCTION, - Self::PushOne => PushOne::INSTRUCTION, - Self::PushInt8 => PushInt8::INSTRUCTION, - Self::PushInt16 => PushInt16::INSTRUCTION, - Self::PushInt32 => PushInt32::INSTRUCTION, - Self::PushRational => PushRational::INSTRUCTION, - Self::PushNaN => PushNaN::INSTRUCTION, - Self::PushPositiveInfinity => PushPositiveInfinity::INSTRUCTION, - Self::PushNegativeInfinity => PushNegativeInfinity::INSTRUCTION, - Self::PushNull => PushNull::INSTRUCTION, - Self::PushTrue => PushTrue::INSTRUCTION, - Self::PushFalse => PushFalse::INSTRUCTION, - Self::PushUndefined => PushUndefined::INSTRUCTION, - Self::PushLiteral => PushLiteral::INSTRUCTION, - Self::PushEmptyObject => PushEmptyObject::INSTRUCTION, - Self::PushNewArray => PushNewArray::INSTRUCTION, - Self::PushValueToArray => PushValueToArray::INSTRUCTION, - Self::PushElisionToArray => PushElisionToArray::INSTRUCTION, - Self::PushIteratorToArray => PushIteratorToArray::INSTRUCTION, - Self::Add => Add::INSTRUCTION, - Self::Sub => Sub::INSTRUCTION, - Self::Div => Div::INSTRUCTION, - Self::Mul => Mul::INSTRUCTION, - Self::Mod => Mod::INSTRUCTION, - Self::Pow => Pow::INSTRUCTION, - Self::ShiftRight => ShiftRight::INSTRUCTION, - Self::ShiftLeft => ShiftLeft::INSTRUCTION, - Self::UnsignedShiftRight => UnsignedShiftRight::INSTRUCTION, - Self::BitOr => BitOr::INSTRUCTION, - Self::BitAnd => BitAnd::INSTRUCTION, - Self::BitXor => BitXor::INSTRUCTION, - Self::BitNot => BitNot::INSTRUCTION, - Self::In => In::INSTRUCTION, - Self::Eq => Eq::INSTRUCTION, - Self::StrictEq => StrictEq::INSTRUCTION, - Self::NotEq => NotEq::INSTRUCTION, - Self::StrictNotEq => StrictNotEq::INSTRUCTION, - Self::GreaterThan => GreaterThan::INSTRUCTION, - Self::GreaterThanOrEq => GreaterThanOrEq::INSTRUCTION, - Self::LessThan => LessThan::INSTRUCTION, - Self::LessThanOrEq => LessThanOrEq::INSTRUCTION, - Self::InstanceOf => InstanceOf::INSTRUCTION, - Self::TypeOf => TypeOf::INSTRUCTION, - Self::Void => Void::INSTRUCTION, - Self::LogicalNot => LogicalNot::INSTRUCTION, - Self::LogicalAnd => LogicalAnd::INSTRUCTION, - Self::LogicalOr => LogicalOr::INSTRUCTION, - Self::Coalesce => Coalesce::INSTRUCTION, - Self::Pos => Pos::INSTRUCTION, - Self::Neg => Neg::INSTRUCTION, - Self::Inc => Inc::INSTRUCTION, - Self::IncPost => IncPost::INSTRUCTION, - Self::Dec => Dec::INSTRUCTION, - Self::DecPost => DecPost::INSTRUCTION, - Self::DefInitArg => DefInitArg::INSTRUCTION, - Self::DefVar => DefVar::INSTRUCTION, - Self::DefInitVar => DefInitVar::INSTRUCTION, - Self::DefLet => DefLet::INSTRUCTION, - Self::DefInitLet => DefInitLet::INSTRUCTION, - Self::DefInitConst => DefInitConst::INSTRUCTION, - Self::GetName => GetName::INSTRUCTION, - Self::GetNameOrUndefined => GetNameOrUndefined::INSTRUCTION, - Self::SetName => SetName::INSTRUCTION, - Self::GetPropertyByName => GetPropertyByName::INSTRUCTION, - Self::GetPropertyByValue => GetPropertyByValue::INSTRUCTION, - Self::GetPropertyByValuePush => GetPropertyByValuePush::INSTRUCTION, - Self::SetPropertyByName => SetPropertyByName::INSTRUCTION, - Self::DefineOwnPropertyByName => DefineOwnPropertyByName::INSTRUCTION, - Self::SetPropertyByValue => SetPropertyByValue::INSTRUCTION, - Self::DefineOwnPropertyByValue => DefineOwnPropertyByValue::INSTRUCTION, - Self::SetPropertyGetterByName => SetPropertyGetterByName::INSTRUCTION, - Self::SetPropertyGetterByValue => SetPropertyGetterByValue::INSTRUCTION, - Self::SetPropertySetterByName => SetPropertySetterByName::INSTRUCTION, - Self::SetPropertySetterByValue => SetPropertySetterByValue::INSTRUCTION, - Self::DeletePropertyByName => DeletePropertyByName::INSTRUCTION, - Self::DeletePropertyByValue => DeletePropertyByValue::INSTRUCTION, - Self::CopyDataProperties => CopyDataProperties::INSTRUCTION, - Self::Jump => Jump::INSTRUCTION, - Self::JumpIfFalse => JumpIfFalse::INSTRUCTION, - Self::JumpIfNotUndefined => JumpIfNotUndefined::INSTRUCTION, - Self::JumpIfNullOrUndefined => JumpIfNullOrUndefined::INSTRUCTION, - Self::Throw => Throw::INSTRUCTION, - Self::TryStart => TryStart::INSTRUCTION, - Self::TryEnd => TryEnd::INSTRUCTION, - Self::CatchStart => CatchStart::INSTRUCTION, - Self::CatchEnd => CatchEnd::INSTRUCTION, - Self::CatchEnd2 => CatchEnd2::INSTRUCTION, - Self::FinallyStart => FinallyStart::INSTRUCTION, - Self::FinallyEnd => FinallyEnd::INSTRUCTION, - Self::FinallySetJump => FinallySetJump::INSTRUCTION, - Self::ToBoolean => ToBoolean::INSTRUCTION, - Self::This => This::INSTRUCTION, - Self::Super => Super::INSTRUCTION, - Self::SuperCall => SuperCall::INSTRUCTION, - Self::SuperCallSpread => SuperCallSpread::INSTRUCTION, - Self::SuperCallDerived => SuperCallDerived::INSTRUCTION, - Self::Case => Case::INSTRUCTION, - Self::Default => Default::INSTRUCTION, - Self::GetArrowFunction => GetArrowFunction::INSTRUCTION, - Self::GetFunction => GetFunction::INSTRUCTION, - Self::GetFunctionAsync => GetFunctionAsync::INSTRUCTION, - Self::GetGenerator => GetGenerator::INSTRUCTION, - Self::GetGeneratorAsync => GetGeneratorAsync::INSTRUCTION, - Self::CallEval => CallEval::INSTRUCTION, - Self::CallEvalSpread => CallEvalSpread::INSTRUCTION, - Self::Call => Call::INSTRUCTION, - Self::CallSpread => CallSpread::INSTRUCTION, - Self::New => New::INSTRUCTION, - Self::NewSpread => NewSpread::INSTRUCTION, - Self::Return => Return::INSTRUCTION, - Self::PushDeclarativeEnvironment => PushDeclarativeEnvironment::INSTRUCTION, - Self::PushFunctionEnvironment => PushFunctionEnvironment::INSTRUCTION, - Self::PopEnvironment => PopEnvironment::INSTRUCTION, - Self::LoopStart => LoopStart::INSTRUCTION, - Self::LoopContinue => LoopContinue::INSTRUCTION, - Self::LoopEnd => LoopEnd::INSTRUCTION, - Self::ForInLoopInitIterator => ForInLoopInitIterator::INSTRUCTION, - Self::InitIterator => InitIterator::INSTRUCTION, - Self::InitIteratorAsync => InitIteratorAsync::INSTRUCTION, - Self::IteratorNext => IteratorNext::INSTRUCTION, - Self::IteratorClose => IteratorClose::INSTRUCTION, - Self::IteratorToArray => IteratorToArray::INSTRUCTION, - Self::ForInLoopNext => ForInLoopNext::INSTRUCTION, - Self::ForAwaitOfLoopIterate => ForAwaitOfLoopIterate::INSTRUCTION, - Self::ForAwaitOfLoopNext => ForAwaitOfLoopNext::INSTRUCTION, - Self::ConcatToString => ConcatToString::INSTRUCTION, - Self::RequireObjectCoercible => RequireObjectCoercible::INSTRUCTION, - Self::ValueNotNullOrUndefined => ValueNotNullOrUndefined::INSTRUCTION, - Self::RestParameterInit => RestParameterInit::INSTRUCTION, - Self::RestParameterPop => RestParameterPop::INSTRUCTION, - Self::PopOnReturnAdd => PopOnReturnAdd::INSTRUCTION, - Self::PopOnReturnSub => PopOnReturnSub::INSTRUCTION, - Self::Yield => Yield::INSTRUCTION, - Self::GeneratorNext => GeneratorNext::INSTRUCTION, - Self::AsyncGeneratorNext => AsyncGeneratorNext::INSTRUCTION, - Self::PushNewTarget => PushNewTarget::INSTRUCTION, - Self::Await => Await::INSTRUCTION, - Self::GeneratorNextDelegate => GeneratorNextDelegate::INSTRUCTION, - Self::Nop => Nop::INSTRUCTION, - Self::PushClassPrototype => PushClassPrototype::INSTRUCTION, - Self::SetClassPrototype => SetClassPrototype::INSTRUCTION, - Self::SetHomeObject => SetHomeObject::INSTRUCTION, - Self::DefineClassMethodByName => DefineClassMethodByName::INSTRUCTION, - Self::DefineClassMethodByValue => DefineClassMethodByValue::INSTRUCTION, - Self::DefineClassGetterByName => DefineClassGetterByName::INSTRUCTION, - Self::DefineClassGetterByValue => DefineClassGetterByValue::INSTRUCTION, - Self::DefineClassSetterByName => DefineClassSetterByName::INSTRUCTION, - Self::DefineClassSetterByValue => DefineClassSetterByValue::INSTRUCTION, - Self::AssignPrivateField => AssignPrivateField::INSTRUCTION, - Self::SetPrivateField => SetPrivateField::INSTRUCTION, - Self::SetPrivateMethod => SetPrivateMethod::INSTRUCTION, - Self::SetPrivateSetter => SetPrivateSetter::INSTRUCTION, - Self::SetPrivateGetter => SetPrivateGetter::INSTRUCTION, - Self::GetPrivateField => GetPrivateField::INSTRUCTION, - Self::PushClassField => PushClassField::INSTRUCTION, - Self::PushClassFieldPrivate => PushClassFieldPrivate::INSTRUCTION, - Self::PushClassPrivateGetter => PushClassPrivateGetter::INSTRUCTION, - Self::PushClassPrivateSetter => PushClassPrivateSetter::INSTRUCTION, - Self::PushClassPrivateMethod => PushClassPrivateMethod::INSTRUCTION, - Self::ToPropertyKey => ToPropertyKey::INSTRUCTION, - } +generate_impl! { + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] + #[repr(u8)] + pub enum Opcode { + /// Pop the top value from the stack. + /// + /// Operands: + /// + /// Stack: value **=>** + Pop, + + /// Pop the top value from the stack if the last try block has thrown a value. + /// + /// Operands: + /// + /// Stack: value **=>** + PopIfThrown, + + /// Push a copy of the top value on the stack. + /// + /// Operands: + /// + /// Stack: value **=>** value, value + Dup, + + /// Swap the top two values on the stack. + /// + /// Operands: + /// + /// Stack: second, first **=>** first, second + Swap, + + /// Rotates the top `n` values of the stack to the left by `1`. + /// + /// Equivalent to calling [`slice::rotate_left`] with argument `1` on the top `n` values of the + /// stack. + /// + /// Operands: n: `u8` + /// + /// Stack: v\[n\], v\[n-1\], ... , v\[1\], v\[0\] **=>** v\[n-1\], ... , v\[1\], v\[0\], v\[n\] + RotateLeft, + + /// Rotates the top `n` values of the stack to the right by `1`. + /// + /// Equivalent to calling [`slice::rotate_right`] with argument `1` on the top `n` values of the + /// stack. + /// + /// Operands: n: `u8` + /// + /// Stack: v\[n\], v\[n-1\], ... , v\[1\], v\[0\] **=>** v\[0\], v\[n\], v\[n-1\], ... , v\[1\] + RotateRight, + + /// Push integer `0` on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `0` + PushZero, + + /// Push integer `1` on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `1` + PushOne, + + /// Push `i8` value on the stack. + /// + /// Operands: value: `i8` + /// + /// Stack: **=>** value + PushInt8, + + /// Push i16 value on the stack. + /// + /// Operands: value: `i16` + /// + /// Stack: **=>** value + PushInt16, + + /// Push i32 value on the stack. + /// + /// Operands: value: `i32` + /// + /// Stack: **=>** value + PushInt32, + + /// Push `f64` value on the stack. + /// + /// Operands: value: `f64` + /// + /// Stack: **=>** value + PushRational, + + /// Push `NaN` integer on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `NaN` + PushNaN, + + /// Push `Infinity` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `Infinity` + PushPositiveInfinity, + + /// Push `-Infinity` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `-Infinity` + PushNegativeInfinity, + + /// Push `null` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `null` + PushNull, + + /// Push `true` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `true` + PushTrue, + + /// Push `false` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `false` + PushFalse, + + /// Push `undefined` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `undefined` + PushUndefined, + + /// Push literal value on the stack. + /// + /// Like strings and bigints. The index operand is used to index into the `literals` + /// array to get the value. + /// + /// Operands: index: `u32` + /// + /// Stack: **=>** (`literals[index]`) + PushLiteral, + + /// Push empty object `{}` value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `{}` + PushEmptyObject, + + /// Get the prototype of a superclass and push it on the stack. + /// + /// Operands: + /// + /// Stack: class, superclass **=>** class, superclass.prototype + PushClassPrototype, + + /// Set the prototype of a class object. + /// + /// Operands: + /// + /// Stack: class, prototype **=>** class.prototype + SetClassPrototype, + + /// Set home object internal slot of a function object. + /// + /// Operands: + /// + /// Stack: home, function **=>** home, function + SetHomeObject, + + /// Push an empty array value on the stack. + /// + /// Operands: + /// + /// Stack: **=>** `[]` + PushNewArray, + + /// Push a value to an array. + /// + /// Operands: + /// + /// Stack: array, value **=>** array + PushValueToArray, + + /// Push an empty element/hole to an array. + /// + /// Operands: + /// + /// Stack: array **=>** array + PushElisionToArray, + + /// Push all iterator values to an array. + /// + /// Operands: + /// + /// Stack: array, iterator, next_method, done **=>** array + PushIteratorToArray, + + /// Binary `+` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs + rhs) + Add, + + /// Binary `-` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs - rhs) + Sub, + + /// Binary `/` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs / rhs) + Div, + + /// Binary `*` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs * rhs) + Mul, + + /// Binary `%` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs % rhs) + Mod, + + /// Binary `**` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs ** rhs) + Pow, + + /// Binary `>>` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs >> rhs) + ShiftRight, + + /// Binary `<<` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs << rhs) + ShiftLeft, + + /// Binary `>>>` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs >>> rhs) + UnsignedShiftRight, + + /// Binary bitwise `|` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs | rhs) + BitOr, + + /// Binary bitwise `&` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs & rhs) + BitAnd, + + /// Binary bitwise `^` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs ^ rhs) + BitXor, + + /// Unary bitwise `~` operator. + /// + /// Operands: + /// + /// Stack: value **=>** ~value + BitNot, + + /// Binary `in` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs `in` rhs) + In, + + /// Binary `==` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs `==` rhs) + Eq, + + /// Binary `===` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs `===` rhs) + StrictEq, + + /// Binary `!=` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs `!=` rhs) + NotEq, + + /// Binary `!==` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs `!==` rhs) + StrictNotEq, + + /// Binary `>` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs > rhs) + GreaterThan, + + /// Binary `>=` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs >= rhs) + GreaterThanOrEq, + + /// Binary `<` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs < rhs) + LessThan, + + /// Binary `<=` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs <= rhs) + LessThanOrEq, + + /// Binary `instanceof` operator. + /// + /// Operands: + /// + /// Stack: lhs, rhs **=>** (lhs instanceof rhs) + InstanceOf, + + /// Binary logical `&&` operator. + /// + /// This is a short-circuit operator, if the `lhs` value is `false`, then it jumps to `exit` address. + /// + /// Operands: exit: `u32` + /// + /// Stack: lhs, rhs **=>** (lhs && rhs) + LogicalAnd, + + /// Binary logical `||` operator. + /// + /// This is a short-circuit operator, if the `lhs` value is `true`, then it jumps to `exit` address. + /// + /// Operands: exit: `u32` + /// + /// Stack: lhs, rhs **=>** (lhs || rhs) + LogicalOr, + + /// Binary `??` operator. + /// + /// This is a short-circuit operator, if the `lhs` value is **not** `null` or `undefined`, + /// then it jumps to `exit` address. + /// + /// Operands: exit: `u32` + /// + /// Stack: lhs, rhs **=>** (lhs ?? rhs) + Coalesce, + + /// Unary `typeof` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (`typeof` value) + TypeOf, + + /// Unary `void` operator. + /// + /// Operands: + /// + /// Stack: value **=>** `undefined` + Void, + + /// Unary logical `!` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (!value) + LogicalNot, + + /// Unary `+` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (+value) + Pos, + + /// Unary `-` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (-value) + Neg, + + /// Unary `++` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (value + 1) + Inc, + + /// Unary postfix `++` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (ToNumeric(value)), (value + 1) + IncPost, + + /// Unary `--` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (value - 1) + Dec, + + /// Unary postfix `--` operator. + /// + /// Operands: + /// + /// Stack: value **=>** (ToNumeric(value)), (value - 1) + DecPost, + + /// Declare and initialize a function argument. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value **=>** + DefInitArg, + + /// Declare `var` type variable. + /// + /// Operands: name_index: `u32` + /// + /// Stack: **=>** + DefVar, + + /// Declare and initialize `var` type variable. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, has_declarative_binding **=>** + DefInitVar, + + /// Declare `let` type variable. + /// + /// Operands: name_index: `u32` + /// + /// Stack: **=>** + DefLet, + + /// Declare and initialize `let` type variable. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value **=>** + DefInitLet, + + /// Declare and initialize `const` type variable. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value **=>** + DefInitConst, + + /// Find a binding on the environment chain and push its value. + /// + /// Operands: name_index: `u32` + /// + /// Stack: **=>** value + GetName, + + /// Find a binding on the environment chain and push its value. If the binding does not exist push undefined. + /// + /// Operands: name_index: `u32` + /// + /// Stack: **=>** value + GetNameOrUndefined, + + /// Find a binding on the environment chain and assign its value. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value **=>** + SetName, + + /// Get a property by name from an object an push it on the stack. + /// + /// Like `object.name` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object **=>** value + GetPropertyByName, + + /// Get a property by value from an object an push it on the stack. + /// + /// Like `object[key]` + /// + /// Operands: + /// + /// Stack: key, object **=>** value + GetPropertyByValue, + + /// Get a property by value from an object an push the key and value on the stack. + /// + /// Like `object[key]` + /// + /// Operands: + /// + /// Stack: key, object **=>** key, value + GetPropertyByValuePush, + + /// Sets a property by name of an object. + /// + /// Like `object.name = value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + SetPropertyByName, + + /// Defines a own property of an object by name. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + DefineOwnPropertyByName, + + /// Defines a class method by name. + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + DefineClassMethodByName, + + /// Sets a property by value of an object. + /// + /// Like `object[key] = value` + /// + /// Operands: + /// + /// Stack: value, key, object **=>** + SetPropertyByValue, + + /// Defines a own property of an object by value. + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + DefineOwnPropertyByValue, + + /// Defines a class method by value. + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + DefineClassMethodByValue, + + /// Sets a getter property by name of an object. + /// + /// Like `get name() value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + SetPropertyGetterByName, + + /// Defines a getter class method by name. + /// + /// Like `get name() value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + DefineClassGetterByName, + + /// Sets a getter property by value of an object. + /// + /// Like `get [key]() value` + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + SetPropertyGetterByValue, + + /// Defines a getter class method by value. + /// + /// Like `get [key]() value` + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + DefineClassGetterByValue, + + /// Sets a setter property by name of an object. + /// + /// Like `set name() value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + SetPropertySetterByName, + + /// Defines a setter class method by name. + /// + /// Like `set name() value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: value, object **=>** + DefineClassSetterByName, + + /// Sets a setter property by value of an object. + /// + /// Like `set [key]() value` + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + SetPropertySetterByValue, + + /// Defines a setter class method by value. + /// + /// Like `set [key]() value` + /// + /// Operands: + /// + /// Stack: object, key, value **=>** + DefineClassSetterByValue, + + /// Assign the value of a private property of an object by it's name. + /// + /// Like `obj.#name = value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object, value **=>** + AssignPrivateField, + + /// Set a private property of a class constructor by it's name. + /// + /// Like `#name = value` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object, value **=>** + SetPrivateField, + + /// Set a private method of a class constructor by it's name. + /// + /// Like `#name() {}` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object, value **=>** + SetPrivateMethod, + + /// Set a private setter property of a class constructor by it's name. + /// + /// Like `set #name() {}` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object, value **=>** + SetPrivateSetter, + + /// Set a private getter property of a class constructor by it's name. + /// + /// Like `get #name() {}` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object, value **=>** + SetPrivateGetter, + + /// Get a private property by name from an object an push it on the stack. + /// + /// Like `object.#name` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object **=>** value + GetPrivateField, + + /// Push a field to a class. + /// + /// Operands: + /// + /// Stack: class, field_name, field_function **=>** + PushClassField, + + /// Push a private field to the class. + /// + /// Operands: name_index: `u32` + /// + /// Stack: class, field_function **=>** + PushClassFieldPrivate, + + /// Push a private getter to the class. + /// + /// Operands: name_index: `u32` + /// + /// Stack: class, getter **=>** + PushClassPrivateGetter, + + /// Push a private setter to the class. + /// + /// Operands: name_index: `u32` + /// + /// Stack: class, setter **=>** + PushClassPrivateSetter, + + /// Push a private method to the class. + /// + /// Operands: name_index: `u32` + /// + /// Stack: class, method **=>** + PushClassPrivateMethod, + + /// Deletes a property by name of an object. + /// + /// Like `delete object.key` + /// + /// Operands: name_index: `u32` + /// + /// Stack: object **=>** + DeletePropertyByName, + + /// Deletes a property by value of an object. + /// + /// Like `delete object[key]` + /// + /// Operands: + /// + /// Stack: key, object **=>** + DeletePropertyByValue, + + /// Copy all properties of one object to another object. + /// + /// Operands: excluded_key_count: `u32`, excluded_key_count_computed: `u32` + /// + /// Stack: excluded_key_computed_0 ... excluded_key_computed_n, source, value, excluded_key_0 ... excluded_key_n **=>** value + CopyDataProperties, + + /// Call ToPropertyKey on the value on the stack. + /// + /// Operands: + /// + /// Stack: value **=>** key + ToPropertyKey, + + /// Unconditional jump to address. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** + Jump, + + /// Conditional jump to address. + /// + /// If the value popped is [`falsy`][falsy] then jump to `address`. + /// + /// Operands: address: `u32` + /// + /// Stack: cond **=>** + /// + /// [falsy]: https://developer.mozilla.org/en-US/docs/Glossary/Falsy + JumpIfFalse, + + /// Conditional jump to address. + /// + /// If the value popped is not undefined jump to `address`. + /// + /// Operands: address: `u32` + /// + /// Stack: value **=>** value + JumpIfNotUndefined, + + /// Conditional jump to address. + /// + /// If the value popped is undefined jump to `address`. + /// + /// Operands: address: `u32` + /// + /// Stack: value **=>** value + JumpIfNullOrUndefined, + + /// Throw exception + /// + /// Operands: + /// + /// Stack: value **=>** + Throw, + + /// Start of a try block. + /// + /// Operands: next_address: `u32`, finally_address: `u32` + /// + /// Stack: **=>** + TryStart, + + /// End of a try block. + /// + /// Operands: + /// + /// Stack: **=>** + TryEnd, + + /// Start of a catch block. + /// + /// Operands: + /// + /// Stack: **=>** + CatchStart, + + /// End of a catch block. + /// + /// Operands: + /// + /// Stack: **=>** + CatchEnd, + + /// End of a catch block. + /// + /// Operands: + /// + /// Stack: **=>** + CatchEnd2, + + /// Start of a finally block. + /// + /// Operands: + /// + /// Stack: **=>** + FinallyStart, + + /// End of a finally block. + /// + /// Operands: + /// + /// Stack: **=>** + FinallyEnd, + + /// Set the address for a finally jump. + /// + /// Operands: + /// + /// Stack: **=>** + FinallySetJump, + + /// Pops value converts it to boolean and pushes it back. + /// + /// Operands: + /// + /// Stack: value **=>** (`ToBoolean(value)`) + ToBoolean, + + /// Pushes `this` value + /// + /// Operands: + /// + /// Stack: **=>** this + This, + + /// Pushes the current `super` value to the stack. + /// + /// Operands: + /// + /// Stack: **=>** super + Super, + + /// Execute the `super()` method. + /// + /// Operands: argument_count: `u32` + /// + /// Stack: argument_1, ... argument_n **=>** + SuperCall, + + /// Execute the `super()` method where the arguments contain spreads. + /// + /// Operands: + /// + /// Stack: arguments_array **=>** + SuperCallSpread, + + /// Execute the `super()` method when no constructor of the class is defined. + /// + /// Operands: + /// + /// Stack: argument_1, ... argument_n **=>** + SuperCallDerived, + + /// Pop the two values of the stack, strict equal compares the two values, + /// if true jumps to address, otherwise push the second pop'ed value. + /// + /// Operands: address: `u32` + /// + /// Stack: value, cond **=>** cond (if `cond !== value`). + Case, + + /// Pops the top of stack and jump to address. + /// + /// Operands: address: `u32` + /// + /// Stack: `value` **=>** + Default, + + /// Get arrow function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetArrowFunction, + + /// Get function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetFunction, + + /// Get async function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetFunctionAsync, + + /// Get generator function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetGenerator, + + /// Get async generator function from the pre-compiled inner functions. + /// + /// Operands: address: `u32` + /// + /// Stack: **=>** func + GetGeneratorAsync, + + /// Call a function named "eval". + /// + /// Operands: argument_count: `u32` + /// + /// Stack: this, func, argument_1, ... argument_n **=>** result + CallEval, + + /// Call a function named "eval" where the arguments contain spreads. + /// + /// Operands: + /// + /// Stack: this, func, arguments_array **=>** result + CallEvalSpread, + + /// Call a function. + /// + /// Operands: argument_count: `u32` + /// + /// Stack: this, func, argument_1, ... argument_n **=>** result + Call, + + /// Call a function where the arguments contain spreads. + /// + /// Operands: + /// + /// Stack: this, func, arguments_array **=>** result + CallSpread, + + /// Call construct on a function. + /// + /// Operands: argument_count: `u32` + /// + /// Stack: func, argument_1, ... argument_n **=>** result + New, + + /// Call construct on a function where the arguments contain spreads. + /// + /// Operands: + /// + /// Stack: arguments_array, func **=>** result + NewSpread, + + /// Return from a function. + /// + /// Operands: + /// + /// Stack: **=>** + Return, + + /// Push a declarative environment. + /// + /// Operands: num_bindings: `u32`, compile_environments_index: `u32` + /// + /// Stack: **=>** + PushDeclarativeEnvironment, + + /// Push a function environment. + /// + /// Operands: num_bindings: `u32`, compile_environments_index: `u32` + /// + /// Stack: **=>** + PushFunctionEnvironment, + + /// Pop the current environment. + /// + /// Operands: + /// + /// Stack: **=>** + PopEnvironment, + + /// Push loop start marker. + /// + /// Operands: + /// + /// Stack: **=>** + LoopStart, + + /// Clean up environments when a loop continues. + /// + /// Operands: + /// + /// Stack: **=>** + LoopContinue, + + /// Clean up environments at the end of a loop. + /// + /// Operands: + /// + /// Stack: **=>** + LoopEnd, + + /// Initialize the iterator for a for..in loop or jump to after the loop if object is null or undefined. + /// + /// Operands: address: `u32` + /// + /// Stack: object **=>** iterator, next_method, done + ForInLoopInitIterator, + + /// Initialize an iterator. + /// + /// Operands: + /// + /// Stack: object **=>** iterator, next_method, done + InitIterator, + + /// Initialize an async iterator. + /// + /// Operands: + /// + /// Stack: object **=>** iterator, next_method, done + InitIteratorAsync, + + /// Advance the iterator by one and put the value on the stack. + /// + /// Operands: + /// + /// Stack: iterator, next_method, done **=>** iterator, next_method, done, next_value + IteratorNext, + + /// Close an iterator. + /// + /// Operands: + /// + /// Stack: iterator, next_method, done **=>** + IteratorClose, + + /// Consume the iterator and construct and array with all the values. + /// + /// Operands: + /// + /// Stack: iterator, next_method, done **=>** iterator, next_method, done, array + IteratorToArray, + + /// Move to the next value in a for..in loop or jump to exit of the loop if done. + /// + /// Note: next_result is only pushed if the iterator is not done. + /// + /// Operands: address: `u32` + /// + /// Stack: iterator, next_method, done **=>** iterator, next_method, done, next_result + ForInLoopNext, + + /// Move to the next value in a for await..of loop. + /// + /// Operands: + /// + /// Stack: iterator, next_method, done **=>** iterator, next_method, next_result + ForAwaitOfLoopIterate, + + /// Get the value from a for await..of loop next result. + /// + /// Operands: address: `u32` + /// + /// Stack: next_result **=>** done, value + ForAwaitOfLoopNext, + + /// Concat multiple stack objects into a string. + /// + /// Operands: value_count: `u32` + /// + /// Stack: value_1,...value_n **=>** string + ConcatToString, + + /// Call RequireObjectCoercible on the stack value. + /// + /// Operands: + /// + /// Stack: value **=>** value + RequireObjectCoercible, + + /// Require the stack value to be neither null nor undefined. + /// + /// Operands: + /// + /// Stack: value **=>** value + ValueNotNullOrUndefined, + + /// Initialize the rest parameter value of a function from the remaining arguments. + /// + /// Operands: + /// + /// Stack: `argument_1` .. `argument_n` **=>** `array` + RestParameterInit, + + /// Pop the remaining arguments of a function. + /// + /// Operands: + /// + /// Stack: `argument_1` .. `argument_n` **=>** + RestParameterPop, + + /// Add one to the pop on return count. + /// + /// Operands: + /// + /// Stack: **=>** + PopOnReturnAdd, + + /// Subtract one from the pop on return count. + /// + /// Operands: + /// + /// Stack: **=>** + PopOnReturnSub, + + /// Yield from the current execution. + /// + /// Operands: + /// + /// Stack: value **=>** + Yield, + + /// Resumes the current generator function. + /// + /// Operands: + /// + /// Stack: received **=>** + GeneratorNext, + + /// Resumes the current generator function. + /// + /// Operands: + /// + /// Stack: received **=>** Option, skip_0, skip_1 + AsyncGeneratorNext, + + /// Delegates the current generator function another generator. + /// + /// Operands: done_address: `u32` + /// + /// Stack: iterator, next_method, done, received **=>** iterator, next_method, done + GeneratorNextDelegate, + + /// Stops the current async function and schedules it to resume later. + /// + /// Operands: + /// + /// Stack: promise **=>** + Await, + + /// Push the current new target to the stack. + /// + /// Operands: + /// + /// Stack: **=>** new_target + PushNewTarget, + + /// No-operation instruction, does nothing. + /// + /// Operands: + /// + /// Stack: **=>** + // Safety: Must be last in the list since, we use this for range checking + // in TryFrom impl. + Nop, } }