読者です 読者をやめる 読者になる 読者になる

レガシーコード生産ガイド

私に教えられることなら

作業記録

forth 学習記録

RFR64で末尾呼び出し最適化

サブルーチンスレッディングで作ったRFR64だけど、せっかく最適化をいろいろ試すためにサブルーチンスレッディングを選んだので、そろそろ取り掛かってみることにした。

末尾呼び出し最適化自体についてはここらへんが詳しい

Forthはスタックを使って引数・返り値を管理するので、いくつか特殊なワードやコードを除けば基本的にそのままjumpに書き換えられる(と思う)。

末尾呼び出し最適化の為には最後にコンパイルしたcallのコンパイル位置が必要になる。また、それ以外の最適化の為になるかもしれないので、コンパイルルーチンを呼ぶと、自動的にコンパイルしたワード(のコード)アドレスとcallの位置を専用のスタックに積むようにした。ワード定義開始時にそのスタックをクリアする。

https://github.com/phaendal/RFR64/blob/master/rfr64.asm:本体の「最適化用コンパイルスタック」のあたりでいろいろ定義している。

末尾呼び出し最適化は、最後に積まれた32bit相対call(x86-64)を32bit相対jumpに置き換えることで一応できた。litDOVARDODOESなどの、リターンスタックを扱う特殊なコードの場合は最適化をしない。

全ての可能な末尾呼び出しを自動で最適化したいところだけど、問題が起きるワードを特定できてないので現時点では難しい。例えばリターンアドレスを扱うワードでは、jumpではなくcallで来ることを期待しているので、それらも最適化を避ける必要がある。callを要求するワードである、というフラグを使えばいいだろうか?結構骨が折れそうだ。

というわけで、現時点は: inc 1+ ; optimizeのように、最適化するワードの直後に書いて使うことにしている。ウーム。

いろいろやる前にまずはインラインワードの展開かな。それと0=などの条件判断命令とbranchの組み合わせを、jnzなどに置き換えるのもできればやってみたい。VFXForthとかのdup 2 =cmp rbx, 2に置き換えるような最適化はどうやればいいのか見当もつかない。パターンかな……

Forthやる気マンマンみたいな書き方だけど、実際は仕事でJavaScriptを、かなりClosure濫用して使っていることから、λでいろいろやるのやっぱり面白いなと再認識している。で、3imp読んで実装してみたいなどの欲求もあってSchemeを再び触っている。今日でForthの仕組みを書き終えたので、その分の時間を回したい。

広告を非表示にする