突然VM気分

私自身はオブザーバー的にしか関与していない某プロジェクトのリリース機運が盛り上がっていて、VMをに新しい機能を入れてフィックスさせようとする動きがある。僕もいくつか入れて欲しいものがあるので、泥縄的にInterpreterとObjectMemoryのメソッドを書き換えてみた。

primitive番号115は、レシーバーとなっているオブジェクトのクラスを、引数として渡されたオブジェクトのクラスに変える、というものであった。が、いったいいかなる歴史的理由か、引数はクラスオブジェクトではなく、そのクラスのインスタンス変数ということになっている。そのため、自分で新しく作り出したクラスのインスタンスに変えたいだけなのに、意味もなく新しいクラスのインスタンスをひとつ作って、それを引数に渡さなくてはいけない。

それより意味不明なのは、こうやってクラスを変えた後に、ダミーのインスタンスを即座に消去すべく、明示的にガーベージコレクションを呼んでいることである。コードを書いたAndreasに聞いても、「ハックだったんだけど、なんでそのインスタンスを消さなくちゃいけないのか忘れた」ということだった。

要は、引数をクラスオブジェクトに変えればすべて解決なのだが、いちおう過去との互換性も維持するために、引数をひとつ余計にとっている場合はクラスが直接渡されたと思ってそのクラスに変更するように変えてみた。

引数に渡されたものがクラスオブジェクトかどうか調べれば良いのでは、と思われるかもしれないが、クラスオブジェクトであってもそのメタクラスを変えたくなることがあるかもしれないのでそういうわけには行かない。そもそもVM上ではそれがクラスオブジェクトかどうかを簡単に見分ける術はなかったりするし。

もうひとつは、non-pointerオブジェクトを作るときに、0-fillしないで作れる道を作るという変更。copyFrom:to:やForm>>copy:は結果となる新しいオブジェクトを作ってからその中身を埋めるのだが、どうせ埋めるということが判っているのに全部0(あるいはnil)で初期化した後、もう一度書き直している。non-pointerオブジェクトなら、別に危ないことはないので(メモリ中にあったパスワードのような文字列が取れてきてしまう、という危険はあるのかもしれないが)、初期化しないことによって25%くらいの高速化が図れるわけである。最近は、大きなnon-pointerオブジェクトがあちこちで使われているので、トータルで見ても結構効き目があるのではないかと思う。