Initial SSA impl + docs

This commit is contained in:
2026-09-02 13:16:05 +00:00
parent a8acb7706c
commit c7d44584d9
6 changed files with 1255 additions and 33 deletions
+626
View File
@@ -0,0 +1,626 @@
# quickjs-ng opcodes
Generated from `third_party/quickjs-ng` (v0.16.1). Read this beside a listing.
**#** is the opcode byte. **Size** counts that byte and its operands
together, so it is how far the next instruction is. **Stack** is pop → push,
excluding call arguments, which the operand counts instead. **Format** names
the operand encoding, described in the next table.
Two things to know about the numbering. Short opcodes such as `get_loc2` fold
an operand into the opcode byte, which is why several names can mean the same
operation at different indexes. And short opcodes share numbers with the
compiler's temporary opcodes, which never reach a file, so a decoder has to
shift the high range past them.
# Operand formats
| Format | Bytes after the opcode |
|---|---|
| `none` | No operand. |
| `none_int` | No operand; the integer is folded into the opcode, as in `push_3`. |
| `none_loc` | No operand; the local index is folded into the opcode, as in `get_loc2`. |
| `none_arg` | No operand; the argument index is folded into the opcode. |
| `none_var_ref` | No operand; the closure variable index is folded into the opcode. |
| `u8` | One unsigned byte. |
| `i8` | One signed byte. |
| `loc8` | One byte, a local index. |
| `const8` | One byte, a constant pool index. |
| `label8` | One signed byte, a jump offset from its own position. |
| `u16` | Two bytes, unsigned. |
| `i16` | Two bytes, signed. |
| `label16` | Two signed bytes, a jump offset from its own position. |
| `npop` | Two bytes, an argument count. The arguments are on the stack and are not counted in the stack effect. |
| `npopx` | No operand; the argument count is folded into the opcode, as in `call2`. |
| `npop_u16` | Two bytes of argument count, then two more bytes. |
| `loc` | Two bytes, a local index. |
| `arg` | Two bytes, an argument index. |
| `var_ref` | Two bytes, a closure variable index. |
| `u32` | Four bytes, unsigned. |
| `u32x2` | Two four-byte values. |
| `i32` | Four bytes, signed. |
| `const` | Four bytes, a constant pool index. |
| `label` | Four signed bytes, a jump offset from its own position. |
| `atom` | Four bytes, an atom reference. Not a raw atom number: it is an index in the file's atom space. |
| `atom_u8` | An atom reference then one byte. |
| `atom_u16` | An atom reference then two bytes. |
| `atom_label_u8` | An atom reference, a four-byte jump offset, then one byte. |
| `atom_label_u16` | An atom reference, a four-byte jump offset, then two bytes. |
| `label_u16` | A four-byte jump offset then two bytes. |
# Common opcodes
## Function prologue
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `push_this` | 8 | 1 | 0 → 1 | `none` | Push the `this` binding. Only emitted at the start of a function. |
| `special_object` | 12 | 2 | 0 → 1 | `u8` | Push one of the objects a prologue may need, selected by the operand: the arguments object, a mapped arguments object, `this.__proto__`, `new.target`, or the home object. |
| `rest` | 13 | 3 | 0 → 1 | `u16` | Build the rest parameter array from the arguments at or after the given index. |
| `fclosure` | 3 | 5 | 0 → 1 | `const` | Take the function template at the given constant pool index and make a closure of it, capturing the current frame's variables. |
| `fclosure8` | 197 | 2 | 0 → 1 | `const8` | `fclosure` with a one-byte pool index. |
| `init_ctor` | 44 | 1 | 0 → 1 | `none` | Initialise a derived constructor's `this` slot. |
## Constants
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `push_i32` | 1 | 5 | 0 → 1 | `i32` | Push a 32-bit signed integer given inline. |
| `push_i8` | 194 | 2 | 0 → 1 | `i8` | Push a small signed integer, one byte inline. |
| `push_i16` | 195 | 3 | 0 → 1 | `i16` | Push a signed integer, two bytes inline. |
| `push_const` | 2 | 5 | 0 → 1 | `const` | Push the constant pool entry at the given index. The pool holds nested functions, template objects, and any literal too large to inline. |
| `push_const8` | 196 | 2 | 0 → 1 | `const8` | `push_const` with a one-byte pool index. |
| `push_atom_value` | 4 | 5 | 0 → 1 | `atom` | Push an interned string, named by an atom rather than stored inline. |
| `push_empty_string` | 198 | 1 | 0 → 1 | `none` | Push `""`. |
| `push_bigint_i32` | 177 | 5 | 0 → 1 | `i32` | Push a BigInt small enough to fit in 32 bits. |
| `undefined` | 6 | 1 | 0 → 1 | `none` | Push `undefined`. |
| `null` | 7 | 1 | 0 → 1 | `none` | Push `null`. |
| `push_true` | 10 | 1 | 0 → 1 | `none` | Push `true`. |
| `push_false` | 9 | 1 | 0 → 1 | `none` | Push `false`. |
| `push_minus1` | 185 | 1 | 0 → 1 | `none_int` | Push the integer -1. One of the folded push opcodes, where the value is part of the opcode. |
| `push_0` | 186 | 1 | 0 → 1 | `none_int` | Push the integer 0. `push_0` through `push_7` fold the value into the opcode byte. |
| `object` | 11 | 1 | 0 → 1 | `none` | Push a new empty object, as `{}` does. |
| `regexp` | 52 | 1 | 2 → 1 | `none` | Pop a pattern and its compiled libregexp bytecode, push a new RegExp object. |
## Locals and arguments
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `get_loc` | 87 | 3 | 0 → 1 | `loc` | Push local variable N. |
| `put_loc` | 88 | 3 | 1 → 0 | `loc` | Pop and store into local variable N. |
| `set_loc` | 89 | 3 | 1 → 1 | `loc` | Store into local variable N, leaving the value on the stack. This is what an assignment used as an expression compiles to. |
| `get_loc8` | 199 | 2 | 0 → 1 | `loc8` | `get_loc` with a one-byte index. |
| `get_loc0` | 203 | 1 | 0 → 1 | `none_loc` | Push local 0. `get_loc0` through `get_loc3` fold the index into the opcode. |
| `get_loc0_loc1` | 202 | 1 | 0 → 2 | `none_loc` | Push local 0 then local 1, in one instruction. |
| `get_arg` | 90 | 3 | 0 → 1 | `arg` | Push argument N. |
| `put_arg` | 91 | 3 | 1 → 0 | `arg` | Pop and store into argument N. |
| `set_arg` | 92 | 3 | 1 → 1 | `arg` | Store into argument N, leaving the value on the stack. |
| `get_arg0` | 215 | 1 | 0 → 1 | `none_arg` | Push argument 0. `get_arg0` through `get_arg3` fold the index into the opcode. |
| `get_var_ref` | 93 | 3 | 0 → 1 | `var_ref` | Push closure variable N, that is, a variable captured from an enclosing function. |
| `put_var_ref` | 94 | 3 | 1 → 0 | `var_ref` | Pop and store into closure variable N. |
| `set_var_ref` | 95 | 3 | 1 → 1 | `var_ref` | Store into closure variable N, leaving the value on the stack. |
| `get_var_ref0` | 227 | 1 | 0 → 1 | `none_var_ref` | Push closure variable 0. Indexes 0 to 3 are folded into the opcode. |
| `set_loc_uninitialized` | 96 | 3 | 0 → 0 | `loc` | Mark a local as being in its temporal dead zone. Reading it before initialisation must throw, and this is what sets that state. |
| `get_loc_check` | 97 | 3 | 0 → 1 | `loc` | Push a `let` or `const` local, throwing a ReferenceError if it is still in its temporal dead zone. |
| `put_loc_check` | 98 | 3 | 1 → 0 | `loc` | Store into a `let` local, throwing if it is still in its temporal dead zone. |
| `put_loc_check_init` | 99 | 3 | 1 → 0 | `loc` | Perform the initialising store to a `let` or `const` local, which is what leaves the dead zone. |
| `get_var_ref_check` | 100 | 3 | 0 → 1 | `var_ref` | Push a captured `let` or `const`, throwing if it is still in its temporal dead zone. |
| `put_var_ref_check` | 101 | 3 | 1 → 0 | `var_ref` | Store into a captured `let`, throwing if it is still in its temporal dead zone. |
| `put_var_ref_check_init` | 102 | 3 | 1 → 0 | `var_ref` | Perform the initialising store to a captured `let` or `const`, which is what leaves the dead zone. |
| `close_loc` | 103 | 3 | 0 → 0 | `loc` | Close over a local, so that a closure keeps it alive after the frame goes away. |
| `inc_loc` | 146 | 2 | 0 → 0 | `loc8` | Increment a local in place, without moving it through the stack. |
| `dec_loc` | 145 | 2 | 0 → 0 | `loc8` | Decrement a local in place. |
| `add_loc` | 147 | 2 | 1 → 0 | `loc8` | Add the top of the stack into a local in place. |
## Variables by name
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `get_var` | 56 | 5 | 0 → 1 | `atom` | Push a variable looked up by name at run time, throwing a ReferenceError if it does not exist. |
| `get_var_undef` | 55 | 5 | 0 → 1 | `atom` | Like `get_var`, but push `undefined` instead of throwing when the variable does not exist. This is what `typeof x` on an unknown name uses. |
| `put_var` | 57 | 5 | 1 → 0 | `atom` | Store into a variable looked up by name. |
| `put_var_init` | 58 | 5 | 1 → 0 | `atom` | Perform the initialising store to a global lexical variable. |
| `define_var` | 61 | 6 | 0 → 0 | `atom_u8` | Define a `var` or function binding on the global object. |
| `check_define_var` | 62 | 6 | 0 → 0 | `atom_u8` | Check that defining this global name is allowed before `define_var` does it. |
| `define_func` | 63 | 6 | 1 → 0 | `atom_u8` | Define a global function binding from the closure on the stack. |
| `delete_var` | 152 | 5 | 0 → 1 | `atom` | `delete` applied to a bare name. |
## The `with` statement
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `with_get_var` | 115 | 10 | 1 → 0 | `atom_label_u8` | Read the name from the `with` object, or jump to the label if the object does not have it. |
| `with_put_var` | 116 | 10 | 2 → 1 | `atom_label_u8` | Store into the name on the `with` object, or jump to the label if the object does not have it. |
| `with_delete_var` | 117 | 10 | 1 → 0 | `atom_label_u8` | `delete` the name on the `with` object, or jump to the label if the object does not have it. |
| `with_make_ref` | 118 | 10 | 1 → 0 | `atom_label_u8` | Push the object and the property name as a reference pair, for an assignment target inside `with`. |
| `with_get_ref` | 119 | 10 | 1 → 0 | `atom_label_u8` | Push the object and the named method together, so a call inside `with` gets its receiver. |
| `with_get_ref_undef` | 120 | 10 | 1 → 0 | `atom_label_u8` | `with_get_ref`, but push `undefined` as the receiver instead of the object. |
## Properties
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `get_field` | 64 | 5 | 1 → 1 | `atom` | Pop an object, push `obj.name`. |
| `get_field2` | 65 | 5 | 1 → 2 | `atom` | Push `obj.name` but keep the object underneath it, so a following call has its receiver. This is the `a.b()` shape. |
| `put_field` | 66 | 5 | 2 → 0 | `atom` | Pop a value and an object, store `obj.name = value`. |
| `get_array_el` | 70 | 1 | 2 → 1 | `none` | Pop a key and an object, push `obj[key]`. |
| `get_array_el2` | 71 | 1 | 2 → 2 | `none` | Push `obj[key]` while keeping the object, the computed-key form of `get_field2`. |
| `put_array_el` | 72 | 1 | 3 → 0 | `none` | Pop a value, a key, and an object, store `obj[key] = value`. |
| `define_field` | 75 | 5 | 2 → 1 | `atom` | Define a named property on an object literal being built. |
| `define_array_el` | 80 | 1 | 3 → 2 | `none` | Define an indexed property on an array literal being built. |
| `append` | 81 | 1 | 3 → 2 | `none` | Append the elements of a spread operand to an array being built, updating its length. |
| `copy_data_properties` | 82 | 2 | 3 → 3 | `u8` | Copy the own enumerable properties of one object to another, for object spread and rest. |
| `delete` | 151 | 1 | 2 → 1 | `none` | `delete obj[key]`, with the key on the stack. |
| `get_length` | 239 | 1 | 1 → 1 | `none` | Push `obj.length`. Common enough to get its own opcode. |
| `set_name` | 76 | 5 | 1 → 1 | `atom` | Give an anonymous function the name it is being assigned to. |
| `set_name_computed` | 77 | 1 | 2 → 2 | `none` | Give an anonymous function a name computed at run time. |
| `set_proto` | 78 | 1 | 2 → 1 | `none` | Set an object's prototype, from `__proto__` in an object literal. |
| `set_home_object` | 79 | 1 | 2 → 2 | `none` | Record a method's home object, which is what `super` resolves against. |
| `to_object` | 112 | 1 | 1 → 1 | `none` | Coerce the top of the stack to an object. |
| `to_propkey` | 113 | 1 | 1 → 1 | `none` | Coerce the top of the stack to a valid property key. |
| `check_object` | 111 | 1 | 1 → 1 | `none` | Throw if the top of the stack is not an object. |
## Private fields
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `private_symbol` | 5 | 5 | 0 → 1 | `atom` | Push the unique symbol that backs a `#name` private field. |
| `get_private_field` | 67 | 1 | 2 → 1 | `none` | Read a `#name` private field, throwing if the object does not carry it. |
| `put_private_field` | 68 | 1 | 3 → 0 | `none` | Write a `#name` private field. |
| `define_private_field` | 69 | 1 | 3 → 1 | `none` | Install a `#name` private field on a new instance. |
| `private_in` | 176 | 1 | 2 → 1 | `none` | The `#name in obj` test, which reports whether the object carries the field. |
| `check_brand` | 45 | 1 | 2 → 2 | `none` | Check that the receiver really is an instance of the class that owns this private method. |
| `add_brand` | 46 | 1 | 2 → 0 | `none` | Mark a new instance as belonging to a class that has private methods. |
## Classes
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `define_class` | 85 | 6 | 2 → 2 | `atom_u8` | Build a class: pop the parent and the constructor, push the constructor and its prototype. |
| `define_class_computed` | 86 | 6 | 3 → 3 | `atom_u8` | `define_class` for a class whose name is computed at run time. |
| `define_method` | 83 | 6 | 2 → 1 | `atom_u8` | Define a method on a prototype or object literal. |
| `define_method_computed` | 84 | 2 | 3 → 1 | `u8` | `define_method` with a key computed at run time. |
| `get_super` | 53 | 1 | 1 → 1 | `none` | Push the prototype of the home object, which is what `super` refers to. |
| `get_super_value` | 73 | 1 | 3 → 1 | `none` | Read `super.name`, which needs the receiver as well as the home object. |
| `put_super_value` | 74 | 1 | 4 → 0 | `none` | Write `super.name`. |
| `check_ctor` | 43 | 1 | 0 → 0 | `none` | Throw if a class constructor was called without `new`. |
| `check_ctor_return` | 42 | 1 | 1 → 2 | `none` | Apply the rule that a constructor returning a non-object yields `this` instead. |
## Calls
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `call` | 34 | 3 | 1 → 1 | `npop` | Call a function with N arguments. The argument count is the operand, and the arguments are not counted in the stack effect. |
| `call0` | 244 | 1 | 1 → 1 | `npopx` | Call with no arguments. `call0` through `call3` fold the count into the opcode. |
| `call_method` | 36 | 3 | 2 → 1 | `npop` | Call a method, which takes a receiver as well as the function. |
| `call_constructor` | 33 | 3 | 2 → 1 | `npop` | Call with `new`, taking the function and `new.target`. |
| `tail_call` | 35 | 3 | 1 → 0 | `npop` | A call in tail position, which reuses the frame instead of growing the stack. |
| `tail_call_method` | 37 | 3 | 2 → 0 | `npop` | A method call in tail position. |
| `apply` | 39 | 3 | 3 → 1 | `u16` | Call with an array of arguments, as `Function.prototype.apply` does. |
| `eval` | 50 | 5 | 1 → 1 | `npop_u16` | A direct `eval` call, which can see the enclosing scope. |
| `apply_eval` | 51 | 3 | 2 → 1 | `u16` | A direct `eval` call whose arguments come from an array. |
| `array_from` | 38 | 3 | 0 → 1 | `npop` | Build an array from N values on the stack. |
| `return` | 40 | 1 | 1 → 0 | `none` | Return the top of the stack. |
| `return_undef` | 41 | 1 | 0 → 0 | `none` | Return `undefined`, which is what a function ending without `return` does. |
| `return_async` | 47 | 1 | 1 → 0 | `none` | Return from an async function, resolving its promise. |
## Control flow
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `goto` | 106 | 5 | 0 → 0 | `label` | Jump. The operand is a signed offset from its own position, which the listing shows resolved to a label. |
| `goto8` | 242 | 2 | 0 → 0 | `label8` | `goto` with a one-byte offset. |
| `goto16` | 243 | 3 | 0 → 0 | `label16` | `goto` with a two-byte offset. |
| `if_false` | 104 | 5 | 1 → 0 | `label` | Pop a value and jump if it is falsy. |
| `if_true` | 105 | 5 | 1 → 0 | `label` | Pop a value and jump if it is truthy. |
| `if_false8` | 240 | 2 | 1 → 0 | `label8` | `if_false` with a one-byte offset. |
| `if_true8` | 241 | 2 | 1 → 0 | `label8` | `if_true` with a one-byte offset. |
| `catch` | 107 | 5 | 0 → 1 | `label` | Push a catch context pointing at the handler, arming the `try` block that follows. |
| `gosub` | 108 | 5 | 0 → 0 | `label` | Enter a `finally` block, remembering where to resume. |
| `ret` | 109 | 1 | 1 → 0 | `none` | Leave a `finally` block and resume where `gosub` came from. |
| `nip_catch` | 110 | 1 | 2 → 1 | `none` | Drop a catch context from under the value on top, leaving the `try` block. |
| `throw` | 48 | 1 | 1 → 0 | `none` | Throw the value on top of the stack. |
| `throw_error` | 49 | 6 | 0 → 0 | `atom_u8` | Throw a built-in error, named by the operand. Used for the errors the compiler knows about in advance. |
| `nop` | 184 | 1 | 0 → 0 | `none` | Do nothing. Left behind where an optimisation removed an instruction. |
| `invalid` | 0 | 1 | 0 → 0 | `none` | Opcode 0, which upstream marks *never emitted*. Seeing it in a listing means the decode lost its place, not that the compiler produced it. |
## Iteration
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `for_in_start` | 125 | 1 | 1 → 1 | `none` | Begin a `for...in` loop over the object on the stack. |
| `for_in_next` | 128 | 1 | 1 → 3 | `none` | Take the next key of a `for...in` loop, pushing the key and whether the loop is done. |
| `for_of_start` | 126 | 1 | 1 → 3 | `none` | Begin a `for...of` loop by fetching the iterator of the object on the stack. |
| `for_of_next` | 129 | 2 | 3 → 5 | `u8` | Take the next value of a `for...of` loop. |
| `for_await_of_start` | 127 | 1 | 1 → 3 | `none` | Begin a `for await...of` loop, fetching the async iterator. |
| `iterator_next` | 132 | 1 | 4 → 4 | `none` | Call the iterator's `next` method. |
| `iterator_call` | 133 | 2 | 4 → 5 | `u8` | Call an optional iterator method such as `return` or `throw`, if the iterator has it. |
| `iterator_get_value_done` | 130 | 1 | 1 → 2 | `none` | Split an iterator result object into its `value` and `done` fields. |
| `iterator_close` | 131 | 1 | 3 → 0 | `none` | Close an iterator early, which is what a `break` out of `for...of` must do. |
## Generators and async
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `initial_yield` | 134 | 1 | 0 → 0 | `none` | Suspend immediately on entry, so a generator body does not run until the first `next` call. |
| `yield` | 135 | 1 | 1 → 2 | `none` | Suspend and hand a value to the caller. |
| `yield_star` | 136 | 1 | 1 → 2 | `none` | `yield*`, delegating to another iterator. |
| `async_yield_star` | 137 | 1 | 1 → 2 | `none` | `yield*` inside an async generator. |
| `await` | 138 | 1 | 1 → 1 | `none` | Suspend until a promise settles. |
| `import` | 54 | 1 | 2 → 1 | `none` | A dynamic `import()`, which yields a promise. |
## Resource management
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `using_check` | 183 | 2 | 1 → 2 | `u8` | Check that a `using` declaration's value has the disposal method it needs. |
| `using_dispose_init` | 178 | 1 | 0 → 1 | `none` | Start the disposal list for a scope holding `using` declarations. |
| `using_dispose` | 179 | 3 | 1 → 1 | `loc` | Register a value for disposal when the scope ends. |
| `using_dispose_async` | 180 | 3 | 0 → 1 | `loc` | Register a value for `await using` disposal. |
| `using_dispose_merge` | 181 | 1 | 2 → 1 | `none` | Merge an inner scope's disposal list into the enclosing one. |
| `using_dispose_end` | 182 | 1 | 1 → 0 | `none` | Run the disposal list as the scope ends. |
## Operators
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `add` | 156 | 1 | 2 → 1 | `none` | `a + b`, which is either numeric addition or string concatenation. |
| `sub` | 157 | 1 | 2 → 1 | `none` | `a - b`. |
| `mul` | 153 | 1 | 2 → 1 | `none` | `a * b`. |
| `div` | 154 | 1 | 2 → 1 | `none` | `a / b`. |
| `mod` | 155 | 1 | 2 → 1 | `none` | `a % b`. |
| `pow` | 164 | 1 | 2 → 1 | `none` | `a ** b`. |
| `neg` | 139 | 1 | 1 → 1 | `none` | Unary `-a`. |
| `plus` | 140 | 1 | 1 → 1 | `none` | Unary `+a`, which coerces to a number. |
| `inc` | 142 | 1 | 1 → 1 | `none` | Add one, for the prefix `++a`. |
| `dec` | 141 | 1 | 1 → 1 | `none` | Subtract one, for the prefix `--a`. |
| `post_inc` | 144 | 1 | 1 → 2 | `none` | `a++`: push the old value as well, since that is what the expression evaluates to. |
| `post_dec` | 143 | 1 | 1 → 2 | `none` | `a--`, keeping the old value. |
| `not` | 148 | 1 | 1 → 1 | `none` | Bitwise `~a`. |
| `lnot` | 149 | 1 | 1 → 1 | `none` | Logical `!a`. |
| `typeof` | 150 | 1 | 1 → 1 | `none` | `typeof a`. |
| `shl` | 158 | 1 | 2 → 1 | `none` | `a << b`. |
| `sar` | 159 | 1 | 2 → 1 | `none` | `a >> b`, the sign-propagating shift. |
| `shr` | 160 | 1 | 2 → 1 | `none` | `a >>> b`, the zero-filling shift. |
| `and` | 161 | 1 | 2 → 1 | `none` | Bitwise `a & b`. |
| `or` | 163 | 1 | 2 → 1 | `none` | Bitwise `a \| b`. |
| `xor` | 162 | 1 | 2 → 1 | `none` | Bitwise `a ^ b`. |
| `lt` | 165 | 1 | 2 → 1 | `none` | `a < b`. |
| `lte` | 166 | 1 | 2 → 1 | `none` | `a <= b`. |
| `gt` | 167 | 1 | 2 → 1 | `none` | `a > b`. |
| `gte` | 168 | 1 | 2 → 1 | `none` | `a >= b`. |
| `eq` | 171 | 1 | 2 → 1 | `none` | `a == b`, with coercion. |
| `neq` | 172 | 1 | 2 → 1 | `none` | `a != b`. |
| `strict_eq` | 173 | 1 | 2 → 1 | `none` | `a === b`. |
| `strict_neq` | 174 | 1 | 2 → 1 | `none` | `a !== b`. |
| `instanceof` | 169 | 1 | 2 → 1 | `none` | `a instanceof b`. |
| `in` | 170 | 1 | 2 → 1 | `none` | `a in b`. |
| `is_undefined` | 248 | 1 | 1 → 1 | `none` | Test for `undefined` without a comparison. |
| `is_null` | 249 | 1 | 1 → 1 | `none` | Test for `null` without a comparison. |
| `is_undefined_or_null` | 175 | 1 | 1 → 1 | `none` | The `== null` test, which both `?.` and `??` need. |
| `typeof_is_undefined` | 250 | 1 | 1 → 1 | `none` | The whole of `typeof a === "undefined"` in one instruction. |
| `typeof_is_function` | 251 | 1 | 1 → 1 | `none` | The whole of `typeof a === "function"` in one instruction. |
## Stack
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `drop` | 14 | 1 | 1 → 0 | `none` | Discard the top of the stack. |
| `dup` | 17 | 1 | 1 → 2 | `none` | Duplicate the top of the stack. |
| `dup1` | 18 | 1 | 2 → 3 | `none` | Duplicate the second item, leaving `a b` as `a a b`. |
| `dup2` | 19 | 1 | 2 → 4 | `none` | Duplicate the top pair. |
| `dup3` | 20 | 1 | 3 → 6 | `none` | Duplicate the top three. |
| `nip` | 15 | 1 | 2 → 1 | `none` | Drop the second item, leaving `a b` as `b`. |
| `nip1` | 16 | 1 | 3 → 2 | `none` | Drop the third item. |
| `swap` | 27 | 1 | 2 → 2 | `none` | Exchange the top two. |
| `swap2` | 28 | 1 | 4 → 4 | `none` | Exchange the top two pairs. |
| `insert2` | 21 | 1 | 2 → 3 | `none` | Copy the top item below the one beneath it, so a receiver survives a call. |
| `insert3` | 22 | 1 | 3 → 4 | `none` | Copy the top item down past two others. |
| `insert4` | 23 | 1 | 4 → 5 | `none` | Copy the top item down past three others. |
| `perm3` | 24 | 1 | 3 → 3 | `none` | Rotate the top three so the deepest comes second. |
| `perm4` | 25 | 1 | 4 → 4 | `none` | Rotate the top four. |
| `perm5` | 26 | 1 | 5 → 5 | `none` | Rotate the top five. |
| `rot3l` | 29 | 1 | 3 → 3 | `none` | Rotate the top three left. |
| `rot3r` | 30 | 1 | 3 → 3 | `none` | Rotate the top three right. |
| `rot4l` | 31 | 1 | 4 → 4 | `none` | Rotate the top four left. |
| `rot5l` | 32 | 1 | 5 → 5 | `none` | Rotate the top five left. |
## References
| Opcode | # | Size | Stack | Format | Meaning |
|---|---|---|---|---|---|
| `make_loc_ref` | 121 | 7 | 0 → 2 | `atom_u16` | Build a reference to a local, so it can be written through later. |
| `make_arg_ref` | 122 | 7 | 0 → 2 | `atom_u16` | Build a reference to an argument. |
| `make_var_ref` | 124 | 5 | 0 → 2 | `atom` | Build a reference to a variable named by an atom. |
| `make_var_ref_ref` | 123 | 7 | 0 → 2 | `atom_u16` | Build a reference to a captured variable. |
| `get_ref_value` | 59 | 1 | 2 → 3 | `none` | Read through a reference. |
| `put_ref_value` | 60 | 1 | 3 → 0 | `none` | Write through a reference. |
# All opcodes
Every opcode quickjs-ng defines, in numeric order. The comment column is upstream's own, where it has one.
| # | Name | Size | Pop | Push | Format | Notes |
|---|---|---|---|---|---|---|
| 0 | `invalid` | 1 | 0 | 0 | `none` | explained above |
| 1 | `push_i32` | 5 | 0 | 1 | `i32` | explained above |
| 2 | `push_const` | 5 | 0 | 1 | `const` | explained above |
| 3 | `fclosure` | 5 | 0 | 1 | `const` | explained above |
| 4 | `push_atom_value` | 5 | 0 | 1 | `atom` | explained above |
| 5 | `private_symbol` | 5 | 0 | 1 | `atom` | explained above |
| 6 | `undefined` | 1 | 0 | 1 | `none` | explained above |
| 7 | `null` | 1 | 0 | 1 | `none` | explained above |
| 8 | `push_this` | 1 | 0 | 1 | `none` | explained above |
| 9 | `push_false` | 1 | 0 | 1 | `none` | explained above |
| 10 | `push_true` | 1 | 0 | 1 | `none` | explained above |
| 11 | `object` | 1 | 0 | 1 | `none` | explained above |
| 12 | `special_object` | 2 | 0 | 1 | `u8` | explained above |
| 13 | `rest` | 3 | 0 | 1 | `u16` | explained above |
| 14 | `drop` | 1 | 1 | 0 | `none` | explained above |
| 15 | `nip` | 1 | 2 | 1 | `none` | explained above |
| 16 | `nip1` | 1 | 3 | 2 | `none` | explained above |
| 17 | `dup` | 1 | 1 | 2 | `none` | explained above |
| 18 | `dup1` | 1 | 2 | 3 | `none` | explained above |
| 19 | `dup2` | 1 | 2 | 4 | `none` | explained above |
| 20 | `dup3` | 1 | 3 | 6 | `none` | explained above |
| 21 | `insert2` | 1 | 2 | 3 | `none` | explained above |
| 22 | `insert3` | 1 | 3 | 4 | `none` | explained above |
| 23 | `insert4` | 1 | 4 | 5 | `none` | explained above |
| 24 | `perm3` | 1 | 3 | 3 | `none` | explained above |
| 25 | `perm4` | 1 | 4 | 4 | `none` | explained above |
| 26 | `perm5` | 1 | 5 | 5 | `none` | explained above |
| 27 | `swap` | 1 | 2 | 2 | `none` | explained above |
| 28 | `swap2` | 1 | 4 | 4 | `none` | explained above |
| 29 | `rot3l` | 1 | 3 | 3 | `none` | explained above |
| 30 | `rot3r` | 1 | 3 | 3 | `none` | explained above |
| 31 | `rot4l` | 1 | 4 | 4 | `none` | explained above |
| 32 | `rot5l` | 1 | 5 | 5 | `none` | explained above |
| 33 | `call_constructor` | 3 | 2 | 1 | `npop` | explained above |
| 34 | `call` | 3 | 1 | 1 | `npop` | explained above |
| 35 | `tail_call` | 3 | 1 | 0 | `npop` | explained above |
| 36 | `call_method` | 3 | 2 | 1 | `npop` | explained above |
| 37 | `tail_call_method` | 3 | 2 | 0 | `npop` | explained above |
| 38 | `array_from` | 3 | 0 | 1 | `npop` | explained above |
| 39 | `apply` | 3 | 3 | 1 | `u16` | explained above |
| 40 | `return` | 1 | 1 | 0 | `none` | explained above |
| 41 | `return_undef` | 1 | 0 | 0 | `none` | explained above |
| 42 | `check_ctor_return` | 1 | 1 | 2 | `none` | explained above |
| 43 | `check_ctor` | 1 | 0 | 0 | `none` | explained above |
| 44 | `init_ctor` | 1 | 0 | 1 | `none` | explained above |
| 45 | `check_brand` | 1 | 2 | 2 | `none` | explained above |
| 46 | `add_brand` | 1 | 2 | 0 | `none` | explained above |
| 47 | `return_async` | 1 | 1 | 0 | `none` | explained above |
| 48 | `throw` | 1 | 1 | 0 | `none` | explained above |
| 49 | `throw_error` | 6 | 0 | 0 | `atom_u8` | explained above |
| 50 | `eval` | 5 | 1 | 1 | `npop_u16` | explained above |
| 51 | `apply_eval` | 3 | 2 | 1 | `u16` | explained above |
| 52 | `regexp` | 1 | 2 | 1 | `none` | explained above |
| 53 | `get_super` | 1 | 1 | 1 | `none` | explained above |
| 54 | `import` | 1 | 2 | 1 | `none` | explained above |
| 55 | `get_var_undef` | 5 | 0 | 1 | `atom` | explained above |
| 56 | `get_var` | 5 | 0 | 1 | `atom` | explained above |
| 57 | `put_var` | 5 | 1 | 0 | `atom` | explained above |
| 58 | `put_var_init` | 5 | 1 | 0 | `atom` | explained above |
| 59 | `get_ref_value` | 1 | 2 | 3 | `none` | explained above |
| 60 | `put_ref_value` | 1 | 3 | 0 | `none` | explained above |
| 61 | `define_var` | 6 | 0 | 0 | `atom_u8` | explained above |
| 62 | `check_define_var` | 6 | 0 | 0 | `atom_u8` | explained above |
| 63 | `define_func` | 6 | 1 | 0 | `atom_u8` | explained above |
| 64 | `get_field` | 5 | 1 | 1 | `atom` | explained above |
| 65 | `get_field2` | 5 | 1 | 2 | `atom` | explained above |
| 66 | `put_field` | 5 | 2 | 0 | `atom` | explained above |
| 67 | `get_private_field` | 1 | 2 | 1 | `none` | explained above |
| 68 | `put_private_field` | 1 | 3 | 0 | `none` | explained above |
| 69 | `define_private_field` | 1 | 3 | 1 | `none` | explained above |
| 70 | `get_array_el` | 1 | 2 | 1 | `none` | explained above |
| 71 | `get_array_el2` | 1 | 2 | 2 | `none` | explained above |
| 72 | `put_array_el` | 1 | 3 | 0 | `none` | explained above |
| 73 | `get_super_value` | 1 | 3 | 1 | `none` | explained above |
| 74 | `put_super_value` | 1 | 4 | 0 | `none` | explained above |
| 75 | `define_field` | 5 | 2 | 1 | `atom` | explained above |
| 76 | `set_name` | 5 | 1 | 1 | `atom` | explained above |
| 77 | `set_name_computed` | 1 | 2 | 2 | `none` | explained above |
| 78 | `set_proto` | 1 | 2 | 1 | `none` | explained above |
| 79 | `set_home_object` | 1 | 2 | 2 | `none` | explained above |
| 80 | `define_array_el` | 1 | 3 | 2 | `none` | explained above |
| 81 | `append` | 1 | 3 | 2 | `none` | explained above |
| 82 | `copy_data_properties` | 2 | 3 | 3 | `u8` | explained above |
| 83 | `define_method` | 6 | 2 | 1 | `atom_u8` | explained above |
| 84 | `define_method_computed` | 2 | 3 | 1 | `u8` | explained above |
| 85 | `define_class` | 6 | 2 | 2 | `atom_u8` | explained above |
| 86 | `define_class_computed` | 6 | 3 | 3 | `atom_u8` | explained above |
| 87 | `get_loc` | 3 | 0 | 1 | `loc` | explained above |
| 88 | `put_loc` | 3 | 1 | 0 | `loc` | explained above |
| 89 | `set_loc` | 3 | 1 | 1 | `loc` | explained above |
| 90 | `get_arg` | 3 | 0 | 1 | `arg` | explained above |
| 91 | `put_arg` | 3 | 1 | 0 | `arg` | explained above |
| 92 | `set_arg` | 3 | 1 | 1 | `arg` | explained above |
| 93 | `get_var_ref` | 3 | 0 | 1 | `var_ref` | explained above |
| 94 | `put_var_ref` | 3 | 1 | 0 | `var_ref` | explained above |
| 95 | `set_var_ref` | 3 | 1 | 1 | `var_ref` | explained above |
| 96 | `set_loc_uninitialized` | 3 | 0 | 0 | `loc` | explained above |
| 97 | `get_loc_check` | 3 | 0 | 1 | `loc` | explained above |
| 98 | `put_loc_check` | 3 | 1 | 0 | `loc` | explained above |
| 99 | `put_loc_check_init` | 3 | 1 | 0 | `loc` | explained above |
| 100 | `get_var_ref_check` | 3 | 0 | 1 | `var_ref` | explained above |
| 101 | `put_var_ref_check` | 3 | 1 | 0 | `var_ref` | explained above |
| 102 | `put_var_ref_check_init` | 3 | 1 | 0 | `var_ref` | explained above |
| 103 | `close_loc` | 3 | 0 | 0 | `loc` | explained above |
| 104 | `if_false` | 5 | 1 | 0 | `label` | explained above |
| 105 | `if_true` | 5 | 1 | 0 | `label` | explained above |
| 106 | `goto` | 5 | 0 | 0 | `label` | explained above |
| 107 | `catch` | 5 | 0 | 1 | `label` | explained above |
| 108 | `gosub` | 5 | 0 | 0 | `label` | explained above |
| 109 | `ret` | 1 | 1 | 0 | `none` | explained above |
| 110 | `nip_catch` | 1 | 2 | 1 | `none` | explained above |
| 111 | `check_object` | 1 | 1 | 1 | `none` | explained above |
| 112 | `to_object` | 1 | 1 | 1 | `none` | explained above |
| 113 | `to_propkey` | 1 | 1 | 1 | `none` | explained above |
| 114 | `to_propkey2` | 1 | 2 | 2 | `none` | |
| 115 | `with_get_var` | 10 | 1 | 0 | `atom_label_u8` | explained above |
| 116 | `with_put_var` | 10 | 2 | 1 | `atom_label_u8` | explained above |
| 117 | `with_delete_var` | 10 | 1 | 0 | `atom_label_u8` | explained above |
| 118 | `with_make_ref` | 10 | 1 | 0 | `atom_label_u8` | explained above |
| 119 | `with_get_ref` | 10 | 1 | 0 | `atom_label_u8` | explained above |
| 120 | `with_get_ref_undef` | 10 | 1 | 0 | `atom_label_u8` | explained above |
| 121 | `make_loc_ref` | 7 | 0 | 2 | `atom_u16` | explained above |
| 122 | `make_arg_ref` | 7 | 0 | 2 | `atom_u16` | explained above |
| 123 | `make_var_ref_ref` | 7 | 0 | 2 | `atom_u16` | explained above |
| 124 | `make_var_ref` | 5 | 0 | 2 | `atom` | explained above |
| 125 | `for_in_start` | 1 | 1 | 1 | `none` | explained above |
| 126 | `for_of_start` | 1 | 1 | 3 | `none` | explained above |
| 127 | `for_await_of_start` | 1 | 1 | 3 | `none` | explained above |
| 128 | `for_in_next` | 1 | 1 | 3 | `none` | explained above |
| 129 | `for_of_next` | 2 | 3 | 5 | `u8` | explained above |
| 130 | `iterator_get_value_done` | 1 | 1 | 2 | `none` | explained above |
| 131 | `iterator_close` | 1 | 3 | 0 | `none` | explained above |
| 132 | `iterator_next` | 1 | 4 | 4 | `none` | explained above |
| 133 | `iterator_call` | 2 | 4 | 5 | `u8` | explained above |
| 134 | `initial_yield` | 1 | 0 | 0 | `none` | explained above |
| 135 | `yield` | 1 | 1 | 2 | `none` | explained above |
| 136 | `yield_star` | 1 | 1 | 2 | `none` | explained above |
| 137 | `async_yield_star` | 1 | 1 | 2 | `none` | explained above |
| 138 | `await` | 1 | 1 | 1 | `none` | explained above |
| 139 | `neg` | 1 | 1 | 1 | `none` | explained above |
| 140 | `plus` | 1 | 1 | 1 | `none` | explained above |
| 141 | `dec` | 1 | 1 | 1 | `none` | explained above |
| 142 | `inc` | 1 | 1 | 1 | `none` | explained above |
| 143 | `post_dec` | 1 | 1 | 2 | `none` | explained above |
| 144 | `post_inc` | 1 | 1 | 2 | `none` | explained above |
| 145 | `dec_loc` | 2 | 0 | 0 | `loc8` | explained above |
| 146 | `inc_loc` | 2 | 0 | 0 | `loc8` | explained above |
| 147 | `add_loc` | 2 | 1 | 0 | `loc8` | explained above |
| 148 | `not` | 1 | 1 | 1 | `none` | explained above |
| 149 | `lnot` | 1 | 1 | 1 | `none` | explained above |
| 150 | `typeof` | 1 | 1 | 1 | `none` | explained above |
| 151 | `delete` | 1 | 2 | 1 | `none` | explained above |
| 152 | `delete_var` | 5 | 0 | 1 | `atom` | explained above |
| 153 | `mul` | 1 | 2 | 1 | `none` | explained above |
| 154 | `div` | 1 | 2 | 1 | `none` | explained above |
| 155 | `mod` | 1 | 2 | 1 | `none` | explained above |
| 156 | `add` | 1 | 2 | 1 | `none` | explained above |
| 157 | `sub` | 1 | 2 | 1 | `none` | explained above |
| 158 | `shl` | 1 | 2 | 1 | `none` | explained above |
| 159 | `sar` | 1 | 2 | 1 | `none` | explained above |
| 160 | `shr` | 1 | 2 | 1 | `none` | explained above |
| 161 | `and` | 1 | 2 | 1 | `none` | explained above |
| 162 | `xor` | 1 | 2 | 1 | `none` | explained above |
| 163 | `or` | 1 | 2 | 1 | `none` | explained above |
| 164 | `pow` | 1 | 2 | 1 | `none` | explained above |
| 165 | `lt` | 1 | 2 | 1 | `none` | explained above |
| 166 | `lte` | 1 | 2 | 1 | `none` | explained above |
| 167 | `gt` | 1 | 2 | 1 | `none` | explained above |
| 168 | `gte` | 1 | 2 | 1 | `none` | explained above |
| 169 | `instanceof` | 1 | 2 | 1 | `none` | explained above |
| 170 | `in` | 1 | 2 | 1 | `none` | explained above |
| 171 | `eq` | 1 | 2 | 1 | `none` | explained above |
| 172 | `neq` | 1 | 2 | 1 | `none` | explained above |
| 173 | `strict_eq` | 1 | 2 | 1 | `none` | explained above |
| 174 | `strict_neq` | 1 | 2 | 1 | `none` | explained above |
| 175 | `is_undefined_or_null` | 1 | 1 | 1 | `none` | explained above |
| 176 | `private_in` | 1 | 2 | 1 | `none` | explained above |
| 177 | `push_bigint_i32` | 5 | 0 | 1 | `i32` | explained above |
| 178 | `using_dispose_init` | 1 | 0 | 1 | `none` | explained above |
| 179 | `using_dispose` | 3 | 1 | 1 | `loc` | explained above |
| 180 | `using_dispose_async` | 3 | 0 | 1 | `loc` | explained above |
| 181 | `using_dispose_merge` | 1 | 2 | 1 | `none` | explained above |
| 182 | `using_dispose_end` | 1 | 1 | 0 | `none` | explained above |
| 183 | `using_check` | 2 | 1 | 2 | `u8` | explained above |
| 184 | `nop` | 1 | 0 | 0 | `none` | explained above |
| 185 | `push_minus1` | 1 | 0 | 1 | `none_int` | explained above |
| 186 | `push_0` | 1 | 0 | 1 | `none_int` | explained above |
| 187 | `push_1` | 1 | 0 | 1 | `none_int` | |
| 188 | `push_2` | 1 | 0 | 1 | `none_int` | |
| 189 | `push_3` | 1 | 0 | 1 | `none_int` | |
| 190 | `push_4` | 1 | 0 | 1 | `none_int` | |
| 191 | `push_5` | 1 | 0 | 1 | `none_int` | |
| 192 | `push_6` | 1 | 0 | 1 | `none_int` | |
| 193 | `push_7` | 1 | 0 | 1 | `none_int` | |
| 194 | `push_i8` | 2 | 0 | 1 | `i8` | explained above |
| 195 | `push_i16` | 3 | 0 | 1 | `i16` | explained above |
| 196 | `push_const8` | 2 | 0 | 1 | `const8` | explained above |
| 197 | `fclosure8` | 2 | 0 | 1 | `const8` | explained above |
| 198 | `push_empty_string` | 1 | 0 | 1 | `none` | explained above |
| 199 | `get_loc8` | 2 | 0 | 1 | `loc8` | explained above |
| 200 | `put_loc8` | 2 | 1 | 0 | `loc8` | |
| 201 | `set_loc8` | 2 | 1 | 1 | `loc8` | |
| 202 | `get_loc0_loc1` | 1 | 0 | 2 | `none_loc` | explained above |
| 203 | `get_loc0` | 1 | 0 | 1 | `none_loc` | explained above |
| 204 | `get_loc1` | 1 | 0 | 1 | `none_loc` | |
| 205 | `get_loc2` | 1 | 0 | 1 | `none_loc` | |
| 206 | `get_loc3` | 1 | 0 | 1 | `none_loc` | |
| 207 | `put_loc0` | 1 | 1 | 0 | `none_loc` | |
| 208 | `put_loc1` | 1 | 1 | 0 | `none_loc` | |
| 209 | `put_loc2` | 1 | 1 | 0 | `none_loc` | |
| 210 | `put_loc3` | 1 | 1 | 0 | `none_loc` | |
| 211 | `set_loc0` | 1 | 1 | 1 | `none_loc` | |
| 212 | `set_loc1` | 1 | 1 | 1 | `none_loc` | |
| 213 | `set_loc2` | 1 | 1 | 1 | `none_loc` | |
| 214 | `set_loc3` | 1 | 1 | 1 | `none_loc` | |
| 215 | `get_arg0` | 1 | 0 | 1 | `none_arg` | explained above |
| 216 | `get_arg1` | 1 | 0 | 1 | `none_arg` | |
| 217 | `get_arg2` | 1 | 0 | 1 | `none_arg` | |
| 218 | `get_arg3` | 1 | 0 | 1 | `none_arg` | |
| 219 | `put_arg0` | 1 | 1 | 0 | `none_arg` | |
| 220 | `put_arg1` | 1 | 1 | 0 | `none_arg` | |
| 221 | `put_arg2` | 1 | 1 | 0 | `none_arg` | |
| 222 | `put_arg3` | 1 | 1 | 0 | `none_arg` | |
| 223 | `set_arg0` | 1 | 1 | 1 | `none_arg` | |
| 224 | `set_arg1` | 1 | 1 | 1 | `none_arg` | |
| 225 | `set_arg2` | 1 | 1 | 1 | `none_arg` | |
| 226 | `set_arg3` | 1 | 1 | 1 | `none_arg` | |
| 227 | `get_var_ref0` | 1 | 0 | 1 | `none_var_ref` | explained above |
| 228 | `get_var_ref1` | 1 | 0 | 1 | `none_var_ref` | |
| 229 | `get_var_ref2` | 1 | 0 | 1 | `none_var_ref` | |
| 230 | `get_var_ref3` | 1 | 0 | 1 | `none_var_ref` | |
| 231 | `put_var_ref0` | 1 | 1 | 0 | `none_var_ref` | |
| 232 | `put_var_ref1` | 1 | 1 | 0 | `none_var_ref` | |
| 233 | `put_var_ref2` | 1 | 1 | 0 | `none_var_ref` | |
| 234 | `put_var_ref3` | 1 | 1 | 0 | `none_var_ref` | |
| 235 | `set_var_ref0` | 1 | 1 | 1 | `none_var_ref` | |
| 236 | `set_var_ref1` | 1 | 1 | 1 | `none_var_ref` | |
| 237 | `set_var_ref2` | 1 | 1 | 1 | `none_var_ref` | |
| 238 | `set_var_ref3` | 1 | 1 | 1 | `none_var_ref` | |
| 239 | `get_length` | 1 | 1 | 1 | `none` | explained above |
| 240 | `if_false8` | 2 | 1 | 0 | `label8` | explained above |
| 241 | `if_true8` | 2 | 1 | 0 | `label8` | explained above |
| 242 | `goto8` | 2 | 0 | 0 | `label8` | explained above |
| 243 | `goto16` | 3 | 0 | 0 | `label16` | explained above |
| 244 | `call0` | 1 | 1 | 1 | `npopx` | explained above |
| 245 | `call1` | 1 | 1 | 1 | `npopx` | |
| 246 | `call2` | 1 | 1 | 1 | `npopx` | |
| 247 | `call3` | 1 | 1 | 1 | `npopx` | |
| 248 | `is_undefined` | 1 | 1 | 1 | `none` | explained above |
| 249 | `is_null` | 1 | 1 | 1 | `none` | explained above |
| 250 | `typeof_is_undefined` | 1 | 1 | 1 | `none` | explained above |
| 251 | `typeof_is_function` | 1 | 1 | 1 | `none` | explained above |
# Temporary opcodes
These exist only inside the compiler and are removed before anything is written to a file. They are listed because their numbers overlap the short opcodes, starting at `OP_TEMP_START` = 185, and a decoder must account for the 19 of them.
| Name | Size | Format |
|---|---|---|
| `enter_scope` | 3 | `u16` |
| `leave_scope` | 3 | `u16` |
| `label` | 5 | `label` |
| `scope_get_var_undef` | 7 | `atom_u16` |
| `scope_get_var` | 7 | `atom_u16` |
| `scope_put_var` | 7 | `atom_u16` |
| `scope_delete_var` | 7 | `atom_u16` |
| `scope_make_ref` | 11 | `atom_label_u16` |
| `scope_get_ref` | 7 | `atom_u16` |
| `scope_put_var_init` | 7 | `atom_u16` |
| `scope_get_private_field` | 7 | `atom_u16` |
| `scope_get_private_field2` | 7 | `atom_u16` |
| `scope_put_private_field` | 7 | `atom_u16` |
| `scope_in_private_field` | 7 | `atom_u16` |
| `get_field_opt_chain` | 5 | `atom` |
| `get_array_el_opt_chain` | 1 | `none` |
| `set_class_name` | 5 | `u32` |
| `dispose_scope` | 3 | `u16` |
| `source_loc` | 9 | `u32x2` |
---
252 opcodes, 206 explained above.