### ----------------------------------------------------
### -- MoarVM::Bytecode
### -- Licenses: Artistic-2.0
### -- Authors: Elizabeth Mattijsen
### -- File: doc/bytecode-7.md
### ----------------------------------------------------
# Bytecode
This document describes the bytecode that the VM interprets or JIT compiles.
Note that this is just one part of an input file to the VM; along with it
will also be a bunch of serialized objects, and some container. This just
describes the way the executable segment of things looks. (In a sense, this
is the low-level reification of the Actions/World distinction at the level
of the compiler).

## Endianness
All integer values are stored in little endian format.

## Floats
Floating point numbers are represented according to IEEE 754.

## Header
The header appears at the start of the MoarVM bytecode file, and indicates
what it contains.

    +---------------------------------------------------------+
    | "MOARVM\r\n"                                            |
    |    8-byte magic string; includes \r\n to catch mangling |
    |    of line endings                                      |
    +---------------------------------------------------------+
    | Version                                                 |
    |    32-bit unsigned integer; since we'll never reach a   |
    |    huge number of versions, this also doubles up as a   |
    |    check that no weird big/little endian issues keep us |
    |    from reading the bytecode.                           |
    +---------------------------------------------------------+
    | Offset (from start of file) of the SC dependencies      |
    | table                                                   |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of entries in the SC dependencies table          |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the extension ops table  |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of entries in the extension ops table            |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the frames data segment  |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of frames we should end up finding in the frames |
    | data segment                                            |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the callsites data       |
    | segment                                                 |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of callsites we should end up finding in the     |
    | callsites data segment                                  |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the strings heap         |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of entries in the strings heap                   |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the SC data segment      |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Length of the SC data segment                           |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the bytecode segment     |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Length of the bytecode segment                          |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Offset (from start of file) of the annotation segment   |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Length of the annotation segment                        |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | HLL Name                                                |
    |    32-bit unsigned integer index into the string heap,  |
    |    providing the name of the HLL this compilation unit  |
    |    was compiled from. May be the empty string.          |
    +---------------------------------------------------------+
    | Main entry point frame index + 1; 0 if no main frame    |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Library load frame index + 1; 0 if no load frame        |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Deserialization frame index + 1; 0 if none              |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+

## Strings heap
This segment contains a bunch of string data. Each string is laid out as:

    +---------------------------------------------------------+
    | String length in bytes                                  |
    |    32-bit unsigned integer left shifted by 1            |
    |    LSB is flag where 1 means UTF-8 and 0 means latin-1  |
    +---------------------------------------------------------+
    | String data encoded as UTF-8/latin-1                    |
    |    Bunch of bytes, padded at end to 32 bit boundary     |
    +---------------------------------------------------------+

## SC Dependencies Table
This table describes the SCs (Serialization Contexts) that the bytecode in
this file references objects from. The wval opcode specifies an index in
this table and an index in the SC itself. When the bytecode file is first
loaded, we look in the known SCs table and resolve all that we can. Then,
the deserialize code for the compilation unit is run. Whenever the SC
creation opcode is used, we search all known compilation units to see if they
have any unresolved SCs, and fill in any gaps that correspond to the newly
created SC. By the time the deserialize phase for a compilation unit is over,
we expect that all SCs have been resolved. Thus, the lifetime of an SC is
equal to the lifetimes of all the compilation units that reference it,
since their code depends on it. Note that the primary way an SC is rooted
is through a compilation unit, and that these roots are established as
soon as it is created, and before it's returned to userspace (which could
allocate more) are the way we make sure it isn't collected too early.

    +---------------------------------------------------------+
    | Index into the string heap of the SC ID                 |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+

## Extension ops table

    +---------------------------------------------------------+
    | Index into the string heap of the extension op ID       |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Operand descriptor                                      |
    |    Bunch of bytes describing a single operand each,     |
    |    zero-padded to 8 bytes                               |
    +---------------------------------------------------------+

The operand descriptor follows the same format as used by MVMOpInfo.
The 8 bytes limit corresponds to MVM_MAX_OPERANDS.

## Frames Data
The frames data segment contains data that describes all of the frames in
the compilation unit. It also points into the bytecode segment, which contains
the bytecode we will execute for this frame. This is stored elsewhere at least
partly for the sake of demand paging and CPU cache efficiency; once we
processed the static data, it's not very interesting at runtime, so there's no
real reason for it to stay in memory, let alone be cached by the CPU. The
actual bytecode itself, on the other hand, is (at least until JIT happens) of
interest for execution.

Each frame starts with the following data.

    +---------------------------------------------------------+
    | Bytecode segment offset                                 |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Bytecode length in bytes                                |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of locals/registers                              |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of lexicals                                      |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Compilation unit ID                                     |
    |    32-bit string heap index                             |
    +---------------------------------------------------------+
    | Name                                                    |
    |    32-bit string heap index                             |
    +---------------------------------------------------------+
    | Outer                                                   |
    |    16-bit frame index of the outer frame. For no outer, |
    |    this is set to the current frame index.              |
    +---------------------------------------------------------+
    | Annotation segment offset                               |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of annotations                                   |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Number of handlers                                      |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Frame flag bits                                         |
    |    16-bit integer                                       |
    |    1 = frame has an exit handler                        |
    |    2 = frame is a thunk                                 |
    |    Remaining values reserved                            |
    | [NEW IN VERSION 2]                                      |
    +---------------------------------------------------------+
    | Number of entries in static lexical values table        |
    |    16-bit integer                                       |
    | [NEW IN VERSION 4]                                      |
    +---------------------------------------------------------+
    | Code object SC dependency index + 1; 0 if none          |
    |    32-bit unsigned integer                              |
    | [NEW IN VERSION 4]                                      |
    +---------------------------------------------------------+
    | SC object index; ignored if above is 0                  |
    |    32-bit unsigned integer                              |
    | [NEW IN VERSION 4]                                      |
    +---------------------------------------------------------+
    | Number of local debug name mappings                     |
    |    32-bit unsigned integer                              |
    | [NEW IN VERSION 6]                                      |
    +---------------------------------------------------------+

This is followed, for each local, by a number indicating what kind of
local it is. These are stored as 16-bit unsigned integers.

    int8        1
    int16       2
    int32       3
    int64       4
    num32       5
    num64       6
    str         7
    obj         8
    uint8      17
    uint16     18
    uint32     19
    uint64     20

Lexicals are similar, apart from each entry is followed by a 32-bit unsigned
index into the string heap, which gives the name of the lexical.

[Conjectural: a future MoarVM may instead do these in terms of REPRs.]

Next comes the handlers table. Each handler has an entry as follows:

    +---------------------------------------------------------+
    | Start of protected region. Inclusive offset from start  |
    | of the frame's bytecode                                 |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | End of protected region. Exclusive offset from start of |
    | the frame's bytecode                                    |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Handler category mask bitfield                          |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Handler action (see exceptions spec for values)         |
    |    16-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Register number containing the block to invoke, for a   |
    | block handler.                                          |
    |    16-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Handler address to go to, or where to unwind to after   |
    | an invoked handler. Offset from start of the frame's    |
    | bytecode.                                               |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+

From version 7 and up, an additional 16-bit unsigned integer value
is added if the category mask bitfield has bit 0x01000 set.

From version 4 and up, this is followed by a static lexical values
table. Each entry is as follows:

    +---------------------------------------------------------+
    | Lexical index                                           |
    |    16-bit unsigned integer                              |
    +---------------------------------------------------------+
    | Flag                                                    |
    |    16-bit unsigned integer                              |
    |    0 = static lexical value                             |
    |    1 = container var (cloned per frame)                 |
    |    2 = state var (cloned per closure)                   |
    +---------------------------------------------------------+
    | SC dependency index                                     |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+
    | SC object index                                         |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+

From version 6 and up, this is followed by a debug local names table. Each
entry is as follows:

    +---------------------------------------------------------+
    | Local index                                             |
    |    16-bit unsigned integer                              |
    +---------------------------------------------------------+
    | String heap index for the debug name                    |
    |    32-bit unsigned integer                              |
    +---------------------------------------------------------+

## Callsites Data
This data blob contains all of the callsite descriptors that are used in
the compilation unit. At the point of loading the bytecode, they will
be set up, and a table pointing to them created. This means that a
callsite descriptor will always be a pointer + offset away.

Each callsite consists of a 16-bit unsigned integer indicating the number
of argument flags of which only the lowest 8 bits should be considered.

This is followed by the flags, taking 8 bits each. If the number of
argument flags is odd, then an extra padding byte will be written
afterwards.

Since version 3, this is then followed with one index to the string
heap (in the form of a 32-bit unsigned integer) for each argument
flag that has the `MVM_CALLSITE_ARG_NAMED` bit set and has the
`MVM_CALLSITE_ARG_FLAT` bit **NOT** set.

## Bytecode segment
This consists of a sequence of instructions. Instruction codes are always
16 bits in length.

Opcodes may be followed by zero or more operands. The instruction set will
have the needed operands described by the following set of descriptors.

    r       local variable index being read, 16 bits unsigned
    w       local variable index being written, 16 bits unsigned
    rl      lexical variable being read, 16 bits unsigned for the
            index within a frame and 16 bits for how many frames out
            to go to locate it
    wl      lexical variable being written, 16 bits unsigned for the
            index within a frame and 16 bits for how many frames out
            to go to locate it
    int16   16-bit integer constant
    int32   32-bit integer constant
    int64   64-bit integer constant
    num32   32-bit floating point constant
    num64   64-bit floating point constant
    uint16  16-bit unsigned integer constant
    uint32  32-bit unsigned integer constant
    uint64  64-bit unsigned integer constant
    str     Strings table index, 32 bits unsigned
    ins     Instruction offset from frame start (for goto), 32 bits unsigned

Note that this ensures we always keep at least 16-bit alignment for ops.

Some instructions place demands on the type of value in the register.
This is perhaps most noticable when it comes to integers of different
sizes; all computations are done on them in full-width (64-bit) form,
and loading/storing them to registers representing locals of more
constrained sizes needs explict sign extension and truncate ops.
Wherever a register is specified, the kind of value in it is also
indicated. These are typechecked *once*, either at bytecode load time
or (perhaps better) on the first execution. After that, all future
interpreter executions can just plow through the instructions without
ever having to do checks.

The set of ops is listed in src/core/oplist.

## Annotation segment
This consists of a number of records, composed of:

* 32-bit unsigned integer offset into the bytecode segment
* 32-bit unsigned integer strings heap index (filename)
* 32-bit unsigned integer (line number)


