https://eli.thegreenplace.net/2012/07/12/computed-goto-for-e...
Consider this example for dispatching instructions from the article:
while (running)
{
uint16_t op = mem_read(reg[R_PC]++) >> 12;
switch (op)
{
case OP_ADD:
{ADD, 6}
break;
case OP_AND:
{AND, 7}
break;
case OP_NOT:
{NOT, 7}
break;
case OP_BR:
{BR, 7}
break;
...
}
}
That code has a lot of branching. The switch statement has to jump to the corresponding case, the break statement branches to the bottom, and then there is third branch to get back to the top of the while loop. Three branches just to hit one instruction.Now imagine we had written the above as:
static void* dispatch_table[] = { &&OP_ADD, &&OP_AND, &&OP_NOT, &&OP_BR,
... };
#define DISPATCH() goto *dispatch_table[memory[reg[R_PC]++] >> 12]
DISPATCH();
OP_ADD:
{ADD, 6}
DISPATCH();
OP_AND:
{AND, 7}
DISPATCH();
OP_NOT:
{NOT, 7}
DISPATCH();
OP_BR:
{BR, 7}
DISPATCH();
...
Now there is only one branch per instruction. The handler for each instruction directly jumps to the next location via the goto. There is no need to be in an explicit loop because the interpreter runs until it hits a halting instruction.Many VMs now use this technique, including the canonical Ruby and Python interpreters.