GCInfo完整编码,从0bit到开始

前言
看下GCInfo里面除了包含要标记的对象的偏移(spoffset)之外,还有哪些东西。

概括

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   1Bm_m_StackBaseRegister ==1 1Bm_ReturnKind==0  2Bm_CodeLength==7C 8B +1BnumCallSites==0 2b+1b0==0 1b1==1 1bnumStackSlots==0 2b+1bnumUntrackedSlots==1 1b+1bpSlotDesc->Slot.Stack.Base==0  2bcurrentNormStackSlot 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。他们的值是:0010m_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位给它还原到正确的位置。