SIODのGCリーディング(2) - GC Advent Calendar

Garbage Collection Advent Calendarの11日目の記事です。

mark-sweepの方はなんだかんだ一緒だったので、まあ別に説明するほどでもなさそうです。
読みやすいソースコードで楽しかったです。

ということでCopyingGCを見てみましょう。

void gc_stop_and_copy(void)
{LISP newspace,oldspace,end;
 long flag;
 flag = no_interrupt(1);
 errjmp_ok = 0;
 oldspace = heap_org;
 end = heap;
 old_heap_used = end - oldspace;
 newspace = get_newspace();
 scan_registers(); // <- (1)
 scan_newspace(newspace);
 free_oldspace(oldspace,end);
 errjmp_ok = 1;
 no_interrupt(flag);}

まず確かめたいのはこれがConservativeなCopyingGCなのかなー、という点です。
(1)のscan_registers()を詳しく見てみましょう。

void scan_registers(void)
{struct gc_protected *reg;
 LISP *location;
 long j,n;
 for(reg = protected_registers; reg; reg = (*reg).next) // <- (2)
   {location = (*reg).location;
    n = (*reg).length;
    for(j=0;j<n;++j)
      location[j] = gc_relocate(location[j]);}}  // <- (3)

(2)のprotected_registersというのはgc_protect()という関数で登録されます。
(3)のgc_relocate()というのでnewspaceにオブジェクトを移動するみたいですねえ。

scan_newspace()でscan_registersでnewspaceに移動しておいたオブジェクトをtraverseしながら移動するようです。

void scan_newspace(LISP newspace)
{LISP ptr;
 struct user_type_hooks *p;
 for(ptr=newspace; ptr < heap; ++ptr)
   {switch TYPE(ptr)
      {case tc_cons:
       case tc_closure:
         CAR(ptr) = gc_relocate(CAR(ptr));
         CDR(ptr) = gc_relocate(CDR(ptr));
         break;
       /* 略 */
       default:
         p = get_user_type_hooks(TYPE(ptr));
         if (p->gc_scan) (*p->gc_scan)(ptr);}}}

(2)で観たとおりgc_protect()で登録したポインタがrootsとなるようですね。
では、どこで呼ばれているかというと、それはドキュメントに書いてありました。

The procedure gc_protect is called once (e.g. at startup) on each global location which will contain a lisp object.

http://people.delphiforums.com/gjc/siod.html#garbage

起動時にlisp objectを収容するであろうglobal locationをそれぞれ登録するみたいです。
シンボルとか、そういうやつですね。

じゃあマシンスタックに乗ったりレジスタに乗ったりしたやつはルートにしないのかあ、と思ったんですけど、これでも実装できるのかなあ。
関数実行中に消えちゃったりしないのかな、と、思ったが。

YOU CAN GC ONLY AT TOP-LEVEL

http://people.delphiforums.com/gjc/siod.html#garbage

GCのタイミングがトップレベルに限られているらしい。
そうかあ、メモリは増え続けちゃいそうだけど、致命的な問題にはならないかあ。

とりあえずSIODシリーズは終わりー。