summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRuben Ayrapetyan <ruben-ayrapetyan@users.noreply.github.com>2017-06-27 00:18:19 +0300
committerJan Kotas <jkotas@microsoft.com>2017-06-26 14:18:19 -0700
commit8cc7e35dd0a625a3b883703387291739a148e8c8 (patch)
tree33ea4e95260aba8be3bc63f6ec789dea8c4a9bc0 /src
parent959dacc9f0b09eb9f8c418eabb1b9180ceb6f5ac (diff)
downloadcoreclr-8cc7e35dd0a625a3b883703387291739a148e8c8.tar.gz
coreclr-8cc7e35dd0a625a3b883703387291739a148e8c8.tar.bz2
coreclr-8cc7e35dd0a625a3b883703387291739a148e8c8.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/vm/amd64/JitHelpers_InlineGetThread.asm39
-rw-r--r--src/vm/amd64/JitHelpers_Slow.asm69
-rw-r--r--src/vm/amd64/asmconstants.h4
-rw-r--r--src/vm/arm/asmconstants.h3
-rw-r--r--src/vm/arm/patchedcode.asm42
-rw-r--r--src/vm/arm/stubs.cpp4
-rw-r--r--src/vm/compile.cpp8
-rw-r--r--src/vm/gchelpers.cpp50
-rw-r--r--src/vm/gchelpers.h8
-rw-r--r--src/vm/i386/jitinterfacex86.cpp24
-rw-r--r--src/vm/interpreter.cpp7
-rw-r--r--src/vm/jithelpers.cpp52
-rw-r--r--src/vm/jitinterface.cpp12
-rw-r--r--src/vm/jitinterface.h10
-rw-r--r--src/vm/jitinterfacegen.cpp12
-rw-r--r--src/vm/methodtable.cpp13
-rw-r--r--src/vm/object.cpp18
-rw-r--r--src/vm/object.h50
-rw-r--r--src/vm/object.inl27
-rw-r--r--src/vm/prestub.cpp4
20 files changed, 245 insertions, 211 deletions
diff --git a/src/vm/amd64/JitHelpers_InlineGetThread.asm b/src/vm/amd64/JitHelpers_InlineGetThread.asm
index 700c3b393c..022ec675df 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 293e447540..448bcb2279 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 e4f77deb42..4a100c1823 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 41597b2dbe..704fa28556 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 2ef175ea56..9fdd60961d 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 7cc937e99a..2e8bb19d49 100644
--- a/src/vm/arm/stubs.cpp
+++ b/src/vm/arm/stubs.cpp
@@ -2560,9 +2560,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 269e1948df..5782a0bfc8 100644
--- a/src/vm/compile.cpp
+++ b/src/vm/compile.cpp
@@ -1816,6 +1816,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 9669f988d7..046f06e2d5 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 449524aa9a..73933f691f 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 4ffed2d2bd..3e8cbc0232 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 f0a7a852f4..034f8ee6fe 100644
--- a/src/vm/interpreter.cpp
+++ b/src/vm/interpreter.cpp
@@ -6070,13 +6070,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 d93331d74e..e5fc596689 100644
--- a/src/vm/jithelpers.cpp
+++ b/src/vm/jithelpers.cpp
@@ -3001,7 +3001,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;
@@ -3027,16 +3027,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);
@@ -3055,7 +3053,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);
@@ -3071,14 +3069,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;
@@ -3099,14 +3097,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);
@@ -3123,7 +3119,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);
@@ -3139,14 +3135,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;
@@ -3154,11 +3150,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);
@@ -3175,7 +3171,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
@@ -3208,9 +3204,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
{
@@ -3220,7 +3220,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 8a41c89aa8..5e459af321 100644
--- a/src/vm/jitinterface.cpp
+++ b/src/vm/jitinterface.cpp
@@ -2670,7 +2670,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)
{
@@ -3348,7 +3355,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 26f32bec3a..10efca197c 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 8d1c8cdf67..26387405b7 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 191efb83e9..20376d3bb9 100644
--- a/src/vm/methodtable.cpp
+++ b/src/vm/methodtable.cpp
@@ -5902,6 +5902,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 15c3a457a9..cf7d775d5c 100644
--- a/src/vm/object.cpp
+++ b/src/vm/object.cpp
@@ -1824,6 +1824,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 a6719e5c96..add704a2f7 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 5698321993..5dc3d6d116 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 1ebcdc4b4d..31a5670e00 100644
--- a/src/vm/prestub.cpp
+++ b/src/vm/prestub.cpp
@@ -2742,7 +2742,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;