OK, I'm rephrasing to make sure I understand.
In the ordinary, C compliant switch code, you would do this:
int instructions[] = { /* bytecode */ };
// main loop
int* ip = instructions;
while(1) {
switch (*ip) {
case 1: /* instruction 1 */ break;
case 2: /* instruction 2 */ break;
case 3: /* instruction 3 */ break;
/* etc */
}
ip++; /* goto next instruction. beware jumps */
}
With a jump threaded implementation, you would do this instead:
int instructions[] = { /* bytecode */ };
void jump_table[] = {
&&lbl1,
&&lbl2,
&&lbl3,
/* etc */
};
// main loop
int* ip = instructions;
goto *jump_table[*ip];
lbl1: /* instruction1 */ ip++; goto *jump_table[*ip];
lbl2: /* instruction2 */ ip++; goto *jump_table[*ip];
lbl3: /* instruction3 */ ip++; goto *jump_table[*ip];
/* etc */
Which means, instead of having the compiler constructing a jump table under the hood, I do this myself, and get the benefit of jumping from several locations instead of just one. But I still look up that table. Now the indirect threading you speak of:
int instructions[] = { /* bytecode */ };
void jump_table[] = {
&&lbl1,
&&lbl2,
&&lbl3,
/* etc */
};
// translating bytecode into adresses
void* labels[] = malloc(sizeof(void*) * nb_instructions);
for (uint i = 0; i
If I got that correctly, instead of accessing the jump table at some random place, I only access the label table in a much more linear fashion, saving one indirection and some memory access in the process —this should relieve some pressure off the L1 cache.
Did I get that right?