diff options
Diffstat (limited to 'packaging/0012-Replace-array-type-handle-with-method-table-in-argum.patch')
-rw-r--r-- | packaging/0012-Replace-array-type-handle-with-method-table-in-argum.patch | 1214 |
1 files changed, 1214 insertions, 0 deletions
diff --git a/packaging/0012-Replace-array-type-handle-with-method-table-in-argum.patch b/packaging/0012-Replace-array-type-handle-with-method-table-in-argum.patch new file mode 100644 index 0000000000..348709c38e --- /dev/null +++ b/packaging/0012-Replace-array-type-handle-with-method-table-in-argum.patch @@ -0,0 +1,1214 @@ +From a0dc56413e9e5c61c0f6617e1ef091966b2f7a1d Mon Sep 17 00:00:00 2001 +From: Ruben Ayrapetyan <ruben-ayrapetyan@users.noreply.github.com> +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 <lower bound 1>, <count 1>, <lower bound 2>, ... +-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<ArrayBase *>(allocPtr); +- array->SetMethodTable(arrayMethodTable); ++ array->SetArrayMethodTable(pArrayMT); + _ASSERTE(static_cast<DWORD>(componentCount) == componentCount); + array->m_NumComponents = static_cast<DWORD>(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<ArrayBase *>(allocPtr); +- array->SetMethodTable(arrayMethodTable); ++ array->SetArrayMethodTable(pArrayMT); + _ASSERTE(static_cast<DWORD>(componentCount) == componentCount); + array->m_NumComponents = static_cast<DWORD>(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 <optdefault.h> + + /*************************************************************/ +-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<DWORD>(size), bAllocateInLargeHeap); ++ newArray = FastAllocatePrimitiveArray(pArrayMT, static_cast<DWORD>(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<TADDR>(pArrayMT), CEEJitInfo::getHelperFtnStatic(helpFunc)); + } + break; + +-- +2.7.4 + |