The Harbour virtual machine (VM)¶
What is VM¶
The VM is formed by the main execution loop and several subsystems, each of which could be theoretically replaced, supposing that you respect the
interface of each subsystem.
- the pcode instructions to execute
- and the local symbol table (a portion of the OBJs (static) symbol table) used by that pcode1
VM¶
The VM may invoke the VM (itself) again. This lets the harbour language access harbour functions and methods and external C language functions again and again.
The VM organizes these multiple accesses in an ordered and fully controlled way, and implements services to access these multiple execution levels (ProcName(), ProcLine(), debugging, and stack variables access).
VM subsystems¶
The VM subsystems are continuously used by the main execution loop. Let's review these VM subsystems:
a) VM startup subsystem¶
The startup: Controls the initialization of the different VM subsystems.
It is invoked at the beginning of the application. It also controls the exiting of the application.
b) VM stack subsystem¶
The VM does not use the stack of the computer directly, it uses instead its own stack for manipulating values (parameters, returned values, and symbols) as a hardware stack does.
c) VM static symbol table¶
Created by the compiler at compile time (and grouped by the linker on OBJs), this subsystem is responsible for an immediate access to functions location and it is highly related to the
dynamic symbol table at runtime. It contains many duplicated symbols that will be optimized by the dynamic symbol table.
d) VM dynamic symbol table¶
The dynamic symbol table: Dynamically generated from the startup subsystem at the beginning of the application. It organizes in an efficient way the static symbol table creating an alphabetical index that allows a dicotomic search of symbols. This subsystem is responsible for quick access to symbols (functions, variables, fields and workareas aliases).
e) VM subsystem: The static and public variables¶
Responsible for storing public and static variables.
f) VM subsystem: memory¶
The memory: Responsible for allocating, reallocating, locking, unlocking and freeing memory.
g) The extend system¶
Defines the interface (_parc(), ..., _retc() ) from low level (C language) to high level (harbour language). This subsystem is responsible for connecting in a proper way C language functions to the entire application.
h) Multidimensional arrays¶
This subsystem allows the creation of arrays, and the services to manipulate these arrays in all ways. The arrays are extensively used by the harbour language and also they are the foundation of
the Objects (Objects are just arrays related to a specific Class).
i) The Objects engine¶
Responsible for the creation of Classes and Objects. It also defines the way to access a specific Class method to be invoked by the
VM and provides all kind of Classes information that may be requested at runtime.
j) The macro subsystem¶
It implements a reduced compiler that may be used at runtime to generate pcode to be used by the application. In fact it is a portion of the harbour yacc specifications.
k) The workareas subsystem¶
Responsible for databases management. It defines the locations where the used workareas will be stored and provides all the
functions to access those workareas. It also implements the interface to the replaceable database drivers.
Opcodes¶
Harbour opcodes are defined in hbpcode.h.
We are trying to use very easy to remember mnemonics, so PUSHWORD seems easier than PUSHW.
The opcodes values are meaningless as they are just used by a C language switch sentence (in fact there is a powerful optimization which is to use the pcode opcodes
themselves as an index to a VM functions pointers array, so VM execution speed may increase).
References¶
- based on: harbour/doc/vm.txt, written by, Antonio, commited to repos: "Thu Mar 2 11:58:22 2000"
1 review hbpcode.h for the currently implemented pcode opcodes