tl;dr for those who don't want to read the paper in detail: * Interpreters are conceptually a big switch(bytecode) statement in an infinite loop. They use various tricks to make it easier for the processor to predict the target of the next indirect branch * This previously had a dramatic impact on performance, because branch mispredictions are very expensive and it was difficult for the processor to predict them accu…
They actually present (approximately) a very simple construct that is used to speed the interpreters up:
void labels[] = { &&ADD, &&SUB . . . };
...
goto labels[ vpc++ ];
ADD:
...
goto labels[ vpc++ ];
instead of ...
switch ( *vpc++ )
{
case ADD:
....
break;
case SUB:
It's not really hard. The only problem is that the former is not a standard C and not present in MSVC. Seehttp://stackoverflow.com/questions/6421433/address-of-labels...
"Erlang does (that) for building on Windows. They use MSVC for most of the build, and then GCC for one file to make use of the labels-as-values extension. The resulting object code is then hacked to be made compatible with the MSVC linker."
It obviously mattered enough for Erlang developers to use GCC even for just that critical piece of C code. It doesn't mean that it has to be regularly used in every code (not every switch is executed the way the main interpreter loop is).