pub enum Op {
Show 140 variants
LoadConst {
dst: Register,
idx: u16,
},
LoadUndefined {
dst: Register,
},
LoadNull {
dst: Register,
},
LoadBool {
dst: Register,
value: bool,
},
LoadInt {
dst: Register,
value: i32,
},
Move {
dst: Register,
src: Register,
},
Add {
dst: Register,
left: Register,
right: Register,
},
Sub {
dst: Register,
left: Register,
right: Register,
},
Mul {
dst: Register,
left: Register,
right: Register,
},
Div {
dst: Register,
left: Register,
right: Register,
},
Mod {
dst: Register,
left: Register,
right: Register,
},
Exp {
dst: Register,
left: Register,
right: Register,
},
Eq {
dst: Register,
left: Register,
right: Register,
},
NotEq {
dst: Register,
left: Register,
right: Register,
},
StrictEq {
dst: Register,
left: Register,
right: Register,
},
StrictNotEq {
dst: Register,
left: Register,
right: Register,
},
Lt {
dst: Register,
left: Register,
right: Register,
},
LtEq {
dst: Register,
left: Register,
right: Register,
},
Gt {
dst: Register,
left: Register,
right: Register,
},
GtEq {
dst: Register,
left: Register,
right: Register,
},
BitAnd {
dst: Register,
left: Register,
right: Register,
},
BitOr {
dst: Register,
left: Register,
right: Register,
},
BitXor {
dst: Register,
left: Register,
right: Register,
},
LShift {
dst: Register,
left: Register,
right: Register,
},
RShift {
dst: Register,
left: Register,
right: Register,
},
URShift {
dst: Register,
left: Register,
right: Register,
},
In {
dst: Register,
left: Register,
right: Register,
},
Instanceof {
dst: Register,
left: Register,
right: Register,
},
Neg {
dst: Register,
src: Register,
},
Plus {
dst: Register,
src: Register,
},
Not {
dst: Register,
src: Register,
},
BitNot {
dst: Register,
src: Register,
},
Typeof {
dst: Register,
src: Register,
},
Void {
dst: Register,
src: Register,
},
Jump {
target: JumpTarget,
},
JumpIfTrue {
cond: Register,
target: JumpTarget,
},
JumpIfFalse {
cond: Register,
target: JumpTarget,
},
JumpIfNullish {
cond: Register,
target: JumpTarget,
},
JumpIfNotNullish {
cond: Register,
target: JumpTarget,
},
Break {
target: JumpTarget,
try_depth: u8,
},
Continue {
target: JumpTarget,
try_depth: u8,
},
GetVar {
dst: Register,
name: u16,
},
TryGetVar {
dst: Register,
name: u16,
},
SetVar {
name: u16,
src: Register,
},
DeclareVar {
name: u16,
init: Register,
mutable: bool,
},
DeclareVarHoisted {
name: u16,
init: Register,
},
GetGlobal {
dst: Register,
name: u16,
},
SetGlobal {
name: u16,
src: Register,
},
CreateObject {
dst: Register,
},
CreateArray {
dst: Register,
start: Register,
count: u16,
},
ArrayPush {
arr: Register,
value: Register,
},
GetProperty {
dst: Register,
obj: Register,
key: Register,
},
GetPropertyConst {
dst: Register,
obj: Register,
key: u16,
},
SetProperty {
obj: Register,
key: Register,
value: Register,
},
SetPropertyConst {
obj: Register,
key: u16,
value: Register,
},
DeleteProperty {
dst: Register,
obj: Register,
key: Register,
},
DeletePropertyConst {
dst: Register,
obj: Register,
key: u16,
},
DefineProperty {
obj: Register,
key: Register,
value: Register,
flags: u8,
},
Call {
dst: Register,
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
CallSpread {
dst: Register,
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
DirectEval {
dst: Register,
arg: Register,
},
CallMethod {
dst: Register,
obj: Register,
method: u16,
args_start: Register,
argc: u8,
},
TailCall {
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
TailCallSpread {
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
TailCallAwait {
dst: Register,
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
TailCallAwaitSpread {
dst: Register,
callee: Register,
this: Register,
args_start: Register,
argc: u8,
},
Construct {
dst: Register,
callee: Register,
args_start: Register,
argc: u8,
},
ConstructSpread {
dst: Register,
callee: Register,
args_start: Register,
argc: u8,
},
Return {
value: Register,
},
ReturnUndefined,
CreateClosure {
dst: Register,
chunk_idx: u16,
},
CreateArrow {
dst: Register,
chunk_idx: u16,
},
CreateGenerator {
dst: Register,
chunk_idx: u16,
},
CreateAsync {
dst: Register,
chunk_idx: u16,
},
CreateAsyncGenerator {
dst: Register,
chunk_idx: u16,
},
Throw {
value: Register,
},
PushTry {
catch_target: JumpTarget,
finally_target: JumpTarget,
},
PopTry,
FinallyEnd,
GetException {
dst: Register,
},
PushIterTry {
iterator: Register,
catch_target: JumpTarget,
},
PopIterTry,
Rethrow,
Await {
dst: Register,
promise: Register,
},
Yield {
dst: Register,
value: Register,
},
YieldStar {
dst: Register,
iterable: Register,
},
PushScope,
PopScope,
GetIterator {
dst: Register,
obj: Register,
},
GetKeysIterator {
dst: Register,
obj: Register,
},
GetAsyncIterator {
dst: Register,
obj: Register,
},
IteratorNext {
dst: Register,
iterator: Register,
},
IteratorDone {
result: Register,
target: JumpTarget,
},
IteratorValue {
dst: Register,
result: Register,
},
IteratorClose {
iterator: Register,
},
CreateClass {
dst: Register,
constructor: Register,
super_class: Register,
},
DefineMethod {
class: Register,
name: u16,
method: Register,
is_static: bool,
},
DefineAccessor {
class: Register,
name: u16,
getter: Register,
setter: Register,
is_static: bool,
},
DefineMethodComputed {
class: Register,
key: Register,
method: Register,
is_static: bool,
},
DefineAccessorComputed {
class: Register,
key: Register,
getter: Register,
setter: Register,
is_static: bool,
},
SuperCall {
dst: Register,
args_start: Register,
argc: u8,
},
SuperCallSpread {
dst: Register,
args_array: Register,
},
SuperGet {
dst: Register,
key: Register,
},
SuperGetConst {
dst: Register,
key: u16,
},
SuperSet {
key: Register,
value: Register,
},
SuperSetConst {
key: u16,
value: Register,
},
ApplyClassDecorator {
class: Register,
decorator: Register,
class_name: u16,
initializers: Register,
},
RunClassInitializers {
class: Register,
initializers: Register,
},
ApplyMethodDecorator {
method: Register,
decorator: Register,
name: u16,
kind: u8,
is_static: bool,
is_private: bool,
},
ApplyParameterDecorator {
target: Register,
decorator: Register,
method_name: u16,
param_name: u16,
param_index: u8,
is_static: bool,
},
ApplyFieldDecorator {
dst: Register,
decorator: Register,
name: u16,
is_static: bool,
is_private: bool,
is_accessor: bool,
},
StoreFieldInitializer {
class: Register,
name: u16,
initializer: Register,
},
GetFieldInitializer {
dst: Register,
class: Register,
name: u16,
},
ApplyFieldInitializer {
value: Register,
initializer: Register,
},
DefineAutoAccessor {
class: Register,
name: u16,
init_value: Register,
target_dst: Register,
is_static: bool,
},
StoreAutoAccessor {
class: Register,
name: u16,
accessor_obj: Register,
is_static: bool,
},
ApplyAutoAccessorDecorator {
target: Register,
decorator: Register,
name: u16,
is_static: bool,
},
SpreadArray {
dst: Register,
src: Register,
},
CreateRestArray {
dst: Register,
start_index: u8,
},
CreateObjectRest {
dst: Register,
src: Register,
excluded_keys: u16,
},
SpreadObject {
dst: Register,
src: Register,
},
TemplateConcat {
dst: Register,
start: Register,
count: u8,
},
TaggedTemplate {
dst: Register,
tag: Register,
this: Register,
template: u16,
exprs_start: Register,
exprs_count: u8,
},
GetPrivateField {
dst: Register,
obj: Register,
class_brand: u32,
field_name: u16,
},
SetPrivateField {
obj: Register,
class_brand: u32,
field_name: u16,
value: Register,
},
DefinePrivateField {
obj: Register,
class_brand: u32,
field_name: u16,
value: Register,
},
DefinePrivateMethod {
class: Register,
class_brand: u32,
method_name: u16,
method: Register,
is_static: bool,
},
InstallPrivateMethod {
class_brand: u32,
method_name: u16,
},
SetFunctionName {
func: Register,
name: u16,
},
Nop,
Halt,
Debugger,
Pop,
Dup {
dst: Register,
src: Register,
},
LoadThis {
dst: Register,
},
LoadArguments {
dst: Register,
},
LoadNewTarget {
dst: Register,
},
ExportBinding {
export_name: u16,
binding_name: u16,
value: Register,
},
ExportNamespace {
export_name: u16,
module_specifier: u16,
},
ReExport {
export_name: u16,
source_module: u16,
source_key: u16,
},
}Expand description
Bytecode instruction
Each instruction operates on virtual registers. The register-based design generates fewer instructions than a stack-based VM and has better cache locality.
Op is Copy because all variants contain only primitive types (u8, u16, u32, bool). This allows efficient pass-by-value without heap allocation or reference counting.
Variants§
LoadConst
Load constant from pool: r[dst] = constants[idx]
LoadUndefined
Load undefined: r[dst] = undefined
LoadNull
Load null: r[dst] = null
LoadBool
Load boolean: r[dst] = value
LoadInt
Load integer (small numbers without constant pool): r[dst] = value
Move
Move register: r[dst] = r[src]
Add
Add: r[dst] = r[left] + r[right]
Sub
Subtract: r[dst] = r[left] - r[right]
Mul
Multiply: r[dst] = r[left] * r[right]
Div
Divide: r[dst] = r[left] / r[right]
Mod
Modulo: r[dst] = r[left] % r[right]
Exp
Exponentiation: r[dst] = r[left] ** r[right]
Eq
Loose equality: r[dst] = r[left] == r[right]
NotEq
Loose inequality: r[dst] = r[left] != r[right]
StrictEq
Strict equality: r[dst] = r[left] === r[right]
StrictNotEq
Strict inequality: r[dst] = r[left] !== r[right]
Lt
Less than: r[dst] = r[left] < r[right]
LtEq
Less than or equal: r[dst] = r[left] <= r[right]
Gt
Greater than: r[dst] = r[left] > r[right]
GtEq
Greater than or equal: r[dst] = r[left] >= r[right]
BitAnd
Bitwise AND: r[dst] = r[left] & r[right]
BitOr
Bitwise OR: r[dst] = r[left] | r[right]
BitXor
Bitwise XOR: r[dst] = r[left] ^ r[right]
LShift
Left shift: r[dst] = r[left] << r[right]
RShift
Signed right shift: r[dst] = r[left] >> r[right]
URShift
Unsigned right shift: r[dst] = r[left] >>> r[right]
In
In operator: r[dst] = r[left] in r[right]
Instanceof
Instanceof: r[dst] = r[left] instanceof r[right]
Neg
Negate: r[dst] = -r[src]
Plus
Unary plus: r[dst] = +r[src] (ToNumber)
Not
Logical not: r[dst] = !r[src]
BitNot
Bitwise not: r[dst] = ~r[src]
Typeof
Typeof: r[dst] = typeof r[src]
Void
Void: r[dst] = void r[src] (always undefined)
Jump
Unconditional jump
Fields
target: JumpTargetJumpIfTrue
Jump if r[cond] is truthy
JumpIfFalse
Jump if r[cond] is falsy
JumpIfNullish
Jump if r[cond] is null or undefined (for ??)
JumpIfNotNullish
Jump if r[cond] is NOT null or undefined (for ?.)
Break
Break to target (runs finally blocks first) try_depth is the try stack depth at the target loop
Continue
Continue to target (runs finally blocks first) try_depth is the try stack depth at the target loop
GetVar
Load variable: r[dst] = env[name]
TryGetVar
Try to load variable, returns undefined if not found: r[dst] = env[name] ?? undefined
SetVar
Store variable: env[name] = r[src]
DeclareVar
Declare variable with let/const: env.define(name, r[init], mutable)
DeclareVarHoisted
Declare variable with var (hoisted): env.define_var(name, r[init])
GetGlobal
Get global variable (optimized path for globals)
SetGlobal
Set global variable
CreateObject
Create empty object: r[dst] = {}
CreateArray
Create array from registers: r[dst] = [r[start]..r[start+count]]
ArrayPush
Push element onto array: r[arr].push(r[value])
GetProperty
Get property with computed key: r[dst] = r[obj][r[key]]
GetPropertyConst
Get property with constant key: r[dst] = r[obj].name
SetProperty
Set property with computed key: r[obj][r[key]] = r[value]
SetPropertyConst
Set property with constant key: r[obj].name = r[value]
DeleteProperty
Delete property: r[dst] = delete r[obj][r[key]]
DeletePropertyConst
Delete property with constant key: r[dst] = delete r[obj].name
DefineProperty
Define property with descriptor (for object literals with getters/setters)
Call
Call function: r[dst] = r[callee].call(r[this], r[args_start..args_start+argc])
CallSpread
Call with spread arguments (some args may need spreading)
DirectEval
Direct eval call: r[dst] = eval(r[arg]) This is a special form that preserves the calling scope for direct eval. Unlike regular Call, direct eval has access to the lexical scope.
CallMethod
Call method: r[dst] = r[obj].name(args…)
Optimized form that preserves this correctly
TailCall
Tail call: reuse current frame instead of pushing new one Used for tail call optimization when a call is directly returned
TailCallSpread
Tail call with spread arguments
TailCallAwait
Async tail call: reuse current frame for return await fn() pattern
Used for tail call optimization in async functions
The dst register is used when falling back to non-optimized path (native functions)
TailCallAwaitSpread
Async tail call with spread arguments
Construct
Construct: r[dst] = new rcallee
ConstructSpread
Construct with spread arguments (args_start points to an args array)
Return
Return from function with value
ReturnUndefined
Return undefined from function
CreateClosure
Create closure from bytecode chunk: r[dst] = function from chunk[idx]
CreateArrow
Create arrow function (captures lexical this)
CreateGenerator
Create generator function
CreateAsync
Create async function
CreateAsyncGenerator
Create async generator function
Throw
Throw exception: throw r[value]
PushTry
Push try handler with catch at catch_target If finally_target is 0, there’s no finally block
PopTry
Pop try handler (normal completion)
FinallyEnd
End of finally block - complete any pending return/throw
GetException
Get caught exception value: r[dst] = caught_exception
PushIterTry
Push iterator try handler - like PushTry but calls iterator.return() on exception Used by for-of loops to implement iterator close protocol on throws
PopIterTry
Pop iterator try handler (normal exit, no iterator close needed)
Rethrow
Rethrow current exception (in catch block)
Await
Await: suspend execution, r[dst] = await r[promise]
Yield
Yield: suspend generator, r[dst] = yield r[value]
YieldStar
Yield*: delegate to iterable, r[dst] = yield* r[iterable]
PushScope
Push new lexical scope
PopScope
Pop lexical scope
GetIterator
Get iterator: r[dst] = r[obj]Symbol.iterator
GetKeysIterator
Get keys iterator for for-in loops: iterates over own enumerable string keys
GetAsyncIterator
Get async iterator: r[dst] = r[obj]Symbol.asyncIterator
IteratorNext
Iterator next: r[dst] = r[iterator].next()
IteratorDone
Check if iterator result is done: jump if r[result].done
IteratorValue
Get iterator result value: r[dst] = r[result].value
IteratorClose
Close iterator: call r[iterator].return() if it exists Used for early loop exit (break, return, throw) in for-of loops
CreateClass
Create class: r[dst] = class with r[constructor] and r[super_class]
DefineMethod
Define class method on prototype
DefineAccessor
Define getter/setter
DefineMethodComputed
Define class method with computed key
DefineAccessorComputed
Define getter/setter with computed key
SuperCall
Super call: r[dst] = super(args…)
SuperCallSpread
Super call with spread: r[dst] = super(…r[args_array]) args_array should contain an array of arguments
SuperGet
Super property get: r[dst] = super[r[key]]
SuperGetConst
Super property get with constant key: r[dst] = super.name
SuperSet
Super property set: super[r[key]] = r[value]
SuperSetConst
Super property set with constant key: super.name = r[value]
ApplyClassDecorator
Apply class decorator: r[class] = decorator(r[class], context) The class_name constant is optional (ConstantIndex::MAX means no name) The initializers register holds an array that addInitializer() pushes callbacks to
RunClassInitializers
Run class decorator initializers: calls each function in r[initializers] with r[class] as this
ApplyMethodDecorator
Apply method decorator: r[method] = decorator(r[method], context) context contains { kind: “method”|“getter”|“setter”, name, static, private }
ApplyParameterDecorator
Apply parameter decorator: decorator(r[target], context) context contains { kind: “parameter”, name, function, index, static } Parameter decorators are called for side effects only (like metadata registration)
Fields
ApplyFieldDecorator
Apply field decorator: r[dst] = decorator(undefined, context) Field decorators receive undefined as first arg, return an initializer transformer For auto-accessors, is_accessor=true and context.kind will be “accessor” instead of “field”
Fields
StoreFieldInitializer
Store field initializer on class: class.field_initializers[name] = r[initializer] This is used to store the result of field decorators on the class
GetFieldInitializer
Get field initializer from class: r[dst] = class.field_initializers[name] Used during instance construction to retrieve stored initializers
ApplyFieldInitializer
Apply field initializer: r[value] = rinitializer Transforms the initial value using the decorator’s returned initializer
DefineAutoAccessor
Define auto-accessor property: creates getter/setter and defines them on prototype r[target_dst] = { get, set } object for decorator use (or undefined if no decorators) The accessor is defined on the class prototype (or class itself if is_static)
StoreAutoAccessor
Store auto-accessor (decorated getter/setter) on class Takes the decorated { get, set } object and defines the accessor property
ApplyAutoAccessorDecorator
Apply auto-accessor decorator: r[target] = decorator(r[target], context) context contains { kind: “accessor”, name, static }
SpreadArray
Spread array into registers for function calls Copies elements from r[src] into r[dst..dst+actual_count] Returns actual count in a hidden register
CreateRestArray
Create rest array from remaining arguments
CreateObjectRest
Create object rest from source object, excluding specified keys
excluded_keys is a constant index pointing to a Vec
SpreadObject
Spread object properties: copy all enumerable own properties from r[src] to r[dst]
TemplateConcat
Concatenate template parts: r[dst] = r[start..start+count].join()
TaggedTemplate
Tagged template call
Fields
GetPrivateField
Get private field: r[dst] = r[obj].#name class_brand is a unique id per class definition (for brand checking) field_name is a constant index for the field name (including # prefix)
SetPrivateField
Set private field: r[obj].#name = r[value]
DefinePrivateField
Define private field on object: r[obj].#name = r[value] Called during instance creation to install private fields
DefinePrivateMethod
Define private method on class (stored in constructor for later installation) When constructing instances, these get copied to the instance’s private_fields
InstallPrivateMethod
Install stored private method on instance during construction Reads method from new.target’s private_methods and installs on this
SetFunctionName
Set function name if the value is an anonymous function This implements the SetFunctionName abstract operation from the spec. If r[func] is a function without a name, sets its name to the constant. If it already has a name or is not a function, this is a no-op.
Nop
No operation (used for alignment/patching)
Halt
Halt execution (end of program)
Debugger
Debugger statement
Pop
Pop value from stack (discard expression result)
Dup
Duplicate value: r[dst] = r[src] (same as Move but semantically different)
LoadThis
Load this value: r[dst] = this
LoadArguments
Load arguments object: r[dst] = arguments
LoadNewTarget
Load new.target: r[dst] = new.target
ExportBinding
Export a binding: exports[export_name] = { name: binding_name, value: r[value] }
Used for export const foo = ... and export { foo }
ExportNamespace
Export a namespace re-export: exports[name] = module_namespace
Used for export * as ns from "module"
ReExport
Re-export from another module: exports[export_name] = { from: source_module, key: source_key }
Used for export { foo } from "./bar"