From a0dc56413e9e5c61c0f6617e1ef091966b2f7a1d Mon Sep 17 00:00:00 2001 From: Ruben Ayrapetyan Date: Tue, 27 Jun 2017 00:18:19 +0300 Subject: [PATCH 12/32] Replace array type handle with method table in arguments of array allocation helpers (#12369) * Remove direct usage of type handle in JIT_NewArr1, with except of retrieving template method table. * Assert that array type descriptor is loaded when array object's method table is set. * Pass template method tables instead of array type descriptors to array allocation helpers. --- src/vm/amd64/JitHelpers_InlineGetThread.asm | 39 ++++------------ src/vm/amd64/JitHelpers_Slow.asm | 69 ++++++++--------------------- src/vm/amd64/asmconstants.h | 4 -- src/vm/arm/asmconstants.h | 3 -- src/vm/arm/patchedcode.asm | 42 ++++-------------- src/vm/arm/stubs.cpp | 4 +- src/vm/compile.cpp | 8 ++++ src/vm/gchelpers.cpp | 50 ++++++++++++++------- src/vm/gchelpers.h | 8 ++-- src/vm/i386/jitinterfacex86.cpp | 24 +++------- src/vm/interpreter.cpp | 7 ++- src/vm/jithelpers.cpp | 52 +++++++++++----------- src/vm/jitinterface.cpp | 12 ++++- src/vm/jitinterface.h | 10 ++--- src/vm/jitinterfacegen.cpp | 12 ++--- src/vm/methodtable.cpp | 13 ++++++ src/vm/object.cpp | 18 ++++++++ src/vm/object.h | 50 ++++++++++++++++++--- src/vm/object.inl | 27 +++++++++++ src/vm/prestub.cpp | 4 +- 20 files changed, 245 insertions(+), 211 deletions(-) diff --git a/src/vm/amd64/JitHelpers_InlineGetThread.asm b/src/vm/amd64/JitHelpers_InlineGetThread.asm index 700c3b3..022ec67 100644 --- a/src/vm/amd64/JitHelpers_InlineGetThread.asm +++ b/src/vm/amd64/JitHelpers_InlineGetThread.asm @@ -147,15 +147,6 @@ align 16 jmp JIT_Box NESTED_END JIT_BoxFastMP_InlineGetThread, _TEXT -FIX_INDIRECTION macro Reg -ifdef FEATURE_PREJIT - test Reg, 1 - jz @F - mov Reg, [Reg-1] - @@: -endif -endm - LEAF_ENTRY AllocateStringFastMP_InlineGetThread, _TEXT ; We were passed the number of characters in ECX @@ -203,10 +194,9 @@ endif ; _DEBUG jmp FramedAllocateString LEAF_END AllocateStringFastMP_InlineGetThread, _TEXT -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1VC_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread, _TEXT - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -223,17 +213,12 @@ LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread, _TEXT ; In both cases we do a final overflow check after adding to the alloc_ptr. - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - cmp rdx, (65535 - 256) jae OversizedArray - movzx r8d, word ptr [r9 + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits + movzx r8d, word ptr [rcx + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits imul r8d, edx - add r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + add r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] ; round the size to a multiple of 8 @@ -252,7 +237,7 @@ LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread, _TEXT ja AllocFailed mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8 - mov [rax], r9 + mov [rax], rcx mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx @@ -268,10 +253,9 @@ endif ; _DEBUG LEAF_END JIT_NewArr1VC_MP_InlineGetThread, _TEXT -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1OBJ_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -285,16 +269,11 @@ LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT cmp rdx, (ASM_LARGE_OBJECT_SIZE - 256)/8 ; sizeof(void*) jae OversizedArray - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - ; In this case we know the element size is sizeof(void *), or 8 for x64 ; This helps us in two ways - we can shift instead of multiplying, and ; there's no need to align the size either - mov r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + mov r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] lea r8d, [r8d + edx * 8] ; No need for rounding in this case - element size is 8, and m_BaseSize is guaranteed @@ -310,7 +289,7 @@ LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT ja AllocFailed mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8 - mov [rax], r9 + mov [rax], rcx mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx diff --git a/src/vm/amd64/JitHelpers_Slow.asm b/src/vm/amd64/JitHelpers_Slow.asm index 293e447..448bcb2 100644 --- a/src/vm/amd64/JitHelpers_Slow.asm +++ b/src/vm/amd64/JitHelpers_Slow.asm @@ -321,22 +321,12 @@ endif ; _DEBUG jmp FramedAllocateString NESTED_END AllocateStringFastMP, _TEXT -FIX_INDIRECTION macro Reg -ifdef FEATURE_PREJIT - test Reg, 1 - jz @F - mov Reg, [Reg-1] - @@: -endif -endm - -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1VC_MP, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) NESTED_ENTRY JIT_NewArr1VC_MP, _TEXT alloc_stack MIN_SIZE END_PROLOGUE - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -356,17 +346,12 @@ NESTED_ENTRY JIT_NewArr1VC_MP, _TEXT CALL_GETTHREAD mov r11, rax - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - cmp rdx, (65535 - 256) jae OversizedArray - movzx r8d, word ptr [r9 + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits + movzx r8d, word ptr [rcx + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits imul r8d, edx ; signed mul, but won't overflow due to length restriction above - add r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + add r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] ; round the size to a multiple of 8 @@ -383,7 +368,7 @@ NESTED_ENTRY JIT_NewArr1VC_MP, _TEXT ja AllocFailed mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8 - mov [rax], r9 + mov [rax], rcx mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx @@ -401,13 +386,12 @@ endif ; _DEBUG NESTED_END JIT_NewArr1VC_MP, _TEXT -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1OBJ_MP, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) NESTED_ENTRY JIT_NewArr1OBJ_MP, _TEXT alloc_stack MIN_SIZE END_PROLOGUE - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -424,16 +408,11 @@ NESTED_ENTRY JIT_NewArr1OBJ_MP, _TEXT CALL_GETTHREAD mov r11, rax - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - ; In this case we know the element size is sizeof(void *), or 8 for x64 ; This helps us in two ways - we can shift instead of multiplying, and ; there's no need to align the size either - mov r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + mov r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] lea r8d, [r8d + edx * 8] ; No need for rounding in this case - element size is 8, and m_BaseSize is guaranteed @@ -448,7 +427,7 @@ NESTED_ENTRY JIT_NewArr1OBJ_MP, _TEXT ja AllocFailed mov [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr], r8 - mov [rax], r9 + mov [rax], rcx mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx @@ -626,11 +605,10 @@ endif ; _DEBUG jmp FramedAllocateString LEAF_END AllocateStringFastUP, _TEXT -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1VC_UP, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) LEAF_ENTRY JIT_NewArr1VC_UP, _TEXT - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -647,17 +625,12 @@ LEAF_ENTRY JIT_NewArr1VC_UP, _TEXT ; In both cases we do a final overflow check after adding to the alloc_ptr. - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - cmp rdx, (65535 - 256) jae JIT_NewArr1 - movzx r8d, word ptr [r9 + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits + movzx r8d, word ptr [rcx + OFFSETOF__MethodTable__m_dwFlags] ; component size is low 16 bits imul r8d, edx ; signed mul, but won't overflow due to length restriction above - add r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + add r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] ; round the size to a multiple of 8 @@ -677,7 +650,7 @@ LEAF_ENTRY JIT_NewArr1VC_UP, _TEXT ja AllocFailed mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr - mov [rax], r9 + mov [rax], rcx mov [g_global_alloc_lock], -1 mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx @@ -694,11 +667,10 @@ endif ; _DEBUG LEAF_END JIT_NewArr1VC_UP, _TEXT -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1OBJ_UP, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) LEAF_ENTRY JIT_NewArr1OBJ_UP, _TEXT - ; We were passed a type descriptor in RCX, which contains the (shared) - ; array method table and the element type. + ; We were passed a (shared) method table in RCX, which contains the element type. ; The element count is in RDX @@ -712,16 +684,11 @@ LEAF_ENTRY JIT_NewArr1OBJ_UP, _TEXT cmp rdx, (ASM_LARGE_OBJECT_SIZE - 256)/8 ; sizeof(void*) jae OversizedArray - ; we need to load the true method table from the type desc - mov r9, [rcx + OFFSETOF__ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r9 - ; In this case we know the element size is sizeof(void *), or 8 for x64 ; This helps us in two ways - we can shift instead of multiplying, and ; there's no need to align the size either - mov r8d, dword ptr [r9 + OFFSET__MethodTable__m_BaseSize] + mov r8d, dword ptr [rcx + OFFSET__MethodTable__m_BaseSize] lea r8d, [r8d + edx * 8] ; No need for rounding in this case - element size is 8, and m_BaseSize is guaranteed @@ -739,7 +706,7 @@ LEAF_ENTRY JIT_NewArr1OBJ_UP, _TEXT ja AllocFailed mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr - mov [rax], r9 + mov [rax], rcx mov [g_global_alloc_lock], -1 mov dword ptr [rax + OFFSETOF__ArrayBase__m_NumComponents], edx diff --git a/src/vm/amd64/asmconstants.h b/src/vm/amd64/asmconstants.h index e4f77de..4a100c1 100644 --- a/src/vm/amd64/asmconstants.h +++ b/src/vm/amd64/asmconstants.h @@ -609,10 +609,6 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__ArrayBase__m_NumComponents ASMCONSTANTS_C_ASSERT(OFFSETOF__StringObject__m_StringLength == offsetof(StringObject, m_StringLength)); -#define OFFSETOF__ArrayTypeDesc__m_TemplateMT 8 -ASMCONSTANTS_C_ASSERT(OFFSETOF__ArrayTypeDesc__m_TemplateMT - == offsetof(ArrayTypeDesc, m_TemplateMT)); - #define OFFSETOF__ArrayTypeDesc__m_Arg 0x10 ASMCONSTANTS_C_ASSERT(OFFSETOF__ArrayTypeDesc__m_Arg == offsetof(ArrayTypeDesc, m_Arg)); diff --git a/src/vm/arm/asmconstants.h b/src/vm/arm/asmconstants.h index 41597b2..704fa28 100644 --- a/src/vm/arm/asmconstants.h +++ b/src/vm/arm/asmconstants.h @@ -110,9 +110,6 @@ ASMCONSTANTS_C_ASSERT(SIZEOF__ArrayOfValueType == ObjSizeOf(ArrayBase)); #define ArrayBase__m_NumComponents 0x4 ASMCONSTANTS_C_ASSERT(ArrayBase__m_NumComponents == offsetof(ArrayBase, m_NumComponents)); -#define ArrayTypeDesc__m_TemplateMT 0x4 -ASMCONSTANTS_C_ASSERT(ArrayTypeDesc__m_TemplateMT == offsetof(ArrayTypeDesc, m_TemplateMT)); - #define ArrayTypeDesc__m_Arg 0x8 ASMCONSTANTS_C_ASSERT(ArrayTypeDesc__m_Arg == offsetof(ArrayTypeDesc, m_Arg)); diff --git a/src/vm/arm/patchedcode.asm b/src/vm/arm/patchedcode.asm index 2ef175e..9fdd609 100644 --- a/src/vm/arm/patchedcode.asm +++ b/src/vm/arm/patchedcode.asm @@ -63,17 +63,6 @@ $label TEXTAREA - MACRO - FIX_INDIRECTION $Reg, $label -#ifdef FEATURE_PREJIT - tst $Reg, #1 - beq $label - ldr $Reg, [$Reg, #-1] -$label -#endif - MEND - - ; ------------------------------------------------------------------ ; Start of the writeable code region LEAF_ENTRY JIT_PatchedCodeStart @@ -336,11 +325,11 @@ AllocFailed3 LEAF_END -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1VC_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) ;--------------------------------------------------------------------------- -; IN: r0: type descriptor which contains the (shared) array method table and the element type. +; IN: r0: a (shared) array method table, which contains the element type. ; IN: r1: number of array elements -;; OUT: r0: address of newly allocated string +;; OUT: r0: address of newly allocated object LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread @@ -358,13 +347,8 @@ AllocFailed3 cmp r1, #MAX_FAST_ALLOCATE_ARRAY_VC_SIZE bhs OverSizedArray3 - ;load MethodTable from ArrayTypeDesc - ldr r3, [r0, #ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r3, label1 - ;get element size - stored in low 16bits of m_dwFlags - ldrh r12, [r3, #MethodTable__m_dwFlags] + ldrh r12, [r0, #MethodTable__m_dwFlags] ; getting size of object to allocate @@ -398,11 +382,7 @@ AllocFailed3 str r1, [r2, #ArrayBase__m_NumComponents] ;store methodtable - ldr r3, [r0, #ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r3, label2 - - str r3, [r2] + str r0, [r2] ;copy return value mov r0, r2 @@ -426,11 +406,11 @@ OverSizedArray3 -; HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +; HCIMPL2(Object*, JIT_NewArr1OBJ_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) ;--------------------------------------------------------------------------- -; IN: r0: type descriptor which contains the (shared) array method table and the element type. +; IN: r0: a (shared) array method table, which contains the element type. ; IN: r1: number of array elements -;; OUT: r0: address of newly allocated string +;; OUT: r0: address of newly allocated object LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread @@ -466,11 +446,7 @@ OverSizedArray3 str r1, [r2, #ArrayBase__m_NumComponents] ;store methodtable - ldr r3, [r0, #ArrayTypeDesc__m_TemplateMT - 2] - - FIX_INDIRECTION r3, label3 - - str r3, [r2] + str r0, [r2] ;copy return value mov r0, r2 diff --git a/src/vm/arm/stubs.cpp b/src/vm/arm/stubs.cpp index c832911..70cc900 100644 --- a/src/vm/arm/stubs.cpp +++ b/src/vm/arm/stubs.cpp @@ -2567,9 +2567,9 @@ static const LPVOID InlineGetThreadLocations[] = { //EXTERN_C Object* JIT_TrialAllocSFastMP(CORINFO_CLASS_HANDLE typeHnd_); Object* JIT_TrialAllocSFastMP(CORINFO_CLASS_HANDLE typeHnd_); -EXTERN_C Object* JIT_NewArr1OBJ_MP(CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); +EXTERN_C Object* JIT_NewArr1OBJ_MP(CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); EXTERN_C Object* AllocateStringFastMP(CLR_I4 cch); -EXTERN_C Object* JIT_NewArr1VC_MP(CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); +EXTERN_C Object* JIT_NewArr1VC_MP(CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); EXTERN_C Object* JIT_BoxFastMP(CORINFO_CLASS_HANDLE type, void* unboxedData); diff --git a/src/vm/compile.cpp b/src/vm/compile.cpp index 9727430..22b8203 100644 --- a/src/vm/compile.cpp +++ b/src/vm/compile.cpp @@ -1857,6 +1857,14 @@ void EncodeTypeInDictionarySignature( return; } + else if((CorElementTypeZapSig)typ == ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG) + { + pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG); + + IfFailThrow(ptr.GetElemType(&typ)); + + _ASSERTE(typ == ELEMENT_TYPE_SZARRAY || typ == ELEMENT_TYPE_ARRAY); + } pSigBuilder->AppendElementType(typ); diff --git a/src/vm/gchelpers.cpp b/src/vm/gchelpers.cpp index 9669f98..046f06e 100644 --- a/src/vm/gchelpers.cpp +++ b/src/vm/gchelpers.cpp @@ -439,11 +439,31 @@ void ThrowOutOfMemoryDimensionsExceeded() // // Handles arrays of arbitrary dimensions // +// This is wrapper overload to handle TypeHandle arrayType +// +OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap + DEBUG_ARG(BOOL bDontSetAppDomain)) +{ + CONTRACTL + { + WRAPPER_NO_CONTRACT; + } CONTRACTL_END; + + ArrayTypeDesc* arrayDesc = arrayType.AsArray(); + MethodTable* pArrayMT = arrayDesc->GetMethodTable(); + + return AllocateArrayEx(pArrayMT, pArgs, dwNumArgs, bAllocateInLargeHeap + DEBUG_ARG(bDontSetAppDomain)); +} + +// +// Handles arrays of arbitrary dimensions +// // If dwNumArgs is set to greater than 1 for a SZARRAY this function will recursively // allocate sub-arrays and fill them in. // // For arrays with lower bounds, pBounds is , , , ... -OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap +OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain)) { CONTRACTL { @@ -464,14 +484,12 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B } #endif - ArrayTypeDesc* arrayDesc = arrayType.AsArray(); - MethodTable* pArrayMT = arrayDesc->GetMethodTable(); - _ASSERTE(pArrayMT->CheckInstanceActivated()); + _ASSERTE(pArrayMT->CheckInstanceActivated()); PREFIX_ASSUME(pArrayMT != NULL); - CorElementType kind = arrayType.GetInternalCorElementType(); + CorElementType kind = pArrayMT->GetInternalCorElementType(); _ASSERTE(kind == ELEMENT_TYPE_ARRAY || kind == ELEMENT_TYPE_SZARRAY); - CorElementType elemType = arrayDesc->GetTypeParam().GetInternalCorElementType(); + CorElementType elemType = pArrayMT->GetArrayElementType(); // Disallow the creation of void[,] (a multi-dim array of System.Void) if (elemType == ELEMENT_TYPE_VOID) COMPlusThrow(kArgumentException); @@ -481,7 +499,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B // IBC Log MethodTable access g_IBCLogger.LogMethodTableAccess(pArrayMT); - SetTypeHandleOnThreadForAlloc(arrayType); + SetTypeHandleOnThreadForAlloc(TypeHandle(pArrayMT)); SIZE_T componentSize = pArrayMT->GetComponentSize(); bool maxArrayDimensionLengthOverflow = false; @@ -489,7 +507,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B if (kind == ELEMENT_TYPE_ARRAY) { - unsigned rank = arrayDesc->GetRank(); + unsigned rank = pArrayMT->GetRank(); _ASSERTE(dwNumArgs == rank || dwNumArgs == 2*rank); // Morph a ARRAY rank 1 with 0 lower bound into an SZARRAY @@ -498,7 +516,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B // This recursive call doesn't go any farther, because the dwNumArgs will be 1, // so don't bother with stack probe. - TypeHandle szArrayType = ClassLoader::LoadArrayTypeThrowing(arrayDesc->GetArrayElementTypeHandle(), ELEMENT_TYPE_SZARRAY, 1); + TypeHandle szArrayType = ClassLoader::LoadArrayTypeThrowing(pArrayMT->GetApproxArrayElementTypeHandle(), ELEMENT_TYPE_SZARRAY, 1); return AllocateArrayEx(szArrayType, &pArgs[dwNumArgs - 1], 1, bAllocateInLargeHeap DEBUG_ARG(bDontSetAppDomain)); } @@ -561,12 +579,12 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B if (bAllocateInLargeHeap) { orArray = (ArrayBase *) AllocLHeap(totalSize, FALSE, pArrayMT->ContainsPointers()); - orArray->SetMethodTableForLargeObject(pArrayMT); + orArray->SetArrayMethodTableForLargeObject(pArrayMT); } else { #ifdef FEATURE_64BIT_ALIGNMENT - MethodTable *pElementMT = arrayDesc->GetTypeParam().GetMethodTable(); + MethodTable *pElementMT = pArrayMT->GetApproxArrayElementTypeHandle().GetMethodTable(); if (pElementMT->RequiresAlign8() && pElementMT->IsValueType()) { // This platform requires that certain fields are 8-byte aligned (and the runtime doesn't provide @@ -582,7 +600,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B { orArray = (ArrayBase *) Alloc(totalSize, FALSE, pArrayMT->ContainsPointers()); } - orArray->SetMethodTable(pArrayMT); + orArray->SetArrayMethodTable(pArrayMT); } // Initialize Object @@ -655,7 +673,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B GCStressPolicy::InhibitHolder iholder; // Allocate dwProvidedBounds arrays - if (!arrayDesc->GetArrayElementTypeHandle().IsArray()) + if (!pArrayMT->GetApproxArrayElementTypeHandle().IsArray()) { orArray = NULL; } @@ -666,7 +684,7 @@ OBJECTREF AllocateArrayEx(TypeHandle arrayType, INT32 *pArgs, DWORD dwNumArgs, B _ASSERTE(GetThread()); INTERIOR_STACK_PROBE(GetThread()); - TypeHandle subArrayType = arrayDesc->GetArrayElementTypeHandle(); + TypeHandle subArrayType = pArrayMT->GetApproxArrayElementTypeHandle(); for (UINT32 i = 0; i < cElements; i++) { OBJECTREF obj = AllocateArrayEx(subArrayType, &pArgs[1], dwNumArgs-1, bAllocateInLargeHeap DEBUG_ARG(bDontSetAppDomain)); @@ -809,7 +827,7 @@ OBJECTREF FastAllocatePrimitiveArray(MethodTable* pMT, DWORD cElements, BOOL b } // Initialize Object - orObject->SetMethodTable( pMT ); + orObject->SetArrayMethodTable( pMT ); _ASSERTE(orObject->GetMethodTable() != NULL); orObject->m_NumComponents = cElements; @@ -931,7 +949,7 @@ OBJECTREF AllocateObjectArray(DWORD cElements, TypeHandle ElementType) Thread::DisableSOCheckInHCALL disableSOCheckInHCALL; #endif // FEATURE_STACK_PROBE #endif // _DEBUG - return OBJECTREF( HCCALL2(fastObjectArrayAllocator, ArrayType.AsPtr(), cElements)); + return OBJECTREF( HCCALL2(fastObjectArrayAllocator, ArrayType.AsArray()->GetTemplateMethodTable(), cElements)); } STRINGREF AllocateString( DWORD cchStringLength ) diff --git a/src/vm/gchelpers.h b/src/vm/gchelpers.h index 449524a..73933f6 100644 --- a/src/vm/gchelpers.h +++ b/src/vm/gchelpers.h @@ -22,6 +22,8 @@ OBJECTREF AllocateValueSzArray(TypeHandle elementType, INT32 length); // The main Array allocation routine, can do multi-dimensional +OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE + DEBUG_ARG(BOOL bDontSetAppDomain = FALSE)); OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap = FALSE DEBUG_ARG(BOOL bDontSetAppDomain = FALSE)); // Optimized verion of above @@ -47,10 +49,8 @@ OBJECTREF AllocatePrimitiveArray(CorElementType type, DWORD cElements); OBJECTREF AllocatePrimitiveArray(CorElementType type, DWORD cElements, BOOL bAllocateInLargeHeap); -// Allocate SD array of object pointers. StubLinker-generated asm code might -// implement this, so the element TypeHandle is passed as a PVOID to avoid any -// struct calling convention weirdness. -typedef HCCALL2_PTR(Object*, FastObjectArrayAllocatorFuncPtr, /*TypeHandle*/PVOID ArrayType, DWORD cElements); +// Allocate SD array of object pointers. +typedef HCCALL2_PTR(Object*, FastObjectArrayAllocatorFuncPtr, MethodTable *pArrayMT, DWORD cElements); extern FastObjectArrayAllocatorFuncPtr fastObjectArrayAllocator; diff --git a/src/vm/i386/jitinterfacex86.cpp b/src/vm/i386/jitinterfacex86.cpp index 18acbf0..cdabb52 100644 --- a/src/vm/i386/jitinterfacex86.cpp +++ b/src/vm/i386/jitinterfacex86.cpp @@ -855,7 +855,7 @@ void *JIT_TrialAlloc::GenBox(Flags flags) } -HCIMPL2_RAW(Object*, UnframedAllocateObjectArray, /*TypeHandle*/PVOID ArrayType, DWORD cElements) +HCIMPL2_RAW(Object*, UnframedAllocateObjectArray, MethodTable *pArrayMT, DWORD cElements) { // This isn't _really_ an FCALL and therefore shouldn't have the // SO_TOLERANT part of the FCALL_CONTRACT b/c it is not entered @@ -867,7 +867,7 @@ HCIMPL2_RAW(Object*, UnframedAllocateObjectArray, /*TypeHandle*/PVOID ArrayType, SO_INTOLERANT; } CONTRACTL_END; - return OBJECTREFToObject(AllocateArrayEx(TypeHandle::FromPtr(ArrayType), + return OBJECTREFToObject(AllocateArrayEx(pArrayMT, (INT32 *)(&cElements), 1, FALSE @@ -902,8 +902,7 @@ void *JIT_TrialAlloc::GenAllocArray(Flags flags) CodeLabel *noLock = sl.NewCodeLabel(); CodeLabel *noAlloc = sl.NewCodeLabel(); - // We were passed a type descriptor in ECX, which contains the (shared) - // array method table and the element type. + // We were passed a (shared) method table in RCX, which contains the element type. // If this is the allocator for use from unmanaged code, ECX contains the // element type descriptor, or the CorElementType. @@ -920,12 +919,7 @@ void *JIT_TrialAlloc::GenAllocArray(Flags flags) if (flags & NO_FRAME) { - if (flags & OBJ_ARRAY) - { - // we need to load the true method table from the type desc - sl.X86EmitIndexRegLoad(kECX, kECX, offsetof(ArrayTypeDesc,m_TemplateMT)-2); - } - else + if ((flags & OBJ_ARRAY) == 0) { // mov ecx,[g_pPredefinedArrayTypes+ecx*4] sl.Emit8(0x8b); @@ -937,16 +931,10 @@ void *JIT_TrialAlloc::GenAllocArray(Flags flags) // je noLock sl.X86EmitCondJump(noLock, X86CondCode::kJZ); - - // we need to load the true method table from the type desc - sl.X86EmitIndexRegLoad(kECX, kECX, offsetof(ArrayTypeDesc,m_TemplateMT)); } } else { - // we need to load the true method table from the type desc - sl.X86EmitIndexRegLoad(kECX, kECX, offsetof(ArrayTypeDesc,m_TemplateMT)-2); - #ifdef FEATURE_PREJIT CodeLabel *indir = sl.NewCodeLabel(); @@ -1064,7 +1052,7 @@ void *JIT_TrialAlloc::GenAllocArray(Flags flags) // pop edx - element count sl.X86EmitPopReg(kEDX); - // pop ecx - array type descriptor + // pop ecx - array method table sl.X86EmitPopReg(kECX); // mov dword ptr [eax]ArrayBase.m_NumComponents, edx @@ -1089,7 +1077,7 @@ void *JIT_TrialAlloc::GenAllocArray(Flags flags) // pop edx - element count sl.X86EmitPopReg(kEDX); - // pop ecx - array type descriptor + // pop ecx - array method table sl.X86EmitPopReg(kECX); CodeLabel * target; diff --git a/src/vm/interpreter.cpp b/src/vm/interpreter.cpp index 010fee6..4e39efb 100644 --- a/src/vm/interpreter.cpp +++ b/src/vm/interpreter.cpp @@ -6068,13 +6068,12 @@ void Interpreter::NewArr() } #endif - TypeHandle typeHnd(elemClsHnd); - ArrayTypeDesc* pArrayClassRef = typeHnd.AsArray(); + MethodTable *pArrayMT = (MethodTable *) elemClsHnd; - pArrayClassRef->GetMethodTable()->CheckRunClassInitThrowing(); + pArrayMT->CheckRunClassInitThrowing(); INT32 size32 = (INT32)sz; - Object* newarray = OBJECTREFToObject(AllocateArrayEx(typeHnd, &size32, 1)); + Object* newarray = OBJECTREFToObject(AllocateArrayEx(pArrayMT, &size32, 1)); GCX_FORBID(); OpStackTypeSet(stkInd, InterpreterType(CORINFO_TYPE_CLASS)); diff --git a/src/vm/jithelpers.cpp b/src/vm/jithelpers.cpp index aaab589..2552b01 100644 --- a/src/vm/jithelpers.cpp +++ b/src/vm/jithelpers.cpp @@ -3002,7 +3002,7 @@ HCIMPLEND //************************************************************* // Array allocation fast path for arrays of value type elements // -HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) { FCALL_CONTRACT; @@ -3028,16 +3028,14 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn // some reshuffling of intermediate values into nonvolatile registers around the call. Thread *thread = GetThread(); - TypeHandle arrayTypeHandle(arrayTypeHnd_); - ArrayTypeDesc *arrayTypeDesc = arrayTypeHandle.AsArray(); - MethodTable *arrayMethodTable = arrayTypeDesc->GetTemplateMethodTable(); + MethodTable *pArrayMT = (MethodTable *)arrayMT; - _ASSERTE(arrayMethodTable->HasComponentSize()); - SIZE_T componentSize = arrayMethodTable->RawGetComponentSize(); + _ASSERTE(pArrayMT->HasComponentSize()); + SIZE_T componentSize = pArrayMT->RawGetComponentSize(); SIZE_T totalSize = componentCount * componentSize; _ASSERTE(totalSize / componentSize == componentCount); - SIZE_T baseSize = arrayMethodTable->GetBaseSize(); + SIZE_T baseSize = pArrayMT->GetBaseSize(); totalSize += baseSize; _ASSERTE(totalSize >= baseSize); @@ -3056,7 +3054,7 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn _ASSERTE(allocPtr != nullptr); ArrayBase *array = reinterpret_cast(allocPtr); - array->SetMethodTable(arrayMethodTable); + array->SetArrayMethodTable(pArrayMT); _ASSERTE(static_cast(componentCount) == componentCount); array->m_NumComponents = static_cast(componentCount); @@ -3072,14 +3070,14 @@ HCIMPL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHn // Tail call to the slow helper ENDFORBIDGC(); - return HCCALL2(JIT_NewArr1, arrayTypeHnd_, size); + return HCCALL2(JIT_NewArr1, arrayMT, size); } HCIMPLEND //************************************************************* // Array allocation fast path for arrays of object elements // -HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) { FCALL_CONTRACT; @@ -3100,14 +3098,12 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH // some reshuffling of intermediate values into nonvolatile registers around the call. Thread *thread = GetThread(); - TypeHandle arrayTypeHandle(arrayTypeHnd_); - ArrayTypeDesc *arrayTypeDesc = arrayTypeHandle.AsArray(); - MethodTable *arrayMethodTable = arrayTypeDesc->GetTemplateMethodTable(); - SIZE_T totalSize = componentCount * sizeof(void *); _ASSERTE(totalSize / sizeof(void *) == componentCount); - SIZE_T baseSize = arrayMethodTable->GetBaseSize(); + MethodTable *pArrayMT = (MethodTable *)arrayMT; + + SIZE_T baseSize = pArrayMT->GetBaseSize(); totalSize += baseSize; _ASSERTE(totalSize >= baseSize); @@ -3124,7 +3120,7 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH _ASSERTE(allocPtr != nullptr); ArrayBase *array = reinterpret_cast(allocPtr); - array->SetMethodTable(arrayMethodTable); + array->SetArrayMethodTable(pArrayMT); _ASSERTE(static_cast(componentCount) == componentCount); array->m_NumComponents = static_cast(componentCount); @@ -3140,14 +3136,14 @@ HCIMPL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayTypeH // Tail call to the slow helper ENDFORBIDGC(); - return HCCALL2(JIT_NewArr1, arrayTypeHnd_, size); + return HCCALL2(JIT_NewArr1, arrayMT, size); } HCIMPLEND #include /*************************************************************/ -HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) +HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size) { FCALL_CONTRACT; @@ -3155,11 +3151,11 @@ HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) HELPER_METHOD_FRAME_BEGIN_RET_0(); // Set up a frame - TypeHandle typeHnd(arrayTypeHnd_); + MethodTable *pArrayMT = (MethodTable *)arrayMT; - _ASSERTE(typeHnd.GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY); - typeHnd.CheckRestore(); - ArrayTypeDesc* pArrayClassRef = typeHnd.AsArray(); + _ASSERTE(pArrayMT->IsFullyLoaded()); + _ASSERTE(pArrayMT->IsArray()); + _ASSERTE(!pArrayMT->IsMultiDimArray()); if (size < 0) COMPlusThrow(kOverflowException); @@ -3176,7 +3172,7 @@ HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) // is this a primitive type? // - CorElementType elemType = pArrayClassRef->GetArrayElementTypeHandle().GetSignatureCorElementType(); + CorElementType elemType = pArrayMT->GetInternalCorElementType(); if (CorTypeInfo::IsPrimitiveType(elemType) #ifdef FEATURE_64BIT_ALIGNMENT @@ -3209,9 +3205,13 @@ HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) #endif if (g_pPredefinedArrayTypes[elemType] == NULL) - g_pPredefinedArrayTypes[elemType] = pArrayClassRef; + { + TypeHandle elemTypeHnd = TypeHandle(MscorlibBinder::GetElementType(elemType)); + + g_pPredefinedArrayTypes[elemType] = ClassLoader::LoadArrayTypeThrowing(elemTypeHnd, ELEMENT_TYPE_SZARRAY, 0).AsArray(); + } - newArray = FastAllocatePrimitiveArray(pArrayClassRef->GetMethodTable(), static_cast(size), bAllocateInLargeHeap); + newArray = FastAllocatePrimitiveArray(pArrayMT, static_cast(size), bAllocateInLargeHeap); } else { @@ -3221,7 +3221,7 @@ HCIMPL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size) } #endif // _DEBUG INT32 size32 = (INT32)size; - newArray = AllocateArrayEx(typeHnd, &size32, 1); + newArray = AllocateArrayEx(pArrayMT, &size32, 1); } HELPER_METHOD_FRAME_END(); diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 84f635a..f756c90 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -2726,7 +2726,14 @@ void CEEInfo::embedGenericHandle( pResult->handleType = CORINFO_HANDLETYPE_CLASS; - pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)th.AsPtr(); + if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr) + { + pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)th.AsArray()->GetTemplateMethodTable(); + } + else + { + pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)th.AsPtr(); + } if (fEmbedParent && pResolvedToken->hMethod != NULL) { @@ -3404,7 +3411,10 @@ NoSpecialCase: case TypeHandleSlot: { if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr) + { + sigBuilder.AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG); sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY); + } // Note that we can come here with pResolvedToken->pTypeSpec == NULL for invalid IL that // directly references __Canon diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index d287248..a3017ef 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -215,9 +215,9 @@ extern FCDECL1(StringObject*, AllocateString_MP_FastPortable, DWORD stringLength extern FCDECL1(StringObject*, UnframedAllocateString, DWORD stringLength); extern FCDECL1(StringObject*, FramedAllocateString, DWORD stringLength); -extern FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -extern FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -extern FCDECL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); +extern FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +extern FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +extern FCDECL2(Object*, JIT_NewArr1, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); #ifndef JIT_Stelem_Ref #define JIT_Stelem_Ref JIT_Stelem_Ref_Portable @@ -326,8 +326,8 @@ private: #ifdef _WIN64 EXTERN_C FCDECL1(Object*, JIT_TrialAllocSFastMP_InlineGetThread, CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C FCDECL2(Object*, JIT_BoxFastMP_InlineGetThread, CORINFO_CLASS_HANDLE type, void* data); -EXTERN_C FCDECL2(Object*, JIT_NewArr1VC_MP_InlineGetThread, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); -EXTERN_C FCDECL2(Object*, JIT_NewArr1OBJ_MP_InlineGetThread, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); +EXTERN_C FCDECL2(Object*, JIT_NewArr1VC_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +EXTERN_C FCDECL2(Object*, JIT_NewArr1OBJ_MP_InlineGetThread, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); #endif // _WIN64 diff --git a/src/vm/jitinterfacegen.cpp b/src/vm/jitinterfacegen.cpp index 8d1c8cd..2638740 100644 --- a/src/vm/jitinterfacegen.cpp +++ b/src/vm/jitinterfacegen.cpp @@ -30,8 +30,8 @@ EXTERN_C Object* JIT_TrialAllocSFastMP_InlineGetThread(CORINFO_CLASS_HANDLE typeHnd_); EXTERN_C Object* JIT_BoxFastMP_InlineGetThread (CORINFO_CLASS_HANDLE type, void* unboxedData); EXTERN_C Object* AllocateStringFastMP_InlineGetThread (CLR_I4 cch); -EXTERN_C Object* JIT_NewArr1OBJ_MP_InlineGetThread (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); -EXTERN_C Object* JIT_NewArr1VC_MP_InlineGetThread (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); +EXTERN_C Object* JIT_NewArr1OBJ_MP_InlineGetThread (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +EXTERN_C Object* JIT_NewArr1VC_MP_InlineGetThread (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); // This next set is the fast version that invoke GetThread but is still faster than the VM implementation (i.e. // the "slow" versions). @@ -42,10 +42,10 @@ EXTERN_C Object* JIT_BoxFastUP (CORINFO_CLASS_HANDLE type, void* unboxedData); EXTERN_C Object* AllocateStringFastMP (CLR_I4 cch); EXTERN_C Object* AllocateStringFastUP (CLR_I4 cch); -EXTERN_C Object* JIT_NewArr1OBJ_MP (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); -EXTERN_C Object* JIT_NewArr1OBJ_UP (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); -EXTERN_C Object* JIT_NewArr1VC_MP (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); -EXTERN_C Object* JIT_NewArr1VC_UP (CORINFO_CLASS_HANDLE arrayTypeHnd_, INT_PTR size); +EXTERN_C Object* JIT_NewArr1OBJ_MP (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +EXTERN_C Object* JIT_NewArr1OBJ_UP (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +EXTERN_C Object* JIT_NewArr1VC_MP (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); +EXTERN_C Object* JIT_NewArr1VC_UP (CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); //For the optimized JIT_Mon helpers #if defined(_TARGET_AMD64_) diff --git a/src/vm/methodtable.cpp b/src/vm/methodtable.cpp index 21fab72..598759a 100644 --- a/src/vm/methodtable.cpp +++ b/src/vm/methodtable.cpp @@ -5903,6 +5903,19 @@ void MethodTable::DoFullyLoad(Generics::RecursionGraph * const pVisited, const } + if (level >= CLASS_DEPENDENCIES_LOADED && IsArray()) + { + // The array type should be loaded, if template method table is loaded + // See also: ArrayBase::SetArrayMethodTable, ArrayBase::SetArrayMethodTableForLargeObject + TypeHandle th = ClassLoader::LoadArrayTypeThrowing(GetApproxArrayElementTypeHandle(), + GetInternalCorElementType(), + GetRank(), + ClassLoader::LoadTypes, + level); + _ASSERTE(th.IsTypeDesc() && th.IsArray()); + _ASSERTE(!(level == CLASS_LOADED && !th.IsFullyLoaded())); + } + END_SO_INTOLERANT_CODE; #endif //!DACCESS_COMPILE diff --git a/src/vm/object.cpp b/src/vm/object.cpp index 4c08f02..daa20e7 100644 --- a/src/vm/object.cpp +++ b/src/vm/object.cpp @@ -1818,6 +1818,24 @@ VOID Object::ValidateInner(BOOL bDeep, BOOL bVerifyNextHeader, BOOL bVerifySyncB #endif // VERIFY_HEAP +#ifndef DACCESS_COMPILE +#ifdef _DEBUG +void ArrayBase::AssertArrayTypeDescLoaded() +{ + _ASSERTE (m_pMethTab->IsArray()); + + // The type should already be loaded + // See also: MethodTable::DoFullyLoad + TypeHandle th = ClassLoader::LoadArrayTypeThrowing(m_pMethTab->GetApproxArrayElementTypeHandle(), + m_pMethTab->GetInternalCorElementType(), + m_pMethTab->GetRank(), + ClassLoader::DontLoadTypes); + + _ASSERTE(!th.IsNull()); +} +#endif // DEBUG +#endif // !DACCESS_COMPILE + /*==================================NewString=================================== **Action: Creates a System.String object. **Returns: diff --git a/src/vm/object.h b/src/vm/object.h index cb3743c..00def1d 100644 --- a/src/vm/object.h +++ b/src/vm/object.h @@ -207,19 +207,34 @@ class Object m_pMethTab = pMT; } - VOID SetMethodTable(MethodTable *pMT) + VOID SetMethodTable(MethodTable *pMT + DEBUG_ARG(BOOL bAllowArray = FALSE)) { LIMITED_METHOD_CONTRACT; m_pMethTab = pMT; + +#ifdef _DEBUG + if (!bAllowArray) + { + AssertNotArray(); + } +#endif // _DEBUG } - VOID SetMethodTableForLargeObject(MethodTable *pMT) + VOID SetMethodTableForLargeObject(MethodTable *pMT + DEBUG_ARG(BOOL bAllowArray = FALSE)) { // This function must be used if the allocation occurs on the large object heap, and the method table might be a collectible type WRAPPER_NO_CONTRACT; ErectWriteBarrierForMT(&m_pMethTab, pMT); + +#ifdef _DEBUG + if (!bAllowArray) + { + AssertNotArray(); + } +#endif // _DEBUG } - #endif //!DACCESS_COMPILE // An object might be a proxy of some sort, with a thunking VTable. If so, we can @@ -664,6 +679,15 @@ class Object BOOL ShouldCheckAppDomainAgile(BOOL raiseAssert, BOOL *pfResult); #endif +#ifdef _DEBUG + void AssertNotArray() + { + if (m_pMethTab->IsArray()) + { + _ASSERTE(!"ArrayBase::SetArrayMethodTable/ArrayBase::SetArrayMethodTableForLargeObject should be used for arrays"); + } + } +#endif // _DEBUG }; /* @@ -745,10 +769,10 @@ class ArrayBase : public Object friend class GCHeap; friend class CObjectHeader; friend class Object; - friend OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain)); + friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap DEBUG_ARG(BOOL bDontSetAppDomain)); friend OBJECTREF FastAllocatePrimitiveArray(MethodTable* arrayType, DWORD cElements, BOOL bAllocateInLargeHeap); - friend FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); - friend FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE typeHnd_, INT_PTR size); + friend FCDECL2(Object*, JIT_NewArr1VC_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); + friend FCDECL2(Object*, JIT_NewArr1OBJ_MP_FastPortable, CORINFO_CLASS_HANDLE arrayMT, INT_PTR size); friend class JIT_TrialAlloc; friend class CheckAsmOffsets; friend struct _DacGlobals; @@ -790,6 +814,11 @@ public: // Total element count for the array inline DWORD GetNumComponents() const; +#ifndef DACCESS_COMPILE + inline void SetArrayMethodTable(MethodTable *pArrayMT); + inline void SetArrayMethodTableForLargeObject(MethodTable *pArrayMT); +#endif // !DACCESS_COMPILE + // Get pointer to elements, handles any number of dimensions PTR_BYTE GetDataPtr(BOOL inGC = FALSE) const { LIMITED_METHOD_CONTRACT; @@ -865,6 +894,13 @@ public: inline static unsigned GetBoundsOffset(MethodTable* pMT); inline static unsigned GetLowerBoundsOffset(MethodTable* pMT); + +private: +#ifndef DACCESS_COMPILE +#ifdef _DEBUG + void AssertArrayTypeDescLoaded(); +#endif // _DEBUG +#endif // !DACCESS_COMPILE }; // @@ -905,7 +941,7 @@ class PtrArray : public ArrayBase { friend class GCHeap; friend class ClrDataAccess; - friend OBJECTREF AllocateArrayEx(TypeHandle arrayClass, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap); + friend OBJECTREF AllocateArrayEx(MethodTable *pArrayMT, INT32 *pArgs, DWORD dwNumArgs, BOOL bAllocateInLargeHeap); friend class JIT_TrialAlloc; friend class CheckAsmOffsets; diff --git a/src/vm/object.inl b/src/vm/object.inl index 5698321..5dc3d6d 100644 --- a/src/vm/object.inl +++ b/src/vm/object.inl @@ -146,6 +146,7 @@ inline /* static */ TypeHandle ArrayBase::GetTypeHandle(MethodTable * pMT) // for T[] is available and restored // @todo This should be turned into a probe with a hard SO when we have one + // See also: ArrayBase::SetArrayMethodTable, ArrayBase::SetArrayMethodTableForLargeObject and MethodTable::DoFullyLoad CONTRACT_VIOLATION(SOToleranceViolation); // == FailIfNotLoadedOrNotRestored TypeHandle arrayType = ClassLoader::LoadArrayTypeThrowing(pMT->GetApproxArrayElementTypeHandle(), kind, rank, ClassLoader::DontLoadTypes); @@ -174,6 +175,32 @@ inline DWORD ArrayBase::GetNumComponents() const return m_NumComponents; } +#ifndef DACCESS_COMPILE +inline void ArrayBase::SetArrayMethodTable(MethodTable *pArrayMT) +{ + LIMITED_METHOD_CONTRACT; + + SetMethodTable(pArrayMT + DEBUG_ARG(TRUE)); + +#ifdef _DEBUG + AssertArrayTypeDescLoaded(); +#endif // _DEBUG +} + +inline void ArrayBase::SetArrayMethodTableForLargeObject(MethodTable *pArrayMT) +{ + LIMITED_METHOD_CONTRACT; + + SetMethodTableForLargeObject(pArrayMT + DEBUG_ARG(TRUE)); + +#ifdef _DEBUG + AssertArrayTypeDescLoaded(); +#endif // _DEBUG +} +#endif // !DACCESS_COMPILE + inline /* static */ unsigned ArrayBase::GetDataPtrOffset(MethodTable* pMT) { LIMITED_METHOD_CONTRACT; diff --git a/src/vm/prestub.cpp b/src/vm/prestub.cpp index af3f190..746e415 100644 --- a/src/vm/prestub.cpp +++ b/src/vm/prestub.cpp @@ -2764,7 +2764,9 @@ PCODE DynamicHelperFixup(TransitionBlock * pTransitionBlock, TADDR * pCell, DWOR case ENCODE_NEW_ARRAY_HELPER: { CorInfoHelpFunc helpFunc = CEEInfo::getNewArrHelperStatic(th); - pHelper = DynamicHelpers::CreateHelperArgMove(pModule->GetLoaderAllocator(), th.AsTAddr(), CEEJitInfo::getHelperFtnStatic(helpFunc)); + ArrayTypeDesc *pArrayTypeDesc = th.AsArray(); + MethodTable *pArrayMT = pArrayTypeDesc->GetTemplateMethodTable(); + pHelper = DynamicHelpers::CreateHelperArgMove(pModule->GetLoaderAllocator(), dac_cast(pArrayMT), CEEJitInfo::getHelperFtnStatic(helpFunc)); } break; -- 2.7.4