Hivm

the friendly, accessible high-level virtual machine

Introduction

Virtual machines are complex, intimidating beasts. Although they do provide a level of abstraction from the physical machine, they are by no means high-level computing environments. An understanding of registers, pointers, and stacks is recommended, and having a good grasp of the fetch-execute principles of stored-program computation (specifically the modified Harvard architecture) is also advised.

The virtual machine

The Hivm machine itself is inspired by reduced instruction set computing architectures: it only has about 40 instructions. It operates as a modified Harvard architecture: the program and the data exist in separate spaces in memory. There are also no instructions for modifying program memory, however primitive subroutines do exist for doing so. This level of abstraction is intended to simplify privilege control and make it easier to execute code at different capability levels.

Hivm is a register machine. All instructions read and write to registers (there are 3+1 types of registers available). It is designed to have a large number of registers (128 general registers by default), making the need for complex register allocation hopefully unnecessary (that said, a linear scan register allocator tool is being planned to make complex allocation scenarios relatively painless).

Hivm features a simple, single-threaded precise mark-and-sweep compacting garbage collector. Currently garbage collection must be triggered manually; however, the garbage collection runs within in the object space and requires no additional memory. Furthermore the in-place compaction ensures fast allocation of new objects.

Lifecycle

Interacting with the machine follows a fairly standard model:

  1. Initialize the VM (and normally also bootstrap primitive components, however this step is completely optional)
  2. Load the core/bootstrap of your own runtime environment into the machine
  3. Begin parsing your source(s) and generating bytecode chunks
  4. Load bytecode chunks into the machine
  5. Run the machine (as the machine is running additional code can be loaded, however this naturally requires pausing execution so it's best to do all loading as early in execution as possible)