メモリ管理とか

メモリ管理について。LuaがあくまでGCなのに対してSquirrelは基本的なメモリのライフタイムの管理にリファレンスカウンタを採用している。バリアント変数の実体のような、すべての型の共用体とその内容の型情報を保持するSQObject構造体があり、これを継承してスマートポインタ的機能をつけたSQObjectPtr構造体が作られている。Squirrelスクリプトがユーザーに提供する変数等のデータ保持機構は必ずこの構造体を用いている。

リファレンスカウンタ方式は循環参照が形成されたときにお互いがお互いを消せなくなって残ってしまう。例えばgeneratorというthreadの泥臭い版のようなものがサポートされているが、これは途中で関数の実行を止めたり再開したりするために自分が実行された環境を保管している。多くの場合でここには自分自身が帰属するテーブルが含まれている。このために循環参照ができてしまい、実際このようなgeneratorを実行中にこのテーブルへの参照を切ってしまうと、generatorとテーブルの間の循環参照だけが取り残されてしまい、メモリリークとなる。こういった問題を補完するためにGCを併用することもできる。デフォルトではこのGCが有効になっている。GCを使っていればこのようなVMを閉じたときに発生するメモリリークは絶対に起こらないが、VM内のメモリの確保や開放時に余分なコードが差し挟まれてしまう。

ちょっといい話
SQObjectPtrはソースコードのsqobject.h : 130行目あたりから定義されている。すべての型のためのオーバーロードされたコンストラクタと代入のためのoperator=が書かれている。現状では(ver.2.1.1)、このSQObjectPtrにSQIntegerやSQFloat等のプリミティブ型を代入したいとき、無駄にSQObjectPtrのコンストラクタが呼ばれ、また、無駄にoperator=内の_AddRef() (リファレンスカウンタのインクリメントを行うマクロ。プリミティブ型かどうか調べ、そうであれば何もしない。) が呼ばれている。算術演算が多い場合にはここが結構なボトルネックになる。ここへならべてSQIntegerやSQFloatを引数にとる_AddRef()しないoperator=を定義してやればそれなりのスピードアップが期待できると思う。