在CodeGen中有以下概念:
下图是CodeGen的实例:
如图所示, CodeGen会按LIR中的节点和LSRA分配的寄存器信息生成汇编指令, 并且会对指令进行分组储存在不同的IG中.
进入函数的prolog和离开函数的epilog指令也会在这里添加.
CodeGen还会对汇编指令的大小进行估算, 确定最多需要分配多少内存才可以编码这些指令.
在最后, Emiiter会从LoaderHeap中分配内存, 并且根据instrDesc编码机器代码.
下图是Emitter的实例:
除了写入机器代码外, Emiiter还会写入以下的信息:
最终写入的函数在内存中的结构如下:
机器代码的前面是函数头信息(CodeHeader), 函数头信息指向真正的函数头信息(RealCodeHeader), 真正的头信息中包含了上面提到的信息.
我们可以实际在Visual Studio中确认这一点:
图中的0x7ffa46d0d898就是CodeHeader的内容, 也是指向RealCodeHeader的指针.
后面的55 57 56 ...是机器代码, 表示push rbp; push rdi; push rsi; ....
打开0x7ffa46d0d898可以看到RealCodeHeader的内容.
参考链接这篇是JIT的入门+科普教程, 为了让内容更加易懂我省略了大量的实现细节, 也没有贴出CoreCLR中的代码.
在下一篇我将结合CoreCLR中的代码讲解JIT的具体工作流程, 内容会比这一篇难很多, 绝大多数C#程序员只要理解这一篇就很足够了.
posted on