# 2019q1W7下: 陳冠廷 ### 測驗 `1` 程式碼中利用 `__gc_object.ptr_map[i]` 加速 linked list 存取 每當呼叫 `gc_alloc` 時,會在 hashmap 中對應的 linked list 插入一個`gc_list_t` 用於保存 malloc 的地址以及大小和一個 marked 的 flag,在稍後的 GC 流程中會使用到(注意在建立時不會設定 marked) 除此以外也會將 `__gc_object.ptr_num` 的值加 1 :::warning 搭配解釋 `HASH` 巨集的用法 :notes: jserv ::: 在 `__gc_object.ptr_num >= __gc_object.limit` 的情況下呼叫 `gc_alloc()` 就會觸發 `gc_run()` 執行 garbege collection,做法是從目前的 stack 頂端也就是下方程式碼中的 `&tmp` 開始,掃到最一開始在 main 中設定的 `__gc_object.stack_start` ```cpp void gc_mark_stack(void) { uint8_t tmp; gc_mark(__gc_object.stack_start, &tmp); ... } ``` ```cpp int main(int argc, char *argv[]) { gc_init(&argc, 1); ... } ``` 將存在這個區段中的任意值取出來作為指標,接著到 hashmap 中查詢該指標是否是使用者透過 `gc_alloc()` 所配置的記憶體,若是則標註 `idx->data.marked` 並以相同方式繼續在該記憶體區段中 dfs 搜尋,若非就不做任何改變 :::warning 其實只是從`gc_mark_stack()`的 stack frame 隨便挑一個位置開始算到 `main()` 結束,所以實際上若是 stack 上有殘留沒被清除或覆蓋掉的`gc_alloc()`指標就會多算 ::: ```cpp void gc_mark(uint8_t *start, uint8_t *end) { if (start > end) swap_ptr(&start, &end); while (start < end) { gc_list_t *idx = gc_ptr_index((uintptr_t)(*((void **) start))); if (idx && idx->data.marked != true) { idx->data.marked = true; gc_mark((uint8_t *) (idx->data.start), (uint8_t *) (idx->data.start + idx->data.size)); } start++; } } ``` 接著 `gc_sweep()` 會遍歷 `__gc_object.ptr_map` 將沒有被標記 (marked) 的指標 free 掉,並刪除 list 中該節點,要注意的是此時若是遇到有標記的指標會將該標記清除,至此完成一次的 GC ```cpp void gc_sweep(void) { for (int i = 0; ++i < PTR_MAP_SIZE;) { gc_list_t *e = __gc_object.ptr_map[i]; int k = 0; while (e) { if (!e->data.marked) { gc_mfree(e); e = e->next; gc_list_del(&__gc_object.ptr_map[i], k); } else { e->data.marked = false; e = e->next; } k++; } } } ```
×
Sign in
Email
Password
Forgot password
or
Sign in via Google
Sign in via Facebook
Sign in via X(Twitter)
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
Continue with a different method
New to HackMD?
Sign up
By signing in, you agree to our
terms of service
.