There are also some slots reserved for dedicated functionality, holding values like
this and the callee / return value.
There is always a "Top of Stack" (TOS) that corresponds to the latest value pushed onto the expression stack. All bytecodes implicitly operate in terms of this location.
All opcodes are annotated with a [-popcount, +pushcount] to represent the overall stack-effects their execution.
If any data for an opcode is implicit in the bytecode stream, it is listed out as parameters in a function-like invocation for the opcode; i.e.
- Argument slots: holds the actual arguments passed to the current frame.
- Local slots: holds the local variables used by the current code.
- Expression slots: holds the temporary space that you need to calculate expressions on a stack. For example, in
(a + b) + cyou would push a, then push b, then add, then push c, then add, which requires a maximum depth of two expression slots.
- JSOP_NOP [-0, +0]
- A no-operation bytecode. This was historically used to blacklist loops in TraceMonkey (switching a JSOP_LOOPHEAD to a JSOP_NOP) and (FIXME) apparently still has some relevance for the decompiler.
- JSOP_PUSH [-0, +1]
- Pushes undefined onto the stack.
- JSOP_POPV [-1, +0]
- Pops the top stack value into the return-value slot for the currently executing frame.
- JSOP_ENTERWITH [-1, +1]
- Turn the value at TOS into a member of the scope chain. Pops the value, and pushes the new scope-chain object. The fact that the new scope chain object gets pushed is a bit scary, because that's an engine-only internal data structure, and it ends up on the stack with all the user data.
- JSOP_LEAVEWITH [-1, +0]
- Pops the scope-chain object from JSOP_ENTERWITH off TOS.
- JSOP_RETURN [-1, +0, STOPS]
- Pops the TOS into the return value slot and returns the currently executing code to its caller.
- JSOP_GOTO(int16_t offset) [-0, +0, JUMPS]
- Jumps to a 16-bit offset from the current bytecode.
- JSOP_IFEQ(int16_t offset) [-1, +0, JUMPS]
- Pops a value from TOS, converts it to a boolean, and, if the result is false, jumps to a 16-bit offset from the current bytecode. The idea is that a sequence like JSOP_ZERO; JSOP_ZERO; JSOP_EQ; JSOP_IFEQ; JSOP_RETURN; reads like a nice linear sequence that will execute the return.
- JSOP_IFNE(int16_t offset) [-1, +0, JUMPS]
- Same as JSOP_IFEQ, but jumps if the result is true.
- JSOP_ARGUMENTS [-0, +1]
Pushes the arguments object (corresponding to
arguments) for the current frame. Arguments objects are created lazily.
- JSOP_SWAP [-0, +0]
- Swaps the top two values on the stack. This is useful for things like post- increment/decrement.
- JSOP_POPN(uint16_t N) [-N, +0]
- Pops the top N values on the stack in a single opcode.