アセンブリコードを読んでみたら - Scheme VM を書く

Gaku さんに指摘された件。
命令列の終端に達しているか?を毎回チェックしているが重そうだよねえという話。
確かに僕も気になっていた。これを番人形式にすれば速いのではなかろうか。


ただやってみるのではなくてアセンブリのコードを眺める。
その後にどれくらい改善されるかを予想するのが良さそうということに。

movl	12(%ebp), %eax
movl	16(%eax), %eax
cmpl	-120(%ebp), %eax
jb	.L948	

うん。まあ予想通りのコード。


番人形式にするならば他のインストラクションと同じ道をたどり dispatch_table を使った jump になる。

    goto *dispatch_table[(*pc_++).val()];
leal	-1452(%ebp), %eax
movl	%eax, (%esp)
call	_ZNK6scheme6Object3valEv
movl	_ZZN6scheme2VM3runENS_6ObjectEE14dispatch_table(,%eax,4), %eax
movl	%eax, -1472(%ebp)
jmp	.L1887
.L952:
.L1887:
jmp	*-1472(%ebp)


ええええええ。 val() がインライン展開されてねぇ。毎回 call されている。

word val() const { return val_; }


public にして (*pc_++).val で参照するようにした。


計測結果。ちょw。ありえねぇぇえ。2倍くらい速くなった。


この結果には満足していますが偶然たどり着いたようなもの(&Gakuさんのおかげ)なのでちと修行します。
まだ速くなりそう。
これくらいインライン展開されるだろうと思ってたんだけど。
クリティカルなところはちゃんと見ないとな。