Leopardの発売から1カ月半が経過した。Objective-C 2.0に深く切り込みたいものとしては、Mac OS X 10.5であるDarwin 9.0に搭載されているObjective-Cランタイムのソースコード公開を待ち望んでいるのだが、なかなかその気配は訪れない。
ただ待っているだけでは仕方ないので、手持ちの材料だけでObjective-C 2.0を探っていくことにしよう。Appleから公開されているドキュメントと、Mac OS X 10.4であるDarwin 8.10で公開されているソースコードを参考にしていく。
ガベージコレクタの実体とそのソースコード
では、前回の続きでガベージコレクションを探っていこう。
本連載としては、まずソースコードレベルから話を始めたかったのだが、前述のとおりLeopardではまだソースコードが公開されていない。
だがよく考えると、ガベージコレクションの機能自体は、Tigerで実装されていることを思い出した。たとえば、TigerのXcodeでビルドの設定を調べると、「Objective-Cガベージコレクションを有効にする」という項目がある。
![]() |
このように、ガベージコレクタ自体は実装されていた。ただし、Cocoaなどのフレームワークが対応していなかったため、使用することは事実上できなかったのだが。
そこで、TigerのObjective-Cランタイムのソースコードをあたってみよう。Darwin 8系の最新であるDarwin 8.10に搭載されている、objc4-274のソースコードを見てみる。すると、objc-auto.mというファイルがある。これが、Objective-Cランタイムでのガベージコレクションを担当しているものになる。
このファイルには、objc_collectという関数がある。ガベージコレクションを開始するトリガーとなるものだ。そのソースコードを見てみよう。
objc-auto.m
void objc_collect(void)
{
if (UseGC) {
auto_collect(gc_zone, AUTO_COLLECTION_FULL_COLLECTION, NULL);
}
}
auto_collectという関数を呼んでいる。この関数の実体はどこにあるのか?
実は、auto_collectはObjective-Cランタイムの機能では、ない。libautoという、ランタイムとは別の、外部のライブラリに含まれる関数だ。このlibautoライブラリが、ガベージコレクションを実現している。Objective-Cランタイムは、このライブラリの1クライアントという立場になる。libautoは、/usr/lib/libauto.dylibにある※。
※このlibautoとObjective-Cランタイムとの関係は、Appleのドキュメント「Garbage Collection Programming Guide: Architecture」にも記述されている。
では、libautoのソースコードは公開されているかというと、Darwinの状況や、objc-auto.mに書かれているコメントから判断するに、オープンソースではないようだ。
という訳で、ガベージコレクタの実体がlibautoにあることはわかったが、そのソースコードは得られないようだ。
ガベージコレクタの統計的情報
とはいっても、objc-auto.mのソースコードからわかることもいくつかある。たとえば、autostatisticstという構造体の定義がある。これは、libautoで使われているもののようだ。
objc-auto.m
typedef struct {
unsigned version; // reserved - 0 for now
/* Memory usage */
unsigned long long num_allocs; // number of allocations performed
volatile unsigned blocks_in_use;// number of pointers in use
unsigned bytes_in_use; // sum of the sizes of all pointers in use
unsigned max_bytes_in_use; // high water mark
unsigned bytes_allocated;
/* GC stats */
/* When there is an array, 0 stands for full collection, 1 for generational */
unsigned num_collections[2];
boolean_t last_collection_was_generational;
unsigned bytes_in_use_after_last_collection[2];
unsigned bytes_allocated_after_last_collection[2];
unsigned bytes_freed_during_last_collection[2];
auto_date_t duration_last_collection[2];
auto_date_t duration_all_collections[2];
} auto_statistics_t;
libautoが管理するオブジェクトの統計的情報を表すもののようだ。メモリの使用状況や、ガベージコレクション発動後の状況が得られるようだ。この構造体の値は、libautoに含まれる関数、auto_collection_statisticsなどを使えば取得できるようだ。
これらの情報も使いながら、ガベージコレクションの動作を探っていきたい。