HTML5技术

CoreCLR源码探索(二) new是什么 - q303248153

字号+ 作者:H5之家 来源:H5之家 2017-01-12 09:04 我要评论( )

前一篇我们看到了CoreCLR中对Object的定义,这一篇我们将会看CoreCLR中对new的定义和处理 new对于.Net程序员们来说同样是耳熟能详的关键词,我们每天都会用到new,然而new究竟是什么? 因为篇幅限制和避免难度跳的太高,这一篇将不会详细讲解以下的内容,请

前一篇我们看到了CoreCLR中对Object的定义,这一篇我们将会看CoreCLR中对new的定义和处理
new对于.Net程序员们来说同样是耳熟能详的关键词,我们每天都会用到new,然而new究竟是什么?

因为篇幅限制和避免难度跳的太高,这一篇将不会详细讲解以下的内容,请耐心等待后续的文章

使用到的名词和缩写

以下的内容将会使用到一些名词和缩写,如果碰到看不懂的可以到这里来对照

BasicBlock: 在同一个分支(Branch)的一群指令,使用双向链表连接 GenTree: 语句树,节点类型以GT开头 Importation: 从BasicBlock生成GenTree的过程 Lowering: 具体化语句树,让语句树的各个节点可以明确的转换到机器码 SSA: Static Single Assignment R2R: Ready To Run Phases: JIT编译IL到机器码经过的各个阶段 JIT: Just In Time CEE: CLR Execute Engine ee: Execute Engine EH: Exception Handling Cor: CoreCLR comp: Compiler fg: FlowGraph imp: Import LDLOCA: Load Local Variable gt: Generate hlp: Help Ftn: Function MP: Multi Process CER: Constrained Execution Regions TLS: Thread Local Storage .Net中的三种new

请看图中的代码和生成的IL,我们可以看到尽管同样是new,却生成了三种不同的IL代码


我们先来看newobj和newarr这两个指令在coreclr中是怎么定义的
源代码:

OPDEF(CEE_NEWOBJ, "newobj", VarPop, PushRef, InlineMethod, IObjModel, 1, 0xFF, 0x73, CALL) OPDEF(CEE_NEWARR, "newarr", PopI, PushRef, InlineType, IObjModel, 1, 0xFF, 0x8D, NEXT)

我们可以看到这两个指令的定义,名称分别是CEE_NEWOBJ和CEE_NEWARR,请记住这两个名称

第一种new(对class的new)生成了什么机器码

接下来我们将看看coreclr是如何把CEE_NEWOBJ指令变为机器码的
在讲解之前请先大概了解JIT的工作流程,JIT编译按函数为单位,当调用函数时会自动触发JIT编译

下面的代码虽然进过努力的提取,但仍然比较长,请耐心阅读

我们从JIT的入口函数开始看,这个函数会被EE(运行引擎)调用
源代码:
源代码:
注: 按微软文档中说CILJit是32位上的实现,PreJit是64位上的实现,但实际我找不到PreJit在哪里

CorJitResult CILJit::compileMethod( ICorJitInfo* compHnd, CORINFO_METHOD_INFO* methodInfo, unsigned flags, BYTE** entryAddress, ULONG* nativeSizeOfCode) { // 省略部分代码...... assert(methodInfo->ILCode); result = jitNativeCode(methodHandle, methodInfo->scope, compHnd, methodInfo, &methodCodePtr, nativeSizeOfCode, &jitFlags, nullptr); // 省略部分代码...... return CorJitResult(result); }

jitNativeCode是一个负责使用JIT编译单个函数的静态函数,会在内部为编译的函数创建单独的Compiler实例
源代码:

int jitNativeCode(CORINFO_METHOD_HANDLE methodHnd, CORINFO_MODULE_HANDLE classPtr, COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags, void* inlineInfoPtr) { // 省略部分代码...... pParam->pComp->compInit(pParam->pAlloc, pParam->inlineInfo); pParam->pComp->jitFallbackCompile = pParam->jitFallbackCompile; // Now generate the code pParam->result = pParam->pComp->compCompile(pParam->methodHnd, pParam->classPtr, pParam->compHnd, pParam->methodInfo, pParam->methodCodePtr, pParam->methodCodeSize, pParam->compileFlags); // 省略部分代码...... return result; }

Compiler::compCompile是Compiler类提供的入口函数,作用同样是编译函数
注意这个函数有7个参数,等一会还会有一个同名但只有3个参数的函数
这个函数主要调用了Compiler::compCompileHelper函数
源代码:

int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd, CORINFO_MODULE_HANDLE classPtr, COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags) { // 省略部分代码...... pParam->result = pParam->pThis->compCompileHelper(pParam->classPtr, pParam->compHnd, pParam->methodInfo, pParam->methodCodePtr, pParam->methodCodeSize, pParam->compileFlags, pParam->instVerInfo); // 省略部分代码...... return param.result; }

让我们继续看Compiler::compCompileHelper
源代码:

int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, COMP_HANDLE compHnd, CORINFO_METHOD_INFO* methodInfo, void** methodCodePtr, ULONG* methodCodeSize, JitFlags* compileFlags, CorInfoInstantiationVerification instVerInfo) { // 省略部分代码...... // 初始化本地变量表 lvaInitTypeRef(); // 省略部分代码...... // 查找所有BasicBlock fgFindBasicBlocks(); // 省略部分代码...... // 调用3个参数的compCompile函数,注意不是7个函数的compCompile函数 compCompile(methodCodePtr, methodCodeSize, compileFlags); // 省略部分代码...... return CORJIT_OK; }

现在到了3个参数的compCompile,这个函数被微软认为是JIT最被感兴趣的入口函数
你可以额外阅读一下微软的JIT介绍文档
源代码:

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • CoreCLR源码探索(一) Object是什么 - q303248153

    CoreCLR源码探索(一) Object是什么 - q303248153

    2017-01-06 11:04

  • 升讯威ADO.NET增强组件(源码):送给喜欢原生ADO.NET的你 - sheng.chao

    升讯威ADO.NET增强组件(源码):送给喜欢原生ADO.NET的你 - sheng.c

    2016-12-20 11:01

  • html5 Sortable.js 拖拽排序源码分析 - qq281113270

    html5 Sortable.js 拖拽排序源码分析 - qq281113270

    2016-11-04 15:00

  • MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则) - 懒得安分

    MVC系列——MVC源码学习:打造自己的MVC框架(三:自定义路由规则)

    2016-11-03 18:00

网友点评
g