GC Heap 運行一段時間後,配置空間不斷增長。進行局部或完整 GC 時,會執行 壓縮:移動倖存物件消除碎片。問題來了——若某「小物件」被移動,且被其他物件引用,GC 必須找到所有指向該物件的引用並更新。遍歷整個 Heap、Root、Handle Table 極其昂貴。Card Table 與 Brick Table 正是為解決此問題而生的輔助索引結構。
0xFF。obj.Field = otherObj)時,JIT 生成的代碼會自動插入寫入屏障,呼叫 GCHeap::ErectWriteBarrier 或 WriteBarrierHelper。0xFF(標記「髒」)。ErectWriteBarriervoid GCHeap::ErectWriteBarrier(OBJECTREF *dst, OBJECTREF ref)
{
// 1. 檢查 dst 是否在 GC Heap 範圍內
if (((BYTE**)&dst) < g_lowest_address || ((BYTE**)&dst) >= g_highest_address)
return;
// 2. 檢查引用目標 ref 是否在 Ephemeral 範圍內(Gen 0/1)
if ((BYTE*)OBJECTREFToObject(ref) >= g_ephemeral_low
&& (BYTE*)OBJECTREFToObject(ref) < g_ephemeral_high)
{
size_t card = gcard_of((BYTE*)dst);
BYTE* pCardByte = (BYTE*)g_card_table + card / 8; // CARDS_PER_BYTE = 8
BYTE bitMask = (BYTE)(1 << (card % 8));
// 3. 若該 bit 未置位,整個 byte 置 0xFF(標記 1KB 區域為髒)
if (!(*pCardByte & bitMask))
*pCardByte = 0xFF;
}
}
stfld, stobj, stelem.ref 等)後插入屏障代碼,x86 下通常為幾條組合語言指令。short[])。GC 壓縮/掃描階段,快速定位 Heap 中某位址對應的物件起始位置。配合 Card Table 使用:Card Table 粗略定位「髒區域」,Brick Table 精確定位區域內的物件邊界。
Card Table 與 Brick Table 均為近似結構: