OBJECTREF FastAllocatePrimitiveArray(MethodTable* pMT, DWORD cElements, BOOL bAllocateInLargeHeap) { // 省略部分代码...... // 检查元素数量不能大于一个硬性限制 SIZE_T componentSize = pMT->GetComponentSize(); if (cElements > MaxArrayLength(componentSize)) ThrowOutOfMemory(); // 检查总大小不能溢出 S_SIZE_T safeTotalSize = S_SIZE_T(cElements) * S_SIZE_T(componentSize) + S_SIZE_T(pMT->GetBaseSize()); if (safeTotalSize.IsOverflow()) ThrowOutOfMemory(); size_t totalSize = safeTotalSize.Value(); // 省略部分代码...... // 调用gc的帮助函数分配内存 ArrayBase* orObject; if (bAllocateInLargeHeap) { orObject = (ArrayBase*) AllocLHeap(totalSize, FALSE, FALSE); } else { ArrayTypeDesc *pArrayR8TypeDesc = g_pPredefinedArrayTypes[ELEMENT_TYPE_R8]; if (DATA_ALIGNMENT < sizeof(double) && pArrayR8TypeDesc != NULL && pMT == pArrayR8TypeDesc->GetMethodTable() && totalSize < LARGE_OBJECT_SIZE - MIN_OBJECT_SIZE) { _ASSERTE(DATA_ALIGNMENT == sizeof(double)/2); _ASSERTE((MIN_OBJECT_SIZE % sizeof(double)) == DATA_ALIGNMENT); // used to change alignment _ASSERTE(pMT->GetComponentSize() == sizeof(double)); _ASSERTE(g_pObjectClass->GetBaseSize() == MIN_OBJECT_SIZE); _ASSERTE(totalSize < totalSize + MIN_OBJECT_SIZE); orObject = (ArrayBase*) Alloc(totalSize + MIN_OBJECT_SIZE, FALSE, FALSE); Object *orDummyObject; if((size_t)orObject % sizeof(double)) { orDummyObject = orObject; orObject = (ArrayBase*) ((size_t)orObject + MIN_OBJECT_SIZE); } else { orDummyObject = (Object*) ((size_t)orObject + totalSize); } _ASSERTE(((size_t)orObject % sizeof(double)) == 0); orDummyObject->SetMethodTable(g_pObjectClass); } else { orObject = (ArrayBase*) Alloc(totalSize, FALSE, FALSE); bPublish = (totalSize >= LARGE_OBJECT_SIZE); } } // 设置类型信息(MethodTable) // Initialize Object orObject->SetMethodTable( pMT ); _ASSERTE(orObject->GetMethodTable() != NULL); // 设置数组长度 orObject->m_NumComponents = cElements; // 省略部分代码...... return( ObjectToOBJECTREF((Object*)orObject) ); }
再看AllocateArrayEx函数,这个函数比起上面的函数多出了对多维数组的处理
JIT_NewArr1调用AllocateArrayEx时传了3个参数,剩下2个参数是可选参数
源代码:
OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain)) { // 省略部分代码...... ArrayBase * orArray = NULL; (bAllocateInLargeHeap) { orArray = (ArrayBase *) AllocLHeap(totalSize, FALSE, pArrayMT->ContainsPointers()); // 设置类型信息(MethodTable) orArray->SetMethodTableForLargeObject(pArrayMT); } else { #ifdef FEATURE_64BIT_ALIGNMENT MethodTable *pElementMT = arrayDesc->GetTypeParam().GetMethodTable(); if (pElementMT->RequiresAlign8() && pElementMT->IsValueType()) { _ASSERTE(((pArrayMT->GetBaseSize() - SIZEOF_OBJHEADER) & 7) == 0); orArray = (ArrayBase *) AllocAlign8(totalSize, FALSE, pArrayMT->ContainsPointers(), FALSE); } else #endif { orArray = (ArrayBase *) Alloc(totalSize, FALSE, pArrayMT->ContainsPointers()); } // 设置类型信息(MethodTable) orArray->SetMethodTable(pArrayMT); } // 设置数组长度 // Initialize Object orArray->m_NumComponents = cElements; // 省略部分代码...... return ObjectToOBJECTREF((Object *) orArray); }
总结:
第二种new做的事情主要有
对struct的new不会从GCHeap申请内存,也不会设置类型信息(MethodTable),所以可以直接进入总结
总结:
第三种new做的事情主要有
打开VS反汇编和内存窗口,让我们来看看第一种new实际做了什么事情
第一种new的反汇编结果如下,一共有两个call