概括
1.示例
以如下代码为例:.
static void Main()
{
int[] array = new int[10_000_000];
GC.Collect();
for (int i = 0; i < 1_000_000; i++)
{
Test(array);
}
}
2.格式
它的格式大致如下:
Slim encoding ==0 1B
m_m_StackBaseRegister ==1 1B
m_ReturnKind==0 2B
m_CodeLength==7C 8B +1B
numCallSites==0 2b+1b
0==0 1b
1==1 1b
numStackSlots==0 2b+1b
numUntrackedSlots==1 1b+1b
pSlotDesc->Slot.Stack.Base==0 2b
currentNormStackSlot 6b +1b
Slim encoding表示超薄编码,意味着没有什么特别的,部分可中断,可能是默认的帧寄存器。后面的==0表示它的值为0,后面的1B表示它占据了内存空间的1个bit位。其它的以此类推,比如第二个m_m_StackBaseRegister它的值是1,占据1个bit位。
3.解析
Main的GCInfo在内存里面设若如下数值:0x00000000712207c2。它的二进制是:0111 0001 0010 0010 0000 0111 1100 0010
小端来看,从右到左。0010表示Slim encoding,m_m_StackBaseRegister,m_ReturnKind。共占据了四个bit。他们的值是:0010
m_CodeLength,numCallSites,0,1共占据了14个bit。他们的值是:10 0000 0111 1100.
最后的numStackSlots,numUntrackedSlots,Base,currentNormStackSlot共占了14个bit。值是:0111 0001 0010 00。
所以最终内存数值就是:0x00000000712207c2。
注意它这个里面的currentNormStackSlot,它实际上就是对象的偏移值。比如-8。十六进制是:0xfffffff8。它经过GCInfo的编码最终变成了:0x0000000070000000。
关于这个-8变成0x0000000070000000的过程,可以看前一篇:点击此处
4.补充
关于为啥左移0x3A,右移0x3A就能实现0x70000000到0x38的变化,实质上在(n &((1<< base)-1))里面,它获取到就是n的最后六个bit位,这个左移和右移0x3A无非是把这6个bit位给它还原到正确的位置。