言語処理系のC拡張とGC

GCがある処理系、特にポインタが移動するCopying GCやGenerational GCなどは、プリミティブやC拡張を書くのが結構面倒だったりする。 Cやマシン語での処理の際に、新しいオブジェクトを作ると、GCが発動してポインタが動いてしまう可能性があるから。

そういった言語がいかに拡張を書きやすくしているか調べてみる。

Chicken Scheme

Cheney on the M.T.AでCのスタックから移すのでポインタが移動するはず。

Interface to external functions and variablesEmbeddingを見ると、CHICKEN_new_gc_root関数がある。

という使用法かな。

処理系側の実装は楽そうだけど、使う際に消し忘れに気を付けないといけない。Early Returnの際に特に注意が必要。

Lua

Incremental Mark&SweepとGenerational GCの複合?

APIの章にThe Stackとある。 Cの関数呼び出しの際にスタックが用意され、引数や返り値の受け渡しはそこで行われる。また、GC Rootとしても扱われる。

スタックが関数呼び出し毎に用意されるので、push/popが必ず対になってる必要はない。indexから値を参照・変更すればいい。多値を返すときも楽そう。

まあちょっと面倒だとは思うし、面倒だとよく聞くけど、一番Cへの埋め込みに使われているし安定した手法なのかな。return時にUnprotectが必要ないのが良い。

考察

LuaみたいにC関数を呼び出すときにスタックを割り当てておいて、ローカル変数の位置をGCルートとしてスタック上に記録してしまうのはどうなんだろう。ただそんなに軽い処理とは思えないので、プリミティブのCコード実行時には使えなさそう。ここは要調査。

参照カウントとConservativeGCはそれぞれ利点欠点あるけど、一番面倒そうなのはデフラグ。この処理を自前でやるなら結構大変。ringではribbitの真似して3セルのみのオブジェクト表現でConservativeGCにしたので、まあ書くのはかなり楽だった。遅いけど。

TODO