Labels as Values による Compiled goto でインタプリタを高速化

Androidインタプリタは C で実装されたバージョンとアセンブラで実装されたバージョンがあって、どちらもインストラクションを goto で処理するように実装されている。

ずっと気になっていた C の goto の仕組みを調べてみた。

純化したのが以下の擬似コード

#include <stdio.h>

int main(int argc, char *argv[]) {
    void *table[] = { &&l0, &&l1, &&l2 }; // ←これがキモい
    goto *table[1];

l0:
    printf("l0\n");
    goto *table[2];
l1:
    printf("l1\n");
    goto *table[0];
l2:
    printf("l2\n");

    return 0;
}

このコードを実行すると、l1、l0、l2 と表示されるのだが、はたして table に格納している &&l0 などは何者なのか。以下のページで氷解した。

DSAS開発者の部屋:インタプリタ型言語を高速化する computed goto

なるほど、gcc の拡張なのか(どうりでキモいわけだ)。これはインタプリタが楽に書けてかつ高速になるという魅力的な機能なんだけど、移植性を損なうのも事実。