PSLはまあ遅いです.
まあ最低限必要な分はあるし、そこまで速度が要求される場面でもないだろう、
というのが一応の統一見解ではあるのですが、
だからといって速い方がいいことはいいに決まっている.
でまあ、JITというのは当然に選択肢の一つにはなるわけですが、
他のアプローチと比較すると、これがまあ何をしたらいいの?って感じではある.
動的型付け言語であるとかそういうこともあるんですが、
まず、機械語を動的に生成してそれを実行するってどうするんだ、っていう話です.
生成はまあいいですよ、生成ですよ、コンパイラと同じことやれっていうだけですよ.
その場で生成したコードをどうやって実行させるのさ?
まあC言語なんてメモリやスタックが丸見えですよ、どうとでもなるんじゃないの、
取り敢えず試してみましょうよ.
#include <stdio.h> int add(int a, int b) { return a + b; } int main(void) { printf("%d\n", add(10, 20)); return 0; }
こいつをコンパイルして逆アセンブルしてみるとですね.
00401000 /$ 55 PUSH EBP 00401001 |. 8BEC MOV EBP,ESP 00401003 |. 8B45 08 MOV EAX,DWORD PTR SS:[EBP+8] 00401006 |. 0345 0C ADD EAX,DWORD PTR SS:[EBP+C] 00401009 |. 5D POP EBP 0040100A \. C3 RETN
addの中身はこんな感じでありまする.
したらば、
#include <stdio.h> int main(void) { void *p = "\x55\x8B\xEC\x8B\x45\x08\x03\x45\x0C\x5D\xC3"; int (*add)(int,int) = p; printf("%d\n", add(10, 20)); return 0; }
こいつを実行してみれば、普通に実行出来ますとも.
まあこれが普通に実行出来なかったらバッファオーバーランとか大したことにならんしな.
ついでに、
#include <stdio.h> int add(int a, int b) { return a + b; } int main(void) { unsigned char *p = (unsigned char*)add; int i; for (i = 0; i < 16; i++) printf("%.2X ", p[i]); return 0; }
こうやってみたるらば、
55 8B EC 8B 45 08 03 45 0C 5D C3 CC CC CC CC CC
が出力されます.
addのsizeofを取ろうとしたら無理でしたがね.
うーん、それが出来るのならば幾分マシな方法がありはするのだが.
その場で生成したコード(まあ今回は埋め込んでますけど)を、
動的に実行すること自体は簡単でした.
まあしかし実際は当然ですが、
(そのアーキテクチャに応じた)機械語コードをその場で生成せねばなりません.
対象がx86でWindowsで、と決まっているならまあやらんでもないですが、
可搬性も(後付けながら)ウリの一つではあるので厳しい.
この方面のアプローチであれば現実的にはLLVMに載せる、辺りになるのでしょうか.
しかしそうすると、「PSLを使うにはLLVMも入れて下さい(キリッ」とかいうことになって、
エンドユーザー死ぬ.
ピンバック: PSLの遅さの理由とか速度改善案とかJITの使い道とか | 生存確認兼近況報告日記