OGC 中 reference counting 的機制相當簡單。利用 grep
查看程式碼中有那些地方更改到了 garbage collector 中 ref_count
的值,來進一步做程式碼的閱讀。
在其他程式碼中,開發者可能會多次呼叫 core.c
中的 gc_init
,來代表使用(reference) 到 garbage collector。
在上述程式碼 3-6 行,為當已經有人使用了 garbage collector,其他人再次使用時,只會將 garbage collector 的 ref_count++
,代表在其他程式碼中,有 ref_count
個地方使用到 garbage collector。
反之,當我們使用完 garbage collector 時,會呼叫 core.c
中 gc_destroy
。這個函式很簡單,當 garbage collector 的 ref_count
減為 0 時,代表沒有人使用 garbage collector。程式碼就將由 garbage collector 控管的記憶體全部 free
掉。
程式碼中執行 mark & sweep 的動作在 core.c
中的 void gc_run(void)
。
gc_mark_stack
做完後,所有 reachable 的 memory block 都會被 mark。因此在接下來的 gc_sweep
,這些 memory block 就不會被 free 掉,反之,沒有被 mark 的都會被 free 掉。
這邊觀看一下 gc_mark_stack
.
程式碼第 4 行,程式碼呼叫 gc_mark
,並傳入 __gc_object.stack_start
, &tmp
。用 test/dummy.c
這個測試碼,stack_start
為 &argc
。
上述的 for 迴圈初始值會永遠保持 NULL,似乎是 BUG。我認為可以直接忽略。
再來看看 gc_mark
的行為
程式碼會在傳進去的某個地址範圍,找尋 gc_list_t 的指標,若有找到則查看此 memory block 有否被 mark,若無則 mark。然後繼續遞迴的搜索此 memory block 有沒有 gc_list_t 的指標。
以下用是上述程式碼的圖解
最後是 gc_sweep
做 garbage collection 的操作。
程式碼還算直覺,查看所有由 garbage collector 控管的 memory block,若其沒有被 mark (!e->data.marked
),就會被 free 掉,反之則將 marked 的 memory block 變為 unmark,留待下一輪的 garbage collection 處理。
sysprog2019