JIT…その前に

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も入れて下さい(キリッ」とかいうことになって、
エンドユーザー死ぬ.

カテゴリー: コンピューターとインターネット パーマリンク

JIT…その前に への1件のフィードバック

  1. ピンバック: PSLの遅さの理由とか速度改善案とかJITの使い道とか | 生存確認兼近況報告日記

コメントを残す