JIT コンパイルが再帰して困った
JIT コンパイラが Scheme で書かれているので、JIT コンパイラ自身も JIT コンパイルされる可能性があることに気付いた。そうすると
- 手続き A を JIT コンパイルしようとする。
- JIT コンパイラ中の手続き B が閾値を超えて call される。
- 手続き B を JIT コンパイルしようとする。
- JIT コンパイラ中の手続き B が閾値を超えて call される。
- 手続き B を JIT コンパイルしようとする。
と繰り返されてしまう。同じ手続き B が再帰的に何回も JIT コンパイルされるのが問題なので、手続き B にコンパイル中フラグをつければ良いかと思ったがそうも行かない。
例えば以下のような場合を考えれば分かる。
(define (jit-compile x) ... ... (map (lambda (x) (+ x 2)) lst) ...)
手続き B が (lambda (x) (+ x 2)) だとすると jit-compile の呼び出し毎に、新しい手続きがアロケーションされるので、ソースコード上は同じ手続きでも実行時には別の手続きなのだ。(コンパイラが賢ければ、(lambda (x) (+ x 2)) を静的にくくりだす事も可能だがそれはまた別の話なので置いておく)
上記のような事情から、JIT コンパイラは再帰的に起動しない。グローバルで JIT コンパイル中フラグを持つ。という方針にしようかと思う。ただし欠点があって良く呼ばれるであろう JIT コンパイラ自身が JIT の恩恵を受けられない。
もっと良い方法はないだろうか。