CLR深度结构内存模型,主要是跨代引用。用以描述老年代引用新生代(短暂堆)里面的对象范围。
1.GCDesc GC对象内存范围操作结构模型
class CGCDesc
{
CGCDesc () {}
}
可以看到它里面只有一个默认构造函数。
2.CGCDescSeries GC对象内存范围描述结构模型
class CGCDescSeries
{
public:
union
{
size_t seriessize;
val_serie_item val_serie[1];
};
size_t startoffset;
}
一个共用体和一个八字节的成员变量。
3.card_table 位标记描述表,它是一块二进制内存,用十六进制表示
0x7fffffff44444444 ffffffffffffffff ffffffffffffffff
ffffffffffffffff ffffffffffffffff
ffffffffffffffff 00000000000000ff
比如n1.selfName= n2会用JIT_WriteBarrier设置0xff,也即是上面的
00000000000000ff
4.整体
card_table确认老年代里面包含了引用新生代(短暂堆)的对象,遍历card_table查找出这个范围。然后遍历这个范围,找到老年代引用的新生代对象,对它的MethodTable最后一位标记存活。 这里的找到老年代引用的新生代对象,需要借助GCDesc和CGCDescSeries,它们的大致内存模型如下,某个对象的地址0x000001E0F5043F28,00007fff4a423448是MT.
0x000001E0F5043F28 00007fff4a423448
它的MT如下:
0x00007FFF4A423448 0000002001000000 0000000400080080 00007fff4a423338 00007fff49ab6110 00007fff49e3dc88
从它MT-0x20start=开始:
0x00007FFF4A423420 00007fffa956d5f8 0000000000001b78 fffffffffffffff0 0000000000000008 0000000000000001
0x00007FFF4A423448 0000002001000000 0000000400080080 00007fff4a423338 00007fff49ab6110 00007fff49e3dc88
看内存,此时计算范围公式是:
start=0x000001E0F5043F28+*(uint64_t*)(0x00007FFF4A423448-0x10);
end =start+*(uint64_t*)(0x00007FFF4A423448-0x18)+8;
在star和end之间寻找老年代引用的新生代对象,然后对它进行标记。