ES-VM #1
(1)
- ES-Cでは、いきなりx86の機械語を生成するのではなく、仮想的なCPU(=VM)の機械語を生成して、そのVM用のコードから実CPUの機械語を生成するという仕組みを採用しようと思っています。
- これはx86だけを考えるのなら明らかに無駄です。x86だけ考えていればよいのであれば、こんな余計な中間レイヤはないほうが速いし、処理系は小さくできるのです。・・・しかしx86以外も考えるのであれば、この仕組みは理にかなっています。
- 今はx86やx64が主流ですが、今後もそうであるかは不明です。私は将来自作CPUを作るのかもしれません。そうなったら、自作のCPU上でES-Cを動かしたいです。もしこのVMレイヤがあれば、最小限の手間で自作CPUに移植できるでしょう。
- そういうVMレイヤがあったほうがよいのだとしても、自分でわざわざ独自仕様を考えたりせずに、それこそx86の仕様をそのまま使うか、もしくはそのサブセットでいいじゃないかという考え方もできます。この場合、x86であればVM用のコードはそのままかもしくは軽微な変換ですぐに実行できることになります。そして他のCPU上で動かす場合は、変換して動かすことになります。
- しかしこれはうまい方法ではないと思います。なぜならx86よりもレジスタを多く持つCPUはいくつかありますが、x86からこれに変換するとすべてのレジスタを活用しない機械語になってしまうからです。
- またx86は32bitもしくは64bitですが、遠い将来はもっと幅の広いCPUがでてくるかもしれません。そのときに32bitや64bitを前提にしている、ちまちまと計算するプログラムは、広いビット幅を十分には活用できません。
- ということで、VMレイヤの機械語の仕様は、ビット幅に上限がなく、またレジスタ数にも上限がないようなそういうものであるべきです。そしてそれぞれのCPUの実際の仕様に合わせて、必要に応じて多倍長演算したり、レジスタに乗りきらないものはメモリに置くなどして、機械語を生成することになります。
- x86やx64の仕様ではこれらを表現できないので、独自の機械語を考えようと思います。これがES-VMです。
(2)
- さてES-VMはコンパイラの移植性を高めるためだけの、単なる中間コードなのでしょうか。・・・そういう設計で作ることもできると思いますが、私は直感的にそれでは不十分だと感じています。
- ES-VMは、レイヤとして最下層であるべきです。つまり、実CPUの知識がなくても何も困らないようになっているべきです。
- たとえて言うなら、x86は世代によって内部構成が異なっていますが、それでも最適化の時以外はその内部構成に配慮する必要はありません。実にうまくできています。
- つまりデバッグの際にx86の機械語を見たり、x86のマシンのレジスタの値を見たりするというのはダメだということです。例外で止まったりブレークポイントで止まったりしたときは、ES-VMの命令のどこで止まったのか、その時のES-VMのレジスタはどうなっているのか、メモリはどうなのかなど、すべてES-VMの知識の範囲内で説明できなければいけないという意味です。
- 「とりあえずES-VMの機械語からx86に変換したよー、それじゃあとはよろしくねー」はダメだというわけです。
- 私は数年前からJITコンパイラを何度か作っていますが、その時に思ったのは、「なぜ21世紀にもなって、x86の機械語の知識がなければやりたいことができないのか」ということでした。プログラミング言語は何度も何度も大きな進化を遂げてきたはずなのに、そして普段はC++とかを使うだけで十分に高速なプログラムが書けるのに、JITコンパイラを作ろうと思ったとたんにすべてのメッキははがれて、機械語の知識が必要になってしまったのです。
- gccは内部で何度か変換を繰り返して、最終的にアセンブラのソースを出力し、それがx86のアセンブラに入って、それがリンカに入って機械語が出てきます。つまり、JITではない普通のコンパイラに限れば、リンカの上にアセンブラ、その上にコンパイラ、とどんどん積み重ねられて正常進化してきたのです。でもJITコンパイラを作ろうとすると、何も積み重なってなくて、むき出しの地面だったのです。こういうのはいけないのです。
- だからもういかなる時もES-VMより下のレイヤの知識がなくてもいいようにする、それが目標です。