Interpreters101

2012/03/01
While watching "Google I/O 2008 - Dalvik Virtual Machine Internals" (http://www.youtube.com/watch?v=ptjedOZEXPM) they demonstrated a great example of how a simple bytecode interpreter is implemented. Since I am fascinated by the inner workings of compilers and VM/interpreters I thought I would share the example here for anyone else that is interested.

The first example is the simplest version, a simple for loop that loops over each byte and depending on the value of each byte it will execute a different command, this version is very portable as it doesn't use any low level assembly code, so this example can be compiled for many different platforms.


/*
Google I/O 2008 - Dalvik Virtual Machine Internals
Interpreters 101, toy interpreter
This is a simple toy bytecode interpreter
*/
#include <cstdio>
static void interpreter(const char* stringOfBytecode);
int main(int argc, char *argv[]) {
interpreter("abcbbbbde");
}
static void interpreter(const char* stringOfBytecode) {
for (;;) {
switch (*(stringOfBytecode++)) {
case 'a': printf("Hell"); break;
case 'b': printf("o"); break;
case 'c': printf(" w"); break;
case 'd': printf("rld!\n"); break;
case 'e': return;
}
}
}

The next example whos a much more efficient implementation: the gcc way! It removes a number of the branches required in the last example, so right after executing the op code code it can go staright into the enxt opcode! Rather than the first example where it had to branch to the end then to the next for loop iteration etc. So it is alot more efficient!


/*
The gcc way
*/
#define DISPATCH() \
{ goto *op_table[*((stringOfBytecode)++) - 'a']; }
static void interpreter_the_gcc_way(const char* stringOfBytecode) {
static void* op_table[] = {
&&op_a, &&op_b, &&op_c, &&op_d, &&op_e
};
DISPATCH();
op_a: printf("Hell"); DISPATCH();
op_b: printf("o"); DISPATCH();
op_c: printf(" w"); DISPATCH();
op_d: printf("rld!\n"); DISPATCH();
op_e: return;
}

There is also an assembly example which is even more efficient, since there are still come cases where humans can write more efficient assembly than compilers.

Table of Contents