Virtual machine layout and interface definition

Virtual machine layout and interface definition
SchemeStation documentation

1 Introduction

The VM consists of

  1. Instruction fetcher & decoder
  2. Instruction selector (/executor)
  3. Exception handler
  4. Individual instructions

The purpose of this structure is to make VM as modular and as simple as possible. It is especially important to be able to add/change individual instructions by changing only the instruction module.

2.10 The functions of module VM external interface


File vm.h

C-functions:


File vm_debug.h

C-functions:


File vm_encode.h

C-functions:


File vm_instr.h

C-functions:

3 Internal interfaces

This internal interface definition specifies the current implementation decisions of the SCHEMESTATION VM.

3.1 Instruction encoding & decoding

With each instruction (VM_INSTR_*) there is an association to instruction encoder and decoder functions. The purpose of the instruction decoding phase is to pick out the operands of the instruction and place them to a structure that holds all possible operand combinations. This structure can then be passed to individual instruction function. The encoder is placed here for convenience; the assembler uses the encoder to produce the binary from instructions and their operands.

Each decoder instruction is implemented as a function that has the following fingerprint:

Vm_status vm_decoder_*(IN uint32 instr, /* Instruction item to be decoded */
                       IN Heap heap, /* Constants are located here */
                       IN uint64 *imm_offset, /* IMM_EXTEND support */
                       OUT Vm_decoded_instr *decoded); /* The final result */

Encoder function fingerprint:

Vm_status vm_encoder_*(IN Vm_instruction instr, /* The instruction */
                       OUT unsigned char *buf, /* Output buffer */
                       OUT int *instr_size, /* Size of the encoded instruction */
                       IN uint64 *args); /* Operand vector */

3.2 Instruction selection and individual instructions

Instructions are associated to an instruction function and using a table of associations, the particular instruction function for an instruction is selected. Each instruction is implemented as a function that has the following fingerprint:

Vm_status vm_operator_*(INOUT Heap heap,
                        INOUT Registerset *registers,
                        IN Vm_decoded_instr *instr);

If instruction return status is different from VM_STATUS_OK, some decisions has to be made: either the VM exception mechanism can handle the situation and continue execution or the status value will be passed to the external interface of the VM and the instruction scheduling discontinued.

3.3 Exceptions

The exception mechanism is based on the register VM_REG_EXCEPTION which contains the address of the user-defined exception handler. If this register contains NIL, it means that the exceptions are disabled; if an exception should occur whenever exceptions are disabled, the VM acts like VM_INSTR_HALT would have been executed (the program dies). When an exception is raised, the following instructions are executed internally:

VM_INSTR_SAVE_IMMEDIATE    VM_REG_STACK, B1111111111110111 ; save registers except VM_REG_MSG_QUEUE
VM_INSTR_JUMP              VM_REG_EXCEPTION ; jump to the exception handler
VM_INSTR_LOAD_NULL         VM_REG_EXCEPTION ; set the exception handler to NIL -> exceptions disabled

After that, the parameter is placed to VM_REG_R2 and the execution can continue. This implies that whenever the instruction VM_INSTR_RESTORE_IMMEDIATE, VM_REG_STACK, B11111111111111 is executed, it has the effect of returning from the exception handler and continuing the execution from the point where the exception occurred. Note that the register VM_REG_MSG_QUEUE is not saved or restored.

NOTE: Current implementation does not generate fatal exceptions, as there are no defined semantics to handle them - instead, the program that generated the exception is terminated.

3.4 VM and asynchronous messages

vm_message() interface invokes the exception handling facility which passes the message to the exception handler of this particular bytecode instance. This message delinearizes the message (a linearized heap, formed as a list of parameters, where the first parameter is a bitstring identifying the message) and passes it to the program as the parameter of the exception handler.

NOTE: It is assumed that the exception mechanism (once defined) will be using this kind of parameter passing - that is, exceptions behave like "out of band" messages, and they can be recognized just like normal messages.