HTML5技术

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

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

// Produce code for a GT_CALL node void CodeGen::genCallInstruction(GenTreePtr node){ // 省略部分代码...... if (callType == CT_HELPER){ // 把句柄转换为帮助函数的句柄,默认是CORINFO_HELP_NEWFAST helpe

// Produce code for a GT_CALL node void CodeGen::genCallInstruction(GenTreePtr node) { // 省略部分代码...... if (callType == CT_HELPER) { // 把句柄转换为帮助函数的句柄,默认是CORINFO_HELP_NEWFAST helperNum = compiler->eeGetHelperNum(methHnd); // 获取指向帮助函数的指针 // 这里等于调用compiler->compGetHelperFtn(CORINFO_HELP_NEWFAST, ...) addr = compiler->compGetHelperFtn(helperNum, (void**)&pAddr); } else { // 调用普通函数 // Direct call to a non-virtual user function. addr = call->gtDirectCallAddress; } }

我们来看下compGetHelperFtn究竟把CORINFO_HELP_NEWFAST转换到了什么函数
compGetHelperFtn的定义
源代码:

void* Compiler::compGetHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ void** ppIndirection) /* OUT */ { // 省略部分代码...... addr = info.compCompHnd->getHelperFtn(ftnNum, ppIndirection); return addr; }

getHelperFtn的定义
这里我们可以看到获取了hlpDynamicFuncTable这个函数表中的函数
源代码:

void* CEEJitInfo::getHelperFtn(CorInfoHelpFunc ftnNum, /* IN */ void ** ppIndirection) /* OUT */ { // 省略部分代码...... pfnHelper = hlpDynamicFuncTable[dynamicFtnNum].pfnHelper; // 省略部分代码...... result = (LPVOID)GetEEFuncEntryPoint(pfnHelper); return result; }

hlpDynamicFuncTable函数表使用了jithelpers.h中的定义,其中CORINFO_HELP_NEWFAST对应的函数如下
源代码:

JITHELPER(CORINFO_HELP_NEWFAST, JIT_New, CORINFO_HELP_SIG_REG_ONLY)

可以看到对应了JIT_New,这个就是JIT生成的代码调用分配内存的函数了,JIT_New的定义如下
需要注意的是函数表中的JIT_New在满足一定条件时会被替换为更快的实现,但作用和JIT_New是一样的,这一块将在后面提及
源代码:

HCIMPL1(Object*, JIT_New, CORINFO_CLASS_HANDLE typeHnd_) { // 省略部分代码...... MethodTable *pMT = typeHnd.AsMethodTable(); newobj = AllocateObject(pMT); // 省略部分代码...... return(OBJECTREFToObject(newobj)); } HCIMPLEND

总结:
JIT从CEE_NEWOBJ生成了两段代码,一段是调用JIT_New函数分配内存的代码,一段是调用构造函数的代码

第二种new(对array的new)生成了什么机器码

我们来看一下CEE_NEWARR指令是怎样处理的,因为前面已经花了很大篇幅介绍对CEE_NEWOBJ的处理,这里仅列出不同的部分
源代码:

Compiler::impImportBlockCode(BasicBlock* block) { CEE_NEWARR: // 省略部分代码...... args = gtNewArgList(op1, op2); op1 = gtNewHelperCallNode(info.compCompHnd->getNewArrHelper(resolvedToken.hClass), TYP_REF, 0, args); }

我们可以看到CEE_NEWARR直接生成了GT_CALL节点,不像CEE_NEWOBJ需要进一步的转换
getNewArrHelper返回了调用的帮助函数,我们来看一下getNewArrHelper
源代码:

CorInfoHelpFunc CEEInfo::getNewArrHelper (CORINFO_CLASS_HANDLE arrayClsHnd) { // 省略部分代码...... TypeHandle arrayType(arrayClsHnd); result = getNewArrHelperStatic(arrayType); // 省略部分代码...... return result; }

再看getNewArrHelperStatic,我们可以看到一般情况下会返回CORINFO_HELP_NEWARR_1_OBJ
源代码:

CorInfoHelpFunc CEEInfo::getNewArrHelperStatic(TypeHandle clsHnd) { // 省略部分代码...... if (CorTypeInfo::IsGenericVariable(elemType)) { result = CORINFO_HELP_NEWARR_1_OBJ; } else if (CorTypeInfo::IsObjRef(elemType)) { // It is an array of object refs result = CORINFO_HELP_NEWARR_1_OBJ; } else { // These cases always must use the slow helper // 省略部分代码...... } return result; {

CORINFO_HELP_NEWARR_1_OBJ对应的函数如下
源代码:

DYNAMICJITHELPER(CORINFO_HELP_NEWARR_1_OBJ, JIT_NewArr1,CORINFO_HELP_SIG_REG_ONLY)

可以看到对应了JIT_NewArr1这个包装给JIT调用的帮助函数
和JIT_New一样,在满足一定条件时会被替换为更快的实现
源代码:

HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) { // 省略部分代码...... CorElementType elemType = pArrayClassRef->GetArrayElementTypeHandle().GetSignatureCorElementType(); if (CorTypeInfo::IsPrimitiveType(elemType) { // 省略部分代码...... // 如果类型是基元类型(int, double等)则使用更快的FastAllocatePrimitiveArray函数 newArray = FastAllocatePrimitiveArray(pArrayClassRef->GetMethodTable(), static_cast<DWORD>(size), bAllocateInLargeHeap); } else { // 省略部分代码...... // 默认使用AllocateArrayEx函数 INT32 size32 = (INT32)size; newArray = AllocateArrayEx(typeHnd, &size32, 1); } // 省略部分代码...... return(OBJECTREFToObject(newArray)); } HCIMPLEND

总结:
JIT从CEE_NEWARR只生成了一段代码,就是调用JIT_NewArr1函数的代码

第三种new(对struct的new)生成了什么机器码

 

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

网友点评
d