rowlVM/GC ブロック・ページの管理
この論文
Compacting Garbage Collection with Ambiguous Roots
ではあらかじめ固定長のメモリブロックがあって個定数のページがあるような実装になっているので直します。
GHCのアロケータ実装を参考にしています。
まず、メモリはブロック単位(1Mbyte)でアロケートすることにします。
1ページは512バイトにします。
ページデスクリプタには
- joined flag (前のページと連結しているかを表すフラグ。512バイトより大きいオブジェクトのアロケートに必要)
- generation (Copy-GCにおける世代番号)
- next (GC時にスキャン待ち行列に突っ込むので、そのためのポインタ)
が必要です。前者二つは1ワードにパックすることにして、2ワード(8バイト)必要です。
このページデスクリプタ(pd)の配列をブロックの先頭に配置します。
そうすると最大ページ数は(512+8)*N <= 1Mbyteより2016ページになります。末尾の1M - (512+8)*2016 = 256byteはもったいないですが、使用され
ません。
|<------------------ 1Mbyte --------------------------->| |<--- 8*2016 byte --->|<------ 512*2016 byte ------>| |pd0|pd1|pd2|...|pdN-1|page0|page1|page2|...|pageN-1|...|
ページアドレスの計算
各ブロックは1Mbyte境界に配置します。
すると
ページデスクリプタ(pd)のアドレスがpの場合、
p&~((1<<20)-1) == pdが属するブロックの先頭 p&((1<<11)-1) == pdのブロック先頭からのオフセット (pdのオフセット)>>3 == pdの番号 ブロック先頭+8*2016+pdの番号*512 == ページのアドレス
となります。
これを整理して
ページのアドレス == p&~((1<<20)-1) + 16128 + (p&((1<<11)-1))<<6
となります。~((1<<20)-1)と((1<<11)-1)は定数なので見た目ほどステップ数はいりません。
オブジェクトが属するページの計算
オブジェクトのアドレスがpの場合
(p-8*2016)/512がページ番号になります。