Skip to content
  • Yorick Peterse's avatar
    Refactor various aspects of VM instructions · 0619de82
    Yorick Peterse authored
    == Instruction memory layout
    
    VM instructions now have a fixed size of 16 bytes, and no longer make
    use of a separate heap-allocated Vec for their arguments. This reduces
    memory usage, and should make for more cache-friendly instruction
    handling.
    
    Each instruction is limited to six arguments, which is enough for all
    existing instructions. Instructions that need a variable number of
    arguments, such as SetArray, make use of register ranges. Instead of
    specifying all registers, they specify the first one and a length. The
    compiler in turn makes sure all argument registers are in a contiguous
    order. This approach is also taken by Lua, though unlike Lua we don't
    require the arguments to come after the register containing the block
    to run.
    
    Some instructions supported optional arguments, such as SetObject. These
    instructions have been modified to simply always require an argument.
    This simplifies the VM code, and in almost all cases the arguments were
    always specified anyway.
    
    For Inko's test suite, these changes reduce peak RSS usage from 27 MB
    down to 21 MB.
    
    == MoveResult instruction
    
    Values returned and thrown are handled differently. Instead of each
    ExecutionContext storing the register (of the parent frame) to write
    their result to, operations that return or throw a value now store the
    value in a per-process "result" variable. The MoveResult instruction
    moves this value into a register, setting the "result" variable to NULL.
    This approach is inspired by the Dalvik VM, and simplifies instructions
    such as Return and Throw.
    
    == Single instruction for pinning processes
    
    The instructions ProcessPinThread and ProcessUnpinThread have been
    merged into a single ProcessSetPinned instruction. This instruction
    behaves similar to ProcessSetBlocking.
    
    == Removed instructions
    
    The following VM instructions have been removed as they were not used:
    
    * SetPrototype
    * RemoveAttribute
    * BlockSetReceiver
    
    == Refactoring of instruction handlers
    
    The functions used for handling instructions have been refactored,
    renamed (after their instructions), and are now always inlined. This
    looks a bit funny at the moment, but it should make it easier for a
    future JIT to reuse these functions. The renaming also allows one to
    import specific functions, without having to worry about generic names
    such as "get" conflicting with other functions.
    
    == Bytecode parser cleanup
    
    The bytecode parser has been cleaned up a bit, and now limits various
    data sequences to the maximum u16 value; instead of some arbitrarily
    determined limit. The u16::MAX limit ensures that registers can address
    the values directly.
    
    == Argument changes
    
    The VM no longer supports keyword arguments and rest arguments. Instead,
    the compiler takes care of translating these to positional arguments.
    Keyword arguments are translated to positional arguments, with
    unspecified arguments being passed NULL pointers. The way this works is
    straightforward:
    
    1. Create an array with a NULL value/pointer for every _expected_
       argument. This is achieved by reserving register 0 and using that.
    
    2. For every positional argument passed, fill its corresponding cell. So
       argument 1 fills cell 0, argument 2 fills cell 1, etc.
    
    3. For keyword arguments, look up its argument position and set the
       corresponding cell.
    
    4. Pass this array as arguments to the VM instruction.
    
    This is best illustrated with a simple example:
    
        def foo(a = 1, b = 2, c = 3) {}
    
        foo(b: 10)
    
    Here the arguments passed would be:
    
        [NULL, 10, NULL]
    
    The VM then checks if `b` and `c` are set, sees they are NULL, and
    assigns them their default values.
    
    Validating of argument counts is also removed from the VM, now that
    dynamic method calls are no longer supported.
    0619de82